Module: Rigor::Analysis::CheckRules
- Defined in:
- lib/rigor/analysis/check_rules.rb
Overview
First-preview catalogue of ‘rigor check` diagnostic rules.
The rules are intentionally narrow: they fire ONLY when the engine is confident enough to make a useful claim, and they MUST NOT raise on unrecognised AST shapes, RBS gaps, or missing scope information. Each rule consumes the per-node scope index produced by ‘Rigor::Inference::ScopeIndexer.index` and yields zero or more `Rigor::Analysis::Diagnostic` values.
The first shipped rule, ‘UndefinedMethodOnTypedReceiver`, flags an explicit-receiver `Prism::CallNode` whose receiver statically resolves to a `Type::Nominal` or `Type::Singleton` known to the analyzer’s RBS environment AND whose method name does not appear on that class’s instance / singleton method table. This is the canonical “type check” signal (“Foo has no method bar”), but it explicitly does NOT fire for:
-
implicit-self calls (no ‘node.receiver`) — too noisy without per-method RBS for every helper in the class.
-
dynamic / unknown receivers (‘Dynamic`, `Top`, `Union`) — by definition we cannot enumerate the method set.
-
shape carriers (‘Tuple`, `HashShape`, `Constant`) — their dispatch goes through `ShapeDispatch` / `ConstantFolding` which the rule does not yet model.
-
receivers whose class name is NOT registered in the loader (RBS-blind environments, unknown stdlib).
The above list is the deliberate conservative envelope of the first preview; later slices broaden it. rubocop:disable Metrics/ModuleLength
Class Method Summary collapse
-
.diagnose(path:, root:, scope_index:) ⇒ Array<Rigor::Analysis::Diagnostic>
Yields diagnostics for every unrecognised method call on a typed receiver in ‘root`’s subtree.
Class Method Details
.diagnose(path:, root:, scope_index:) ⇒ Array<Rigor::Analysis::Diagnostic>
Yields diagnostics for every unrecognised method call on a typed receiver in ‘root`’s subtree. The caller MUST have already produced ‘scope_index` through `Rigor::Inference::ScopeIndexer.index(root, default_scope:)`.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/rigor/analysis/check_rules.rb', line 56 def diagnose(path:, root:, scope_index:) # rubocop:disable Metrics/CyclomaticComplexity diagnostics = [] Source::NodeWalker.each(root) do |node| next unless node.is_a?(Prism::CallNode) diagnostic = undefined_method_diagnostic(path, node, scope_index) diagnostics << diagnostic if diagnostic arity_diagnostic = wrong_arity_diagnostic(path, node, scope_index) diagnostics << arity_diagnostic if arity_diagnostic nil_diagnostic = nil_receiver_diagnostic(path, node, scope_index) diagnostics << nil_diagnostic if nil_diagnostic dump_diagnostic = dump_type_diagnostic(path, node, scope_index) diagnostics << dump_diagnostic if dump_diagnostic assert_diagnostic = assert_type_diagnostic(path, node, scope_index) diagnostics << assert_diagnostic if assert_diagnostic end diagnostics end |