Module: Rigor::Triage
- Defined in:
- lib/rigor/triage.rb,
lib/rigor/triage/hint.rb,
lib/rigor/triage/catalogue.rb
Overview
ADR-23 — diagnostic triage. Aggregates a ‘rigor check` diagnostic stream into the data behind the `rigor triage` report: a rule-ID distribution, per-file hotspots, and the heuristic hint catalogue (Catalogue).
Pure over the diagnostic stream — no second analysis pass, no analyzer internals. ‘Triage.analyze` is the single entry point; rendering is CLI::TriageRenderer’s job.
Defined Under Namespace
Modules: Catalogue
Classes: Hint, Hotspot, Report, RuleCount, Summary
Constant Summary
collapse
- UNCATEGORISED =
"(uncategorised)"
Class Method Summary
collapse
Class Method Details
.analyze(diagnostics, top: 10, hints: true) ⇒ Report
29
30
31
32
33
34
35
36
|
# File 'lib/rigor/triage.rb', line 29
def analyze(diagnostics, top: 10, hints: true)
Report.new(
summary: build_summary(diagnostics),
distribution: build_distribution(diagnostics),
hotspots: build_hotspots(diagnostics, top),
hints: hints ? Catalogue.recognise(diagnostics) : []
)
end
|
.build_distribution(diagnostics) ⇒ Object
54
55
56
57
58
|
# File 'lib/rigor/triage.rb', line 54
def build_distribution(diagnostics)
diagnostics.group_by { |d| rule_key(d) }
.map { |rule, group| RuleCount.new(rule: rule, count: group.size) }
.sort_by { |row| [-row.count, row.rule] }
end
|
.build_hotspots(diagnostics, top) ⇒ Object
60
61
62
63
64
65
|
# File 'lib/rigor/triage.rb', line 60
def build_hotspots(diagnostics, top)
diagnostics.group_by(&:path)
.map { |path, group| hotspot_for(path, group) }
.sort_by { |spot| [-spot.count, spot.file] }
.first(top)
end
|
.build_summary(diagnostics) ⇒ Object
44
45
46
47
48
49
50
51
52
|
# File 'lib/rigor/triage.rb', line 44
def build_summary(diagnostics)
by_severity = diagnostics.group_by(&:severity).transform_values(&:size)
Summary.new(
total: diagnostics.size,
error: by_severity.fetch(:error, 0),
warning: by_severity.fetch(:warning, 0),
info: by_severity.fetch(:info, 0)
)
end
|
.hotspot_for(path, group) ⇒ Object
67
68
69
70
71
72
73
|
# File 'lib/rigor/triage.rb', line 67
def hotspot_for(path, group)
by_rule = group.group_by { |d| rule_key(d) }
.transform_values(&:size)
.sort_by { |rule, count| [-count, rule] }
.to_h
Hotspot.new(file: path, count: group.size, by_rule: by_rule)
end
|
.report_to_h(report) ⇒ Object
75
76
77
78
79
80
81
82
83
84
85
86
87
|
# File 'lib/rigor/triage.rb', line 75
def report_to_h(report)
{
"summary" => {
"total" => report.summary.total, "error" => report.summary.error,
"warning" => report.summary.warning, "info" => report.summary.info
},
"distribution" => report.distribution.map { |r| { "rule" => r.rule, "count" => r.count } },
"hotspots" => report.hotspots.map do |h|
{ "file" => h.file, "count" => h.count, "by_rule" => h.by_rule }
end,
"hints" => report.hints.map(&:to_h)
}
end
|
.rule_key(diagnostic) ⇒ Object
Diagnostics without a ‘rule` (parse errors, internal-analyzer errors) bucket under a single sentinel rather than vanishing.
40
41
42
|
# File 'lib/rigor/triage.rb', line 40
def rule_key(diagnostic)
diagnostic.qualified_rule || UNCATEGORISED
end
|