Skip to content

Commit 57040d2

Browse files
authoredJan 9, 2025··
Merge pull request #182 from ssi-dk/feature/use-documentation-templates
2 parents 4186a31 + ac87738 commit 57040d2

11 files changed

+126
-39
lines changed
 

‎R/0_documentation.R

+5-7
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ rd_activity_units <- function(type = "param") {
88

99
rd_stratification <- function(type = "param") {
1010
checkmate::assert_choice(type, c("param", "field"))
11-
paste("(`list`(`quosures`))\\cr",
12-
"Default NULL.",
11+
paste("(`list`(`quosures`) or `NULL`)\\cr",
1312
"Use `rlang::quos(...)` to specify stratification.",
1413
"If given, expressions in stratification evaluated to give the stratification level.",
1514
ifelse(type == "field", "Read only.", ""))
@@ -62,7 +61,6 @@ rd_prediction_length <- function(type = "param") {
6261
rd_quantiles <- function(type = "param") {
6362
checkmate::assert_choice(type, c("param", "field"))
6463
paste("(`list`(`numeric`))\\cr",
65-
"Default NULL.",
6664
"If given, results are returned at the quantiles given.",
6765
ifelse(type == "field", "Read only.", ""))
6866
}
@@ -106,7 +104,7 @@ rd_target_conn <- function(type = "param") {
106104
rd_schema <- function(type = "param") {
107105
checkmate::assert_choice(type, c("param", "field"))
108106
paste("(`character`)\\cr",
109-
"A database schema",
107+
"A database schema.",
110108
ifelse(type == "field", "Read only.", ""),
111109
"If the database backend does not support schema, the tables will be prefixed with <schema>.")
112110
}
@@ -178,15 +176,15 @@ rd_get_results_return <- paste(
178176
rd_get_results_seealso <- "[diseasy::DiseasyObservables]"
179177

180178

181-
rd_side_effects <- "NULL (called for side effects)"
179+
rd_side_effects <- "`NULL` (called for side effects)"
182180

183181

184182
rd_age_cuts_lower <- paste(
185183
"(`numeric`)\\cr",
186-
"vector of ages defining the lower bound for each age group. If NULL (default), age groups of contact_basis is used."
184+
"vector of ages defining the lower bound for each age group. If `NULL`, age groups of contact_basis is used."
187185
)
188186

189187
rd_activity_weights <- paste(
190188
"(`numeric(4)`)\\cr",
191-
"vector of weights for the four types of contacts. If NULL (default), no weighting is done."
189+
"vector of weights for the four types of contacts. If `NULL`, no weighting is done."
192190
)

‎R/0_linters.R

+85-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ diseasy_code_linters <- function() {
1212
"nolint_position_linter" = nolint_position_linter(120),
1313
"nolint_line_length_linter" = nolint_line_length_linter(120),
1414
"non_ascii_linter" = non_ascii_linter(),
15-
"param_and_field_linter" = param_and_field_linter()
15+
"param_and_field_linter" = param_and_field_linter(),
16+
"documentation_template_linter" = documentation_template_linter()
1617
)
1718

1819
return(linters)
@@ -211,7 +212,7 @@ non_ascii_linter <- function() {
211212
#'
212213
#' # okay
213214
#' lintr::lint(
214-
#' text = "#' @param (`numeric()`)\cr",
215+
#' text = "#' @param test (`numeric()`)\cr",
215216
#' linters = param_and_field_linter()
216217
#' )
217218
#' @importFrom rlang .data
@@ -290,3 +291,85 @@ param_and_field_linter <- function() {
290291
}
291292
)
292293
}
294+
295+
296+
#' @rdname diseasy_linters
297+
#' @description
298+
#' documentation_template_linter: Ensure documentation templates are used if available.
299+
#'
300+
#' @examples
301+
#' ## documentation_template_linter
302+
#' rd_parameter <- "(`character`)\cr Description of parameter" # Create a template for the "parameter" parameter
303+
#'
304+
#' # will produce lints
305+
#' lintr::lint(
306+
#' text = "#' @param parameter (`character`)\cr Description of parameter", # nolint: documentation_template_linter
307+
#' linters = documentation_template_linter()
308+
#' )
309+
#'
310+
#' # okay
311+
#' lintr::lint(
312+
#' text = "#' @param parameter `r rd_parameter`",
313+
#' linters = documentation_template_linter()
314+
#' )
315+
#'
316+
#' @importFrom rlang .data
317+
#' @noRd
318+
documentation_template_linter <- function() {
319+
general_msg <- paste("Documentation templates should used if available!")
320+
321+
lintr::Linter(
322+
function(source_expression) {
323+
324+
# Only go over complete file
325+
if (!lintr::is_lint_level(source_expression, "file")) {
326+
return(list())
327+
}
328+
329+
# Find all @param and @field lines. All other lines become NA
330+
detection_info <- source_expression$file_lines |>
331+
stringr::str_extract(r"{#' ?@(param|field).*}")
332+
333+
# Convert to data.frame and determine line number
334+
detection_info <- data.frame(
335+
rd_line = detection_info,
336+
line_number = seq_along(detection_info)
337+
)
338+
339+
# Remove non param/field lines
340+
detection_info <- detection_info |>
341+
dplyr::filter(!is.na(.data$rd_line))
342+
343+
# Remove triple-dot-ellipsis params
344+
detection_info <- detection_info |>
345+
dplyr::filter(!stringr::str_detect(.data$rd_line, "@param +\\.{3}"))
346+
347+
# Remove auto-generated documentation
348+
detection_info <- detection_info |>
349+
dplyr::filter(!stringr::str_detect(.data$rd_line, r"{@(param|field) +[\.\w]+ +`r }"))
350+
351+
# Extract the parameter
352+
detection_info <- detection_info |>
353+
dplyr::mutate("param" = stringr::str_extract(.data$rd_line, r"{(@(param|field) +)([\.\w]+)}", group = 3))
354+
355+
# Detect if template exists
356+
detection_info <- detection_info |>
357+
dplyr::mutate("rd_template" = paste0("rd_", .data$param)) |>
358+
dplyr::filter(.data$rd_template %in% names(as.list(base::getNamespace(devtools::as.package(".")$package)))) |>
359+
dplyr::select(!"param")
360+
361+
purrr::pmap(
362+
detection_info,
363+
\(rd_line, line_number, rd_template) {
364+
lintr::Lint(
365+
filename = source_expression$filename,
366+
line_number = line_number,
367+
type = "style",
368+
message = paste(general_msg, "Template", rd_template, "available."),
369+
line = source_expression$file_lines[line_number]
370+
)
371+
}
372+
)
373+
}
374+
)
375+
}

‎R/DiseasystoreBase.R

+4-9
Original file line numberDiff line numberDiff line change
@@ -273,15 +273,10 @@ DiseasystoreBase <- R6::R6Class(
273273
},
274274

275275
#' @description
276-
#' Joins various features from feature store assuming a primary feature (observable)
277-
#' that contains keys to witch the secondary features (defined by `stratification`) can be joined.
278-
#' @param observable (`character`)\cr
279-
#' The name of a feature defined in the feature store
280-
#' @param stratification (`list`(`quosures`) or `NULL`)\cr
281-
#' Expressions in `stratification` are evaluated to find appropriate features.
282-
#' These are then joined to the observable feature before `stratification` is performed.
283-
#'
284-
#' If `NULL` (default) no stratification is performed.
276+
#' Joins various features from the feature store assuming a primary feature (observable)
277+
#' that contains keys to witch the secondary features (defined by `stratification`) are joined.
278+
#' @param observable `r rd_observable()`
279+
#' @param stratification `r rd_stratification()`
285280
#' @param start_date `r rd_start_date()`
286281
#' @param end_date `r rd_end_date()`
287282
#' @return

‎R/drop_diseasystore.R

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
#' @importFrom rlang .data
33
#' @param pattern (`character(1)`)\cr
44
#' Pattern to match the tables by
5-
#' @param schema (`character(1)`)\cr
6-
#' Schema the diseasystore uses to store data in
5+
#' @param schema `r rd_schema()`
6+
#' The location where the `diseasystore` stores data.
77
#' @param conn `r rd_conn()`
88
#' @return `r rd_side_effects`
99
#' @examplesIf requireNamespace("RSQLite", quietly = TRUE)

‎R/source_conn_helpers.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#' * source_conn_path: static url / directory.
66
#' This helper determines whether source_conn is a file path or URL and creates the full path to the
77
#' the file as needed based on the type of source_conn.
8-
#' @param source_conn (`character(1)`)\cr
8+
#' @param source_conn (`character(1)`)\cr # nolint: documentation_template_linter
99
#' File location (path or URL).
1010
#' @param file (`character(1)`)\cr
1111
#' Name (including path) of the file at the location.

‎R/test_diseasystore.R

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
#' Should take a `skip_backend` that does not open connections for the given backends.
1616
#' @param data_files (`character()`)\cr
1717
#' List of files that should be available when testing.
18-
#' @param target_schema (`character(1)`)\cr
19-
#' The data base schema where the tests should be run.
18+
#' @param target_schema `r rd_target_schema()`
2019
#' @param test_start_date (`Date`)\cr
2120
#' The earliest date to retrieve data from during tests.
2221
#' @param skip_backends (`character()`)\cr

‎man/DiseasystoreBase.Rd

+4-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/drop_diseasystore.Rd

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/source_conn_helpers.Rd

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/test_diseasystore.Rd

+2-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎tests/testthat/test-0_linters.R

+18
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,21 @@ test_that("param_and_field_linter works", {
5656
lintr::expect_lint("#' @param test (`type`)\\cr", NULL, param_and_field_linter())
5757
lintr::expect_lint("#' @field test (`type`)\\cr", NULL, param_and_field_linter())
5858
})
59+
60+
61+
test_that("documentation_template_linter works", {
62+
skip_if_not_installed("lintr")
63+
skip_if_not_installed("devtools")
64+
65+
lintr::expect_lint(
66+
"#' @param observable (`character(1)`)\\cr", # rd_observable defined in R/0_documentation.R # nolint: documentation_template_linter
67+
list("line_number" = 1, "type" = "style"),
68+
documentation_template_linter()
69+
)
70+
71+
lintr::expect_lint(
72+
"#' @param observable `r rd_test`",
73+
NULL,
74+
documentation_template_linter()
75+
)
76+
})

0 commit comments

Comments
 (0)
Please sign in to comment.