From 8a0ca108a03c99fa57f2259d8e839cb3709b763a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:58:31 +0100 Subject: [PATCH 01/14] fix: allow non-standard datanames in code dependency --- R/utils-get_code_dependency.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils-get_code_dependency.R b/R/utils-get_code_dependency.R index 48fe6b122..b8dda9dd3 100644 --- a/R/utils-get_code_dependency.R +++ b/R/utils-get_code_dependency.R @@ -53,7 +53,7 @@ get_code_dependency <- function(code, names, check_names = TRUE) { ass_str <- gsub("^['\"]|['\"]$", "", ass_str) symbols <- c(ass_str, symbols) } - if (!all(names %in% unique(symbols))) { + if (!all(sapply(names, as.name) %in% unique(symbols))) { warning("Object(s) not found in code: ", toString(setdiff(names, symbols))) } } From 8b5e76e82666770b9cebf34f54e9bfefc9e58c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:37:10 +0100 Subject: [PATCH 02/14] feature: supports special symbols with backticks --- R/utils-get_code_dependency.R | 6 ++-- tests/testthat/test-get_code.R | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/R/utils-get_code_dependency.R b/R/utils-get_code_dependency.R index b8dda9dd3..643e603ec 100644 --- a/R/utils-get_code_dependency.R +++ b/R/utils-get_code_dependency.R @@ -297,7 +297,7 @@ extract_occurrence <- function(calls_pd) { # What occurs in a function body is not tracked. x <- call_pd[!is_in_function(call_pd), ] - sym_cond <- which(x$token %in% c("SYMBOL", "SYMBOL_FUNCTION_CALL")) + sym_cond <- which(x$token %in% c("SPECIAL", "SYMBOL", "SYMBOL_FUNCTION_CALL")) if (length(sym_cond) == 0) { return(character(0L)) @@ -380,10 +380,12 @@ extract_side_effects <- function(calls_pd) { #' @keywords internal #' @noRd graph_parser <- function(x, graph) { + # normalize x to remove surrounding backticks + x <- gsub("^`|`$", "", x) occurrence <- vapply( graph, function(call) { ind <- match("<-", call, nomatch = length(call) + 1L) - x %in% call[seq_len(ind - 1L)] + x %in% gsub("^`|`$", "", call[seq_len(ind - 1L)]) }, logical(1) ) diff --git a/tests/testthat/test-get_code.R b/tests/testthat/test-get_code.R index 40095f1bc..102a0d08d 100644 --- a/tests/testthat/test-get_code.R +++ b/tests/testthat/test-get_code.R @@ -695,3 +695,58 @@ testthat::test_that("data() call is returned when data name is provided as a cha ) ) }) + +testthat::describe("Backticked special symbols", { + testthat::it("starting with underscore code dependency is being detected", { + td <- teal_data() |> + within({ + `_add_column_` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) + IRIS <- `_add_column_`(iris, dplyr::tibble(new_col = "new column")) + }) + + testthat::expect_identical( + get_code(td, datanames = "IRIS"), + paste( + sep = "\n", + "`_add_column_` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", + "IRIS <- `_add_column_`(iris, dplyr::tibble(new_col = \"new column\"))" + ) + ) + }) + + testthat::it("with spaces code dependency is being detected", { + td <- teal_data() |> + within({ + `add column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) + IRIS <- `add column`(iris, dplyr::tibble(new_col = "new column")) + }) + + testthat::expect_identical( + get_code(td, datanames = "IRIS"), + paste( + sep = "\n", + "`add column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", + "IRIS <- `add column`(iris, dplyr::tibble(new_col = \"new column\"))" + ) + ) + }) + + testthat::it("with non-native pipe code dependency is being detected", { + td <- teal_data() |> + within({ + `%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) + IRIS <- `%add_column%`(iris, dplyr::tibble(new_col = "new column")) + }) + + # Note that the original code is changed to use the non-native pipe operator + # correctly. + testthat::expect_identical( + get_code(td, datanames = "IRIS"), + paste( + sep = "\n", + "`%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", + "IRIS <- iris %add_column% dplyr::tibble(new_col = \"new column\")" + ) + ) + }) +}) From 0a894dfcfbe0feeb3a66e3a4058fec10a68a7da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:51:57 +0100 Subject: [PATCH 03/14] fix: normalize graph in one place --- R/utils-get_code_dependency.R | 6 ++++-- man/cdisc_data.Rd | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/R/utils-get_code_dependency.R b/R/utils-get_code_dependency.R index 643e603ec..f1f9dd9c6 100644 --- a/R/utils-get_code_dependency.R +++ b/R/utils-get_code_dependency.R @@ -382,10 +382,12 @@ extract_side_effects <- function(calls_pd) { graph_parser <- function(x, graph) { # normalize x to remove surrounding backticks x <- gsub("^`|`$", "", x) + graph <- lapply(graph, function(call) gsub("^`|`$", "", call)) occurrence <- vapply( - graph, function(call) { + graph, + function(call) { ind <- match("<-", call, nomatch = length(call) + 1L) - x %in% gsub("^`|`$", "", call[seq_len(ind - 1L)]) + x %in% call[seq_len(ind - 1L)] }, logical(1) ) diff --git a/man/cdisc_data.Rd b/man/cdisc_data.Rd index 05f8ee3fe..932c2f736 100644 --- a/man/cdisc_data.Rd +++ b/man/cdisc_data.Rd @@ -29,7 +29,7 @@ Use \code{\link[=verify]{verify()}} to verify code reproducibility .} A \code{teal_data} object. } \description{ -\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}} +\verb{r lifecycle::badge("stable")} Function is a wrapper around \code{\link[=teal_data]{teal_data()}} and guesses \code{join_keys} for given datasets whose names match ADAM datasets names. From 25d3694e6cae20a209cb37f27848bc60549215d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:59:00 +0100 Subject: [PATCH 04/14] tests: adds test with valid symbol but backticked and corrected titles --- tests/testthat/test-get_code.R | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/testthat/test-get_code.R b/tests/testthat/test-get_code.R index 102a0d08d..650caa875 100644 --- a/tests/testthat/test-get_code.R +++ b/tests/testthat/test-get_code.R @@ -696,8 +696,8 @@ testthat::test_that("data() call is returned when data name is provided as a cha ) }) -testthat::describe("Backticked special symbols", { - testthat::it("starting with underscore code dependency is being detected", { +testthat::describe("Backticked symbol", { + testthat::it("starting with underscore is detected in code dependency", { td <- teal_data() |> within({ `_add_column_` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) @@ -714,7 +714,7 @@ testthat::describe("Backticked special symbols", { ) }) - testthat::it("with spaces code dependency is being detected", { + testthat::it("with space character is detected in code dependency", { td <- teal_data() |> within({ `add column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) @@ -731,7 +731,24 @@ testthat::describe("Backticked special symbols", { ) }) - testthat::it("with non-native pipe code dependency is being detected", { + testthat::it("without special characters is cleaned and detecteed in code dependency", { + td <- teal_data() |> + within({ + `add_column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) + IRIS <- `add_column`(iris, dplyr::tibble(new_col = "new column")) + }) + + testthat::expect_identical( + get_code(td, datanames = "IRIS"), + paste( + sep = "\n", + "add_column <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", + "IRIS <- add_column(iris, dplyr::tibble(new_col = \"new column\"))" + ) + ) + }) + + testthat::it("with non-native pipe is detected code dependency", { td <- teal_data() |> within({ `%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) From 395b7e6e54df929de4e6b9110b072d462cc8432b Mon Sep 17 00:00:00 2001 From: "27856297+dependabot-preview[bot]@users.noreply.github.com" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:02:45 +0000 Subject: [PATCH 05/14] [skip roxygen] [skip vbump] Roxygen Man Pages Auto Update --- man/cdisc_data.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/cdisc_data.Rd b/man/cdisc_data.Rd index 932c2f736..05f8ee3fe 100644 --- a/man/cdisc_data.Rd +++ b/man/cdisc_data.Rd @@ -29,7 +29,7 @@ Use \code{\link[=verify]{verify()}} to verify code reproducibility .} A \code{teal_data} object. } \description{ -\verb{r lifecycle::badge("stable")} +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}} Function is a wrapper around \code{\link[=teal_data]{teal_data()}} and guesses \code{join_keys} for given datasets whose names match ADAM datasets names. From 1d87d84947ae98779626e48c163e082baf8d1303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:08:49 +0100 Subject: [PATCH 06/14] lintr: replaced capitalized iris with iris_ds --- tests/testthat/test-get_code.R | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/testthat/test-get_code.R b/tests/testthat/test-get_code.R index 650caa875..9140686e8 100644 --- a/tests/testthat/test-get_code.R +++ b/tests/testthat/test-get_code.R @@ -700,16 +700,16 @@ testthat::describe("Backticked symbol", { testthat::it("starting with underscore is detected in code dependency", { td <- teal_data() |> within({ - `_add_column_` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) - IRIS <- `_add_column_`(iris, dplyr::tibble(new_col = "new column")) + `_add_column_` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) # nolint: object_name. + iris_ds <- `_add_column_`(iris, dplyr::tibble(new_col = "new column")) }) testthat::expect_identical( - get_code(td, datanames = "IRIS"), + get_code(td, datanames = "iris_ds"), paste( sep = "\n", "`_add_column_` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "IRIS <- `_add_column_`(iris, dplyr::tibble(new_col = \"new column\"))" + "iris_ds <- `_add_column_`(iris, dplyr::tibble(new_col = \"new column\"))" ) ) }) @@ -717,16 +717,16 @@ testthat::describe("Backticked symbol", { testthat::it("with space character is detected in code dependency", { td <- teal_data() |> within({ - `add column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) - IRIS <- `add column`(iris, dplyr::tibble(new_col = "new column")) + `add column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) # nolint: object_name. + iris_ds <- `add column`(iris, dplyr::tibble(new_col = "new column")) }) testthat::expect_identical( - get_code(td, datanames = "IRIS"), + get_code(td, datanames = "iris_ds"), paste( sep = "\n", "`add column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "IRIS <- `add column`(iris, dplyr::tibble(new_col = \"new column\"))" + "iris_ds <- `add column`(iris, dplyr::tibble(new_col = \"new column\"))" ) ) }) @@ -735,15 +735,15 @@ testthat::describe("Backticked symbol", { td <- teal_data() |> within({ `add_column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) - IRIS <- `add_column`(iris, dplyr::tibble(new_col = "new column")) + iris_ds <- `add_column`(iris, dplyr::tibble(new_col = "new column")) }) testthat::expect_identical( - get_code(td, datanames = "IRIS"), + get_code(td, datanames = "iris_ds"), paste( sep = "\n", "add_column <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "IRIS <- add_column(iris, dplyr::tibble(new_col = \"new column\"))" + "iris_ds <- add_column(iris, dplyr::tibble(new_col = \"new column\"))" ) ) }) @@ -752,17 +752,17 @@ testthat::describe("Backticked symbol", { td <- teal_data() |> within({ `%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) - IRIS <- `%add_column%`(iris, dplyr::tibble(new_col = "new column")) + iris_ds <- `%add_column%`(iris, dplyr::tibble(new_col = "new column")) }) # Note that the original code is changed to use the non-native pipe operator # correctly. testthat::expect_identical( - get_code(td, datanames = "IRIS"), + get_code(td, datanames = "iris_ds"), paste( sep = "\n", "`%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "IRIS <- iris %add_column% dplyr::tibble(new_col = \"new column\")" + "iris_ds <- iris %add_column% dplyr::tibble(new_col = \"new column\")" ) ) }) From fcb9c4ad2af29e84a25a0454b20d32ba37b30100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:12:36 +0100 Subject: [PATCH 07/14] tests: checks if code with non-native pipe operator is correctly detected --- tests/testthat/test-get_code.R | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-get_code.R b/tests/testthat/test-get_code.R index 9140686e8..c7a24f4d9 100644 --- a/tests/testthat/test-get_code.R +++ b/tests/testthat/test-get_code.R @@ -748,7 +748,7 @@ testthat::describe("Backticked symbol", { ) }) - testthat::it("with non-native pipe is detected code dependency", { + testthat::it("with non-native pipe used as function is detected code dependency", { td <- teal_data() |> within({ `%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) @@ -766,4 +766,23 @@ testthat::describe("Backticked symbol", { ) ) }) + + testthat::it("with non-native pipe is detected code dependency", { + td <- teal_data() |> + within({ + `%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) + iris_ds <- iris %add_column% dplyr::tibble(new_col = "new column") + }) + + # Note that the original code is changed to use the non-native pipe operator + # correctly. + testthat::expect_identical( + get_code(td, datanames = "iris_ds"), + paste( + sep = "\n", + "`%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", + "iris_ds <- iris %add_column% dplyr::tibble(new_col = \"new column\")" + ) + ) + }) }) From 619e3aed5b97cf4cce68e6ba9b5a6707408b0679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:20:43 +0100 Subject: [PATCH 08/14] fix: use cbind and data.frame in tests instead of dplyr --- tests/testthat/test-get_code.R | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/testthat/test-get_code.R b/tests/testthat/test-get_code.R index c7a24f4d9..57c66fa7e 100644 --- a/tests/testthat/test-get_code.R +++ b/tests/testthat/test-get_code.R @@ -700,16 +700,16 @@ testthat::describe("Backticked symbol", { testthat::it("starting with underscore is detected in code dependency", { td <- teal_data() |> within({ - `_add_column_` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) # nolint: object_name. - iris_ds <- `_add_column_`(iris, dplyr::tibble(new_col = "new column")) + `_add_column_` <- function(lhs, rhs) cbind(lhs, rhs) # nolint: object_name. + iris_ds <- `_add_column_`(iris, data.frame(new_col = "new column")) }) testthat::expect_identical( get_code(td, datanames = "iris_ds"), paste( sep = "\n", - "`_add_column_` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "iris_ds <- `_add_column_`(iris, dplyr::tibble(new_col = \"new column\"))" + "`_add_column_` <- function(lhs, rhs) cbind(lhs, rhs)", + "iris_ds <- `_add_column_`(iris, data.frame(new_col = \"new column\"))" ) ) }) @@ -717,16 +717,16 @@ testthat::describe("Backticked symbol", { testthat::it("with space character is detected in code dependency", { td <- teal_data() |> within({ - `add column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) # nolint: object_name. - iris_ds <- `add column`(iris, dplyr::tibble(new_col = "new column")) + `add column` <- function(lhs, rhs) cbind(lhs, rhs) # nolint: object_name. + iris_ds <- `add column`(iris, data.frame(new_col = "new column")) }) testthat::expect_identical( get_code(td, datanames = "iris_ds"), paste( sep = "\n", - "`add column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "iris_ds <- `add column`(iris, dplyr::tibble(new_col = \"new column\"))" + "`add column` <- function(lhs, rhs) cbind(lhs, rhs)", + "iris_ds <- `add column`(iris, data.frame(new_col = \"new column\"))" ) ) }) @@ -734,16 +734,16 @@ testthat::describe("Backticked symbol", { testthat::it("without special characters is cleaned and detecteed in code dependency", { td <- teal_data() |> within({ - `add_column` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) - iris_ds <- `add_column`(iris, dplyr::tibble(new_col = "new column")) + `add_column` <- function(lhs, rhs) cbind(lhs, rhs) + iris_ds <- `add_column`(iris, data.frame(new_col = "new column")) }) testthat::expect_identical( get_code(td, datanames = "iris_ds"), paste( sep = "\n", - "add_column <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "iris_ds <- add_column(iris, dplyr::tibble(new_col = \"new column\"))" + "add_column <- function(lhs, rhs) cbind(lhs, rhs)", + "iris_ds <- add_column(iris, data.frame(new_col = \"new column\"))" ) ) }) @@ -751,8 +751,8 @@ testthat::describe("Backticked symbol", { testthat::it("with non-native pipe used as function is detected code dependency", { td <- teal_data() |> within({ - `%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) - iris_ds <- `%add_column%`(iris, dplyr::tibble(new_col = "new column")) + `%add_column%` <- function(lhs, rhs) cbind(lhs, rhs) + iris_ds <- `%add_column%`(iris, data.frame(new_col = "new column")) }) # Note that the original code is changed to use the non-native pipe operator @@ -761,8 +761,8 @@ testthat::describe("Backticked symbol", { get_code(td, datanames = "iris_ds"), paste( sep = "\n", - "`%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "iris_ds <- iris %add_column% dplyr::tibble(new_col = \"new column\")" + "`%add_column%` <- function(lhs, rhs) cbind(lhs, rhs)", + "iris_ds <- iris %add_column% data.frame(new_col = \"new column\")" ) ) }) @@ -770,8 +770,8 @@ testthat::describe("Backticked symbol", { testthat::it("with non-native pipe is detected code dependency", { td <- teal_data() |> within({ - `%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs) - iris_ds <- iris %add_column% dplyr::tibble(new_col = "new column") + `%add_column%` <- function(lhs, rhs) cbind(lhs, rhs) + iris_ds <- iris %add_column% data.frame(new_col = "new column") }) # Note that the original code is changed to use the non-native pipe operator @@ -780,8 +780,8 @@ testthat::describe("Backticked symbol", { get_code(td, datanames = "iris_ds"), paste( sep = "\n", - "`%add_column%` <- function(lhs, rhs) dplyr::bind_cols(lhs, rhs)", - "iris_ds <- iris %add_column% dplyr::tibble(new_col = \"new column\")" + "`%add_column%` <- function(lhs, rhs) cbind(lhs, rhs)", + "iris_ds <- iris %add_column% data.frame(new_col = \"new column\")" ) ) }) From ede935527f191569cddfa76c96818b6e912413a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:12:07 +0100 Subject: [PATCH 09/14] fix: regex expression to only replace if initial and ending backticks exist --- R/utils-get_code_dependency.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/utils-get_code_dependency.R b/R/utils-get_code_dependency.R index f1f9dd9c6..762d131d8 100644 --- a/R/utils-get_code_dependency.R +++ b/R/utils-get_code_dependency.R @@ -381,8 +381,8 @@ extract_side_effects <- function(calls_pd) { #' @noRd graph_parser <- function(x, graph) { # normalize x to remove surrounding backticks - x <- gsub("^`|`$", "", x) - graph <- lapply(graph, function(call) gsub("^`|`$", "", call)) + x <- gsub("^`(.*)`$", "\\1", x) + graph <- lapply(graph, function(call) gsub("^`(.*)`$", "\\1", call)) occurrence <- vapply( graph, function(call) { From c3c79cfeaf18bac323708542bdecdbbe17808b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:12:19 +0100 Subject: [PATCH 10/14] tests: typo --- tests/testthat/test-get_code.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-get_code.R b/tests/testthat/test-get_code.R index 57c66fa7e..5eb8cf02b 100644 --- a/tests/testthat/test-get_code.R +++ b/tests/testthat/test-get_code.R @@ -731,7 +731,7 @@ testthat::describe("Backticked symbol", { ) }) - testthat::it("without special characters is cleaned and detecteed in code dependency", { + testthat::it("without special characters is cleaned and detected in code dependency", { td <- teal_data() |> within({ `add_column` <- function(lhs, rhs) cbind(lhs, rhs) From 7ca9deeba31ce81c3710b92f6cfd60e13f392fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:01:06 +0100 Subject: [PATCH 11/14] fix: move normalization out of code_parser function --- R/utils-get_code_dependency.R | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/R/utils-get_code_dependency.R b/R/utils-get_code_dependency.R index 762d131d8..bd99d61e2 100644 --- a/R/utils-get_code_dependency.R +++ b/R/utils-get_code_dependency.R @@ -42,8 +42,10 @@ get_code_dependency <- function(code, names, check_names = TRUE) { code <- parse(text = code, keep.source = TRUE) pd <- utils::getParseData(code) + pd <- normalize_pd(pd) calls_pd <- extract_calls(pd) + if (check_names) { # Detect if names are actually in code. symbols <- unlist(lapply(calls_pd, function(call) call[call$token == "SYMBOL", "text"])) @@ -175,7 +177,7 @@ fix_arrows <- function(calls) { sub_arrows <- function(call) { checkmate::assert_data_frame(call) map <- data.frame( - row.names = c("`<-`", "`<<-`", "`=`"), + row.names = c("<-", "<<-", "="), token = rep("LEFT_ASSIGN", 3), text = rep("<-", 3) ) @@ -380,9 +382,6 @@ extract_side_effects <- function(calls_pd) { #' @keywords internal #' @noRd graph_parser <- function(x, graph) { - # normalize x to remove surrounding backticks - x <- gsub("^`(.*)`$", "\\1", x) - graph <- lapply(graph, function(call) gsub("^`(.*)`$", "\\1", call)) occurrence <- vapply( graph, function(call) { @@ -438,3 +437,19 @@ detect_libraries <- function(calls_pd) { ) ) } + +#' Normalize parsed data removing backticks from symbols +#' +#' @param pd `data.frame` resulting from `utils::getParseData()` call. +#' +#' @return `data.frame` with backticks removed from `text` column for `SYMBOL` tokens. +#' +#' @keywords internal +#' @noRd +normalize_pd <- function(pd) { + # Remove backticks from SYMBOL tokens + symbol_index <- grepl("^SYMBOL.*$", pd$token) + pd[symbol_index, "text"] <- gsub("^`(.*)`$", "\\1", pd[symbol_index, "text"]) + + pd +} From e70bd47e231f5fa04f44419119f386da21a560b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:10:09 +0100 Subject: [PATCH 12/14] revert: given the normalization as.name is no longer required --- R/utils-get_code_dependency.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils-get_code_dependency.R b/R/utils-get_code_dependency.R index bd99d61e2..1f549c360 100644 --- a/R/utils-get_code_dependency.R +++ b/R/utils-get_code_dependency.R @@ -55,7 +55,7 @@ get_code_dependency <- function(code, names, check_names = TRUE) { ass_str <- gsub("^['\"]|['\"]$", "", ass_str) symbols <- c(ass_str, symbols) } - if (!all(sapply(names, as.name) %in% unique(symbols))) { + if (!all(names %in% unique(symbols))) { warning("Object(s) not found in code: ", toString(setdiff(names, symbols))) } } From 998eab3c57c2b1c406b471dd0119d8ad1e4c8597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:50:18 +0100 Subject: [PATCH 13/14] fix: allow for datanames in get_code to have backticks --- R/teal_data-get_code.R | 3 +++ tests/testthat/test-get_code.R | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/R/teal_data-get_code.R b/R/teal_data-get_code.R index d74435bd6..d26aec1f5 100644 --- a/R/teal_data-get_code.R +++ b/R/teal_data-get_code.R @@ -107,6 +107,9 @@ setMethod("get_code", signature = "teal_data", definition = function(object, dep checkmate::assert_character(datanames, min.len = 1L, null.ok = TRUE) checkmate::assert_flag(deparse) + # Normalize in case special it is backticked + datanames <- gsub("^`(.*)`$", "\\1", datanames) + code <- if (!is.null(datanames)) { get_code_dependency(object@code, datanames, ...) } else { diff --git a/tests/testthat/test-get_code.R b/tests/testthat/test-get_code.R index 5eb8cf02b..3dff575ec 100644 --- a/tests/testthat/test-get_code.R +++ b/tests/testthat/test-get_code.R @@ -697,6 +697,32 @@ testthat::test_that("data() call is returned when data name is provided as a cha }) testthat::describe("Backticked symbol", { + testthat::it("code can be retrieved with get_code", { + td <- teal_data() |> + within({ + `%cbind%` <- function(lhs, rhs) cbind(lhs, rhs) # nolint: object_name. + iris_ds <- iris %cbind% data.frame(new_col = "new column") + }) + + testthat::expect_identical( + get_code(td, datanames = "%cbind%"), + "`%cbind%` <- function(lhs, rhs) cbind(lhs, rhs)" + ) + }) + + testthat::it("code can be retrieved with get_code", { + td <- teal_data() |> + within({ + `%cbind%` <- function(lhs, rhs) cbind(lhs, rhs) # nolint: object_name. + iris_ds <- iris %cbind% data.frame(new_col = "new column") + }) + + testthat::expect_identical( + get_code(td, datanames = "`%cbind%`"), + "`%cbind%` <- function(lhs, rhs) cbind(lhs, rhs)" + ) + }) + testthat::it("starting with underscore is detected in code dependency", { td <- teal_data() |> within({ From c5ef914c248dbe64e9f446f65ec04b9677d5386f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ver=C3=ADssimo?= <211358+averissimo@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:53:45 +0100 Subject: [PATCH 14/14] fix: tests --- R/teal_data-get_code.R | 4 ++- tests/testthat/test-get_code.R | 56 +++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/R/teal_data-get_code.R b/R/teal_data-get_code.R index d26aec1f5..5cc5c6494 100644 --- a/R/teal_data-get_code.R +++ b/R/teal_data-get_code.R @@ -108,7 +108,9 @@ setMethod("get_code", signature = "teal_data", definition = function(object, dep checkmate::assert_flag(deparse) # Normalize in case special it is backticked - datanames <- gsub("^`(.*)`$", "\\1", datanames) + if (!is.null(datanames)) { + datanames <- gsub("^`(.*)`$", "\\1", datanames) + } code <- if (!is.null(datanames)) { get_code_dependency(object@code, datanames, ...) diff --git a/tests/testthat/test-get_code.R b/tests/testthat/test-get_code.R index 3dff575ec..114dee932 100644 --- a/tests/testthat/test-get_code.R +++ b/tests/testthat/test-get_code.R @@ -698,11 +698,13 @@ testthat::test_that("data() call is returned when data name is provided as a cha testthat::describe("Backticked symbol", { testthat::it("code can be retrieved with get_code", { - td <- teal_data() |> - within({ + td <- within( + teal_data(), + { `%cbind%` <- function(lhs, rhs) cbind(lhs, rhs) # nolint: object_name. iris_ds <- iris %cbind% data.frame(new_col = "new column") - }) + } + ) testthat::expect_identical( get_code(td, datanames = "%cbind%"), @@ -711,11 +713,13 @@ testthat::describe("Backticked symbol", { }) testthat::it("code can be retrieved with get_code", { - td <- teal_data() |> - within({ + td <- within( + teal_data(), + { `%cbind%` <- function(lhs, rhs) cbind(lhs, rhs) # nolint: object_name. iris_ds <- iris %cbind% data.frame(new_col = "new column") - }) + } + ) testthat::expect_identical( get_code(td, datanames = "`%cbind%`"), @@ -724,11 +728,13 @@ testthat::describe("Backticked symbol", { }) testthat::it("starting with underscore is detected in code dependency", { - td <- teal_data() |> - within({ + td <- within( + teal_data(), + { `_add_column_` <- function(lhs, rhs) cbind(lhs, rhs) # nolint: object_name. iris_ds <- `_add_column_`(iris, data.frame(new_col = "new column")) - }) + } + ) testthat::expect_identical( get_code(td, datanames = "iris_ds"), @@ -741,11 +747,13 @@ testthat::describe("Backticked symbol", { }) testthat::it("with space character is detected in code dependency", { - td <- teal_data() |> - within({ + td <- within( + teal_data(), + { `add column` <- function(lhs, rhs) cbind(lhs, rhs) # nolint: object_name. iris_ds <- `add column`(iris, data.frame(new_col = "new column")) - }) + } + ) testthat::expect_identical( get_code(td, datanames = "iris_ds"), @@ -758,11 +766,13 @@ testthat::describe("Backticked symbol", { }) testthat::it("without special characters is cleaned and detected in code dependency", { - td <- teal_data() |> - within({ + td <- within( + teal_data(), + { `add_column` <- function(lhs, rhs) cbind(lhs, rhs) iris_ds <- `add_column`(iris, data.frame(new_col = "new column")) - }) + } + ) testthat::expect_identical( get_code(td, datanames = "iris_ds"), @@ -775,11 +785,13 @@ testthat::describe("Backticked symbol", { }) testthat::it("with non-native pipe used as function is detected code dependency", { - td <- teal_data() |> - within({ + td <- within( + teal_data(), + { `%add_column%` <- function(lhs, rhs) cbind(lhs, rhs) iris_ds <- `%add_column%`(iris, data.frame(new_col = "new column")) - }) + } + ) # Note that the original code is changed to use the non-native pipe operator # correctly. @@ -794,11 +806,13 @@ testthat::describe("Backticked symbol", { }) testthat::it("with non-native pipe is detected code dependency", { - td <- teal_data() |> - within({ + td <- within( + teal_data(), + { `%add_column%` <- function(lhs, rhs) cbind(lhs, rhs) iris_ds <- iris %add_column% data.frame(new_col = "new column") - }) + } + ) # Note that the original code is changed to use the non-native pipe operator # correctly.