From f6e39167b92b718d391926192b88cd666fcf3347 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sun, 26 Mar 2023 04:59:13 +0000 Subject: [PATCH] detect functional lambdas in object_usage_linter --- NEWS.md | 1 + R/object_usage_linter.R | 10 +++++----- tests/testthat/test-object_usage_linter.R | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index 10355cb66..2356ec76f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -36,6 +36,7 @@ `R CMD check`, it defaults to `TRUE` (#941, #1458, @IndrajeetPatil). + Handles backticked symbols inside {glue} expressions correctly, e.g. ``glue("{`x`}")`` correctly determines `x` was used (#1619, @MichaelChirico) + + Detects problems inside R4.1.0+ lambda functions (`\(...)`) (#1933, @MichaelChirico) * `spaces_inside_linter()` allows terminal missing keyword arguments (e.g. `alist(arg = )`; #540, @MichaelChirico) diff --git a/R/object_usage_linter.R b/R/object_usage_linter.R index b1c94b3e6..934582cf6 100644 --- a/R/object_usage_linter.R +++ b/R/object_usage_linter.R @@ -37,12 +37,12 @@ object_usage_linter <- function(interpret_glue = TRUE, skip_with = TRUE) { # TODO(#1106): use //[...] to capture assignments in more scopes xpath_function_assignment <- paste( # direct assignments - "expr[LEFT_ASSIGN or EQ_ASSIGN]/expr[2][FUNCTION]", - "expr_or_assign_or_help[EQ_ASSIGN]/expr[2][FUNCTION]", - "equal_assign[EQ_ASSIGN]/expr[2][FUNCTION]", + "expr[LEFT_ASSIGN or EQ_ASSIGN]/expr[2][FUNCTION or OP-LAMBDA]", + "expr_or_assign_or_help[EQ_ASSIGN]/expr[2][FUNCTION or OP-LAMBDA]", + "equal_assign[EQ_ASSIGN]/expr[2][FUNCTION or OP-LAMBDA]", # assign() and setMethod() assignments - "//SYMBOL_FUNCTION_CALL[text() = 'assign']/parent::expr/following-sibling::expr[2][FUNCTION]", - "//SYMBOL_FUNCTION_CALL[text() = 'setMethod']/parent::expr/following-sibling::expr[3][FUNCTION]", + "//SYMBOL_FUNCTION_CALL[text() = 'assign']/parent::expr/following-sibling::expr[2][FUNCTION or OP-LAMBDA]", + "//SYMBOL_FUNCTION_CALL[text() = 'setMethod']/parent::expr/following-sibling::expr[3][FUNCTION or OP-LAMBDA]", sep = " | " ) diff --git a/tests/testthat/test-object_usage_linter.R b/tests/testthat/test-object_usage_linter.R index 195dd84f5..020d6f118 100644 --- a/tests/testthat/test-object_usage_linter.R +++ b/tests/testthat/test-object_usage_linter.R @@ -624,3 +624,17 @@ test_that("messages without a quoted name are caught", { object_usage_linter() ) }) + +test_that("functional lambda definitions are also caught", { + skip_if_not_r_version("4.1.0") + + expect_lint( + trim_some(" + fun <- \\() { + a <- 1 + } + "), + rex::rex("local variable", anything, "assigned but may not be used"), + object_usage_linter() + ) +})