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

Improve resilience of object_usage_linter() to glue syntax issues #1597

Merged
merged 13 commits into from
Oct 3, 2022
Merged
13 changes: 12 additions & 1 deletion R/object_usage_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,18 @@ extract_glued_symbols <- function(expr) {
}
""
}
eval(parsed_cl)
# #1459: syntax errors in glue'd code are ignored with warning, rather than crashing lint
tryCatch(
eval(parsed_cl),
error = function(cond) {
warning(
"Evaluating glue expression while testing for local variable usage failed: ",
conditionMessage(cond),
call. = FALSE
)
NULL
}
)
}
ls(envir = glued_symbols, all.names = TRUE)
}
Expand Down
3 changes: 0 additions & 3 deletions tests/testthat/dummy_packages/err_pkg/DESCRIPTION

This file was deleted.

2 changes: 0 additions & 2 deletions tests/testthat/dummy_packages/err_pkg/NAMESPACE

This file was deleted.

6 changes: 0 additions & 6 deletions tests/testthat/dummy_packages/err_pkg/R/glue_error.R

This file was deleted.

17 changes: 16 additions & 1 deletion tests/testthat/test-lint_file.R
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ test_that("compatibility warnings work", {

expect_error(
lint("a <- 1\n", linters = "equals_na_linter"),
regexp = rex("Expected '", anything, "' to be a function of class 'linter'")
regexp = rex::rex("Expected '", anything, "' to be a function of class 'linter'")
)
})

Expand All @@ -225,3 +225,18 @@ test_that("Deprecated positional usage of cache= works, with warning", {
)
expect_identical(l, lint("a = 2\n", assignment_linter(), cache = FALSE))
})

test_that("Linters throwing an error give a helpful error", {
tmp_file <- withr::local_tempfile(lines = "a <- 1")
linter <- function() Linter(function(source_expression) stop("a broken linter"))
# NB: Some systems/setups may use e.g. symlinked files when creating under tempfile();
# we don't care much about that, so just check basename()
expect_error(
lint(tmp_file, linter()),
rex::rex("Linter 'linter' failed in ", anything, basename(tmp_file), ": a broken linter")
)
expect_error(
lint(tmp_file, list(broken_linter = linter())),
rex::rex("Linter 'broken_linter' failed in ", anything, basename(tmp_file), ": a broken linter")
)
})
10 changes: 0 additions & 10 deletions tests/testthat/test-lint_package.R
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,3 @@ test_that("lint_package returns early if no package is found", {
fixed = TRUE
)
})

test_that("lint_package gives helpful failure when package has syntax issues", {
pkg_path <- test_path("dummy_packages", "err_pkg")
withr::local_options(lintr.linter_file = "lintr_test_config")

expect_error(
lint_package(pkg_path, linters = list(object_usage_linter(), assignment_linter())),
"Linter 'object_usage_linter' failed in.*glue_error.R: Expecting '}'"
)
})
33 changes: 33 additions & 0 deletions tests/testthat/test-object_usage_linter.R
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,39 @@ test_that("interprets glue expressions", {
"), "local_var", object_usage_linter(interpret_glue = FALSE))
})

test_that("errors in glue syntax don't fail lint()", {
# no lint & no error, despite glue error
expect_warning(
expect_lint(
trim_some("
fun <- function() {
a <- 2
a + 1
glue::glue('The answer is {a')
}
"),
NULL,
object_usage_linter()
),
"Evaluating glue expression.*failed: Expecting '\\}'"
)

# generates a lint because the "usage" inside glue() is not detected
expect_warning(
expect_lint(
trim_some("
fun <- function() {
a <- 2
glue::glue('The answer is {a')
}
"),
"local variable 'a'",
object_usage_linter()
),
"Evaluating glue expression.*failed: Expecting '\\}'"
)
})

# reported as #1088
test_that("definitions below top level are ignored (for now)", {
expect_lint(
Expand Down