diff --git a/NAMESPACE b/NAMESPACE index 561a63bc..90b86d4e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -69,6 +69,7 @@ S3method(merge,rd_section_inherit_section) S3method(merge,rd_section_minidesc) S3method(merge,rd_section_param) S3method(merge,rd_section_prop) +S3method(merge,rd_section_r6_class) S3method(merge,rd_section_reexport) S3method(merge,rd_section_section) S3method(merge,rd_section_seealso) diff --git a/NEWS.md b/NEWS.md index 01257b6a..70a4d99b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -74,7 +74,7 @@ See `vignette("rd-S7")` for best practices. ## Individual tags -* Tags that expect single-line input now warn when they span multiple lines, catching a common class of mistake. Affected tags: `@aliases`, `@concept`, `@encoding`, `@exportClass`, `@exportMethod`, `@exportPattern`, `@exportS3Method`, `@importFrom`, `@importClassesFrom`, `@importMethodsFrom`, `@include`, `@keywords`, `@method`, `@name`, `@order`, `@rdname`, `@S3method`, `@template`, and `@useDynLib` (#1642, #1688). This may break some existing usage, but it prevents a wide range of otherwise silent errors. +* Tags that expect single-line input now warn when they span multiple lines, catching a common class of mistake. Affected tags: `@aliases`, `@concept`, `@encoding`, `@exportClass`, `@exportMethod`, `@exportPattern`, `@exportS3Method`, `@importFrom`, `@importClassesFrom`, `@importMethodsFrom`, `@include`, `@includeRmd`, `@inheritDotParams`, `@inheritParams`, `@inheritSection`, `@keywords`, `@method`, `@name`, `@order`, `@rdname`, `@S3method`, `@template`, and `@useDynLib` (#1642, #1688). This may break some existing usage, but it prevents a wide range of otherwise silent errors. * Reexported functions now display with `()` appended (e.g. `fun()` instead of `fun`) on the reexports page, except for infix operators like `%>%` (#1222). They also use the modern (>= 4.1.0) linking style. * `@description` no longer errors when the markdown text starts with a heading (#1705). * `@examples` no longer warns about unmatched braces inside raw strings, or inside strings within R comments, e.g. `# '{greeting}'` (#1492). diff --git a/R/rd-describe-in.R b/R/rd-describe-in.R index 3d6b480e..72c5a664 100644 --- a/R/rd-describe-in.R +++ b/R/rd-describe-in.R @@ -10,7 +10,7 @@ roxy_tag_parse.roxy_tag_describeIn <- function(x) { ) NULL } else { - tag_two_part(x, "a topic name", "a description") + tag_two_part(x, "a topic name", "a description", multiline = TRUE) } } diff --git a/R/rd-params.R b/R/rd-params.R index b06277f1..4edb6777 100644 --- a/R/rd-params.R +++ b/R/rd-params.R @@ -1,6 +1,6 @@ #' @export roxy_tag_parse.roxy_tag_param <- function(x) { - tag_two_part(x, "an argument name", "a description") + tag_two_part(x, "an argument name", "a description", multiline = TRUE) } #' @export diff --git a/R/rd-s4.R b/R/rd-s4.R index faeb3333..e22c3d2f 100644 --- a/R/rd-s4.R +++ b/R/rd-s4.R @@ -1,6 +1,6 @@ #' @export roxy_tag_parse.roxy_tag_field <- function(x) { - tag_two_part(x, "a field name", "a description") + tag_two_part(x, "a field name", "a description", multiline = TRUE) } #' @export roxy_tag_rd.roxy_tag_field <- function(x, base_path, env) { @@ -14,7 +14,7 @@ format.rd_section_field <- function(x, ...) { #' @export roxy_tag_parse.roxy_tag_slot <- function(x) { - tag_two_part(x, "a slot name", "a description") + tag_two_part(x, "a slot name", "a description", multiline = TRUE) } #' @export roxy_tag_rd.roxy_tag_slot <- function(x, base_path, env) { diff --git a/R/rd-s7.R b/R/rd-s7.R index a092c397..d9d8864e 100644 --- a/R/rd-s7.R +++ b/R/rd-s7.R @@ -1,6 +1,6 @@ #' @export roxy_tag_parse.roxy_tag_prop <- function(x) { - x <- tag_two_part(x, "a property name", "a description") + x <- tag_two_part(x, "a property name", "a description", multiline = TRUE) if (is.null(x)) { return() } diff --git a/R/rd-template.R b/R/rd-template.R index 1fbf1fc3..9bca3cfe 100644 --- a/R/rd-template.R +++ b/R/rd-template.R @@ -5,7 +5,7 @@ roxy_tag_parse.roxy_tag_template <- function(x) { #' @export roxy_tag_parse.roxy_tag_templateVar <- function(x) { - tag_two_part(x, "a variable name", "a value") + tag_two_part(x, "a variable name", "a value", multiline = TRUE) } process_templates <- function(block, base_path) { diff --git a/R/tag-parser.R b/R/tag-parser.R index 60bf3fbc..0ee91f71 100644 --- a/R/tag-parser.R +++ b/R/tag-parser.R @@ -119,7 +119,14 @@ tag_name <- function(x) { #' @param required Is the second part required (TRUE) or can it be blank #' (FALSE)? #' @param markdown Should the second part be parsed as markdown? -tag_two_part <- function(x, first, second, required = TRUE, markdown = TRUE) { +tag_two_part <- function( + x, + first, + second, + required = TRUE, + markdown = TRUE, + multiline = FALSE +) { if (trimws(x$raw) == "") { if (!required) { warn_roxy_tag(x, "requires {first}") @@ -127,6 +134,8 @@ tag_two_part <- function(x, first, second, required = TRUE, markdown = TRUE) { warn_roxy_tag(x, "requires two parts: {first} and {second}") } NULL + } else if (!multiline && warn_if_multiline(x, trimws(x$raw))) { + NULL } else if (!rdComplete(x$raw, is_code = FALSE)) { warn_roxy_tag(x, "has mismatched braces or quotes") NULL diff --git a/man/tag_parsers.Rd b/man/tag_parsers.Rd index cf534ede..820a25be 100644 --- a/man/tag_parsers.Rd +++ b/man/tag_parsers.Rd @@ -22,7 +22,14 @@ tag_inherit(x) tag_name(x) -tag_two_part(x, first, second, required = TRUE, markdown = TRUE) +tag_two_part( + x, + first, + second, + required = TRUE, + markdown = TRUE, + multiline = FALSE +) tag_name_description(x) diff --git a/tests/testthat/_snaps/tag-parser.md b/tests/testthat/_snaps/tag-parser.md index 4f89e298..b5d52f68 100644 --- a/tests/testthat/_snaps/tag-parser.md +++ b/tests/testthat/_snaps/tag-parser.md @@ -182,6 +182,17 @@ x test.R:1: @test must be only 1 line long, not 3. i The first line is "a" +# tag_two_part() warns on multi-line content by default + + Code + tag <- roxy_test_tag("foo bar\nbaz") + expect_parse_failure(tag_two_part(tag, "a name", "a value")) + Output + + Message: + x test.R:1: @test must be only 1 line long, not 2. + i The first line is "foo bar" + # tag_value() warns on multi-line content Code diff --git a/tests/testthat/test-tag-parser.R b/tests/testthat/test-tag-parser.R index fcb4d5ad..4c06ffcc 100644 --- a/tests/testthat/test-tag-parser.R +++ b/tests/testthat/test-tag-parser.R @@ -87,6 +87,17 @@ test_that("tag_words() warns on multi-line content", { }) }) +test_that("tag_two_part() warns on multi-line content by default", { + expect_snapshot({ + tag <- roxy_test_tag("foo bar\nbaz") + expect_parse_failure(tag_two_part(tag, "a name", "a value")) + }) + + tag <- roxy_test_tag("foo bar\nbaz") + out <- tag_two_part(tag, "a name", "a value", multiline = TRUE) + expect_equal(out$val, list(name = "foo", description = "bar\nbaz")) +}) + test_that("tag_value() warns on multi-line content", { expect_snapshot({ tag <- roxy_test_tag("a\nb")