From ffff6777097a30a68468787dc41588ead3c1dbae Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 13 Nov 2023 17:41:50 +0000 Subject: [PATCH 1/2] improve handling of operators inside lambdas --- NEWS.md | 1 + R/unnecessary_lambda_linter.R | 2 +- tests/testthat/test-unnecessary_lambda_linter.R | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index d530ce605..de9fd6ab3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,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..9cf5002ef 100644 --- a/R/unnecessary_lambda_linter.R +++ b/R/unnecessary_lambda_linter.R @@ -76,8 +76,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) From 66e261773e88b7fdc3ec4da6b9d1541c2dcfb613 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 13 Nov 2023 17:46:23 +0000 Subject: [PATCH 2/2] stale TODO --- R/unnecessary_lambda_linter.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/unnecessary_lambda_linter.R b/R/unnecessary_lambda_linter.R index 9cf5002ef..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