Class: Rbs::Merge::MergeResult

Inherits:
Ast::Merge::MergeResultBase
  • Object
show all
Includes:
Ast::Merge::CommentLayoutEmissionSupport
Defined in:
lib/rbs/merge/merge_result.rb

Overview

Result container for RBS file merge operations. Inherits from Ast::Merge::MergeResultBase for shared functionality.

Tracks merged content, decisions made during merge, and provides methods to reconstruct the final merged RBS file.

Examples:

Basic usage

result = MergeResult.new(template_analysis, dest_analysis)
result.add_from_template(0)
result.add_from_destination(1)
merged_content = result.to_s

See Also:

  • Ast::Merge::MergeResultBase

Constant Summary collapse

DECISION_FREEZE_BLOCK =

Decision indicating content was preserved from a freeze block

:freeze_block
DECISION_TEMPLATE =

Decision indicating content came from the template

:template
DECISION_DESTINATION =

Decision indicating content came from the destination (customization preserved)

:destination
DECISION_ADDED =

Decision indicating content was added from template (new in template)

:added
DECISION_RECURSIVE =

Decision indicating content was recursively merged

:recursive

Instance Method Summary collapse

Constructor Details

#initialize(template_analysis, dest_analysis, **options) ⇒ MergeResult

Initialize a new merge result



45
46
47
48
# File 'lib/rbs/merge/merge_result.rb', line 45

def initialize(template_analysis, dest_analysis, **options)
  super(template_analysis: template_analysis, dest_analysis: dest_analysis, **options)
  @emitted_freeze_blocks = {}
end

Instance Method Details

#add_freeze_block(freeze_node) ⇒ void

This method returns an undefined value.

Add content from a freeze block



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rbs/merge/merge_result.rb', line 91

def add_freeze_block(freeze_node)
  # Use the freeze_node's own analysis to get the correct content
  # (template freeze blocks should use template lines, dest freeze blocks use dest lines)
  source_analysis = freeze_node.analysis
  freeze_key = [source_analysis.object_id, freeze_node.start_line, freeze_node.end_line]
  return if @emitted_freeze_blocks[freeze_key]

  lines = extract_lines(freeze_node, source_analysis)
  @lines.concat(deduplicate_leading_comment_overlap(lines))
  @emitted_freeze_blocks[freeze_key] = true

  # Determine source based on which analysis the freeze_node belongs to
  source = source_analysis == @template_analysis ? :template : :destination

  @decisions << {
    decision: DECISION_FREEZE_BLOCK,
    source: source,
    start_line: freeze_node.start_line,
    end_line: freeze_node.end_line,
    lines: lines.length
  }
end

#add_from_destination(index, decision: DECISION_DESTINATION, comment_source_statement: nil, comment_source_analysis: nil) ⇒ void

This method returns an undefined value.

Add content from the destination at the given statement index



73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rbs/merge/merge_result.rb', line 73

def add_from_destination(index, decision: DECISION_DESTINATION, comment_source_statement: nil,
                         comment_source_analysis: nil)
  statement = @dest_analysis.statements[index]
  return unless statement

  lines = extract_lines(
    statement,
    @dest_analysis,
    comment_source_statement: comment_source_statement,
    comment_source_analysis: comment_source_analysis
  )
  @lines.concat(deduplicate_leading_comment_overlap(lines))
  @decisions << { decision: decision, source: :destination, index: index, lines: lines.length }
end

#add_from_template(index, decision: DECISION_TEMPLATE, comment_source_statement: nil, comment_source_analysis: nil) ⇒ void

This method returns an undefined value.

Add content from the template at the given statement index



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rbs/merge/merge_result.rb', line 54

def add_from_template(index, decision: DECISION_TEMPLATE, comment_source_statement: nil,
                      comment_source_analysis: nil)
  statement = @template_analysis.statements[index]
  return unless statement

  lines = extract_lines(
    statement,
    @template_analysis,
    comment_source_statement: comment_source_statement,
    comment_source_analysis: comment_source_analysis
  )
  @lines.concat(deduplicate_leading_comment_overlap(lines))
  @decisions << { decision: decision, source: :template, index: index, lines: lines.length }
end

#add_raw(lines, decision:) ⇒ void

This method returns an undefined value.

Add raw content lines



138
139
140
141
# File 'lib/rbs/merge/merge_result.rb', line 138

def add_raw(lines, decision:)
  @lines.concat(deduplicate_leading_comment_overlap(lines))
  @decisions << { decision: decision, source: :raw, lines: lines.length }
end

#add_recursive_merge(merged_content, template_index:, dest_index:) ⇒ void

This method returns an undefined value.

Add recursively merged content



119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/rbs/merge/merge_result.rb', line 119

def add_recursive_merge(merged_content, template_index:, dest_index:)
  # Split without trailing newlines for consistency with other methods
  lines = merged_content.split("\n", -1)
  # Remove trailing empty element if content ended with newline
  lines.pop if lines.last == ''
  @lines.concat(deduplicate_leading_comment_overlap(lines))
  @decisions << {
    decision: DECISION_RECURSIVE,
    source: :merged,
    template_index: template_index,
    dest_index: dest_index,
    lines: lines.length
  }
end

#empty?Boolean

Check if any content has been added



157
158
159
# File 'lib/rbs/merge/merge_result.rb', line 157

def empty?
  @lines.empty?
end

#summaryHash

Get summary of merge decisions



163
164
165
166
167
168
169
170
# File 'lib/rbs/merge/merge_result.rb', line 163

def summary
  counts = @decisions.group_by { |d| d[:decision] }.transform_values(&:count)
  {
    total_decisions: @decisions.length,
    total_lines: @lines.length,
    by_decision: counts
  }
end

#to_sString

Convert the merged result to a string



145
146
147
148
149
150
151
152
153
# File 'lib/rbs/merge/merge_result.rb', line 145

def to_s
  return '' if @lines.empty?

  # Lines are stored without trailing newlines, so join with newlines
  result = @lines.join("\n")
  # Ensure file ends with newline if content is non-empty
  result += "\n" unless result.end_with?("\n")
  result
end