Skip to content

Commit bcfb346

Browse files
Merge pull request #563 from owenjonesuob/hook-parsable-roxygen
Add parsable-roxygen hook
2 parents 71142e4 + a899df6 commit bcfb346

File tree

10 files changed

+166
-1
lines changed

10 files changed

+166
-1
lines changed

.pre-commit-hooks.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
language: r
5050
files: '\.[rR](md)?$'
5151
minimum_pre_commit_version: "2.13.0"
52+
- id: parsable-roxygen
53+
name: parsable-roxygen
54+
description: check if roxygen comments in a .R file are parsable
55+
entry: Rscript inst/hooks/exported/parsable-roxygen.R
56+
language: r
57+
files: '\.[rR]$'
58+
minimum_pre_commit_version: "2.13.0"
5259
- id: readme-rmd-rendered
5360
name: readme-rmd-rendered
5461
description: make sure README.Rmd hasn't been edited more recently than `README.md`

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Roxygen: list(markdown = TRUE, roclets = c( "rd", "namespace", "collate",
4747
if (rlang::is_installed("pkgapi")) "pkgapi::api_roclet" else {
4848
warning("Please install r-lib/pkgapi to make sure the file API is kept
4949
up to date"); NULL} ) )
50-
RoxygenNote: 7.3.1
50+
RoxygenNote: 7.3.2
5151
SystemRequirements: git
5252
Config/testthat/parallel: true
5353
Config/testthat/edition: 3
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env Rscript
2+
3+
"Check whether roxygen comments within files are valid
4+
Usage:
5+
parsable-roxygen [--eval] <files>...
6+
7+
Options:
8+
--eval Evaluate file contents after parsing - this is required if `@eval` tags must be evaluated
9+
10+
" -> doc
11+
12+
arguments <- precommit::precommit_docopt(doc)
13+
14+
if (packageVersion("roxygen2") < package_version("7.3.0")) {
15+
rlang::abort("You need at least version 7.3.0 of {roxygen2} to run this hook.")
16+
}
17+
18+
out <- lapply(arguments$files, function(path) {
19+
tryCatch(
20+
# Capture any messages from roxygen2:::warn_roxy()
21+
msg <- capture.output(
22+
roxygen2::parse_file(
23+
path,
24+
env = if (isTRUE(arguments$eval)) {
25+
roxygen2::env_file(path)
26+
} else {
27+
NULL
28+
}
29+
),
30+
type = "message"
31+
),
32+
33+
# In case we encounter a more general file parsing problem
34+
error = function(e) {
35+
cat(c("File ", path, " is not parsable. Full context:\n"))
36+
stop(conditionMessage(e), call. = FALSE)
37+
}
38+
)
39+
40+
if (length(msg) > 0) {
41+
cat(c("Roxygen commentary in file ", path, " is not parsable. Full context:\n"))
42+
stop(paste0(msg, collapse = "\n"), call. = FALSE)
43+
}
44+
})

inst/pre-commit-hooks.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
language: r
5050
files: '\.[rR](md)?$'
5151
minimum_pre_commit_version: "2.13.0"
52+
- id: parsable-roxygen
53+
name: parsable-roxygen
54+
description: check if roxygen comments in a .R file are parsable
55+
entry: Rscript inst/hooks/exported/parsable-roxygen.R
56+
language: r
57+
files: '\.[rR]$'
58+
minimum_pre_commit_version: "2.13.0"
5259
- id: readme-rmd-rendered
5360
name: readme-rmd-rendered
5461
description: make sure README.Rmd hasn't been edited more recently than `README.md`
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#' Some function
2+
#'
3+
#' This function is great! But \code{oh dear, a missing brace...
4+
#'
5+
#' And isn't that a multi-line example? We should probably use @examples...
6+
#'
7+
#' @param x A parameter.
8+
#'
9+
#' @returns Invisible `NULL`.
10+
#'
11+
#' @example
12+
#' some_function(10)
13+
#' some_function(11)
14+
#'
15+
#' @export
16+
some_function <- function(x) {
17+
x
18+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#' Minimal roxygen docs, but there's a problem with our R code!
2+
#'
3+
#' @export
4+
some_function <- function(x) {
5+
(x
6+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#' Some function
2+
#'
3+
#' This function is great!
4+
#'
5+
#' @param x A parameter.
6+
#'
7+
#' @returns Invisible `NULL`.
8+
#'
9+
#' @examples
10+
#' some_function(10)
11+
#'
12+
#' @export
13+
some_function <- function(x) {
14+
x
15+
}
16+
17+
# To check whether code was evaluated
18+
print("A random print statement")

tests/testthat/reference-objects/pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ repos:
5959
)$
6060
- id: readme-rmd-rendered
6161
- id: parsable-R
62+
- id: parsable-roxygen
6263
- id: no-browser-statement
6364
- id: no-print-statement
6465
- id: no-debug-statement
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# success - code not evaluated
2+
run_test(
3+
"parsable-roxygen",
4+
suffix = "-success.R",
5+
std_out = NULL,
6+
std_err = NULL,
7+
read_only = TRUE
8+
)
9+
10+
# success - code evaluated
11+
run_test(
12+
"parsable-roxygen",
13+
suffix = "-success.R",
14+
cmd_args = "--eval",
15+
std_out = "A random print statement",
16+
std_err = NULL,
17+
read_only = TRUE
18+
)
19+
20+
# failure - roxygen problem
21+
run_test(
22+
"parsable-roxygen",
23+
suffix = "-fail.R",
24+
std_out = "Roxygen commentary",
25+
std_err = "@description has mismatched braces or quotes",
26+
read_only = TRUE
27+
)
28+
29+
# failure - R problem
30+
run_test(
31+
"parsable-roxygen",
32+
suffix = "-fail2.R",
33+
std_out = "File ",
34+
std_err = "unexpected '}'",
35+
read_only = TRUE
36+
)

vignettes/available-hooks.Rmd

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,34 @@ returns an error.
139139

140140
This hook does not modify files.
141141

142+
## `parsable-roxygen`
143+
144+
Checks if roxygen comments within your `.R` files are "valid" by checking if
145+
running `roxygen2::parse_file()` on them returns any messages.
146+
147+
This hook does not modify files.
148+
149+
**eval**
150+
151+
By default, each file will be parsed, but code will not be evaluated - neither
152+
any explicit code in the file, nor any `@eval` tags within roxygen comments.
153+
154+
If your commentary contains `@eval` tags which you would prefer to evaluate, you
155+
can specify the `--eval` flag, which will cause the file's code to be evaluated
156+
in an environment created by `roxygen2::env_file()`. Note that dependencies of
157+
the code to evaluate must be available for pre-commit. You may list these as
158+
`additional_dependencies:` for the `parsable-roxygen` hook in
159+
`.pre-commit-config.yaml`.
160+
161+
Inline R code within roxygen comments (i.e. within backticks) is **not**
162+
evaluated by this hook, whether or not `--eval` is specified. You would need
163+
to run the `roxygenize` hook for that.
164+
165+
id: parsable-roxygen
166+
args: [--eval]
167+
168+
This hook was added in version 0.4.3.9000.
169+
142170
## `no-browser-statement`
143171

144172
Guarantees you that you don't accidentally commit code with a

0 commit comments

Comments
 (0)