How to properly document S4 methods using roxygen2

孤街醉人 提交于 2019-11-28 03:04:13
Paul McMurdie

Official Support, explained in devtools doc

http://r-pkgs.had.co.nz/man.html#man-classes (scroll down to the S4 subsection).

The current short example from that page is reproduced in the following (for convenience):

#' An S4 class to represent a bank account.
#'
#' @slot balance A length-one numeric vector
Account <- setClass("Account",
  slots = list(balance = "numeric")
)

The above link very clearly explains S3, S4, and RC support via roxygen/devtools. The explanation there should be considered to supersede the older answer below, which does work for now, but is less clear and more complicated.

The old answer

Here is an example that should work for most S4 methods.

For documenting S4 generics, I find the following three lines necessary in most of my generic headers:

#' @export
#' @docType methods
#' @rdname helloworld-methods

Where helloworld-methods is replaced with the_name_of_your_generic-methods. This will be the name of the Rd file that holds the documentation for the generic and all its methods. This naming convention is not required, but common and useful. The @export tag is necessary now that a namespace is required for your package and you want this method to be available to users of your package, not just other methods/functions in your package.

For documenting methods, I find that only 2 lines are necessary, providing the @rdname and @aliases tag. The @rdname statement should match exactly the one for the generic. The @aliases tag must adhere to a naming convention described in the official S4 documentation section of Writing R Extensions.

#' @rdname helloworld-methods
#' @aliases helloworld,character,ANY-method

There should be no spaces after the commas in the @aliases name. I don't know the exact rules surrounding when to add ,ANY to the end of the signature list. The pattern seems to be that the number of elements in all @aliases signature lists needs to match the number of elements in the longest signature vector among the methods. In the example below, one of the methods is defined with 2-element signature, and so R CMD check wasn't satisfied with the documentation unless ,ANY was added to the aliases tag of the other methods, even if their signature definition only has one element.

A complete example follows. I built this and it works with no documentation-level warnings from R CMD check testpkg, using a bug-fixed fork of a very recent devel version of roxygen2 (which I have made available). For quick installation of this fork on your system, use library("devtools"); install_github("roxygen", "joey711"). The most recent version of roxygen2 won't work this moment because of a quotation error (described in a separate answer), but I expect this will be incorporated very soon and my fork won't be necessary. For looking at this example in context of the rest of a package, and seeing the resulting documentation (Rd) files, I have made it available as a trivial test package on github called testpkg.

##############################################################
#' The title, in this case: Helloworld-ify the argument.
#'
#' Some additional details about this S4 generic and its methods.
#' The extra blank line between this section and the title is
#' critical for roxygen2 to differentiate the title from the
#' description section.
#'
#' @param x Description of \code{x}. The main argument in this
#'  example. Most often has such and such properties.
#'
#' @param y Description of \code{y}. An argument that is rarely
#'  used by \code{"helloworld"} methods. 
#'
#' @param ... Additional argument list that might not ever
#'  be used.
#'
#' @return A helloworld-ified argument. Oh, you'll see.
#' 
#' @seealso \code{\link{print}} and \code{\link{cat}}
#' 
#' @export
#' @docType methods
#' @rdname helloworld-methods
#'
#' @examples
#' helloworld("thisismystring")
#' helloworld(char2helloworld("thisismystring"))
#' helloworld(matrix(0,3,3))
#' helloworld(list(0,0,0))
#' helloworld(integer(0))
setGeneric("helloworld", function(x, y, ...){
    cat("Hello World!")
    cat("\n")
    standardGeneric("helloworld")
})

#' @rdname helloworld-methods
#' @aliases helloworld,ANY,ANY-method
setMethod("helloworld", "ANY", function(x, y, ...){
    cat(class(x))
})

#' @rdname helloworld-methods
#' @aliases helloworld,character,ANY-method
setMethod("helloworld", "character", function(x){
    show(x)
})

#' @rdname helloworld-methods
#' @aliases helloworld,character,character-method
setMethod("helloworld", c("character", "character"), function(x, y){
    show(x)
})

This example assumes that you don't need separate method-specific documentation because your methods haven't veered wildly from the behavior one would expect based on the generic doc. There are means in roxygen2 to handle that alternative case using the @usage tag, but the details would be better handled by a separate SO question.

So most of your documentation effort goes into the roxygen header above the generic definition. This has some basis in the code, since the generic should include all specific arguments that appear in any of the subsequently defined methods . Note that arguments that are handled as part of the ... in the argument list are not included and shouldn't be documented specifically, but the ... itself should be documented above the generic as well (see the full example below).

For further details on the basics of documenting functions, there is a wiki in progress, the old roxygen vignette, as well as the roxygen2 development site on github. There is also a SO question on R documentation with Roxygen in general.

I have tracked down that the answer to part (3) -- the not-so-missing documentation of S4 methods -- is because of quotation marks being added erroneously around the \alias tags when the S4 naming convention is used; most likely a bug resulting from text-handling of an alias that contains a comma as part of its name. This is still true of the latest version of roxygen2 at the time of this posting. I just posted a more thorough description of the bug with a reproducible example on the roxygen2 github page:

https://github.com/klutometis/roxygen/issues/40

Briefly,

#' @aliases show,helloworld-method

becomes

\alias{"show,helloworld-method"}

in the resulting Rd file. Removing the quotations removes the R CMD check warning, and the documentation builds and is functional in both cases.

I think parts (1) and (2) of this question (best practices; good examples) still stand open.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!