Skip to content

Commit 515b267

Browse files
author
Stefan Fleck
committed
fixes handling of R6 classes that inherit their initialize method
1 parent 6173682 commit 515b267

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed

R/utils-rd.R

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
r6_usage <- function(
2+
x,
3+
name = "x",
4+
ignore = NULL,
5+
header = "",
6+
show_methods = TRUE
7+
){
8+
if (is.list(x)){
9+
classname <- deparse(substitute(x))
10+
classname <- gsub("(list\\()|\\)$", "", classname)
11+
classname <- unlist(strsplit(classname, ", ", fixed = TRUE))
12+
13+
res <- lapply(
14+
seq_along(x),
15+
function(i){
16+
collect_usage.R6(
17+
x = x[[i]],
18+
classname = classname[[i]],
19+
ignore = ignore
20+
)
21+
}
22+
)
23+
24+
res <- list(
25+
ctor = unlist(lapply(res, `[[`, "ctor")),
26+
fields = unique(unlist(lapply(res, `[[`, "fields"))),
27+
methods = unique(unlist(lapply(res, `[[`, "methods")))
28+
)
29+
30+
} else if (R6::is.R6Class(x)){
31+
res <- collect_usage.R6(
32+
x,
33+
classname = deparse(substitute(x)),
34+
ignore = ignore
35+
)
36+
} else {
37+
stop("Object ", preview_object(x), "not supported")
38+
}
39+
40+
41+
fmt_r6_usage(
42+
res,
43+
name = name,
44+
header = header,
45+
show_methods = show_methods
46+
)
47+
}
48+
49+
50+
51+
52+
#' Format R6 usage
53+
#'
54+
#' @param x an `R6ClassGenerator`
55+
#' @param classname `character` scalar. The name of the R6 class
56+
#' @param ignore `character` vector. methods/fields to ignore when generating
57+
#' usage
58+
#'
59+
#' @return a `list` with the components `ctor`, `fields` and `methods`
60+
#' @noRd
61+
collect_usage.R6 <- function(
62+
x,
63+
classname = deparse(substitute(x)),
64+
ignore = TRUE
65+
){
66+
public_methods <- vapply(
67+
setdiff(names(x$public_methods), ignore),
68+
function(nm) make_function_usage(nm, formals(x$public_methods[[nm]])),
69+
character(1)
70+
)
71+
72+
73+
ctor <- get_public_method_recursively(x, "initialize")
74+
if (!is.null(ctor)){
75+
ctor <- make_function_usage(paste0(classname, "$new"), formals(ctor))
76+
}
77+
78+
fields <- c(names(x$public_fields), names(x$active))
79+
80+
81+
if (!is.null(fields)) fields <- sort(fields)
82+
fields <- setdiff(fields, ignore)
83+
84+
els <- list(
85+
ctor = ctor,
86+
methods =
87+
public_methods[!names(public_methods) %in% c("initialize", "finalize")],
88+
fields = fields
89+
)
90+
91+
els <- els[!vapply(els, is_empty, FALSE)]
92+
93+
if ("get_inherit" %in% names(x)){
94+
els <- c(els, collect_usage.R6(x$get_inherit(), ignore = ignore))
95+
list(
96+
ctor = els$ctor,
97+
fields = unique(unlist(els[names(els) == "fields"])),
98+
methods = unique(unlist(els[names(els) == "methods"]))
99+
)
100+
} else {
101+
els
102+
}
103+
}
104+
105+
106+
107+
108+
#' Format R6 usage
109+
#'
110+
#' @param x output of collect_usage.R6
111+
#' @param header an optional `character` vector for a heading
112+
#' @param show_methods `logical` scalar: Show methods
113+
#'
114+
#' @return a `character` vector
115+
#' @noRd
116+
fmt_r6_usage <- function(
117+
x,
118+
name = x,
119+
header = "",
120+
show_methods = TRUE
121+
){
122+
assert(is_scalar_bool(show_methods))
123+
124+
res <- c()
125+
res <- c("@section Usage:", "")
126+
127+
128+
ctors <- unlist(lapply(
129+
x$ctor,
130+
function(.x) c(strwrap(paste0(name, " <- ", .x), width = 80, exdent = 2), "")
131+
))
132+
133+
res <- c(
134+
res,
135+
"```",
136+
header,
137+
ctors
138+
)
139+
140+
if (show_methods){
141+
res <- c(
142+
res,
143+
paste0(name, "$", sort(x$methods)), "",
144+
paste0(name, "$", sort(x$fields)), "",
145+
"```"
146+
)
147+
}
148+
149+
res
150+
}
151+
152+
153+
154+
155+
get_public_method_recursively = function(ctor, method){
156+
if (is.function(ctor))
157+
return(ctor)
158+
else if (is.null(ctor))
159+
return(NULL)
160+
161+
if (method %in% names(ctor$public_methods)){
162+
return(ctor$public_methods[[method]])
163+
164+
} else {
165+
get_public_method_recursively(ctor$get_inherit(), method)
166+
}
167+
}
168+
169+
170+
171+
172+
make_function_usage <- function(name, arglist){
173+
paste0(name, "(", fmt_formals(arglist), ")")
174+
}
175+
176+
177+
178+
179+
fmt_formals <- function(fmls){
180+
181+
arg_to_text <- function(.x) {
182+
if (is.symbol(.x) && deparse(.x) == "")
183+
return("")
184+
185+
text <- enc2utf8(deparse(.x, backtick = TRUE, width.cutoff = 500L))
186+
text <- paste0(text, collapse = "\n")
187+
Encoding(text) <- "UTF-8"
188+
text
189+
}
190+
191+
res <- vapply(fmls, arg_to_text, character(1))
192+
sep <- ifelse(res == "", "", " = ")
193+
paste0(names(res), sep, res, collapse = ", ")
194+
}

0 commit comments

Comments
 (0)