Skip to content

Commit 680625c

Browse files
m7praverissimo
andauthored
fix code parser for := operator (#234)
Closes #233 and alternative for #233 This removed `:=` from extracted calls so that it is not treated as `LEFT_ASSIGNMENT`. **Current main** - check row 26 ```r devtools::load_all(".") code <- " iris <- data.table::data.table(iris) %>% .[, NewSpecies := factor(Species)] " code_split <- split_code(paste(code, collapse = "\n"))[[1]] current_call <- parse(text = code_split, keep.source = TRUE) pd <- normalize_pd(utils::getParseData(current_call)) reordered_pd <- extract_calls(pd) reordered_pd[[1]] line1 col1 line2 col2 id parent token terminal text 46 2 1 3 36 46 0 expr FALSE 5 2 1 2 4 5 46 expr FALSE 4 2 6 2 7 4 46 LEFT_ASSIGN TRUE <- 45 2 9 3 36 45 46 expr FALSE 3 2 1 2 4 3 5 SYMBOL TRUE iris 17 2 9 2 36 17 45 expr FALSE 18 2 38 2 40 18 45 SPECIAL TRUE %>% 43 3 3 3 36 43 45 expr FALSE 9 2 9 2 30 9 17 expr FALSE 10 2 31 2 31 10 17 '(' TRUE ( 13 2 32 2 35 13 17 expr FALSE 12 2 36 2 36 12 17 ')' TRUE ) 6 2 9 2 18 6 9 SYMBOL_PACKAGE TRUE data.table 7 2 19 2 20 7 9 NS_GET TRUE :: 8 2 21 2 30 8 9 SYMBOL_FUNCTION_CALL TRUE data.table 11 2 32 2 35 11 13 SYMBOL TRUE iris 22 3 3 3 3 22 43 expr FALSE 21 3 4 3 4 21 43 '[' TRUE [ 23 3 5 3 5 23 43 ',' TRUE , 39 3 7 3 35 39 43 expr FALSE 38 3 36 3 36 38 43 ']' TRUE ] 20 3 3 3 3 20 22 SYMBOL TRUE . 27 3 7 3 16 27 39 expr FALSE 26 3 18 3 19 26 39 LEFT_ASSIGN TRUE := 37 3 21 3 35 37 39 expr FALSE 25 3 7 3 16 25 27 SYMBOL TRUE NewSpecies 30 3 21 3 26 30 37 expr FALSE 29 3 27 3 27 29 37 '(' TRUE ( 33 3 28 3 34 33 37 expr FALSE 32 3 35 3 35 32 37 ')' TRUE ) 28 3 21 3 26 28 30 SYMBOL_FUNCTION_CALL TRUE factor 31 3 28 3 34 31 33 SYMBOL TRUE Species ``` **Feature branch** - row removed ```r line1 col1 line2 col2 id parent token terminal text 46 2 1 3 36 46 0 expr FALSE 5 2 1 2 4 5 46 expr FALSE 4 2 6 2 7 4 46 LEFT_ASSIGN TRUE <- 45 2 9 3 36 45 46 expr FALSE 3 2 1 2 4 3 5 SYMBOL TRUE iris 17 2 9 2 36 17 45 expr FALSE 18 2 38 2 40 18 45 SPECIAL TRUE %>% 43 3 3 3 36 43 45 expr FALSE 9 2 9 2 30 9 17 expr FALSE 10 2 31 2 31 10 17 '(' TRUE ( 13 2 32 2 35 13 17 expr FALSE 12 2 36 2 36 12 17 ')' TRUE ) 6 2 9 2 18 6 9 SYMBOL_PACKAGE TRUE data.table 7 2 19 2 20 7 9 NS_GET TRUE :: 8 2 21 2 30 8 9 SYMBOL_FUNCTION_CALL TRUE data.table 11 2 32 2 35 11 13 SYMBOL TRUE iris 22 3 3 3 3 22 43 expr FALSE 21 3 4 3 4 21 43 '[' TRUE [ 23 3 5 3 5 23 43 ',' TRUE , 39 3 7 3 35 39 43 expr FALSE 38 3 36 3 36 38 43 ']' TRUE ] 20 3 3 3 3 20 22 SYMBOL TRUE . 27 3 7 3 16 27 39 expr FALSE 37 3 21 3 35 37 39 expr FALSE 25 3 7 3 16 25 27 SYMBOL TRUE NewSpecies 30 3 21 3 26 30 37 expr FALSE 29 3 27 3 27 29 37 '(' TRUE ( 33 3 28 3 34 33 37 expr FALSE 32 3 35 3 35 32 37 ')' TRUE ) 28 3 21 3 26 28 30 SYMBOL_FUNCTION_CALL TRUE factor 31 3 28 3 34 31 33 SYMBOL TRUE Species ``` This lead to the fact that below can be executed without errors ```r devtools::load_all(".") code <- " iris <- data.table::data.table(iris) %>% .[, NewSpecies := factor(Species)] " q <- eval_code(qenv(), code) cat(get_code(q)) ``` ```r iris <- data.table::data.table(iris) %>% .[, NewSpecies := factor(Species)] ``` --------- Signed-off-by: Marcin <[email protected]> Co-authored-by: André Veríssimo <[email protected]>
1 parent 584dfc9 commit 680625c

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

R/utils-get_code_dependency.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ extract_calls <- function(pd) {
106106
calls <- Filter(function(call) !(nrow(call) == 1 && call$token == "';'"), calls)
107107
calls <- Filter(Negate(is.null), calls)
108108
calls <- fix_shifted_comments(calls)
109+
calls <- remove_custom_assign(calls, c(":="))
109110
fix_arrows(calls)
110111
}
111112

@@ -144,6 +145,23 @@ fix_shifted_comments <- function(calls) {
144145
Filter(nrow, calls)
145146
}
146147

148+
#' Fixes edge case of custom assignments operator being treated as assignment.
149+
#'
150+
#' @param exclude (`character`) custom assignment operators to be excluded
151+
#' @keywords internal
152+
#' @noRd
153+
remove_custom_assign <- function(calls, exclude = NULL) {
154+
checkmate::assert_list(calls)
155+
checkmate::assert_character(exclude, null.ok = TRUE)
156+
lapply(calls, function(call) {
157+
if (!is.null(exclude)) {
158+
call[!(call$token == "LEFT_ASSIGN" & call$text %in% exclude), ]
159+
} else {
160+
call
161+
}
162+
})
163+
}
164+
147165
#' Fixes edge case of `<-` assignment operator being called as function,
148166
#' which is \code{`<-`(y,x)} instead of traditional `y <- x`.
149167
#' @keywords internal

tests/testthat/test-qenv_eval_code.R

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ testthat::test_that("eval_code accepts calls containing only comments and empty
105105
testthat::expect_identical(get_code(eval_code(qenv(), code)), code)
106106
})
107107

108+
testthat::test_that("eval_code does not treat := as an assignment operator", {
109+
code <- "
110+
x <- 'name'
111+
rlang::list2(!!x := 1)
112+
"
113+
q <- eval_code(qenv(), code)
114+
testthat::expect_identical(get_code(q), code)
115+
})
116+
108117
# comments ----------
109118
testthat::test_that("comments fall into proper calls", {
110119
# If comment is on top, it gets moved to the first call.

0 commit comments

Comments
 (0)