Class: Rigor::SigGen::Writer

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/sig_gen/writer.rb

Overview

Applies a per-source-file group of MethodCandidates to the target .rbs file under the project signature tree.

ADR-14 slice 2: the writer parses the target with RBS::Parser to find the matching class declaration and inserts new method declarations just before the class's closing end keyword. Existing declarations are NEVER touched unless --overwrite is set AND the candidate's classification is tighter-return.

The slice does NOT re-render the whole file through RBS::Writer. That would lose comments / blank-line formatting per upstream design; the byte-range insertion approach taken here preserves untouched declarations verbatim. Mixed hand-written + generated output inside the same class declaration may still lose trailing blank lines on the touched ranges; the --diff review surface from slice 1 is the user's escape hatch.

Safety boundary: the writer ASSERTS the target lives inside the configured signature tree before touching the disk. Files outside that tree route through WriteResult(action: :skipped_outside_sig_root); the caller decides whether to warn or fail.

Instance Method Summary collapse

Constructor Details

#initialize(path_mapper:, overwrite: false) ⇒ Writer

Returns a new instance of Writer.



36
37
38
39
40
41
42
43
44
# File 'lib/rigor/sig_gen/writer.rb', line 36

def initialize(path_mapper:, overwrite: false)
  @path_mapper = path_mapper
  @overwrite = overwrite
  # Run-level (cross-file) namespace-kind view, populated per `#write_all` from every candidate's per-file
  # map. Empty until then so the single-target `#write` path falls back to per-candidate kinds only.
  @global_namespace_kinds = {}
  # Run-level qualified-class-name => superclass-token view, same lifecycle as `@global_namespace_kinds`.
  @global_superclasses = {}
end

Instance Method Details

#write(source_path, candidates) ⇒ WriteResult

Parameters:

  • source_path (String)
  • candidates (Array<MethodCandidate>)

    only emittable classifications (new-method / tighter-return) are honoured; the caller is responsible for filtering.

Returns:



71
72
73
74
75
76
77
# File 'lib/rigor/sig_gen/writer.rb', line 71

def write(source_path, candidates)
  emittable = candidates.select { |c| EMITTABLE.include?(c.classification) }
  return WriteResult.new(source_path: source_path, target_path: nil, action: :noop) if emittable.empty?

  target = @path_mapper.target_for(source_path, class_name: emittable.first.class_name)
  write_target(target, emittable, source_path: source_path)
end

#write_all(candidates) ⇒ Array<WriteResult>

Process the full candidate list by resolving each candidate's target sig file via the path mapper (which may route consolidated-layout classes to existing files) and grouping candidates that share a target before writing.

ADR-14 follow-up: this is the consolidated-layout entry point. The legacy write(source_path, candidates) below assumes all candidates share a target and remains for spec convenience.

Parameters:

Returns:



55
56
57
58
59
60
61
62
63
# File 'lib/rigor/sig_gen/writer.rb', line 55

def write_all(candidates)
  emittable = candidates.select { |c| EMITTABLE.include?(c.classification) }
  return [] if emittable.empty?

  @global_namespace_kinds = build_namespace_kinds(candidates)
  @global_superclasses = build_superclasses(candidates)
  emittable.group_by { |c| @path_mapper.target_for(c.path, class_name: c.class_name) }
           .map { |target, group| write_target(target, group) }
end