Skip to content

Instantly share code, notes, and snippets.

@teunbrand
Last active October 25, 2024 18:43
Show Gist options
  • Save teunbrand/4e260a1e1a469bb4af9e8d73b5b88783 to your computer and use it in GitHub Desktop.
Save teunbrand/4e260a1e1a469bb4af9e8d73b5b88783 to your computer and use it in GitHub Desktop.
library(lintr)
test_file <- tempfile(fileext = ".txt")
cat(
"
1 + 1
switch('x', a = (1 + 1), b = 10, 12) # this is fine
x <- 20
switch('x', b = 20, a = 12) # should find this one
print('foo')
",
file = test_file
)
my_linter <- function(x) {
# Report no lints when expression doesn't have a switch statement
xml_calls <- x$xml_find_function_calls("switch")
if (length(xml_calls) == 0) {
return(list())
}
content <- x$parsed_content
# Deliniate which part of the expression is part of the 'switch()' call
switch_hit <- which(content$token == "SYMBOL_FUNCTION_CALL" & content$text == "switch")
# Find first open '(' after switch
open <- which(content$token == "'('")
open <- min(open[open > switch_hit])
# Find matching close ')' with same parent as open '('
close <- which(content$token == "')'")
close <- close[which(content$parent[close] == content$parent[open])[1]]
# Find the last comma in the call
commas <- which(content$token == "','")
commas <- max(commas[commas > open & commas < close])
# After this comma, do we have an argument symbol?
names <- which(content$token == "SYMBOL_SUB")
names <- names[names > commas & names < close]
# If we do have an unnamed last argument, return without lints
if (length(names) == 0) {
return(list())
}
# Report lint
xml_nodes_to_lints(
xml_calls,
source_expression = x,
lint_message = "switch without last unnamed argument",
type = "warning"
)
}
lint(
test_file,
linters = Linter(my_linter, linter_level = "expression")
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment