Skip to contents

This linter checks functions' return() expressions.

Usage

return_linter(
  return_style = c("implicit", "explicit"),
  allow_implicit_else = TRUE,
  return_functions = NULL,
  except = NULL,
  except_regex = NULL
)

Arguments

return_style

Character string naming the return style. "implicit", the default, enforces the Tidyverse guide recommendation to leave terminal returns implicit. "explicit" style requires that return() always be explicitly supplied.

allow_implicit_else

Logical, default TRUE. If FALSE, functions with a terminal if clause must always have an else clause, making the NULL alternative explicit if necessary. Similarly, functions with terminal switch() statements must have an explicit default case.

return_functions

Character vector of functions that are accepted as terminal calls when return_style = "explicit". These are in addition to exit functions from base that are always allowed: stop(), q(), quit(), invokeRestart(), tryInvokeRestart(), UseMethod(), NextMethod(), standardGeneric(), callNextMethod(), .C(), .Call(), .External(), and .Fortran().

except, except_regex

Character vector of functions that are not checked when return_style = "explicit". These are in addition to namespace hook functions that are never checked: .onLoad(), .onUnload(), .onAttach(), .onDetach(), .Last.lib(), .First() and .Last(). except matches function names exactly, while except_regex does exclusion by pattern matching with rex::re_matches().

See also

Examples

# will produce lints
code <- "function(x) {\n  return(x + 1)\n}"
writeLines(code)
#> function(x) {
#>   return(x + 1)
#> }
lint(
  text = code,
  linters = return_linter()
)
#> <text>:2:3: style: [return_linter] Use implicit return behavior; explicit return() is not needed.
#>   return(x + 1)
#>   ^~~~~~

code <- "function(x) {\n  x + 1\n}"
writeLines(code)
#> function(x) {
#>   x + 1
#> }
lint(
  text = code,
  linters = return_linter(return_style = "explicit")
)
#> <text>:2:3: warning: [return_linter] All functions must have an explicit return().
#>   x + 1
#>   ^

code <- "function(x) {\n  if (x > 0) 2\n}"
writeLines(code)
#> function(x) {
#>   if (x > 0) 2
#> }
lint(
  text = code,
  linters = return_linter(allow_implicit_else = FALSE)
)
#> <text>:2:3: warning: [return_linter] All functions with terminal if statements must have a corresponding terminal else clause.
#>   if (x > 0) 2
#>   ^~~~~~~~~~~~

# okay
code <- "function(x) {\n  x + 1\n}"
writeLines(code)
#> function(x) {
#>   x + 1
#> }
lint(
  text = code,
  linters = return_linter()
)
#>  No lints found.

code <- "function(x) {\n  return(x + 1)\n}"
writeLines(code)
#> function(x) {
#>   return(x + 1)
#> }
lint(
  text = code,
  linters = return_linter(return_style = "explicit")
)
#>  No lints found.

code <- "function(x) {\n  if (x > 0) 2 else NULL\n}"
writeLines(code)
#> function(x) {
#>   if (x > 0) 2 else NULL
#> }
lint(
  text = code,
  linters = return_linter(allow_implicit_else = FALSE)
)
#>  No lints found.