Skip to content

Commit b932e29

Browse files
committed
Handle multiple R6 classes in one file
Fixes #
1 parent cfca3d5 commit b932e29

2 files changed

Lines changed: 78 additions & 23 deletions

File tree

R/rd-r6.R

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,21 @@ topic_add_r6_methods <- function(rd, block, env, base_path) {
1313
}
1414
}
1515

16-
# Store unresolved R6 docs; pass 2 will inherit and format
17-
rd$add(rd_section("r6_class", docs))
16+
# Store unresolved R6 docs; pass 2 will inherit and format. The value is a
17+
# named list keyed by classname so that multiple R6 classes sharing a topic
18+
# (via @rdname) can coexist and be looked up individually.
19+
classname <- block$object$value$classname %||% ""
20+
rd$add(rd_section("r6_class", set_names(list(docs), classname)))
1821
}
1922

2023
#' @export
2124
format.rd_section_r6_class <- function(x, ...) NULL
2225

26+
#' @export
27+
merge.rd_section_r6_class <- function(x, y, ...) {
28+
rd_section("r6_class", c(x$value, y$value))
29+
}
30+
2331
# When an R6 class has inline @description tags for methods, parse_description()
2432
# parser puts the class description into @details instead of @description.
2533
# This function detects that case and promotes the class-level @details back
@@ -94,21 +102,44 @@ tag_has_name <- function(tag, names) {
94102
# to topics. Mirrors topics_process_inherit() but for R6 field/param docs.
95103
topics_process_r6_inherit <- function(topics) {
96104
r6_deps <- function(topic) {
97-
docs <- topic$get_value("r6_class")
98-
docs$superclasses$classname
105+
docs_list <- topic$get_value("r6_class")
106+
unlist(lapply(docs_list, \(d) d$superclasses$classname))
99107
}
100108

101109
topics$topo_apply(r6_deps, r6_resolve_topic)
102110
}
103111

104112
r6_resolve_topic <- function(topic, topics) {
105-
docs <- topic$get_value("r6_class")
106-
if (is.null(docs)) {
113+
docs_list <- topic$get_value("r6_class")
114+
if (is.null(docs_list)) {
107115
return()
108116
}
109117

110118
topic_name <- topic$get_name()
111119

120+
resolved <- lapply(docs_list, function(docs) {
121+
r6_resolve_class(docs, topic_name, topics)
122+
})
123+
124+
# Update stored docs (now resolved, so child classes can read them)
125+
topic$sections$r6_class <- rd_section("r6_class", resolved)
126+
127+
# Format and inject into topic. Each class produces its own block of Rd.
128+
rd_lines <- unlist(lapply(resolved, format))
129+
topic$add(rd_section("rawRd", paste(rd_lines, collapse = "\n")))
130+
131+
# Add combined examples across all methods of all classes in the topic
132+
all_methods <- list(
133+
self = unlist(lapply(resolved, \(d) d$methods$self), recursive = FALSE)
134+
)
135+
ex_lines <- r6_all_examples(all_methods)
136+
if (length(ex_lines) > 0) {
137+
ex_txt <- paste0(ex_lines, collapse = "\n")
138+
topic$add(rd_section("examples", ex_txt), overwrite = FALSE)
139+
}
140+
}
141+
142+
r6_resolve_class <- function(docs, topic_name, topics) {
112143
# Collect resolved parent docs from already-processed topics
113144
parent_docs <- list()
114145
for (classname in docs$superclasses$classname) {
@@ -120,35 +151,22 @@ r6_resolve_topic <- function(topic, topics) {
120151
if (is.null(parent_topic)) {
121152
next
122153
}
123-
parent_docs[[classname]] <- parent_topic$get_value("r6_class")
154+
parent_r6 <- parent_topic$get_value("r6_class")
155+
# Parent topic may contain multiple R6 classes; pick the one by name
156+
parent_docs[[classname]] <- parent_r6[[classname]]
124157
}
125158

126-
# Inherit fields and active bindings
127159
docs$fields <- r6_resolve_fields(docs$fields, parent_docs, topic_name)
128160
docs$active_bindings <- r6_resolve_fields(
129161
docs$active_bindings,
130162
parent_docs,
131163
topic_name
132164
)
133-
134-
# Inherit method params
135165
docs$methods$self <- lapply(docs$methods$self, function(method) {
136166
r6_resolve_method_params(method, parent_docs, topic_name)
137167
})
138168

139-
# Update stored docs (now resolved, so child classes can read them)
140-
topic$sections$r6_class <- rd_section("r6_class", docs)
141-
142-
# Format and inject into topic
143-
rd_lines <- format(docs)
144-
topic$add(rd_section("rawRd", paste(rd_lines, collapse = "\n")))
145-
146-
# Add combined examples for all methods
147-
ex_lines <- r6_all_examples(docs$methods)
148-
if (length(ex_lines) > 0) {
149-
ex_txt <- paste0(ex_lines, collapse = "\n")
150-
topic$add(rd_section("examples", ex_txt), overwrite = FALSE)
151-
}
169+
docs
152170
}
153171

154172
# Field inheritance ----------------------------------------------------------

tests/testthat/test-rd-r6.R

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,40 @@ test_that("integration test", {
1010
expect_equal(length(chk), 0L)
1111
}
1212
})
13+
14+
test_that("multiple R6 classes in one topic (@rdname) produce valid Rd", {
15+
out <- roc_proc_text(
16+
rd_roclet(),
17+
"
18+
#' Title
19+
#' @name shared
20+
NULL
21+
22+
#' @rdname shared
23+
A <- R6::R6Class('A',
24+
public = list(
25+
#' @field x Field x.
26+
x = NULL,
27+
#' @description Method a.
28+
meth_a = function() {}
29+
)
30+
)
31+
32+
#' @rdname shared
33+
B <- R6::R6Class('B',
34+
public = list(
35+
#' @field y Field y.
36+
y = NULL,
37+
#' @description Method b.
38+
meth_b = function() {}
39+
)
40+
)
41+
"
42+
)[[1]]
43+
44+
rd <- out$get_rd("rawRd")
45+
expect_match(rd, "\\item{\\code{x}}{Field x.}", fixed = TRUE)
46+
expect_match(rd, "\\item{\\code{y}}{Field y.}", fixed = TRUE)
47+
expect_match(rd, "A$meth_a", fixed = TRUE)
48+
expect_match(rd, "B$meth_b", fixed = TRUE)
49+
})

0 commit comments

Comments
 (0)