Skip to content

Commit

Permalink
In @exportS3method parse class name from function name
Browse files Browse the repository at this point in the history
Fixes #1085
  • Loading branch information
hadley committed Apr 8, 2022
1 parent 7018719 commit e149b1e
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 20 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# roxygen2 (development version)

* `@exportS3method pkg::generic` now works even when `pkg::generic` isn't
imported by your package (#1085).

* roxygen2 no longer generates invalid HTML (#1290).

* All warning messages have been reviewed to hopefully be more informative
Expand Down
34 changes: 29 additions & 5 deletions R/namespace.R
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,39 @@ roxy_tag_ns.roxy_tag_exportS3Method <- function(x, block, env, import_only = FAL
}

obj <- block$object
if (length(x$val) < 2 && !inherits(obj, "s3method")) {
warn_roxy_tag(x, "must be used with an S3 method when it has 0 or 1 values")
return()
}

if (identical(x$val, "")) {
if (!inherits(obj, "s3method")) {
warn_roxy_tag(x, "must be used with an known S3 method")
return()
}

method <- attr(obj$value, "s3method")
} else if (length(x$val) == 1) {
method <- c(x$val, attr(obj$value, "s3method")[[2]])
if (!inherits(obj, "function")) {
warn_roxy_tag(x, "must be used with a function")
return()
}

if (!str_detect(x$val, "::")) {
warn_roxy_tag(x, "must have form package::generic")
return()
}

generic <- str_split(x$val, "::")[[1]]
generic_re <- paste0("^", generic[[2]], "\\.")

if (!str_detect(obj$alias, generic_re)) {
warn_roxy_tag(x, c(
"doesn't match function name",
x = "Expected to see {.str {generic[[2]]}} to match {.str {x$val}}",
i = "Function name is {.str {obj$alias}}"
))
return()
}

class <- str_remove(obj$alias, generic_re)
method <- c(x$val, class)
} else {
method <- x$val
}
Expand Down
18 changes: 16 additions & 2 deletions tests/testthat/_snaps/namespace.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# @exportS3method generatedsS3method()
# @exportS3method generates fully automatically

[<text>:1] @exportS3Method must be used with an S3 method when it has 0 or 1 values
[<text>:2] @exportS3Method must be used with an known S3 method

# @exportS3method can extract class from generic

[<text>:2] @exportS3Method must have form package::generic

---

[<text>:2] @exportS3Method must be used with a function

---

[<text>:2] @exportS3Method doesn't match function name
x Expected to see "foo" to match "pkg::foo"
i Function name is "foo1.bar"

# poorly formed importFrom throws error

Expand Down
46 changes: 33 additions & 13 deletions tests/testthat/test-namespace.R
Original file line number Diff line number Diff line change
Expand Up @@ -75,33 +75,53 @@ test_that("export handles non-syntactic names", {
expect_equal(out, "S3method(\"foo-bar\",integer)")
})

test_that("@exportS3method generatedsS3method()", {
out <- roc_proc_text(namespace_roclet(),
"#' @exportS3Method
test_that("@exportS3method generates fully automatically", {
out <- roc_proc_text(namespace_roclet(),"
#' @exportS3Method
mean.foo <- function(x) 'foo'
")
expect_equal(out, "S3method(mean,foo)")

out <- roc_proc_text(namespace_roclet(),
"#' @exportS3Method base::mean
mean.foo <- function(x) 'foo'
")
expect_equal(out, "S3method(base::mean,foo)")

expect_snapshot_warning(
roc_proc_text(namespace_roclet(),
"#' @exportS3Method base::mean
NULL
roc_proc_text(namespace_roclet(), "
#' @exportS3Method
f <- function(x) 'foo'
")
)
})

test_that("@exportS3methd can create literal directive", {
out <- roc_proc_text(namespace_roclet(),
"#' @exportS3Method base::mean foo
NULL
")
expect_equal(out, "S3method(base::mean,foo)")
})


test_that("@exportS3method can extract class from generic", {
out <- roc_proc_text(namespace_roclet(), "
#' @exportS3Method pkg::foo
foo.bar <- function(x) 'foo'
")
expect_equal(out, "S3method(pkg::foo,bar)")

block <- "
#' @exportS3Method pkg_foo
foo.bar <- function(x) 'foo'
"
expect_snapshot_warning(roc_proc_text(namespace_roclet(), block))

block <- "
#' @exportS3Method pkg::foo
foo1.bar <- 10
"
expect_snapshot_warning(roc_proc_text(namespace_roclet(), block))

block <- "
#' @exportS3Method pkg::foo
foo1.bar <- function(x) 'foo'
"
expect_snapshot_warning(roc_proc_text(namespace_roclet(), block))
})

test_that("exportClass overrides default class name", {
Expand Down

0 comments on commit e149b1e

Please sign in to comment.