S3 generic method not appearing in package manual - r

In my R package, a few functions are omitted from the package manual .pdf file - and they are all S3 methods where several functions are documented together. All other "normal" functions appear correctly, so I suspect I'm not documenting the S3 methods correctly.
I want an entry for myfun to appear in the manual. Right now, the function is missing from the .pdf manual entirely, though it can still be called correctly and its help page referenced with ?myfun. Are my Roxygen2 keywords wrong?
#' #export
myfun <- function(...) UseMethod("myfun")
#' #inheritParams myfun
#' #describeIn myfun Create a frequency table from a vector.
#' #export
#' #keywords internal
myfun.default <- function(vec, sort = FALSE, show_na = TRUE, ...) {
...
}
#' #inheritParams myfun.default
#' #describeIn myfun Create a frequency table from a data.frame,
#' supplying the unquoted name of the column to tabulate.
#' #export
#' #keywords internal
tabyl.data.frame <- function(.data, ...){
...
}
(I omitted the #title, #description, #param, #return, #examples lines to keep this question shorter but can edit them in if relevant).
The generic methods are exporting as intended, so that the user only sees myfun() and not myfun.default() or myfun.data.frame(), unless they use the triple colon :::. I'd like to retain that behavior, so the user just calls myfun, while also having an entry for myfun in the package manual.

I removed #keywords internal in the two myfun. methods and that did it: myfun appears in the package's manual. I also switched to #rdname myfun instead of #describeIn myfun, to eliminate the section "Methods (by class):" in the function's documentation.
What made this hard to isolate was that if I run devtools::document() and then don't restart the session, the methods myfun.data.frame and myfun.default are visible in RStudio's autocomplete and can be called directly. They are not supposed to be accessible to the user, and I thought my Roxygen2 documentation was to blame.
In fact, all I had to do was remove #keywords internal.
The methods myfun.data.frame and myfun.default do appear in the autocomplete after typing ?, e.g., ?myfun.default, but I think there's no way around that (and it directs to the single help page for all three myfun functions, anyway). This is standard. For example, ?print.aov is a visible help file while print.aov() cannot be called directly.

Related

Explicit namespaces for non-exported functions within same R package - best practice

I have an R package (MyPackage) that has some exported (using #export) and some non-exported functions. If I call a non-exported function from elsewhere in the package, what is the most appropriate way to reference it? For example, given the following code:
#' #export
f1 <- function(){
f2()
}
f2 <- function(){
print('hello')
}
When I run linting on the package I get the warning:
no visible global function definition for 'f2'
I could use MyPackage:f2 but my understanding was that this isn't necessary. I do not expect to get the error 'no visible global function definition' for a function within the same package. What is the best practice in this case?
As myself and others have mentioned, your code does not produce such a warning.
In terms of best practices, don't use MyPackage:::f2. As mentioned here.
A function is not exported to user is not present in the NAMESPACE. If
you use roxygen, putting #export tag ONLY for the function you want to
export will do the job.
As you did, just using the #export tag for the functions you want to make available, and not for the internal functions, is the way to go. You should just decorate your internal functions with a few roxygen comments, then decide whether you want to create a manual page for this function or not.
If you don't wish to create a manual page for f2, you should use the #' #noRd tag. (source)
#' Internal function printing "hello"
#' #description A function that prints the text "hello".
#' #noRd
f2 <- function(){
print('hello')
}
If you wanted to create a manual page for f2, but to exclude it from the index of the manual, you could use #keywords internal, which works even with f1 or basically any function that you wouldn't want too visible in your manual.
#' Internal function printing "hello"
#' #description A function that prints the text "hello".
#' #keywords internal
f2 <- function(){
print('hello')
}

Control where method documentation goes for simple generic, while hiding from package index

I'm writing an R package and largely following Hadley's book on the topic. I'm running into a problem with documenting methods for simple generics like print, plot, head, and tail. When I use the #describeIn tag to control where the method documentation goes, I get the nice feature of them showing up in the help file for the main analysis function that returns an object of the given class. The problem is that these generics also show up in the package's index. If I add #keywords internal to the generics, then they are removed from the package's index, but so is the main analysis function (they are in the same .R file). If I document the generics in a separate .R file, then I can gain control over what is and is not in the package's index, but I have two issues: the main analysis function doesn't come first in the Usage section of the help file; and if add the #keywords internal for the generics, this removes the analysis function from the package index too, even though they are documented (in this instance) in separate files. The crux of the problem seems to be that #keywords internal applies to all functions in the given .R file, and maybe even any function referenced in #describeIn, while #describeIn is designed for documenting multiple functions in a given .R file.
For now, I have the analysis function and generics in the same .R file to control where the method documention goes and its ordering in the Usage section, but am not using #keywords internal and leaving the index cluttered.
Here's a rough sketch of an exported analysis function:
#' #inheritParams foo
#' #export
seats <- function(judgeit.object, ...) {
[...omitted...]
class(out.object) <- "judgeit.seats"
return(out.object)
}
And a generic:
#' #describeIn seats Print a \code{\link{seats}} output
#' #keywords internal
#' #export
print.judgeit.seats <- function(x,...) print(x$output,...)
I want the help file for ?seats to look like this:
seats(judgeit.object, ...)
## S3 method for class 'judgeit.seats'
print(x, ...)
## S3 method for class 'judgeit.seats'
head(x, ...)
## S3 method for class 'judgeit.seats'
tail(x, ...)
I do not want print.judgeit.seats, head.judgeit.seats, etc. to appear in the package index, because it quickly becomes very cluttered.
Unfortunately, I am not aware of any easy fix for what you are asking.
Tags and their effect
#export will make your function visible in the global environment. CRAN requires that you document any such functions that is not hidden (i.e. that starts with .).
If you use #describeIn or #rdname, an automatic alias is created. Any alias creates an entry in the index, but points to the same .Rd file. For example, adding
#' #name myfunction
#' #aliases foo foobar`
would create foo and foobar entries in the index, but refer to the myfunction.Rd documentation file. If you try to delete manually the \alias{} in the .Rd file, CRAN will complain.
#describeIn will list the functions in the order they appear in the .R files (if they are documented in multiple files, they are listed according to the alphabetical order of the .R file, then the order of appearance). Reordering your functions can give you what you want.
#keywords internal (along with #export, a title and a description) will have Roxygen create a .Rd file that can be accessed by the user using ?, but will not be visible in the index (if you have only the tags, Roxygen will not create a .Rd file and you will get a warning because your function is not documented).
If you have a #keywords internal in any of the functions calling #describeIn, that function will be masked from the index. This does not apply to all functions in a .R file, only those which are aliases.
#usage requires you to have an alias for each method documented. You can try using instead #section Usage:, but note sections are listed in alphabetical order and the spacing will be larger.
Workaround
If you document a NULL function, you can add the #param you want. and include a multiple lines #Section: Usage field to include (manually) the S3 methods with your comments. Give it a name such as #name Seats (it cannot be the name of the function, otherwise you have ?seats pointing to two different files).
Then, document your function seats with a different #name tag and a different title, and use #internal' to hide it from the user. Use \code{\link{seats}}` to refer to that documentation.
#' Seats
#' Description of the function
#' #param judgeit.object object
#' #param x object from seats
#' #param ... additional arguments
#' #name seats
#' #section Usage:
#' \preformatted{seats(judgeit.object, ...)
#' ## S3 method for class 'judgeit.seats'
#' print(x, ...)
#' ## S3 method for class 'judgeit.seats'
#' head(x, ...)
#' ## S3 method for class 'judgeit.seats'
#' tail(x, ...)}
NULL
#' Seats function
#' #name internal-function
#' #inheritParams seats
#' #export
#' #keywords internal
#' #seealso \code{\link{seats}}
seats <- function(judgeit.object, ...) {
[...omitted...]
class(out.object) <- "judgeit.seats"
return(out.object)
}
#' Print a \code{\link{seats}} output
#'
#' #inheritParams seats
#' #describeIn internal-function
#' #export
print.judgeit.seats <- function(x,...) print(x$output,...)
This way, the user calling ?seats will be pointed to the overall documentation.

Roxygen documentation [duplicate]

I am writing a package that defines a new class, surveyor, and a print method for this, i.e. print.surveyor. My code works fine and I use roxygen for inline documentation. But R CMD check issues a warning:
Functions/methods with usage in
documentation object 'print.surveyor'
but not in code: print
I have used the following two pages, written by Hadley, as inspiration:
Namespaces and Documenting functions, both of which states that the correct syntax is #method function-name class
So my question is: What is the correct way of documenting the print method for my new class using Roxygen? And more specifically, how do I get rid of the warning?
Here is my code: (The commented documentation indicated attempts at fixing this, none of which worked.)
#' Prints surveyor object.
#'
#' Prints surveyor object
#'
## #' #usage print(x, ...)
## #' #aliases print print.surveyor
#' #param x surveyor object
#' #param ... ignored
#' #S3method print surveyor
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
And the roxygenized output, i.e. print.surveyor.Rd:
\name{print.surveyor}
\title{Prints surveyor object.}
\usage{print(x, ...)
#'}
\description{Prints surveyor object.}
\details{Prints surveyor object
#'}
\alias{print}
\alias{print.surveyor}
\arguments{\item{x}{surveyor object}
\item{...}{ignored}}
Update
As of roxygen2 > 3.0.0 the package has gotten a lot smarter at figuring all this out for you. You now just need the #export tag and roxygen will work out what kind of thing you are documenting and do the appropriate thing when writing the NAMESPACE etc during conversion.
There are exceptions where you may need to help out roxygen. An example that Hadley Wickham uses in his R Packages book is all.equal.data.frame. There is ambiguity in that function name as to what is the class and what is the generic function (all, all.equal, or all.equal.data)?
In such cases, you can help roxygen out by explicitly informing it of the generic and class/method, e.g.
#method all.equal data.frame
The original answer below explains more about the older behaviour if you need to explicitly use #method.
Original
The function should be documented with the #method tag:
#' #method print surveyor
On initial reading, #hadley's document was a little confusing for me as I am not familiar with roxygen, but after several readings of the section, I think I understand the reason why you need #method.
You are writing full documentation for the print method. #S3method is related to the NAMESPACE and arranges for the method to be exported. #S3method is not meant for documenting a method.
Your Rd file should have the following in the usage section:
\method{print}{surveyor}(x, ...)
if this works correctly, as that is the correct way to document S3 methods in Rd files.
As of roxygen2 > 3.0.0., you only need #export because roxygen can figure out that print.surveyor is an S3 method. This means that you now only need
#' Prints surveyor object.
#'
#' #param x surveyor object
#' #param ... ignored
#' #export
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
However, in this case since the documentation isn't very useful, it'd probably better to just do:
#' #export
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
#export only works if the generic is loaded. If the generic is in another package you need to import the generic. With current roxygen this is solved with a block like
#' #importFrom tibble data_frame
#' #export
tibble::data_frame
taken from dplyr/R/reexport-tibble.r . In this example, the data_frame method is imported from the tibble package, and tibble::data_frame is exported. Such re-exported objects are then documented in a reexports.Rd file that - needless to say - satisfies R CMD check.

R-oxygen documentation of S3 method produces error while check [duplicate]

I am writing a package that defines a new class, surveyor, and a print method for this, i.e. print.surveyor. My code works fine and I use roxygen for inline documentation. But R CMD check issues a warning:
Functions/methods with usage in
documentation object 'print.surveyor'
but not in code: print
I have used the following two pages, written by Hadley, as inspiration:
Namespaces and Documenting functions, both of which states that the correct syntax is #method function-name class
So my question is: What is the correct way of documenting the print method for my new class using Roxygen? And more specifically, how do I get rid of the warning?
Here is my code: (The commented documentation indicated attempts at fixing this, none of which worked.)
#' Prints surveyor object.
#'
#' Prints surveyor object
#'
## #' #usage print(x, ...)
## #' #aliases print print.surveyor
#' #param x surveyor object
#' #param ... ignored
#' #S3method print surveyor
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
And the roxygenized output, i.e. print.surveyor.Rd:
\name{print.surveyor}
\title{Prints surveyor object.}
\usage{print(x, ...)
#'}
\description{Prints surveyor object.}
\details{Prints surveyor object
#'}
\alias{print}
\alias{print.surveyor}
\arguments{\item{x}{surveyor object}
\item{...}{ignored}}
Update
As of roxygen2 > 3.0.0 the package has gotten a lot smarter at figuring all this out for you. You now just need the #export tag and roxygen will work out what kind of thing you are documenting and do the appropriate thing when writing the NAMESPACE etc during conversion.
There are exceptions where you may need to help out roxygen. An example that Hadley Wickham uses in his R Packages book is all.equal.data.frame. There is ambiguity in that function name as to what is the class and what is the generic function (all, all.equal, or all.equal.data)?
In such cases, you can help roxygen out by explicitly informing it of the generic and class/method, e.g.
#method all.equal data.frame
The original answer below explains more about the older behaviour if you need to explicitly use #method.
Original
The function should be documented with the #method tag:
#' #method print surveyor
On initial reading, #hadley's document was a little confusing for me as I am not familiar with roxygen, but after several readings of the section, I think I understand the reason why you need #method.
You are writing full documentation for the print method. #S3method is related to the NAMESPACE and arranges for the method to be exported. #S3method is not meant for documenting a method.
Your Rd file should have the following in the usage section:
\method{print}{surveyor}(x, ...)
if this works correctly, as that is the correct way to document S3 methods in Rd files.
As of roxygen2 > 3.0.0., you only need #export because roxygen can figure out that print.surveyor is an S3 method. This means that you now only need
#' Prints surveyor object.
#'
#' #param x surveyor object
#' #param ... ignored
#' #export
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
However, in this case since the documentation isn't very useful, it'd probably better to just do:
#' #export
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
#export only works if the generic is loaded. If the generic is in another package you need to import the generic. With current roxygen this is solved with a block like
#' #importFrom tibble data_frame
#' #export
tibble::data_frame
taken from dplyr/R/reexport-tibble.r . In this example, the data_frame method is imported from the tibble package, and tibble::data_frame is exported. Such re-exported objects are then documented in a reexports.Rd file that - needless to say - satisfies R CMD check.

How to properly document a S3 method of a generic from a different package, using Roxygen?

I am writing a package that defines a new class, surveyor, and a print method for this, i.e. print.surveyor. My code works fine and I use roxygen for inline documentation. But R CMD check issues a warning:
Functions/methods with usage in
documentation object 'print.surveyor'
but not in code: print
I have used the following two pages, written by Hadley, as inspiration:
Namespaces and Documenting functions, both of which states that the correct syntax is #method function-name class
So my question is: What is the correct way of documenting the print method for my new class using Roxygen? And more specifically, how do I get rid of the warning?
Here is my code: (The commented documentation indicated attempts at fixing this, none of which worked.)
#' Prints surveyor object.
#'
#' Prints surveyor object
#'
## #' #usage print(x, ...)
## #' #aliases print print.surveyor
#' #param x surveyor object
#' #param ... ignored
#' #S3method print surveyor
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
And the roxygenized output, i.e. print.surveyor.Rd:
\name{print.surveyor}
\title{Prints surveyor object.}
\usage{print(x, ...)
#'}
\description{Prints surveyor object.}
\details{Prints surveyor object
#'}
\alias{print}
\alias{print.surveyor}
\arguments{\item{x}{surveyor object}
\item{...}{ignored}}
Update
As of roxygen2 > 3.0.0 the package has gotten a lot smarter at figuring all this out for you. You now just need the #export tag and roxygen will work out what kind of thing you are documenting and do the appropriate thing when writing the NAMESPACE etc during conversion.
There are exceptions where you may need to help out roxygen. An example that Hadley Wickham uses in his R Packages book is all.equal.data.frame. There is ambiguity in that function name as to what is the class and what is the generic function (all, all.equal, or all.equal.data)?
In such cases, you can help roxygen out by explicitly informing it of the generic and class/method, e.g.
#method all.equal data.frame
The original answer below explains more about the older behaviour if you need to explicitly use #method.
Original
The function should be documented with the #method tag:
#' #method print surveyor
On initial reading, #hadley's document was a little confusing for me as I am not familiar with roxygen, but after several readings of the section, I think I understand the reason why you need #method.
You are writing full documentation for the print method. #S3method is related to the NAMESPACE and arranges for the method to be exported. #S3method is not meant for documenting a method.
Your Rd file should have the following in the usage section:
\method{print}{surveyor}(x, ...)
if this works correctly, as that is the correct way to document S3 methods in Rd files.
As of roxygen2 > 3.0.0., you only need #export because roxygen can figure out that print.surveyor is an S3 method. This means that you now only need
#' Prints surveyor object.
#'
#' #param x surveyor object
#' #param ... ignored
#' #export
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
However, in this case since the documentation isn't very useful, it'd probably better to just do:
#' #export
print.surveyor <- function(x, ...){
cat("Surveyor\n\n")
print.listof(x)
}
#export only works if the generic is loaded. If the generic is in another package you need to import the generic. With current roxygen this is solved with a block like
#' #importFrom tibble data_frame
#' #export
tibble::data_frame
taken from dplyr/R/reexport-tibble.r . In this example, the data_frame method is imported from the tibble package, and tibble::data_frame is exported. Such re-exported objects are then documented in a reexports.Rd file that - needless to say - satisfies R CMD check.

Resources