7
7
# ' @seealso [linters] for a complete list of linters available in lintr.
8
8
# ' @export
9
9
backport_linter <- function (r_version = getRversion()) {
10
+ r_version <- normalize_r_version(r_version )
11
+
10
12
Linter(function (source_file ) {
11
- if (inherits(r_version , " numeric_version" )) r_version <- format(r_version )
12
- if (r_version < " 3.0.0" ) {
13
- warning(" It is not recommended to depend on an R version older than 3.0.0. Resetting 'r_version' to 3.0.0." )
14
- r_version <- " 3.0.0"
15
- }
16
13
if (is.null(source_file $ xml_parsed_content )) return (list ())
14
+ if (all(r_version > = R_system_version(names(backports )))) return (list ())
17
15
18
16
xml <- source_file $ xml_parsed_content
19
17
20
18
names_xpath <- " //*[self::SYMBOL or self::SYMBOL_FUNCTION_CALL]"
21
19
all_names_nodes <- xml2 :: xml_find_all(xml , names_xpath )
22
20
all_names <- xml2 :: xml_text(all_names_nodes )
23
21
24
- # guaranteed to include 1 by early return above; which.min fails if all TRUE (handled by nomatch)
25
- needs_backport_names <- backports [1 : (match(FALSE , r_version < names(backports ), nomatch = length(backports )) - 1L )]
22
+ backport_blacklist <- backports [r_version < R_system_version(names(backports ))]
26
23
27
24
# not sapply/vapply, which may over-simplify to vector -- cbind makes sure we have a matrix so rowSums works
28
- needs_backport <- do.call(cbind , lapply(needs_backport_names , function (nm ) all_names %in% nm ))
25
+ needs_backport <- do.call(cbind , lapply(backport_blacklist , function (nm ) all_names %in% nm ))
29
26
bad_idx <- rowSums(needs_backport ) > 0L
30
27
31
28
lapply(which(bad_idx ), function (ii ) {
@@ -42,7 +39,7 @@ backport_linter <- function(r_version = getRversion()) {
42
39
type = " warning" ,
43
40
message = sprintf(
44
41
" %s (R %s) is not available for dependency R >= %s." ,
45
- all_names [ii ], names(needs_backport_names )[which(needs_backport [ii , ])], r_version
42
+ all_names [ii ], names(backport_blacklist )[which(needs_backport [ii , ])], r_version
46
43
),
47
44
line = source_file $ lines [[line1 ]],
48
45
ranges = list (c(col1 , col2 ))
@@ -51,8 +48,45 @@ backport_linter <- function(r_version = getRversion()) {
51
48
})
52
49
}
53
50
51
+ normalize_r_version <- function (r_version ) {
52
+ if (is.character(r_version ) &&
53
+ re_matches(r_version , rex(start , " release" %or %
54
+ list (" oldrel" , maybe(" -" , digits )) %or %
55
+ " devel" , end ))) {
56
+ # Support devel, release, oldrel, oldrel-1, ...
57
+
58
+ all_versions <- names(backports )
59
+ minor_versions <- unique(re_substitutes(all_versions , rex(" ." , digits , end ), " " ))
60
+ version_names <- c(" devel" , " release" , " oldrel" , paste0(" oldrel-" , seq_len(length(minor_versions ) - 3L )))
61
+ if (! r_version %in% version_names ) {
62
+ # This can only trip if e.g. oldrel-99 is requested
63
+ stop(" `r_version` must be a version number or one of " , toString(sQuote(version_names )))
64
+ }
65
+ requested_version <- minor_versions [match(r_version , table = version_names )]
66
+ available_patches <- all_versions [startsWith(all_versions , requested_version )]
67
+ selected_patch <- which.max(as.integer(
68
+ substr(available_patches , start = nchar(requested_version ) + 2L , stop = nchar(available_patches ))
69
+ ))
70
+
71
+ r_version <- R_system_version(available_patches [selected_patch ])
72
+ } else if (is.character(r_version )) {
73
+ r_version <- R_system_version(r_version , strict = TRUE )
74
+ } else if (! inherits(r_version , " R_system_version" )) {
75
+ stop(" `r_version` must be a R version number, returned by R_system_version(), or a string." )
76
+ }
77
+ if (r_version < " 3.0.0" ) {
78
+ warning(" It is not recommended to depend on an R version older than 3.0.0. Resetting 'r_version' to 3.0.0." )
79
+ r_version <- R_system_version(" 3.0.0" )
80
+ }
81
+ r_version
82
+ }
83
+
84
+ # Sources:
85
+ # devel NEWS https://cran.rstudio.com/doc/manuals/r-devel/NEWS.html
86
+ # release NEWS https://cran.r-project.org/doc/manuals/r-release/NEWS.html
54
87
backports <- list (
55
- `devel` = c(" ...names" , " checkRdContents" , " numToBits" , " numToInts" , " packBits" ),
88
+ `4.2.0` = c(" .pretty" , " .LC.categories" , " Sys.setLanguage()" ), # R devel needs to be ahead of all other versions
89
+ `4.1.0` = c(" numToBits" , " numToInts" , " gregexec" , " charClass" , " checkRdContents" , " ...names" ),
56
90
`4.0.0` = c(
57
91
" .class2" , " .S3method" , " activeBindingFunction" , " deparse1" , " globalCallingHandlers" ,
58
92
" infoRDS" , " list2DF" , " marginSums" , " proportions" , " R_user_dir" , " socketTimeout" , " tryInvokeRestart"
0 commit comments