Skip to content

Commit 9cf1128

Browse files
m7prgithub-actions[bot]averissimo
authored
Fix ‘sym_cond > ass_cond’: longer object (#236)
Fixes #235 There was a warning thrown by the `get_code_dependency` that is now not visible + the code extraction works for `for` loops. Added 2 tests to prove that. No warning shown during ```r devtools::load_all("../teal.code") devtools::load_all("../teal") devtools::load_all(".") footnote_regression <- teal_transform_module( server = make_teal_transform_server(expression( plot <- plot + labs(caption = deparse(summary(fit)[[1]])) )) ) data <- teal_data() data <- within(data, { require(nestcolor) ADSL <- rADSL }) join_keys(data) <- default_cdisc_join_keys[names(data)] app <- init( data = data, modules = modules( tm_a_regression( label = "Regression", response = data_extract_spec( dataname = "ADSL", select = select_spec( label = "Select variable:", choices = "BMRKR1", selected = "BMRKR1", multiple = FALSE, fixed = TRUE ) ), regressor = data_extract_spec( dataname = "ADSL", select = select_spec( label = "Select variables:", choices = variable_choices(data[["ADSL"]], c("AGE", "SEX", "RACE")), selected = "AGE", multiple = TRUE, fixed = FALSE ) ), decorators = list(footnote_regression) ) ) ) if (interactive()) { shinyApp(app$ui, app$server) } ``` --------- Signed-off-by: Marcin <[email protected]> Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: André Veríssimo <[email protected]>
1 parent 13fec70 commit 9cf1128

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

R/utils-get_code_dependency.R

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ extract_occurrence <- function(pd) {
274274
# What occurs in a function body is not tracked.
275275
x <- pd[!is_in_function(pd), ]
276276
sym_cond <- which(x$token %in% c("SPECIAL", "SYMBOL", "SYMBOL_FUNCTION_CALL"))
277+
sym_fc_cond <- which(x$token == "SYMBOL_FUNCTION_CALL")
277278

278279
if (length(sym_cond) == 0) {
279280
return(character(0L))
@@ -287,28 +288,27 @@ extract_occurrence <- function(pd) {
287288
sym_cond <- setdiff(sym_cond, which(x$id %in% after_dollar))
288289
}
289290

290-
ass_cond <- grep("ASSIGN", x$token)
291-
if (!length(ass_cond)) {
291+
assign_cond <- grep("ASSIGN", x$token)
292+
if (!length(assign_cond)) {
292293
return(c("<-", unique(x[sym_cond, "text"])))
293294
}
294295

295-
sym_cond <- sym_cond[sym_cond > ass_cond] # NOTE 1
296+
# For cases like 'eval(expression(c <- b + 2))' removes 'eval(expression('.
297+
sym_cond <- sym_cond[!(sym_cond < min(assign_cond) & sym_cond %in% sym_fc_cond)]
298+
296299
# If there was an assignment operation detect direction of it.
297-
if (unique(x$text[ass_cond]) == "->") { # NOTE 2
300+
if (unique(x$text[assign_cond]) == "->") { # What if there are 2 assignments: e.g. a <- b -> c.
298301
sym_cond <- rev(sym_cond)
299302
}
300303

301-
after <- match(min(x$id[ass_cond]), sort(x$id[c(min(ass_cond), sym_cond)])) - 1
304+
after <- match(min(x$id[assign_cond]), sort(x$id[c(min(assign_cond), sym_cond)])) - 1
302305
ans <- append(x[sym_cond, "text"], "<-", after = max(1, after))
303306
roll <- in_parenthesis(pd)
304307
if (length(roll)) {
305308
c(setdiff(ans, roll), roll)
306309
} else {
307310
ans
308311
}
309-
310-
### NOTE 2: What if there are 2 assignments: e.g. a <- b -> c.
311-
### NOTE 1: For cases like 'eval(expression(b <- b + 2))' removes 'eval(expression('.
312312
}
313313

314314
#' Extract side effects

tests/testthat/test-qenv_get_code.R

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,54 @@ testthat::test_that("detects occurrence of a function definition with a @linksto
596596
pasten(code[1:2])
597597
)
598598
})
599+
600+
601+
# for loop --------------------------------------------------------------------------------------------------------
602+
603+
testthat::test_that("objects in for loop are extracted if passed as one character", {
604+
code <- "
605+
some_other_dataset <- mtcars
606+
original_dataset <- iris[, 1:4]
607+
count <- 1
608+
for (x in colnames(original_dataset)) {
609+
original_dataset[, x] <- original_dataset[, x] * 2
610+
count <- count + 1
611+
}
612+
output <- rlang::list2(x = original_dataset)
613+
"
614+
q <- eval_code(qenv(), code)
615+
testthat::expect_identical(
616+
get_code(q, names = "output"),
617+
gsub("\n some_other_dataset <- mtcars\n", "", code, fixed = TRUE)
618+
)
619+
})
620+
621+
testthat::test_that("objects in for loop are extracted if passed as separate calls", {
622+
q <- within(qenv(), {
623+
a <- 1
624+
b <- 2
625+
}) |> within({
626+
for (x in c(1, 2)) {
627+
b <- a
628+
b <- b + a + 1
629+
b + 3 -> b # nolint: assignment.
630+
}
631+
})
632+
633+
testthat::expect_setequal(
634+
strsplit(get_code(q, names = "b"), "\n")[[1]],
635+
c(
636+
"a <- 1",
637+
"b <- 2",
638+
"for (x in c(1, 2)) {",
639+
" b <- a",
640+
" b <- b + a + 1",
641+
" b <- b + 3", # ORDER IS CHANGED IN HERE, but we can live with it
642+
"}"
643+
)
644+
)
645+
})
646+
599647
# $ ---------------------------------------------------------------------------------------------------------------
600648

601649
testthat::test_that("understands $ usage and do not treat rhs of $ as objects (only lhs)", {

0 commit comments

Comments
 (0)