Class: Expressir::Express::RemarkAttacher

Inherits:
Object
  • Object
show all
Defined in:
lib/expressir/express/remark_attacher.rb

Overview

Handles attaching remarks (comments) to model elements after parsing.

NOTE: Post-processing remark attachment has inherent limitations for scope-based matching. Remarks with simple tags (like “WR1”) inside scopes (TYPE, ENTITY, etc.) cannot be perfectly matched without parsing context. This implementation prioritizes:

  1. Exact path matches (e.g., “schema.entity.WR1”)

  2. Proximity-based matching for simple tags

  3. NOT creating spurious schema-level items for ambiguous tags

Constant Summary collapse

COLLECTION_REGISTRY =

Type-driven registry: maps each model class to its collection attributes. Replaces runtime method probing (method_defined?) with explicit type declarations.

{
  Model::Declarations::Schema => %i[
    constants types entities subtype_constraints
    functions rules procedures remark_items
  ],
  Model::Declarations::Entity => %i[
    attributes derived_attributes inverse_attributes
    unique_rules where_rules informal_propositions remark_items
  ],
  Model::Declarations::Function => %i[
    parameters types entities subtype_constraints
    functions procedures constants variables statements remark_items
  ],
  Model::Declarations::Procedure => %i[
    parameters types entities subtype_constraints
    functions procedures constants variables statements remark_items
  ],
  Model::Declarations::Rule => %i[
    applies_to types entities subtype_constraints
    functions procedures constants variables statements
    where_rules informal_propositions remark_items
  ],
  Model::Declarations::Type => %i[
    where_rules informal_propositions remark_items
  ],
  Model::ExpFile => %i[schemas],
  Model::Statements::Compound => %i[statements],
  Model::Statements::If => %i[statements],
  Model::Statements::Alias => %i[statements],
  Model::Statements::Repeat => %i[statements],
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ RemarkAttacher

Returns a new instance of RemarkAttacher.



48
49
50
51
52
53
54
55
# File 'lib/expressir/express/remark_attacher.rb', line 48

def initialize(source)
  @source = source
  @attached_spans = Set.new
  @line_cache = {}
  @model = nil
  @source_lines = nil # cached @source.lines
  @scope_map = nil # cached scope at each line number
end

Instance Method Details

#attach(model) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/expressir/express/remark_attacher.rb', line 57

def attach(model)
  @model = model
  remarks = extract_all_remarks

  # Build nodes_with_positions ONCE for both tagged and untagged remark passes.
  # This avoids double tree walk (381K nodes × 2 = 762K visits) which was
  # the largest memory overhead in remark attachment (~430MB for large files).
  nodes_with_positions = build_sorted_nodes_with_positions(model)

  attach_tagged_remarks(model, remarks, nodes_with_positions)
  attach_untagged_remarks(remarks, nodes_with_positions)

  # Free expensive data structures after attachment is complete.
  # These are only needed during the attach process.
  @source = nil
  @source_lines = nil
  @scope_map = nil
  @line_cache = nil

  model
end