diff --git a/NEWS.md b/NEWS.md index 1680bb9b3..ee042c597 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,7 @@ ### Lint accuracy fixes: removing false positives * `unreachable_code_linter()` ignores reachable code in inline functions like `function(x) if (x > 2) stop() else x` (#2259, @MEO265). +* `unnecessary_lambda_linter()` ignores extractions with explicit returns like `lapply(l, function(x) foo(x)$bar)` (#2258, @MichaelChirico). # lintr 3.1.1 diff --git a/R/unnecessary_lambda_linter.R b/R/unnecessary_lambda_linter.R index d57617769..abbd856fb 100644 --- a/R/unnecessary_lambda_linter.R +++ b/R/unnecessary_lambda_linter.R @@ -63,7 +63,6 @@ unnecessary_lambda_linter <- function() { # c. that call's _first_ argument is just the function argument (a SYMBOL) # - and it has to be passed positionally (not as a keyword) # d. the function argument doesn't appear elsewhere in the call - # TODO(#1703): handle explicit returns too: function(x) return(x) default_fun_xpath <- glue(" //SYMBOL_FUNCTION_CALL[ {apply_funs} ] /parent::expr @@ -76,8 +75,8 @@ unnecessary_lambda_linter <- function() { position() = 2 and preceding-sibling::expr/SYMBOL_FUNCTION_CALL and not(preceding-sibling::*[1][self::EQ_SUB]) + and not(parent::expr/following-sibling::*[not(self::OP-RIGHT-PAREN or self::OP-RIGHT-BRACE)]) ]/SYMBOL - and count(OP-LEFT-PAREN) + count(OP-LEFT-BRACE/following-sibling::expr/OP-LEFT-PAREN) = 1 ] /parent::expr ") diff --git a/tests/testthat/test-unnecessary_lambda_linter.R b/tests/testthat/test-unnecessary_lambda_linter.R index 5032f6fec..b3649439d 100644 --- a/tests/testthat/test-unnecessary_lambda_linter.R +++ b/tests/testthat/test-unnecessary_lambda_linter.R @@ -50,6 +50,12 @@ test_that("unnecessary_lambda_linter skips allowed usages", { expect_lint('lapply(l, function(x) rle(x)[["values"]])', NULL, linter) expect_lint("lapply(l, function(x) rle(x)@values)", NULL, linter) + # return() extractions, #2258 + expect_lint("lapply(l, function(x) return(foo(x)$bar))", NULL, linter) + expect_lint('lapply(l, function(x) return(rle(x)["values"]))', NULL, linter) + expect_lint('lapply(l, function(x) return(rle(x)[["values"]]))', NULL, linter) + expect_lint("lapply(l, function(x) return(rle(x)@values))", NULL, linter) + # Other operators, #2247 expect_lint("lapply(l, function(x) foo(x) - 1)", NULL, linter) expect_lint("lapply(l, function(x) foo(x) * 2)", NULL, linter)