9
9
# ' @param code (`character`, `language` or `expression`) code to evaluate.
10
10
# ' It is possible to preserve original formatting of the `code` by providing a `character` or an
11
11
# ' `expression` being a result of `parse(keep.source = TRUE)`.
12
+ # ' @param ... ([`dots`]) additional arguments passed to future methods.
12
13
# '
13
14
# ' @return
14
15
# ' `qenv` environment with `code/expr` evaluated or `qenv.error` if evaluation fails.
21
22
# ' q <- eval_code(q, quote(library(checkmate)))
22
23
# ' q <- eval_code(q, expression(assert_number(a)))
23
24
# '
24
- # ' @aliases eval_code,qenv,character-method
25
- # ' @aliases eval_code,qenv,language-method
26
- # ' @aliases eval_code,qenv,expression-method
27
- # ' @aliases eval_code,qenv.error,ANY-method
28
- # '
25
+ # ' @aliases eval_code,qenv-method
26
+ # ' @aliases eval_code,qenv.error-method
27
+ # ' @seealso [within.qenv]
29
28
# ' @export
30
- setGeneric ("eval_code ", function(object, code) standardGeneric("eval_code"))
29
+ setGeneric ("eval_code ", function(object, code, ...) standardGeneric("eval_code"))
30
+
31
+ setMethod ("eval_code ", signature = c(object = "qenv"), function(object, code, ...) {
32
+ if (! is.language(code ) && ! is.character(code )) {
33
+ stop(" eval_code accepts code being language or character" )
34
+ }
35
+ code <- .preprocess_code(code )
36
+ # preprocess code to ensure it is a character vector
37
+ .eval_code(object = object , code = code , ... )
38
+ })
39
+
40
+ setMethod ("eval_code ", signature = c(object = "qenv.error"), function(object, code, ...) object)
31
41
32
- setMethod ("eval_code ", signature = c("qenv", "character"), function(object, code) {
42
+ # ' @keywords internal
43
+ .eval_code <- function (object , code , ... ) {
44
+ if (identical(trimws(code ), " " ) || length(code ) == 0 ) {
45
+ return (object )
46
+ }
33
47
parsed_code <- parse(text = code , keep.source = TRUE )
34
48
object @ .xData <- rlang :: env_clone(object @ .xData , parent = parent.env(.GlobalEnv ))
35
49
if (length(parsed_code ) == 0 ) {
@@ -42,7 +56,6 @@ setMethod("eval_code", signature = c("qenv", "character"), function(object, code
42
56
for (i in seq_along(code_split )) {
43
57
current_code <- code_split [[i ]]
44
58
current_call <- parse(text = current_code , keep.source = TRUE )
45
-
46
59
# Using withCallingHandlers to capture warnings and messages.
47
60
# Using tryCatch to capture the error and abort further evaluation.
48
61
x <- withCallingHandlers(
@@ -60,7 +73,7 @@ setMethod("eval_code", signature = c("qenv", "character"), function(object, code
60
73
errorCondition(
61
74
message = sprintf(
62
75
" %s \n when evaluating qenv code:\n %s" ,
63
- . ansi_strip(conditionMessage(e )),
76
+ cli :: ansi_strip(conditionMessage(e )),
64
77
current_code
65
78
),
66
79
class = c(" qenv.error" , " try-error" , " simpleError" ),
@@ -69,11 +82,11 @@ setMethod("eval_code", signature = c("qenv", "character"), function(object, code
69
82
}
70
83
),
71
84
warning = function (w ) {
72
- attr(current_code , " warning" ) <<- . ansi_strip(sprintf(" > %s\n " , conditionMessage(w )))
85
+ attr(current_code , " warning" ) <<- cli :: ansi_strip(sprintf(" > %s\n " , conditionMessage(w )))
73
86
invokeRestart(" muffleWarning" )
74
87
},
75
88
message = function (m ) {
76
- attr(current_code , " message" ) <<- . ansi_strip(sprintf(" > %s" , conditionMessage(m )))
89
+ attr(current_code , " message" ) <<- cli :: ansi_strip(sprintf(" > %s" , conditionMessage(m )))
77
90
invokeRestart(" muffleMessage" )
78
91
}
79
92
)
@@ -87,42 +100,17 @@ setMethod("eval_code", signature = c("qenv", "character"), function(object, code
87
100
88
101
lockEnvironment(object @ .xData , bindings = TRUE )
89
102
object
90
- })
91
-
92
- setMethod ("eval_code ", signature = c("qenv", "language"), function(object, code) {
93
- eval_code(object , code = paste(vapply(lang2calls(code ), deparse1 , collapse = " \n " , character (1L )), collapse = " \n " ))
94
- })
103
+ }
95
104
96
- setMethod ("eval_code ", signature = c("qenv", "expression"), function(object, code) {
97
- srcref <- attr(code , " wholeSrcref" )
98
- if (length(srcref )) {
99
- eval_code(object , code = paste(attr(code , " wholeSrcref" ), collapse = " \n " ))
105
+ setGeneric (".preprocess_code ", function(code) standardGeneric(".preprocess_code"))
106
+ setMethod (".preprocess_code ", signature = c("character"), function(code) paste(code, collapse = "\n"))
107
+ setMethod (".preprocess_code ", signature = c("ANY"), function(code) {
108
+ if (is.expression(code ) && length(attr(code , " wholeSrcref" ))) {
109
+ paste(attr(code , " wholeSrcref" ), collapse = " \n " )
100
110
} else {
101
- Reduce(function (u , v ) {
102
- if (inherits(v , " =" ) && identical(typeof(v ), " language" )) {
103
- # typeof(`=`) is language, but it doesn't dispatch on it, so we need to
104
- # explicitly pass it as first class of the object
105
- class(v ) <- unique(c(" language" , class(v )))
106
- }
107
- eval_code(u , v )
108
- }, init = object , x = code )
111
+ paste(
112
+ vapply(lang2calls(code ), deparse1 , collapse = " \n " , character (1L )),
113
+ collapse = " \n "
114
+ )
109
115
}
110
116
})
111
-
112
- setMethod ("eval_code ", signature = c("qenv.error", "ANY"), function(object, code) {
113
- object
114
- })
115
-
116
- # if cli is installed rlang adds terminal printing characters
117
- # which need to be removed
118
- .ansi_strip <- function (chr ) {
119
- if (requireNamespace(" cli" , quietly = TRUE )) {
120
- cli :: ansi_strip(chr )
121
- } else {
122
- chr
123
- }
124
- }
125
-
126
- get_code_attr <- function (qenv , attr ) {
127
- unlist(lapply(qenv @ code , function (x ) attr(x , attr )))
128
- }
0 commit comments