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

Usage section does not contain a linebreak as expected when a default argument is a function itself with a long return value #1281

Closed
AlexisDerumigny opened this issue Jan 21, 2022 · 6 comments · Fixed by #1318
Labels
bug an unexpected problem or unintended behavior rd ✍️
Milestone

Comments

@AlexisDerumigny
Copy link

I am currently documenting a function, which takes as input another function. When the body of the default value of that other function is too long, it looks like roxygen suppress a line break in the \usage section, making the R code invalid.

For my own project, I solved the problem by using the @usage command to supply the proper value manually, but I think this could be a bug in roxygen.
Below is a reprex with two functions at the limiting point : the second function is only two characters longer than the first one, but its \usage section is not valid anymore (while it was the case for the first function).

library(roxygen2)
roc_proc_text(rd_roclet(), "
  #' A test function
  #'
  #' @param f a function
  #'
  #' @return nothing
  MyFunc1 <- function(
    f = function(x){print(x)
      return (1+2+3+4+5+6+7) } )
  {
    return ()
  }

  #' A test function 2
  #'
  #' @param f a function
  #'
  #' @return nothing
  MyFunc2 <- function(
    f = function(x){print(x)
      return (1+2+3+4+5+6+7+8) } )
  {
    return ()
  }
" )
#> $MyFunc1.Rd
#> % Generated by roxygen2: do not edit by hand
#> % Please edit documentation in ./<text>
#> \name{MyFunc1}
#> \alias{MyFunc1}
#> \title{A test function}
#> \usage{
#> MyFunc1(f = function(x) {
#>     print(x)
#>     return(1 + 2 + 3 + 4 + 5 + 6 + 7)
#> })
#> }
#> \arguments{
#> \item{f}{a function}
#> }
#> \value{
#> nothing
#> }
#> \description{
#> A test function
#> }
#> 
#> $MyFunc2.Rd
#> % Generated by roxygen2: do not edit by hand
#> % Please edit documentation in ./<text>
#> \name{MyFunc2}
#> \alias{MyFunc2}
#> \title{A test function 2}
#> \usage{
#> MyFunc2(
#>   f = function(x) {     print(x)     return(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8) }
#> )
#> }
#> \arguments{
#> \item{f}{a function}
#> }
#> \value{
#> nothing
#> }
#> \description{
#> A test function 2
#> }
@gaborcsardi gaborcsardi added the bug an unexpected problem or unintended behavior label Jan 21, 2022
@gaborcsardi
Copy link
Member

Seems like a bug in wrapUsage because usage_args is fine.

A current workaround is to specify @usage manually.

AlexisDerumigny added a commit to AlexisDerumigny/ElliptCopulas that referenced this issue Jan 21, 2022
@hadley
Copy link
Member

hadley commented Mar 29, 2022

I can look into this bug, but I do think you're better off avoiding inline functions as default arguments.

@AlexisDerumigny
Copy link
Author

Thanks for the reply! I agree that it's not the best practice to put an inline function as a default argument (in my use case, I am not sure of being able to find a better solution though, but I can always specify @usage manually indeed).

When thinking more about this, this bug also appears when using non-function inline arguments that are several lines long, as in the example below (maybe this kind of code should be avoided too...).

library(roxygen2)
roc_proc_text(rd_roclet(), "
  #' A test function 3
  #'
  MyFunc3 <- function(
    x = {a = 1
         a+2+3+4+5+6+7+8+9+10+11+12+13 } )
  {
    return (x)
  }
" )
#> $MyFunc3.Rd
#> % Generated by roxygen2: do not edit by hand
#> % Please edit documentation in ./<text>
#> \name{MyFunc3}
#> \alias{MyFunc3}
#> \title{A test function 3}
#> \usage{
#> MyFunc3(
#>   x = {     a = 1     a + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 }
#> )
#> }
#> \description{
#> A test function 3
#> }

I think this is because wrapping R code with correct syntax may lead to a result that is not correct.
This seems to be somehow related to #1257, where the after-wrapping code is correct but has a different value than before wrapping.

An idea to fix for both issues could be the following:

  • inside the delimiters { and }, the newlines shouldn't be removed (they could be replaced by ; though).
  • inside the delimiters ', " and `, no newlines should be added.

I don't know whether this is a good idea since it would require some kind of parsing of the default arguments.

@hadley hadley added this to the v7.1.3 milestone Apr 5, 2022
@hadley
Copy link
Member

hadley commented Apr 5, 2022

@AlexisDerumigny I will look at this bug (which looks like , I really would recommend doing something more like this:

MyFunc3 <- function(x = NULL) {
  if (is.null(x)) {
    x <- {
      a = 1;
      a+2+3+4+5+6+7+8+9+10+11+12+13
    } 
  }
}

See https://design.tidyverse.org/def-short.html for more details.

@hadley
Copy link
Member

hadley commented Apr 5, 2022

Minimal reprex:

library(roxygen2)
out <- roc_proc_text(rd_roclet(), "
  #' Test
  MyFunc2 <- function(
    f = function(x) {
      print(x)
      return (1+2+3+4+5+6+7+8) 
  }) { }")
out[[1]]$get_value("usage")
#> <rd> MyFunc2(
#>   f = function(x) {     print(x)     return(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8) }
#> )

Created on 2022-04-05 by the reprex package (v2.0.1)

It's surprisingly sensitive to the exact contents which doesn't yet make any sense to me.

@hadley
Copy link
Member

hadley commented Apr 5, 2022

Minimal reprex:

library(roxygen2)
out <- roc_proc_text(rd_roclet(), "
  #' Test
  MyFunc2 <- function(
    f = function(x) {
      print(x)
      return (1+2+3+4+5+6+7+8) 
  }) { }")
out[[1]]$get_value("usage")
#> <rd> MyFunc2(
#>   f = function(x) {     print(x)     return(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8) }
#> )

Created on 2022-04-05 by the reprex package (v2.0.1)

It's surprisingly sensitive to the exact contents which doesn't yet make any sense to me.
...
Oh one of the problems is that we look at nchar() which doesn't make sense if the usage contains new lines.

hadley added a commit that referenced this issue Apr 6, 2022
* Teach splitByWhitespace() about backticks. Fixes #1257
* Correctly wrap arguments with newlines. Fixes #1281.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug an unexpected problem or unintended behavior rd ✍️
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants