diff --git a/.lintr b/.lintr index fbe54d2ce..8420e7ba5 100644 --- a/.lintr +++ b/.lintr @@ -1,5 +1,5 @@ linters: all_linters( - backport_linter("3.6.0", except = c("R_user_dir", "deparse1", "...names")), + backport_linter("auto", except = c("R_user_dir", "deparse1", "...names")), line_length_linter(120L), object_overwrite_linter(allow_names = c("line", "lines", "pipe", "symbols")), todo_comment_linter( diff --git a/R/backport_linter.R b/R/backport_linter.R index a285c7e39..e35f7f055 100644 --- a/R/backport_linter.R +++ b/R/backport_linter.R @@ -5,6 +5,8 @@ #' @param r_version Minimum R version to test for compatibility. Defaults to #' the R version currently in use. The version can be specified as a version #' number, or as a version alias (such as `"devel"`, `"oldrel"`, `"oldrel-1"`). +#' It can also be `"auto"` to use the minimum R version declared in the +#' `DESCRIPTION` file of R packages. #' @param except Character vector of functions to be excluded from linting. #' Use this to list explicitly defined backports, e.g. those imported from the `{backports}` package or manually #' defined in your package. @@ -120,6 +122,15 @@ normalize_r_version <- function(r_version) { )) r_version <- R_system_version(available_patches[selected_patch]) + } else if (identical(r_version, "auto")) { + r_version <- min_r_version() + if (is.na(r_version)) { + cli_warn(c( + x = "No DESCRIPTION file or no specified minimum R version could be found.", + i = "Setting {.arg r_version} to the currently running R version (R {getRversion()})." + )) + r_version <- getRversion() + } } else if (is.character(r_version)) { r_version <- R_system_version(r_version, strict = TRUE) } else if (!inherits(r_version, "R_system_version")) { diff --git a/R/settings_utils.R b/R/settings_utils.R index 166dd362a..f114ce415 100644 --- a/R/settings_utils.R +++ b/R/settings_utils.R @@ -112,3 +112,23 @@ pkg_name <- function(path = find_package()) { nm <- read.dcf(file.path(path, "DESCRIPTION"), fields = "Package")[1L] if (!is.na(nm)) nm } + +min_r_version <- function(path = find_package(".")) { + if (is.null(path)) { + return(NA_character_) + } + depends_field <- read.dcf(file.path(path, "DESCRIPTION"), fields = "Depends") + + depends <- trimws(strsplit(depends_field, ",", fixed = TRUE)[[1L]]) + + min_r_ver <- gsub("^R \\(>=?\\s(.+)\\)", "\\1", grep("R ", depends, value = TRUE, fixed = TRUE)) + + if (length(min_r_ver) == 0) { + return(NA_character_) + } + # According to 'Writing R Extensions', the trailing 0 for patch version can + # be dropped. + # But we want to identically match an existing version number so we add it if + # it's missing. + gsub("^(\\d+\\.\\d+)$", "\\1.0", min_r_ver) +} diff --git a/man/backport_linter.Rd b/man/backport_linter.Rd index 22c97ebbe..64bfd3ac9 100644 --- a/man/backport_linter.Rd +++ b/man/backport_linter.Rd @@ -9,7 +9,9 @@ backport_linter(r_version = getRversion(), except = character()) \arguments{ \item{r_version}{Minimum R version to test for compatibility. Defaults to the R version currently in use. The version can be specified as a version -number, or as a version alias (such as \code{"devel"}, \code{"oldrel"}, \code{"oldrel-1"}).} +number, or as a version alias (such as \code{"devel"}, \code{"oldrel"}, \code{"oldrel-1"}). +It can also be \code{"auto"} to use the minimum R version declared in the +\code{DESCRIPTION} file of R packages.} \item{except}{Character vector of functions to be excluded from linting. Use this to list explicitly defined backports, e.g. those imported from the \code{{backports}} package or manually