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

Comment in glue() range causes parse failure in object_usage_linter #1919

Closed
MichaelChirico opened this issue Feb 27, 2023 · 8 comments · Fixed by #1935
Closed

Comment in glue() range causes parse failure in object_usage_linter #1919

MichaelChirico opened this issue Feb 27, 2023 · 8 comments · Fixed by #1935
Labels
bug an unexpected problem or unintended behavior object linters 🏀

Comments

@MichaelChirico
Copy link
Collaborator

lint("
foo <- function() {
  x <- 2
  glue::glue(
    '{x}' # a comment
  )
}
", object_usage_linter())
# Error: Linter 'object_usage_linter' failed in /tmp/RtmpAirXij/file39151e5be6f486: Unexpected failure to parse glue call, please report: <text>:2:0: unexpected end of input
# 1: glue::glue('{x}'# a comment)
#    ^
@MichaelChirico MichaelChirico added the bug an unexpected problem or unintended behavior label Feb 27, 2023
@MichaelChirico
Copy link
Collaborator Author

The trouble is here:

for (call_text in xml2::xml_text(glue_calls)) {

xml_text() will collapse all the text across the nodes, ignoring newlines, hence trying to parse glue::glue('{x}'#a comment).

What we'd ideally do is exclude any COMMENT nodes below each glue_call before attempting to parse.

@jimhester could you offer some guidance/xml2 wizardry here? At a glance xml_remove() is what we want, but we don't want to permanently modify the parse tree, is there an easy way to do that? An alternative would be to set xml_text() of the COMMENT nodes to '', then re-set it on.exit(), which feels a bit clunky too.

Related again to r-lib/xml2#341 (comment) :)

@jimhester
Copy link
Member

I would use something like this to get just the text in the STR_CONST nodes, rather than any node type.

xml2::xml_text(xml2::xml_find_first(glue_calls, "//STR_CONST/text()"))

@AshesITR
Copy link
Collaborator

I would use something like this to get just the text in the STR_CONST nodes, rather than any node type.

xml2::xml_text(xml2::xml_find_first(glue_calls, "//STR_CONST/text()"))

This will break glue calls with multiple fragments, e.g.

glue::glue(
  "This is the first glued line with 1 + 1 = {1 + 1}\n",
  "This is the second line with pi = {pi}"
)

@MichaelChirico
Copy link
Collaborator Author

and a find_all approach will also have to ignore keyword arguments.

I think it's doable but feels like a workaround /much messier than glue_calls |> xml_exclude(comments) |> xml_text()

@AshesITR
Copy link
Collaborator

Do you think it might be feasible to instead develop a xml_parse_data_to_code(xml_node) function that uses the col1 and line1 attributes of nodes to construct the original code?
I can imagine we will have multiple use cases for such a function.

@MichaelChirico
Copy link
Collaborator Author

xml2lang() :)

not a bad idea, this thing with comments definitely comes up here & there

@jimhester
Copy link
Member

paste0(collapse = "", xml2::xml_text(xml2::xml_find_all(glue_calls, "./*[not(self::COMMENT)]")))

@MichaelChirico
Copy link
Collaborator Author

MichaelChirico commented Feb 27, 2023

ah, great minds :)

xml <- parse(text = "glue(\n'{x}' # comment\n)") |>
  xml_parse_data() |>
  read_xml()

xml_node2lang <- function(x) {
  x |>
    xml_find_all(".//*[not(self::COMMENT or self::expr)]") |>
    xml_text() |>
    paste(collapse = "") |>
    str2lang()
}
if (inherits(xml, "xml_document")) {
  # not xml_children, since xml_node2lang() will fail for comments: str2lang("")
  lapply(xml_find_all(xml, "*[not(self::COMMENT)]"), xml_node2lang)
} else {
  xml_node2lang(xml)
}

./* will struggle with more complicated expressions I think:

glue(
  format(
    Sys.Date(),
    "%F {x}" # YYYY-MM-DD, then 'x'
  )
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug an unexpected problem or unintended behavior object linters 🏀
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants