Class: Rigor::Analysis::Diagnostic
- Inherits:
-
Object
- Object
- Rigor::Analysis::Diagnostic
- Defined in:
- lib/rigor/analysis/diagnostic.rb,
sig/rigor.rbs
Constant Summary collapse
- DEFAULT_SOURCE_FAMILY =
The default source family. Matches the existing analyzer-internal rule families; serialised as
"builtin"and is the baseline against which non-default families are recognised. :builtin
Instance Attribute Summary collapse
-
#column ⇒ Integer
readonly
Returns the value of attribute column.
-
#line ⇒ Integer
readonly
Returns the value of attribute line.
-
#message ⇒ String
readonly
Returns the value of attribute message.
-
#method_name ⇒ Object
readonly
Returns the value of attribute method_name.
-
#path ⇒ String
readonly
Returns the value of attribute path.
-
#project_definition_site ⇒ Object
readonly
Returns the value of attribute project_definition_site.
-
#receiver_type ⇒ Object
readonly
Returns the value of attribute receiver_type.
-
#rule ⇒ Object
readonly
Returns the value of attribute rule.
-
#severity ⇒ Symbol
readonly
Returns the value of attribute severity.
-
#source_family ⇒ Object
readonly
Returns the value of attribute source_family.
Class Method Summary collapse
-
.from_location(location, path:, message:, severity: :error, rule: nil, source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) ⇒ Rigor::Analysis::Diagnostic
Builds a Diagnostic from an explicit Prism location, applying the same 1-based
line/start_column + 1convention as Diagnostic.from_node. -
.from_message_loc(node) ⇒ Object
Builds a Diagnostic at a call node's
message_loc(the method-name / matcher span), falling back to the receiver-spanningnode.locationwhen no message location is available. -
.from_name_loc(node) ⇒ Object
Builds a Diagnostic at a definition / assignment node's
name_loc(the declared name span), falling back tonode.location. -
.from_node(node, path:, message:, severity: :error, rule: nil, source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) ⇒ Rigor::Analysis::Diagnostic
Singleton factories plugins build diagnostics through (the
node/locationare Prism values, received asuntyped).
Instance Method Summary collapse
- #error? ⇒ Boolean
-
#initialize(path:, line:, column:, message:, severity: :error, rule: nil, source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) ⇒ Diagnostic
constructor
rule:is the stable identifier (a kebab-case string) of the diagnostic's source rule. -
#qualified_rule ⇒ Object
The fully-qualified rule identifier —
<source_family>.<rule>when the source is non-default, or just<rule>for the:builtinfamily. -
#to_h ⇒ Hash[String, untyped]
--format jsonserialisation. -
#to_s ⇒ String
Text rendering for
rigor check.
Constructor Details
#initialize(path:, line:, column:, message:, severity: :error, rule: nil, source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) ⇒ Diagnostic
rule: is the stable identifier (a kebab-case string) of the diagnostic's source rule. It is used by
the configuration and the in-source # rigor:disable <rule> suppression comment system to identify
diagnostics by category. Diagnostics not produced by CheckRules (parse errors, path errors, internal
analyzer errors) may leave rule as nil and stay unsuppressible.
source_family: names the producer of the rule. The default :builtin covers analyzer-internal
rules; future families like :rbs_extended, :generated, or "plugin.<id>" (per ADR-2 § "Plugin
Diagnostic Provenance") let consumers distinguish where a diagnostic originated without committing to
the plugin API itself.
receiver_type: / method_name: are optional structured fields populated by the call-related rules
(call.undefined-method) — the rendered receiver type and the called method name as plain strings.
ADR-23 WD3 / slice 4: rigor triage's heuristic recognisers read these directly instead of parsing
the diagnostic message, so the catalogue no longer couples to message wording. Both stay nil for
rules that have no such pair; a consumer that finds them nil falls back to message parsing.
project_definition_site: is an optional "path:line" string set by call.undefined-method when
the project itself defines the called method on the receiver class somewhere in the analyzed file set
(a reopened core/stdlib/gem class the dispatcher does not apply cross-file — see ADR-17). Its
presence is the high-confidence "this is a project monkey-patch, not a bug" signal rigor triage keys
on to recommend pre_eval:. Nil for every other diagnostic.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/rigor/analysis/diagnostic.rb', line 34 def initialize(path:, line:, column:, message:, severity: :error, rule: nil, # rubocop:disable Metrics/ParameterLists source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) raise ArgumentError, "line must be >= 1, got #{line}" if line < 1 raise ArgumentError, "column must be >= 1, got #{column}" if column < 1 @path = path @line = line @column = column @message = @severity = severity @rule = rule @source_family = source_family @receiver_type = receiver_type @method_name = method_name @project_definition_site = project_definition_site end |
Instance Attribute Details
#column ⇒ Integer (readonly)
Returns the value of attribute column.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def column @column end |
#line ⇒ Integer (readonly)
Returns the value of attribute line.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def line @line end |
#message ⇒ String (readonly)
Returns the value of attribute message.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def @message end |
#method_name ⇒ Object (readonly)
Returns the value of attribute method_name.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def method_name @method_name end |
#path ⇒ String (readonly)
Returns the value of attribute path.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def path @path end |
#project_definition_site ⇒ Object (readonly)
Returns the value of attribute project_definition_site.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def project_definition_site @project_definition_site end |
#receiver_type ⇒ Object (readonly)
Returns the value of attribute receiver_type.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def receiver_type @receiver_type end |
#rule ⇒ Object (readonly)
Returns the value of attribute rule.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def rule @rule end |
#severity ⇒ Symbol (readonly)
Returns the value of attribute severity.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def severity @severity end |
#source_family ⇒ Object (readonly)
Returns the value of attribute source_family.
10 11 12 |
# File 'lib/rigor/analysis/diagnostic.rb', line 10 def source_family @source_family end |
Class Method Details
.from_location(location, path:, message:, severity: :error, rule: nil, source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) ⇒ Rigor::Analysis::Diagnostic
Builds a Diagnostic from an explicit Prism location, applying the same 1-based line /
start_column + 1 convention as from_node. Use this when the diagnostic should point at a
sub-location rather than the whole node — most often a call's message_loc (the matcher / method
name) instead of the receiver-spanning node.location. from_node is sugar for
from_location(node.location, …).
74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/rigor/analysis/diagnostic.rb', line 74 def self.from_location(location, path:, message:, severity: :error, rule: nil, # rubocop:disable Metrics/ParameterLists source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) new( path: path, line: location.start_line, column: location.start_column + 1, message: , severity: severity, rule: rule, source_family: source_family, receiver_type: receiver_type, method_name: method_name, project_definition_site: project_definition_site ) end |
.from_message_loc(node) ⇒ Object
Builds a Diagnostic at a call node's message_loc (the method-name / matcher span), falling back to
the receiver-spanning node.location when no message location is available. Absorbs the
node.message_loc || node.location idiom the call-related rules otherwise repeat; all other fields
forward to from_location.
91 92 93 |
# File 'lib/rigor/analysis/diagnostic.rb', line 91 def self.(node, **) from_location(node. || node.location, **) end |
.from_name_loc(node) ⇒ Object
Builds a Diagnostic at a definition / assignment node's name_loc (the declared name span), falling
back to node.location. Absorbs the node.name_loc || node.location idiom the def / write rules
otherwise repeat.
98 99 100 |
# File 'lib/rigor/analysis/diagnostic.rb', line 98 def self.from_name_loc(node, **) from_location(node.name_loc || node.location, **) end |
.from_node(node, path:, message:, severity: :error, rule: nil, source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) ⇒ Rigor::Analysis::Diagnostic
Singleton factories plugins build diagnostics through (the
node / location are Prism values, received as untyped).
59 60 61 62 63 64 65 66 67 |
# File 'lib/rigor/analysis/diagnostic.rb', line 59 def self.from_node(node, path:, message:, severity: :error, rule: nil, # rubocop:disable Metrics/ParameterLists source_family: DEFAULT_SOURCE_FAMILY, receiver_type: nil, method_name: nil, project_definition_site: nil) from_location( node.location, path: path, message: , severity: severity, rule: rule, source_family: source_family, receiver_type: receiver_type, method_name: method_name, project_definition_site: project_definition_site ) end |
Instance Method Details
#error? ⇒ Boolean
102 103 104 |
# File 'lib/rigor/analysis/diagnostic.rb', line 102 def error? severity == :error end |
#qualified_rule ⇒ Object
The fully-qualified rule identifier — <source_family>.<rule> when the source is non-default, or
just <rule> for the :builtin family. Returns nil when rule itself is nil (e.g. parse errors and
internal-analyzer errors).
109 110 111 112 113 114 |
# File 'lib/rigor/analysis/diagnostic.rb', line 109 def qualified_rule return nil if rule.nil? return rule if source_family == DEFAULT_SOURCE_FAMILY "#{source_family}.#{rule}" end |
#to_h ⇒ Hash[String, untyped]
--format json serialisation. The structured receiver_type / method_name /
project_definition_site fields are emitted only when populated, so a consumer (jq, rigor triage, an AI agent) can group a rigor check --format json stream by the called class / method
without parsing the human-readable message — the message wording is presentation, not contract.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/rigor/analysis/diagnostic.rb', line 120 def to_h base = { "path" => path, "line" => line, "column" => column, "severity" => severity.to_s, "rule" => rule, "source_family" => source_family.to_s, "message" => } base["receiver_type"] = receiver_type if receiver_type base["method_name"] = method_name if method_name base["project_definition_site"] = project_definition_site if project_definition_site base end |
#to_s ⇒ String
Text rendering for rigor check. The qualified rule identifier (per ADR-2 § "Plugin Diagnostic
Provenance" — plugin.<id>.<rule>, rbs_extended.<rule>, generated.<provider>.<rule>) is appended
in brackets whenever the diagnostic carries a non-default source_family, so plugin / RBS::Extended
/ generated provenance is visible in the standard text output without changing the layout for
built-in rules. Slice 5 (v0.1.0) wires this surface.
141 142 143 144 145 146 147 148 149 |
# File 'lib/rigor/analysis/diagnostic.rb', line 141 def to_s base = "#{path}:#{line}:#{column}: #{severity}: #{}" return base if source_family == DEFAULT_SOURCE_FAMILY qualified = qualified_rule return base if qualified.nil? "#{base} [#{qualified}]" end |