Skip to content

Commit 4b2b2fb

Browse files
committed
let qenv, eval_code and get_code work on @code that has length as the number of calls in @code
1 parent 99ebe96 commit 4b2b2fb

File tree

5 files changed

+51
-28
lines changed

5 files changed

+51
-28
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
* `get_code()` was extended with `names` parameter and allows the code extraction to be limited to objects stored in
66
`qenv` but limited to `names`.
7+
* `eval_code(qenv, code)` analyzes code by single calls and returns `@id`, `@code`, `@messages`, `@warnings` fields of
8+
the length of calls included in `code`.
79

810
# teal.code 0.5.0
911

R/qenv-eval_code.R

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,20 @@
2828
setGeneric("eval_code", function(object, code) standardGeneric("eval_code"))
2929

3030
setMethod("eval_code", signature = c("qenv", "character"), function(object, code) {
31-
id <- sample.int(.Machine$integer.max, size = 1)
31+
parsed_code <- parse(text = code, keep.source = TRUE)
32+
comments <- extract_comments(parsed_code)
33+
id <- sample.int(.Machine$integer.max, size = length(parsed_code))
3234

3335
object@id <- c(object@id, id)
3436
object@env <- rlang::env_clone(object@env, parent = parent.env(.GlobalEnv))
35-
code <- paste(code, collapse = "\n")
36-
object@code <- c(object@code, code)
37+
object@code <- c(object@code, trimws(paste(as.character(parsed_code), comments)))
3738

38-
current_warnings <- ""
39-
current_messages <- ""
39+
current_warnings <- rep("", length(parsed_code))
40+
current_messages <- rep("", length(parsed_code))
4041

41-
parsed_code <- parse(text = code, keep.source = TRUE)
42-
for (single_call in parsed_code) {
42+
43+
for (i in 1:length(parsed_code)) {
44+
single_call <- parsed_code[i]
4345
# Using withCallingHandlers to capture warnings and messages.
4446
# Using tryCatch to capture the error and abort further evaluation.
4547
x <- withCallingHandlers(
@@ -66,11 +68,11 @@ setMethod("eval_code", signature = c("qenv", "character"), function(object, code
6668
}
6769
),
6870
warning = function(w) {
69-
current_warnings <<- paste0(current_warnings, .ansi_strip(sprintf("> %s\n", conditionMessage(w))))
71+
current_warnings[i] <<- .ansi_strip(sprintf("> %s\n", conditionMessage(w)))
7072
invokeRestart("muffleWarning")
7173
},
7274
message = function(m) {
73-
current_messages <<- paste0(current_messages, .ansi_strip(sprintf("> %s", conditionMessage(m))))
75+
current_messages[i] <<- .ansi_strip(sprintf("> %s", conditionMessage(m)))
7476
invokeRestart("muffleMessage")
7577
}
7678
)

R/qenv-get_code.R

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,12 @@ setMethod("get_code", signature = "qenv", function(object, deparse = TRUE, names
124124
}
125125

126126
if (deparse) {
127-
if (length(code) == 0) {
128-
code
129-
} else {
130-
paste(code, collapse = "\n")
131-
}
127+
# if (length(code) == 0) {
128+
# code
129+
# } else {
130+
# paste(code, collapse = "\n")
131+
# }
132+
code
132133
} else {
133134
parse(text = paste(c("{", code, "}"), collapse = "\n"), keep.source = TRUE)
134135
}

R/qenv-subset.R

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,18 @@ setMethod("subset", signature = c("qenv"), function(object, names) {
3030
return(qenv())
3131
}
3232

33-
new_qenv <- qenv()
34-
new_qenv@env <- list2env(mget(x = names_in_env, envir = get_env(object)))
35-
new_qenv@code <- get_code(object, names = names_in_env)
36-
# Question: what about @id, @warnings, @messages?
37-
# Currently:
38-
# > new_qenv@id
39-
# integer(0)
40-
# > new_qenv@warnings
41-
# character(0)
42-
# > new_qenv@messages
43-
# character(0)
44-
new_qenv
33+
limited_code <- get_code(object, names = names_in_env)
34+
indexes <- which(object@code %in% limited_code)
4535

46-
})
36+
object@env <- list2env(mget(x = names_in_env, envir = get_env(object)))
37+
object@code <- limited_code
38+
object@id <- object@id[indexes]
39+
object@warnings <- object@warnings[indexes]
40+
object@messages <- object@messages[indexes]
41+
42+
object
4743

44+
})
4845

4946
setMethod("subset", signature = c("qenv.error", "ANY"), function(object, names) {
5047
object

R/utils-get_code_dependency.R

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ get_code_dependency <- function(code, names, check_names = TRUE) {
4444
pd <- utils::getParseData(code)
4545
pd <- normalize_pd(pd)
4646
calls_pd <- extract_calls(pd)
47+
comments <- extract_comments(code)
4748

4849
if (check_names) {
4950
# Detect if names are actually in code.
@@ -64,7 +65,8 @@ get_code_dependency <- function(code, names, check_names = TRUE) {
6465

6566
lib_ind <- detect_libraries(calls_pd)
6667

67-
as.character(code[sort(unique(c(lib_ind, ind)))])
68+
code_ids <- sort(unique(c(lib_ind, ind)))
69+
trimws(paste(as.character(code[code_ids]), comments[code_ids]))
6870
}
6971

7072
#' Locate function call token
@@ -451,3 +453,22 @@ normalize_pd <- function(pd) {
451453

452454
pd
453455
}
456+
457+
#' Extract comments from parsed code
458+
#'
459+
#' @param parsed_code `expression`, result of `parse()` function
460+
#'
461+
#' @return `character` vector of length of `parsed_code` with comments included in `parsed_code`
462+
#' @keywords internal
463+
#' @noRd
464+
extract_comments <- function(parsed_code) {
465+
get_comments <- function(call) {
466+
comment <- call[call$token == "COMMENT", "text"]
467+
if (length(comment) == 0) "" else comment
468+
}
469+
unlist(lapply(
470+
extract_calls(utils::getParseData(parsed_code)),
471+
get_comments
472+
))
473+
}
474+

0 commit comments

Comments
 (0)