Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export(build_vignettes)
export(check)
export(check_built)
export(check_dep_version)
export(check_doc_fields)
export(check_mac_devel)
export(check_mac_release)
export(check_man)
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# devtools (development version)

* `build_manual()` reports more details on failure (#2586).
* New `check_doc_fields()` checks for missing `\value` and `\examples` fields in Rd files, which are commonly flagged by CRAN (#2525).
* New `check_mac_devel()` function to check a package using the macOS builder at https://mac.r-project.org/macbuilder/submit.html (@nfrerebeau, #2507)
* `is_loading()` is now re-exported from pkgload (#2556).
* `load_all()` now errors if called recursively, i.e. if you accidentally include a `load_all()` call in one of your R source files (#2617).
Expand Down
45 changes: 45 additions & 0 deletions R/check-doc.R
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,48 @@ man_message <- function(x) {
FALSE
}
}

#' Check for missing documentation fields
#'
#' Checks all Rd files in `man/` for missing `\value` and `\examples` sections.
#' These are flagged by CRAN on initial submission.
#'
#' @template devtools
#' @param fields A character vector of Rd field names to check for.
#' @return A named list of character vectors, one for each field, containing
#' the names of Rd files missing that field. Returned invisibly.
#' @export
#' @examples
#' \dontrun{
#' check_doc_fields(".")
#' }
check_doc_fields <- function(pkg = ".", fields = c("value", "examples")) {
pkg <- as.package(pkg)

paths <- dir(path(pkg$path, "man"), pattern = "\\.Rd$", full.names = TRUE)
rd <- lapply(paths, tools::parse_Rd, permissive = TRUE)

has_tag <- function(x, tag) {
tags <- unlist(lapply(x, attr, "Rd_tag"))
any(tags %in% paste0("\\", tag))
}

results <- lapply(stats::setNames(fields, fields), function(field) {
missing <- !vapply(rd, has_tag, logical(1), tag = field)
path_rel(paths[missing], pkg$path)
})

for (field in fields) {
missing <- results[[field]]
if (length(missing) > 0) {
cli::cli_inform(c(
"!" = "Missing {.code \\{field}} section in {length(missing)} file{?s}:",
stats::setNames(missing, rep("*", length(missing)))
))
} else {
cli::cli_inform(c("v" = "All Rd files have {.code \\{field}} sections."))
}
}

invisible(results)
}
27 changes: 27 additions & 0 deletions man/check_doc_fields.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions tests/testthat/_snaps/check-doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# check_doc_fields output - missing fields

Code
check_doc_fields(pkg)
Message
! Missing `\value` section in 1 file:
* man/foo.Rd
! Missing `\examples` section in 1 file:
* man/bar.Rd

# check_doc_fields output - all present

Code
check_doc_fields(pkg)
Message
v All Rd files have `\value` sections.
v All Rd files have `\examples` sections.

28 changes: 28 additions & 0 deletions tests/testthat/test-check-doc.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
test_that("check_doc_fields output - missing fields", {
pkg <- local_package_create()
dir.create(file.path(pkg, "man"))

writeLines(
"\\name{foo}\\title{Foo}\\description{A function.}\\examples{foo()}",
file.path(pkg, "man", "foo.Rd")
)
writeLines(
"\\name{bar}\\title{Bar}\\description{A function.}\\value{Something.}",
file.path(pkg, "man", "bar.Rd")
)

expect_snapshot(check_doc_fields(pkg))
})

test_that("check_doc_fields output - all present", {
pkg <- local_package_create()
dir.create(file.path(pkg, "man"))

writeLines(
"\\name{foo}\\title{Foo}\\description{A function.}\\value{A value.}\\examples{foo()}",
file.path(pkg, "man", "foo.Rd")
)

expect_snapshot(check_doc_fields(pkg))
})

test_that("check_man works", {
# tools:::.check_Rd_xrefs which is called by `check_man()` assumes the base
# and recommended packages will all be in the library path, which is not the
Expand Down