Skip to content

Commit 2b41ba4

Browse files
authored
Dynamically access ggproto super class (#1872)
Fixes #1826
1 parent 3cf9b77 commit 2b41ba4

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

NEWS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Major new features
44

5-
## Subtitle and caption
5+
### Subtitle and caption
66

77
Thanks to @hrbrmstr plots now have subtitles and captions, which can be set with the `subtitle` and `caption` arguments to `ggtitle()` and `labs()`. You can control their appearance with the theme settings `plot.caption` and `plot.subtitle`. The main plot title is now left-aligned to better work better with a subtitle. The caption is right-aligned (@hrbrmstr).
88

@@ -42,6 +42,10 @@ We have also added the following new fatures.
4242
* The theme option `panel.margin` has been deprecated in favour of
4343
`panel.spacing` to more clearly communicate intent.
4444

45+
### Extensions
46+
47+
Unfortunately there was a major oversight in the construction of ggproto which lead to extensions capturing the super object at package build time, instead of at package run time (#1826). This problem has been fixed, but requires re-installation of all extension packages.
48+
4549
## Scales
4650

4751
* The position of x and y axes can now be changed using the `position` argument

R/ggproto.r

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,21 @@ ggproto <- function(`_class` = NULL, `_inherit` = NULL, ...) {
4343
list2env(members, envir = e)
4444
}
4545

46-
if (!is.null(`_inherit`)) {
47-
if (!is.ggproto(`_inherit`)) {
46+
# Dynamically capture parent: this is necessary in order to avoid
47+
# capturing the parent at package build time.
48+
`_inherit` <- substitute(`_inherit`)
49+
env <- parent.frame()
50+
find_super <- function() {
51+
eval(`_inherit`, env, NULL)
52+
}
53+
54+
super <- find_super()
55+
if (!is.null(super)) {
56+
if (!is.ggproto(super)) {
4857
stop("`_inherit` must be a ggproto object.")
4958
}
50-
e$super <- `_inherit`
51-
class(e) <- c(`_class`, class(`_inherit`))
52-
59+
e$super <- find_super
60+
class(e) <- c(`_class`, class(super))
5361
} else {
5462
class(e) <- c(`_class`, "ggproto")
5563
}
@@ -74,8 +82,17 @@ fetch_ggproto <- function(x, name) {
7482
} else {
7583
# If not found here, recurse into super environments
7684
super <- .subset2(x, "super")
77-
if (is.ggproto(super))
78-
res <- fetch_ggproto(super, name)
85+
if (is.null(super)) {
86+
# no super class
87+
} else if (is.function(super)) {
88+
res <- fetch_ggproto(super(), name)
89+
} else {
90+
stop(
91+
class(x)[[1]], " was built with an incompatible version of ggproto.\n",
92+
"Please reinstall the package that provides this extension.",
93+
call. = FALSE
94+
)
95+
}
7996
}
8097

8198
res
@@ -140,8 +157,8 @@ as.list.ggproto <- function(x, inherit = TRUE, ...) {
140157
res <- list()
141158

142159
if (inherit) {
143-
if (!is.null(x$super)) {
144-
res <- as.list(x$super)
160+
if (is.function(x$super)) {
161+
res <- as.list(x$super())
145162
}
146163
}
147164

@@ -200,11 +217,11 @@ format.ggproto <- function(x, ..., flat = TRUE) {
200217
indent(object_summaries(objs, flat = flat), 4)
201218
)
202219

203-
if (flat && !is.null(x$super)) {
220+
if (flat && is.function(x$super)) {
204221
str <- paste0(
205222
str, "\n",
206223
indent(
207-
paste0("super: ", " <ggproto object", classes_str(x$super), ">"),
224+
paste0("super: ", " <ggproto object", classes_str(x$super()), ">"),
208225
4
209226
)
210227
)

0 commit comments

Comments
 (0)