Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RC class - weird NAMESPACE #433

Closed
odinuv opened this issue Nov 9, 2015 · 14 comments
Closed

RC class - weird NAMESPACE #433

odinuv opened this issue Nov 9, 2015 · 14 comments

Comments

@odinuv
Copy link

odinuv commented Nov 9, 2015

Given the following code

#' test
#' @import methods
#' @exportClass 
LGModule <- setRefClass(
    'LGModule',
    methods = list(
       #' some lengthy description
       fooBar = function() {
            NULL    
        }
    )
)

I get a NAMESPACE file:

# Generated by roxygen2: do not edit by hand

exportClasses(description)
exportClasses(lengthy)
exportClasses(some)
import(methods)

Using this code:

#' test
#' @import methods
#' @export
LGModule <- setRefClass(
    'LGModule',
    methods = list(
       #' some lengthy description
       #' @export
       fooBar = function() {
            NULL    
        }
    )
)

i get a namespace file:

# Generated by roxygen2: do not edit by hand

export(description)
export(lengthy)
export(some)
exportClasses(LGModule)
import(methods)

Just for reference - this results in errors like: "classes some, lengthy, description were specified for export but not defined" or "Error in namespaceExport(ns, exports) : undefined exports: description, lengthy, some"

@krlmlr
Copy link
Member

krlmlr commented Nov 10, 2015

Your examples are parsed as

#' test
#' @import methods
#' @exportClass 
#' some lengthy description
LGModule <- setRefClass(
    'LGModule',
    methods = list(
       fooBar = function() {
            NULL    
        }
    )
)

and

#' test
#' @import methods
#' @export
#' some lengthy description
#' @export
LGModule <- setRefClass(
    'LGModule',
    methods = list(
       fooBar = function() {
            NULL    
        }
    )
)

as of roxygen2 5.0.0. The roxygen-style comments inside the ref class definition are now part of the documentation. If you want to add the description to the documentation, use

#' test
#' @import methods
#' @export
LGModule <- setRefClass(
    'LGModule',
    methods = list(
       #' @details some lengthy description
       fooBar = function() {
            NULL    
        }
    )
)

Otherwise, simply revert to using plain comments:

#' test
#' @import methods
#' @exportClass 
LGModule <- setRefClass(
    'LGModule',
    methods = list(
       # some lengthy description
       fooBar = function() {
            NULL    
        }
    )
)

See also #428 and http://stackoverflow.com/a/33530515/946850.

@odinuv
Copy link
Author

odinuv commented Nov 11, 2015

So, how do you document RC classes methods and their parameters ? And how do you export only the methods you want to export? I'd expect something like this would work:

#' some description
#' @import methods
#' @exportClass SomeClass
SomeClass <- setRefClass(
  'SomeClass',
  contains = c('Application'),
  fields = list(
  ),
  methods = list(
    #' method description
    #' @param bar parameter description
    #' @exportMethod
    foo = function(bar) {
    },

    #' private method description
    #' @param foo foo parameter description
    #' @param bar bar parameter description
    fooBar = function(foo, bar) {
    }

    #' another public method description
    #' @param foo foo parameter description
    #' @param bar bar parameter description
    #' @exportMethod
    fooBazBar = function(foo, bar) {
    }
  )
)

Sorry if I'm acting blind, but I cannot find an example of documenting RC methods and their parameters with roxygen.

@krlmlr
Copy link
Member

krlmlr commented Nov 11, 2015

Does your proposed syntax work with pre-5.0.0 roxygen2?

@odinuv
Copy link
Author

odinuv commented Nov 11, 2015

It does not cause errors and correctly exports the marked methods.

@krlmlr
Copy link
Member

krlmlr commented Nov 11, 2015

Thanks, I'll take a look. It would help if you could edit your second-to last comment with the code to add triple-backticks before and after the code block.

@odinuv
Copy link
Author

odinuv commented Nov 11, 2015

thx, done

@krlmlr
Copy link
Member

krlmlr commented Nov 11, 2015

https://github.com/krlmlr/rc is what I get with roxygen2 4.1.1. Are you seeing a different behavior? Please file a pull request to that repo to show where the problem is.

@odinuv
Copy link
Author

odinuv commented Nov 11, 2015

I do get a different namespace file, but I now realized that is due to us having some postprocessing, sorry about that. So the only difference is that it does not cause an error. Since I'm obviously writing the docs in a wrong way - what is the right way to document RC classes? All I found is this http://stackoverflow.com/questions/23707709/documenting-reference-class-with-roxygen2-r-cmd-check-codoc-mismatches-warning and this http://r-pkgs.had.co.nz/man.html non of which shows how to document methods.

@krlmlr
Copy link
Member

krlmlr commented Nov 11, 2015

Actually, I think something like your syntax is what we should strive towards for RC/R6 classes (#306, #388). This was one of the reasons for this change. For now, there are docstrings: https://github.com/klutometis/roxygen/blob/master/NEWS.md#roxygen2-310

@odinuv
Copy link
Author

odinuv commented Nov 13, 2015

Actually I assumed that the docstring is no longer supported, because the example code:

setRefClass("A", methods = list(
  f = function(a, b) {
    "Take numbers \code{a} and \code{b} and add them together"
    a + b
  }
))

Produces error:

Error: '\c' is an unrecognized escape in character string starting ""Take numbers \c"
Execution halted

Without the \code{} it does work, unless the method is "inherited", i.e.

Application <- setRefClass(
  'Application',
  methods = list(
    run = function(a, b) {
      a + b
    }
  )
)

#' Application descendant
#' @import methods
#' @export ApplicationDescendent
#' @exportClass ApplicationDescendent
ApplicationDescendent <- setRefClass(
  'LGModule',
  contains = c('Application'),
  methods = list(
    run = function(a, b) {
      "Take numbers a and b and add them together"
      a + b
    },

    getParameters = function() {
      "Return script parameters"
      list()
    }
  )
)

produces

% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/hello.R
\docType{class}
\name{LGModule-class}
\alias{ApplicationDescendent}
\alias{LGModule-class}
\title{Application descendent}
\description{
Application descendent
}
\section{Methods}{

\describe{
\item{\code{getParameters()}}{Return script parameters}
}}

I.e. - the entry for method run is missing completely. And the code

Application <- setRefClass(
  'Application',
  methods = list(
    run = function(a, b) {
      "ancestor description"
      a + b
    }
  )
)

#' Application descendent
#' @import methods
#' @export ApplicationDescendent
#' @exportClass ApplicationDescendent
ApplicationDescendent <- setRefClass(
  'LGModule',
  contains = c('Application'),
  methods = list(
    run = function(a, b) {
      "child description"
      a + b
    },

    getParameters = function() {
      "Return script parameters"
      list()
    }
  )
)

produces

% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/hello.R
\docType{class}
\name{LGModule-class}
\alias{ApplicationDescendent}
\alias{LGModule-class}
\title{Application descendent}
\description{
Application descendent
}
\section{Methods}{

\describe{
\item{\code{getParameters()}}{Return script parameters}

\item{\code{run(a, b)}}{ancestor description}
}}

In my case the ancestor RC class is a library which has no docstring and in that case the child class cannot be documented at all, since roxygen seems to take the empty parent comment.

@krlmlr
Copy link
Member

krlmlr commented Nov 13, 2015

Need to escape the \ in the docstring.

Sorry, I cannot help with the inheritance issue.

@odinuv
Copy link
Author

odinuv commented Nov 13, 2015

Ok, so to sum it up:

  • The only possible way of documenting RC classes methods is using docstring.
  • Oxygen comments should not be used anywhere inside the class definition.
  • Exports must be listed in the RC class docblock.
  • Methods without a docstring will not be documented.
  • Method parameters and return values must be documented manually
  • It is not possible to override docstring, therefore when inheriting a class, the parent docstring is always used.

I tried to put up together a sample commented RC class:

#' Class name
#'
#' Length class description
#' @import methods
#' @field text Text field description
#' @field fooBar Description of the fooBar field
#' @export SampleClass
#' @exportClass SampleClass
SampleClass <- setRefClass(
  'SampleClass',
  fields = list(
    text = "character",
    fooBar = "integer"
  ),
  methods = list(
    runs = function(a, b) {
      "Lengthy method description.
      \\subsection{Parameters}{\\itemize{
        \\item{\\code{foo} Some foo parameter \\code{code} here.}
        \\item{\\code{bar} Some bar parameter description.}
      }}
      \\subsection{Return Value}{A return value}"
      a + b
    },

    getParameters = function() {
      "Second method lengthy description.
      \\subsection{Parameters}{\\itemize{
      \\item{\\code{fooBar} Another fooBar parameter description.}
      \\item{\\code{fooBaz} Yet another parameter description.}
      }}
      \\subsection{Return Value}{Another return value}"
      list()
    }
  )
)

This generates the following Rd file:

% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/hello.R
\docType{class}
\name{SampleClass-class}
\alias{SampleClass}
\alias{SampleClass-class}
\title{Class name}
\description{
Length class description
}
\section{Fields}{

\describe{
\item{\code{text}}{Text field description}

\item{\code{fooBar}}{Description of the fooBar field}
}}
\section{Methods}{

\describe{
\item{\code{getParameters()}}{Second method lengthy description.
\subsection{Parameters}{\itemize{
\item{\code{fooBar} Another fooBar parameter description.}
\item{\code{fooBaz} Yet another parameter description.}
}}
\subsection{Return Value}{Another return value}}

\item{\code{runs(a, b)}}{Lengthy method description.
\subsection{Parameters}{\itemize{
  \item{\code{foo} Some foo parameter \code{code} here.}
  \item{\code{bar} Some bar parameter description.}
}}
\subsection{Return Value}{A return value}}
}}

and NAMESPACE

# Generated by roxygen2: do not edit by hand

export(SampleClass)
exportClasses(SampleClass)
exportMethods(run)
import(methods)

Renders as:
clipboard02

Please correct me if I'am wrong in some point and something can be done easier. If possible I'd like to ask if the above example can be put into docs.

@Greenall
Copy link

Greenall commented Feb 8, 2016

@odinuv Thanks for this summary. I have pretty much arrived at the same place as you after a fair bit of pain and agree that something needs adding to the official docs!
Can anyone comment on whether there is any enhancement tabled? The docstring method seems incongruous to the standard roxygen markdown and your suggestion definitely seems a more intuitive way to go!

#' some description
#' @import methods
#' @exportClass SomeClass
SomeClass <- setRefClass(
  'SomeClass',
  contains = c('Application'),
  fields = list(
  ),
  methods = list(
    #' method description
    #' @param bar parameter description
    #' @exportMethod
    foo = function(bar) {
    },

    #' private method description
    #' @param foo foo parameter description
    #' @param bar bar parameter description
    fooBar = function(foo, bar) {
    }

    #' another public method description
    #' @param foo foo parameter description
    #' @param bar bar parameter description
    #' @exportMethod
    fooBazBar = function(foo, bar) {
    }
  )
)

@hadley
Copy link
Member

hadley commented Aug 29, 2016

Discussion of RC/R6 method docs in #388

@hadley hadley closed this as completed Aug 29, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants