49

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}}
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
Andrie
  • 176,377
  • 47
  • 447
  • 496

3 Answers3

44

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.

Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
  • Thanks, been struggling with this too, but how do you use it with a class specific [-function, e.g. `[.myClass`? This solution passes `R CMD check` without warnings but the resulting Rd tag is a mess. `@method [ myClass` becomes `\method{[}{myClass} (x, i, j, ...)`. – Backlin Aug 11 '11 at 13:17
  • 1
    @Backlin What's wrong with that? That looks like the proper way to mark-up and S3 method in Rd. It will render properly in the Usage section but with `## S3 method blah blah` above the usage code. – Gavin Simpson Aug 11 '11 at 13:34
  • Oh no, my bad! I was looking at the documentation in an old version of R but it renders correctly in the newer versions. Hope I didn't waste too much of your time with it. – Backlin Aug 11 '11 at 13:58
  • @Backlin - no worries. Glad the Q&A was useful to you. – Gavin Simpson Aug 11 '11 at 13:59
  • Great answer. so what't the deal with `@S3method`? should I use both? is `@S3method` identical to `@export` for an S3 method? – cboettig Nov 02 '12 at 22:29
  • @cboettig no, they are quite different. `@S3method` registers the method but doesn't export it so it can be called from `foo()` but not explicitly via `foo.bar()`. If you also `@export` that method then you can call it directly. Usually you don't want to export the methods just register them, but on some occasions you may want to export a method and in those cases you need both `@S3method` and `@export`. – Gavin Simpson Nov 03 '12 at 10:54
  • @GavinSimpson thanks! So typically I need both `@method` and `@S3method` but not `@export`? – cboettig Nov 03 '12 at 16:37
  • 3
    @cboettig Yes, `@method` is the tag for the documentation (the `.Rd` file) and `@S3method` is for the namespace mechanism. You need both these days if you have your own `NAMESPACE` file. You only need `@export` if you really want to make the method visible outside the namespace of the package. – Gavin Simpson Nov 03 '12 at 17:48
29

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)
}
hadley
  • 102,019
  • 32
  • 183
  • 245
  • Neat. Thank you. I'll try this immediately! – Andrie Mar 24 '14 at 06:58
  • 1
    Hmm. I’d like to register an S3 method *without* exporting it. Unfortunately that generates a deprecation warning. Is there a way around this? – Konrad Rudolph Jun 26 '15 at 21:24
  • @KonradRudolph what does it mean to register an S3 method without exporting it? – hadley Jun 27 '15 at 04:42
  • 1
    @hadley I wanted to avoid using `@export` because then `R CMD check` complained about undocumented parameters (I hadn’t documented the method since it’s supposed to be invisible anyway). However, I cannot reproduce this now: no `.Rd` file is generated and no `R CMD check` warning is displayed for missing parameters. I probably had some empty line in the doc comment beforehand, causing an incomplete documentation to be generated for this method. – Konrad Rudolph Jun 27 '15 at 09:19
3

@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.

Johannes Ranke
  • 469
  • 3
  • 11