Module: Moult::Formatters::DeadCodeTable

Defined in:
lib/moult/formatters/dead_code_table.rb

Overview

Human-readable table of dead-code candidates. Renders from the same DeadCodeReport as the JSON formatter so the two cannot disagree. Sorting already happened in DeadCode; this layer owns column formatting only.

The heading is deliberate: these are confidence-graded candidates, never certainties.

Constant Summary collapse

RIGHT_ALIGNED =

Only the CONF column (col 0) is right-aligned.

[0].freeze

Class Method Summary collapse

Class Method Details

.columns(runtime) ⇒ Object



31
32
33
34
35
# File 'lib/moult/formatters/dead_code_table.rb', line 31

def columns(runtime)
  cols = ["CONF", "KIND"]
  cols << "RUNTIME" if runtime
  cols + ["SYMBOL", "LOCATION", "TOP REASON"]
end

.conf(value) ⇒ Object



61
62
63
# File 'lib/moult/formatters/dead_code_table.rb', line 61

def conf(value)
  format("%.2f", value)
end

.heading(count) ⇒ Object



37
38
39
# File 'lib/moult/formatters/dead_code_table.rb', line 37

def heading(count)
  "Dead-code candidates (confidence-graded — not certainties): #{count} findings"
end

.location(finding) ⇒ Object



47
48
49
50
51
# File 'lib/moult/formatters/dead_code_table.rb', line 47

def location(finding)
  span = finding.span
  line = span&.start_line
  line ? "#{finding.path}:#{line}" : finding.path.to_s
end

.render(report) ⇒ String

Parameters:

Returns:

  • (String)


19
20
21
22
23
24
25
26
27
28
29
# File 'lib/moult/formatters/dead_code_table.rb', line 19

def render(report)
  findings = report.findings
  return "No dead-code candidates found." if findings.empty?

  # The RUNTIME column only appears when coverage was merged, so output
  # without --coverage is byte-for-byte unchanged from Phase 2.
  runtime = findings.any? { |f| !f.runtime.nil? }
  headers = columns(runtime)
  rows = findings.map { |f| row(f, runtime) }
  [heading(findings.size), "", TextTable.render(headers, rows, right_aligned: RIGHT_ALIGNED)].join("\n")
end

.row(finding, runtime) ⇒ Object



41
42
43
44
45
# File 'lib/moult/formatters/dead_code_table.rb', line 41

def row(finding, runtime)
  cells = [conf(finding.confidence), finding.kind.to_s]
  cells << (finding.runtime&.to_s || "-") if runtime
  cells + [finding.name.to_s, location(finding), top_reason(finding)]
end

.top_reason(finding) ⇒ Object

The most informative reason is the last applied non-base adjustment; fall back to the base reason for a bare candidate.



55
56
57
58
59
# File 'lib/moult/formatters/dead_code_table.rb', line 55

def top_reason(finding)
  reasons = finding.reasons.reject { |r| r.rule == :base_score }
  chosen = reasons.last || finding.reasons.first
  chosen ? chosen.detail.to_s : "-"
end