Module: RubynCode::Chisel::Debt

Defined in:
lib/rubyn_code/chisel/debt.rb

Overview

Harvests inline deferral markers from the codebase. A marker is a code comment whose text begins with the lowercase tag “chisel:” and records a simplification you consciously postponed (e.g. a comment reading “chisel: collapse this adapter once a second caller exists”).

Finding them is a deterministic grep — stdlib does it, so there’s no LLM round-trip here (Chisel’s own ladder, applied to Chisel).

Defined Under Namespace

Classes: Item

Constant Summary collapse

MARKER =

The whole line must be a comment whose first token is the lowercase tag: optional indentation, a ‘#` or `//` leader, then `chisel:`, then the note. Anchoring to line-start means a `chisel:` substring inside a string literal or a trailing code comment is NOT harvested — only a marker on its own comment line is. Case-sensitive on purpose, so a descriptive comment that merely starts with “Chisel:” is not a marker.

%r{\A\s*(?:#|//)\s*chisel:\s*(\S.*)}
SCAN_EXTENSIONS =
%w[.rb .rake .erb .ru .gemspec].freeze
SKIP_DIRS =
%w[.git node_modules vendor coverage tmp log].freeze

Class Method Summary collapse

Class Method Details

.scan(root) ⇒ Array<Item>

Returns markers found, in file/line order.

Parameters:

  • root (String, nil)

    project root to scan

Returns:

  • (Array<Item>)

    markers found, in file/line order



30
31
32
33
34
35
36
37
# File 'lib/rubyn_code/chisel/debt.rb', line 30

def scan(root)
  return [] unless root

  base = File.expand_path(root)
  return [] unless Dir.exist?(base)

  source_files(base).flat_map { |path| scan_file(base, path) }
end

.scan_file(base, path) ⇒ Array<Item>

Returns markers in a single file ([] if it can’t be read).

Returns:

  • (Array<Item>)

    markers in a single file ([] if it can’t be read)



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rubyn_code/chisel/debt.rb', line 52

def scan_file(base, path)
  rel = path.delete_prefix("#{base}/")
  items = []
  File.foreach(path).with_index(1) do |line, number|
    match = MARKER.match(line)
    items << Item.new(file: rel, line: number, note: match[1].strip) if match
  end
  items
rescue StandardError
  []
end

.skip?(base, path) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
49
# File 'lib/rubyn_code/chisel/debt.rb', line 46

def skip?(base, path)
  rel = path.delete_prefix("#{base}/")
  SKIP_DIRS.any? { |dir| rel == dir || rel.start_with?("#{dir}/") || rel.include?("/#{dir}/") }
end

.source_files(base) ⇒ Array<String>

Returns absolute paths of scannable source files.

Parameters:

  • base (String)

    expanded project root (no trailing slash)

Returns:

  • (Array<String>)

    absolute paths of scannable source files



41
42
43
44
# File 'lib/rubyn_code/chisel/debt.rb', line 41

def source_files(base)
  pattern = File.join(base, '**', "*{#{SCAN_EXTENSIONS.join(',')}}")
  Dir.glob(pattern).reject { |path| skip?(base, path) }.sort
end