Module: Rigor::ConfigAudit

Defined in:
lib/rigor/config_audit.rb

Overview

Audits a loaded Configuration for the class of mistake where a configured value silently resolves to nothing — a typo'd or moved path, an unknown library name, an inert rule id. The shared failure mode is that the loader filters the bad entry without a word, so the only symptom is downstream and confusing: missing signatures turn every call into the types they were meant to cover into a high-confidence call.undefined-method, and an unrecognised suppression token leaves the rule firing as if the disable: line were never written. This module surfaces each such entry up front so the cause is visible instead of inferred.

Every check is held to the same bar that SignaturePathAudit set: it mirrors the loader's own acceptance test, so a warning means the loader really did load nothing, and it never fires on a setup that works. In particular the rule-token check only flags a token under a built-in family (call, flow, …) — a plugin- or rbs_extended.* rule id (whose family Rigor cannot statically enumerate, since a node_rule block emits any rule: string it likes) is left alone, so disabling a plugin rule is never mistaken for a typo.

Defined Under Namespace

Classes: Warning

Class Method Summary collapse

Class Method Details

.add_missing_dir(warnings, path, project_root, kind, key) ⇒ Object



130
131
132
133
134
135
# File 'lib/rigor/config_audit.rb', line 130

def self.add_missing_dir(warnings, path, project_root, kind, key)
  return if path.nil? || File.directory?(File.expand_path(path, project_root))

  warnings << Warning.new(kind: kind, message: "#{key}: #{path.inspect} is not a directory",
                          fields: { "path" => path })
end

.add_missing_file(warnings, path, project_root, kind, key) ⇒ Object



137
138
139
140
141
# File 'lib/rigor/config_audit.rb', line 137

def self.add_missing_file(warnings, path, project_root, kind, key)
  return if path.nil? || File.file?(File.expand_path(path, project_root))

  warnings << Warning.new(kind: kind, message: "#{key}: #{path.inspect} does not exist", fields: { "path" => path })
end

.explicit_path_warnings(configuration, project_root) ⇒ Object

Explicitly-configured bundler / rbs-collection paths that do not exist. Only the explicit form is audited (a nil value means auto-detection, which finding nothing is normal); messages stay factual about the path rather than guessing the fallback.



119
120
121
122
123
124
125
126
127
128
# File 'lib/rigor/config_audit.rb', line 119

def self.explicit_path_warnings(configuration, project_root)
  warnings = []
  add_missing_dir(warnings, configuration.bundler_bundle_path, project_root,
                  :bundler_bundle_path, "bundler.bundle_path")
  add_missing_file(warnings, configuration.bundler_lockfile, project_root,
                   :bundler_lockfile, "bundler.lockfile")
  add_missing_file(warnings, configuration.rbs_collection_lockfile, project_root,
                   :rbs_collection_lockfile, "rbs_collection.lockfile")
  warnings
end

.inert_builtin_token?(token) ⇒ Boolean

True when token looks like a built-in rule id but matches none — its first segment is a built-in family yet it is neither a bare family wildcard nor a known canonical id. A token whose family is not built-in (a plugin / rbs_extended.* rule, or a bare legacy alias) is deliberately NOT flagged: it may resolve at run time, so under-warning is the FP-safe choice.

Returns:

  • (Boolean)


107
108
109
110
111
112
113
114
# File 'lib/rigor/config_audit.rb', line 107

def self.inert_builtin_token?(token)
  family = token.split(".").first
  return false unless Analysis::CheckRules::RULE_FAMILIES.include?(family)
  return false if token == family
  return false if Analysis::CheckRules::ALL_RULES.include?(token)

  true
end

.library_warnings(configuration) ⇒ Object

libraries: entries RBS does not recognise. Uses the same RBS::EnvironmentLoader#has_library? guard the loader filters through (Environment::RbsLoader build_env_for), so a flagged name is exactly one the loader skipped. Fails soft: if RBS itself raises, no warning rather than a crash.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/rigor/config_audit.rb', line 61

def self.library_warnings(configuration)
  configured = Array(configuration.libraries)
  return [] if configured.empty?

  loader = ::RBS::EnvironmentLoader.new
  configured.reject { |lib| loader.has_library?(library: lib.to_s, version: nil) }.map do |lib|
    Warning.new(
      kind: :library,
      message: "libraries: #{lib.to_s.inspect} is not an available RBS library (no signatures loaded from it)",
      fields: { "name" => lib.to_s }
    )
  end
rescue StandardError
  []
end

.rule_token_warnings(configuration) ⇒ Object

disable: tokens and severity_overrides: keys that name no rule. Restricted to tokens under a built-in family so a plugin rule id is never mis-flagged (see the module docstring).



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/rigor/config_audit.rb', line 80

def self.rule_token_warnings(configuration)
  disable = Array(configuration.disabled_rules).filter_map do |token|
    next unless inert_builtin_token?(token.to_s)

    Warning.new(
      kind: :disabled_rule,
      message: "disable: #{token.to_s.inspect} is not a recognized rule id; the suppression has no effect",
      fields: { "token" => token.to_s }
    )
  end
  overrides = configuration.severity_overrides.keys.filter_map do |key|
    next unless inert_builtin_token?(key.to_s)

    Warning.new(
      kind: :severity_override,
      message: "severity_overrides: #{key.to_s.inspect} is not a recognized rule id; the override has no effect",
      fields: { "token" => key.to_s }
    )
  end
  disable + overrides
end

.signature_path_warnings(configuration) ⇒ Object

signature_paths: entries that resolve to nothing — delegated to SignaturePathAudit, which mirrors the loader's directory? + recursive **/*.rbs acceptance test.



47
48
49
50
51
52
53
54
55
# File 'lib/rigor/config_audit.rb', line 47

def self.signature_path_warnings(configuration)
  SignaturePathAudit.warnings(configuration.signature_paths).map do |entry|
    Warning.new(
      kind: :signature_path,
      message: entry.message,
      fields: { "path" => entry.path, "status" => entry.status.to_s, "rbs_file_count" => entry.rbs_file_count }
    )
  end
end

.warnings(configuration, project_root: Dir.pwd) ⇒ Array<Warning>

Parameters:

  • configuration (Rigor::Configuration)
  • project_root (String) (defaults to: Dir.pwd)

    the directory the run's relative bundler / collection paths resolve against (the CLI's CWD), used only by the explicit-path checks.

Returns:



38
39
40
41
42
43
# File 'lib/rigor/config_audit.rb', line 38

def self.warnings(configuration, project_root: Dir.pwd)
  signature_path_warnings(configuration) +
    library_warnings(configuration) +
    rule_token_warnings(configuration) +
    explicit_path_warnings(configuration, project_root)
end