roxygen2 icon indicating copy to clipboard operation
roxygen2 copied to clipboard

Document R6 methods created on $new()/$initialize()

Open sckott opened this issue 6 years ago • 5 comments

(started in https://community.rstudio.com/t/document-r6-methods-created-on-new/45442 cc @gaborcsardi ) (may be related to #931)

In an R6 class I maintain I create a function in the $initialize() call when a user calls $new(). However, I can't get roxygen2 to use the doc strings no matter where I put them. I imagine this isn't currently and won't be supported in the future, but thought I'd check.

If I put the string within private, either above the factory function or below it and above the nested function definition, roxygen2 throws warnings like

Foo <- R6::R6Class(
  "Foo",
  public = list(
    #' @field bar bar function placeholder
    bar = NULL,
    
    #' @description make a new Foo
    initialize = function() {
      self$bar = private$bar_factory()
    }
  ),
  private = list(
    #' @description Square a number
    #' @param x (numeric) a number
    bar_factory = function() {
      #' @description Square a number
      #' @param x (numeric) a number
      function(x = 5) x^2
    }
  )
)
#> Warning: [/R/foo.R:11] @description Cannot find matching R6 method
#> Warning: [/R/foo.R:12] @param Cannot find matching R6 method

And if I put doc strings above the foo placeholder in public, throws a different warning

Foo <- R6::R6Class(
  "Foo",
  public = list(
    #' @description Square a number
    #' @param x (numeric) a number
    bar = NULL,
    
    #' @description make a new Foo
    initialize = function() {
      self$bar = private$bar_factory()
    }
  ),
  private = list(
    bar_factory = function() {
      function(x = 5) x^2
    }
  )
)
#> Warning: [/R/foo.R:2] undocumented R6 field: `bar`

The motivating use case is in this HttpResponse R6 class https://github.com/ropensci/crul/blob/master/R/response.R

Session Info
─ Session info ────────
 setting  value
 version  R version 3.6.1 Patched (2019-09-23 r77210)
 os       macOS Mojave 10.14.6
 system   x86_64, darwin15.6.0
 ui       X11
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       US/Pacific
 date     2019-11-25

─ Packages ────────────
 package     * version    date       lib source
 assertthat    0.2.1      2019-03-21 [1] CRAN (R 3.6.0)
 backports     1.1.5      2019-10-02 [1] CRAN (R 3.6.1)
 cli           1.9.9.9000 2019-09-23 [1] Github (r-lib/cli@ad6410a)
 crayon        1.3.4      2017-09-16 [1] CRAN (R 3.6.0)
 fansi         0.4.0      2018-10-05 [1] CRAN (R 3.6.0)
 glue          1.3.1      2019-03-12 [1] CRAN (R 3.6.0)
 hms           0.5.2      2019-10-30 [1] CRAN (R 3.6.1)
 magrittr      1.5        2014-11-22 [1] CRAN (R 3.6.0)
 pillar        1.4.2      2019-06-29 [1] CRAN (R 3.6.0)
 pkgconfig     2.0.3      2019-09-22 [1] CRAN (R 3.6.1)
 prettyunits   1.0.2      2015-07-13 [1] CRAN (R 3.6.0)
 progress      1.2.2      2019-05-16 [1] CRAN (R 3.6.0)
 purrr         0.3.3      2019-10-18 [1] CRAN (R 3.6.0)
 R6            2.4.1      2019-11-12 [1] CRAN (R 3.6.1)
 Rcpp          1.0.3      2019-11-08 [1] CRAN (R 3.6.1)
 rlang         0.4.2      2019-11-23 [1] CRAN (R 3.6.0)
 roxygen2    * 7.0.1      2019-11-22 [1] CRAN (R 3.6.1)
 sessioninfo   1.1.1      2018-11-05 [1] CRAN (R 3.6.0)
 stringi       1.4.3      2019-03-12 [1] CRAN (R 3.6.0)
 stringr       1.4.0      2019-02-10 [1] CRAN (R 3.6.0)
 vctrs         0.2.0      2019-07-05 [1] CRAN (R 3.6.0)
 withr         2.1.2      2018-03-15 [1] CRAN (R 3.6.0)
 xml2          1.2.2      2019-08-09 [1] CRAN (R 3.6.1)
 zeallot       0.1.0      2018-01-28 [1] CRAN (R 3.6.0)

[1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

sckott avatar Nov 25 '19 19:11 sckott

Yeah, there is no way roxygen could figure out these "dynamic" methods and members, because it cannot actually create an object of the class.

What we could do is to allow @method, so you could add these methods manually, anywhere you like, inline as well.

gaborcsardi avatar Nov 25 '19 21:11 gaborcsardi

Okay. @method for this use case isn't supported yet though, correct? What would it look like?

sckott avatar Nov 25 '19 22:11 sckott

No, not yet. It could be something like

Foo <- R6::R6Class(
  "Foo",
  public = list(
    #' @method bar
    #' @description Square a number
    #' @param x (numeric) a number
    bar = NULL,
    
    #' @description make a new Foo
    initialize = function() {
      self$bar = private$bar_factory()
    }
  ),
  private = list(
    bar_factory = function() {
      function(x = 5) x^2
    }
  )
)

I am not sure if this will be added any time soon, TBH, because it is quite different from what we have now. Right now, we assume that we can use Foo$public_methods etc. for introspection. But if the methods and members are not in there, then everything is different.

gaborcsardi avatar Nov 25 '19 22:11 gaborcsardi

I am not trying to suggest that you change all your classes now just for the documentation, but if you don't do this a lot, here is a workaround. It might work right now already, if you just add a dummy function to bar, instead of NULL, with the right arguments, etc. and then document the dummy function.

gaborcsardi avatar Nov 25 '19 22:11 gaborcsardi

Okay, I see.

I'll try the dummy function approach

sckott avatar Nov 25 '19 22:11 sckott