@@ -21,6 +21,7 @@ source_file <- function(
2121) {
2222 stopifnot(file.exists(path ))
2323 stopifnot(is.environment(env ))
24+ check_character(desc , allow_null = TRUE )
2425
2526 lines <- brio :: read_lines(path )
2627 srcfile <- srcfilecopy(
@@ -35,7 +36,7 @@ source_file <- function(
3536 con <- textConnection(lines , encoding = " UTF-8" )
3637 on.exit(try(close(con ), silent = TRUE ), add = TRUE )
3738 exprs <- parse(con , n = - 1 , srcfile = srcfile , encoding = " UTF-8" )
38- exprs <- filter_desc (exprs , desc , error_call = error_call )
39+ exprs <- filter_subtests (exprs , desc , error_call = error_call )
3940
4041 n <- length(exprs )
4142 if (n == 0L ) {
@@ -69,63 +70,45 @@ source_file <- function(
6970 }
7071}
7172
72- filter_desc <- function (exprs , desc = NULL , error_call = caller_env()) {
73- if (is.null( desc ) ) {
73+ filter_subtests <- function (exprs , descs , error_call = caller_env()) {
74+ if (length( descs ) == 0 ) {
7475 return (exprs )
7576 }
76- desc_levels <- if (is.list(desc )) {
77- desc
78- } else {
79- as.list(desc )
80- }
8177
82- find_matching_expr <- function (exprs , queue ) {
83- if (length(queue ) == 0 ) {
84- exprs
85- } else {
86- found <- FALSE
87- include <- rep(FALSE , length(exprs ))
88- desc <- queue [[1 ]]
89-
90- for (i in seq_along(exprs )) {
91- expr <- exprs [[i ]]
92-
93- if (! is_call(expr , c(" test_that" , " describe" , " it" ), n = 2 )) {
94- if (! found ) {
95- include [[i ]] <- TRUE
96- }
97- } else {
98- if (! is_string(expr [[2 ]])) {
99- next
100- }
101-
102- test_desc <- as.character(expr [[2 ]])
103- if (test_desc != desc ) {
104- next
105- }
106-
107- if (found ) {
108- abort(
109- " Found multiple tests with specified description" ,
110- call = error_call
111- )
112- }
113- include [[i ]] <- TRUE
114- found <- TRUE
115- exprs [[i ]][[3 ]] <- find_matching_expr(expr [[3 ]], queue [- 1 ])
116- }
117- }
78+ is_subtest <- unname(map_lgl(exprs , is_subtest ))
11879
119- if (! found ) {
120- abort(" Failed to find test with specified description" , call = error_call )
121- }
80+ subtest_idx <- which(is_subtest )
81+ code_idx <- which(! is_subtest )
82+ matching_idx <- keep(subtest_idx , \(idx ) {
83+ exprs [[idx ]][[2 ]] == descs [[1 ]]
84+ })
12285
123- exprs [include ]
124- }
86+ if (length(matching_idx ) == 0 ) {
87+ cli :: cli_abort(
88+ " Failed to find test with specified description" ,
89+ call = error_call
90+ )
91+ } else if (length(matching_idx ) > 1 ) {
92+ cli :: cli_abort(
93+ " Found multiple tests with specified description" ,
94+ call = error_call
95+ )
12596 }
126- find_matching_expr(exprs , desc_levels )
97+
98+ keep_idx <- intersect(seq_along(exprs ), c(matching_idx , code_idx ))
99+ exprs [[matching_idx ]] <- filter_subtests(
100+ exprs [[matching_idx ]],
101+ descs [- 1 ],
102+ error_call = error_call
103+ )
104+ exprs [keep_idx ]
127105}
128106
107+ is_subtest <- function (expr ) {
108+ is_call(expr , c(" test_that" , " describe" , " it" ), n = 2 ) && is_string(expr [[2 ]])
109+ }
110+
111+
129112# ' @rdname source_file
130113# ' @export
131114source_dir <- function (
0 commit comments