Skip to content
Open
Show file tree
Hide file tree
Changes from all 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