|
| 1 | +#!/usr/bin/Rscript |
| 2 | +# Runner for the manual lint checks in .ci/linters |
| 3 | +args = commandArgs(TRUE) |
| 4 | +if (identical(args, '--help')) { |
| 5 | + writeLines(c( |
| 6 | + 'Usage: Rscript .ci/lint.R .ci/linters/<KIND> <WHERE> <WHAT> [PREPROCESS]', |
| 7 | + 'KIND must name the directory containing the *.R files defining the linter functions.', |
| 8 | + 'WHERE must name the directory containing the files to lint, e.g. "po", or "src".', |
| 9 | + "WHAT must contain the regular expression matching the files to lint, e.g., '[.]po$', or '[.][ch]$'.", |
| 10 | + 'PREPROCESS is an optional R function that accepts a file path and returns an R object accepted by the lint functions, or NULL to skip the file.' |
| 11 | + )) |
| 12 | + q('no') |
| 13 | +} |
| 14 | +stopifnot(`Invalid arguments, see .ci/lint.R --help` = length(args) %in% 3:4) |
| 15 | + |
| 16 | +linter_env = new.env() |
| 17 | +for (f in list.files(args[[1]], full.names=TRUE)) sys.source(f, linter_env) |
| 18 | +if (!length(ls(linter_env))) stop( |
| 19 | + "No linters found after sourcing files in ", dQuote(args[[1]]) |
| 20 | +) |
| 21 | + |
| 22 | +sources = list.files(args[[2]], pattern = args[[3]], full.names = TRUE, recursive = TRUE) |
| 23 | +if (!length(sources)) stop( |
| 24 | + "No files to lint found in directory ", dQuote(args[[2]]), " for mask ", dQuote(args[[3]]) |
| 25 | +) |
| 26 | +preprocess = if (length(args) == 4) eval(parse(text = args[[4]])) else identity |
| 27 | +sources = Filter(Negate(is.null), lapply(setNames(nm = sources), preprocess)) |
| 28 | + |
| 29 | +okay = TRUE |
| 30 | +for (src in names(sources)) |
| 31 | +for (linter in ls(linter_env)) tryCatch( |
| 32 | + linter_env[[linter]](sources[[src]]), |
| 33 | + error = function(e) { |
| 34 | + message('Source file ', dQuote(src), ' failed lint check ', dQuote(linter), ': ', conditionMessage(e)) |
| 35 | + okay <<- FALSE |
| 36 | + } |
| 37 | +) |
| 38 | +stopifnot(`Please fix the issues above.` = okay) |
0 commit comments