Skip to content

Commit e81967e

Browse files
fix object_usage_linter with new xml2lang to avoid parsing comments in multi-line expr (#1935)
Co-authored-by: Indrajeet Patil <[email protected]>
1 parent e6cfd4e commit e81967e

File tree

4 files changed

+31
-3
lines changed

4 files changed

+31
-3
lines changed

NEWS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
* `assignment_linter()` no longer lints assignments in braces that include comments when `allow_trailing = FALSE` (#1701, @ashbaldry)
1616

17-
* `object_usage_linter()` no longer silently ignores usage warnings that don't contain a quoted name (#1714, @AshesITR)
17+
* `object_usage_linter()`
18+
+ No longer silently ignores usage warnings that don't contain a quoted name (#1714, @AshesITR)
19+
+ No longer fails on code with comments inside a multi-line call to `glue::glue()` (#1919, @MichaelChirico)
1820

1921
* `namespace_linter()` correctly recognizes backticked operators to be exported from respective namespaces (like `` rlang::`%||%` ``) (#1752, @IndrajeetPatil)
2022

R/object_usage_linter.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,9 @@ extract_glued_symbols <- function(expr) {
188188
stop("Unexpected failure to parse glue call, please report: ", conditionMessage(cond)) # nocov
189189
}
190190
glued_symbols <- new.env(parent = emptyenv())
191-
for (call_text in xml2::xml_text(glue_calls)) {
191+
for (glue_call in glue_calls) {
192192
# TODO(michaelchirico): consider dropping tryCatch() here if we're more confident in our logic
193-
parsed_call <- tryCatch(str2lang(call_text), error = unexpected_error, warning = unexpected_error)
193+
parsed_call <- tryCatch(xml2lang(glue_call), error = unexpected_error, warning = unexpected_error)
194194
parsed_call[[".envir"]] <- glued_symbols
195195
parsed_call[[".transformer"]] <- symbol_extractor
196196
# #1459: syntax errors in glue'd code are ignored with warning, rather than crashing lint

R/utils.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,18 @@ get_r_code <- function(xml) {
277277
paste(lines, collapse = "\n")
278278
}
279279

280+
#' str2lang, but for xml children.
281+
#'
282+
#' [xml2::xml_text()] is deceptively close to obviating this helper, but it collapses
283+
#' text across lines. R is _mostly_ whitespace-agnostic, so this only matters in some edge cases,
284+
#' in particular when there are comments within an expression (<expr> node). See #1919.
285+
#'
286+
#' @noRd
287+
xml2lang <- function(x) {
288+
x_strip_comments <- xml_find_all(x, ".//*[not(self::COMMENT or self::expr)]")
289+
str2lang(paste(xml2::xml_text(x_strip_comments), collapse = ""))
290+
}
291+
280292
is_linter <- function(x) inherits(x, "linter")
281293

282294
is_tainted <- function(lines) {

tests/testthat/test-object_usage_linter.R

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,20 @@ test_that("errors/edge cases in glue syntax don't fail lint()", {
469469
NULL,
470470
linter
471471
)
472+
473+
# comment inside glue range (#1919)
474+
expect_lint(
475+
trim_some("
476+
fun <- function() {
477+
a <- 2
478+
glue::glue(
479+
'The answer is {}: {a}' # show the answer
480+
)
481+
}
482+
"),
483+
NULL,
484+
linter
485+
)
472486
})
473487

474488
test_that("backtick'd names in glue are handled", {

0 commit comments

Comments
 (0)