Walks the module's source via xmlparsedata, collects every reference to sim$x / sim[["x"]] / get("x", envir = envir(sim)) and to parameters (Par$x, P(sim)$x, params(sim)$mod$x), then compares those uses to the module's defineModule() metadata. Reports any mismatches as a structured tibble of findings, optionally printed as grouped tables.

codeCheckModule(path, print = TRUE, enable = NULL, disable = NULL)

codeCheckModules(
  paths = dir(getOption("spades.modulePath"), full.names = TRUE),
  print = TRUE,
  enable = NULL,
  disable = NULL
)

Arguments

path

Path to a module directory (containing <modName>/<modName>.R, and optionally an R/ subfolder of helper scripts) or to a single .R file. If a directory, the module name is the directory's basename.

print

Logical; print the grouped report. Default TRUE.

enable, disable

Optional character vectors of rule IDs to restrict the run. See names(SpaDES.core:::.CC_RULES) for the catalogue.

paths

A character vector of module directories (or .R files), as accepted by path. Defaults to dir(getOption("spades.modulePath"), full.names = TRUE).

Value

codeCheckModule() returns a data.frame of findings (one row per problem), invisibly; empty if the module is clean. codeCheckModules() returns, invisibly, a named list of such data.frames (named by module).

Details

This is the v2 implementation, selectable at simInit() time via options(spades.codeCheckEngine = "v2") (the default). The legacy v1 checker is still available via options(spades.codeCheckEngine = "v1").

Silencing findings

Each finding in the printed report is tagged with its rule id in brackets, e.g. [conflicting_fn_unqualified]; that id (or the • <group> name it is printed under) is what you reference to silence it. Findings can be suppressed three ways (all honoured both here and during simInit()):

  • Inline # nolint (module developer). Put a # nolint comment on the offending source line to silence every rule there, or # nolint: <rule_id>[, <rule_id>] to silence only specific rules (a group name such as globals is accepted in place of a rule id). For a metadata finding such as in_no_default, place it anywhere within the expectsInput() / createsOutput() / defineParameter() declaration, e.g. expectsInput("cloudFolderID", "character", desc = "...") # nolint: in_no_default. This travels with the module and documents the intent.

  • options(spades.codeChecksIgnore = ...) (module user). A named list keyed by rule id (or group name) whose values are object names to ignore, e.g. options(spades.codeChecksIgnore = list(in_no_default = c("cloudFolderID", "ecoregionRst"))). Lets someone running another author's module quiet specific findings without editing its source.

  • options(spades.moduleCodeChecks = list(disable = ...)). Disable whole rules by id (or restrict with enable = ...).

A related developer hint is # nolint: vars a, b: placed on a dynamic bulk-assign line whose names can't be seen statically (e.g. list2env(someList, envir(sim))), it asserts that objects a, b are produced there, so they aren't reported as out_declared_unused.

Rule catalogue

The rule ids (printed in brackets in the report), grouped by the bucket they appear under:

  • inputObjectsin_declared_unused (declared input never used), in_used_undeclared (sim$x read but not in inputObjects), in_no_default (declared input has no default in .inputObjects()).

  • outputObjectsout_declared_unused (declared output never assigned), out_used_undeclared (sim$x <- but not in outputObjects).

  • parametersparam_declared_unused, param_used_undeclared, param_used_other_module.

  • module functionsmust_return_sim (a doEvent.* must return sim), must_assign_to_sim, module_named_object (sim$<module> collides with the module name), clashing_module_fn.

  • globalsconflicting_fn_unqualified (a bare function name collides with a raster:: namesake; qualify it, e.g. raster::scale).

  • unresolvedunresolved_accessor (an accessor whose name could not be resolved statically).

  • codetoolscodetools (findings relayed from codetools::checkUsageEnv).

  • reqdPkgsreqd_pkg_duplicate (a package declared more than once in reqdPkgs, especially with conflicting source/version), reqd_pkg_undeclared (a pkg::fn whose pkg is not in reqdPkgs), reqd_pkg_no_source (best-effort, info: bare calls with no apparent source among the declared packages — only when all declared packages are installed).

codeCheckModule() checks a single module. codeCheckModules() is the vectorized form: it runs codeCheckModule() on each path in paths and returns a list of findings named by module. When paths is not supplied it defaults to every module directory under getOption("spades.modulePath"), so codeCheckModules() with no arguments checks the whole project. It replaces the manual idiom Map(codeCheckModule, dir(getOption("spades.modulePath"), full.names = TRUE)).