Class: Prism::Merge::ConflictResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/prism/merge/conflict_resolver.rb

Overview

Resolves conflicts in boundaries between anchors using structural signatures and comment preservation strategies.

ConflictResolver is responsible for the core merge logic within boundaries (sections where template and destination differ). It:

  • Matches nodes by structural signature

  • Decides which version to keep based on preference

  • Preserves trailing blank lines for proper spacing

  • Handles template-only and destination-only nodes

Examples:

Basic usage (via SmartMerger)

resolver = ConflictResolver.new(template_analysis, dest_analysis)
resolver.resolve(boundary, result)

See Also:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(template_analysis, dest_analysis, signature_match_preference: :destination, add_template_only_nodes: false) ⇒ ConflictResolver

Creates a new ConflictResolver for handling merge conflicts.

Examples:

Create resolver for Appraisals (destination wins)

resolver = ConflictResolver.new(
  template_analysis,
  dest_analysis,
  signature_match_preference: :destination,
  add_template_only_nodes: false
)

Create resolver for version files (template wins)

resolver = ConflictResolver.new(
  template_analysis,
  dest_analysis,
  signature_match_preference: :template,
  add_template_only_nodes: true
)

Parameters:

  • template_analysis (FileAnalysis)

    Analyzed template file

  • dest_analysis (FileAnalysis)

    Analyzed destination file

  • signature_match_preference (Symbol) (defaults to: :destination)

    Which version to prefer when nodes have matching signatures but different content:

    • :destination (default) - Keep destination version (customizations)

    • :template - Use template version (updates)

  • add_template_only_nodes (Boolean) (defaults to: false)

    Whether to add nodes that only exist in template:

    • false (default) - Skip template-only nodes

    • true - Add template-only nodes to result



67
68
69
70
71
72
# File 'lib/prism/merge/conflict_resolver.rb', line 67

def initialize(template_analysis, dest_analysis, signature_match_preference: :destination, add_template_only_nodes: false)
  @template_analysis = template_analysis
  @dest_analysis = dest_analysis
  @signature_match_preference = signature_match_preference
  @add_template_only_nodes = add_template_only_nodes
end

Instance Attribute Details

#add_template_only_nodesBoolean (readonly)

Returns Whether to add template-only nodes.

Returns:

  • (Boolean)

    Whether to add template-only nodes



35
36
37
# File 'lib/prism/merge/conflict_resolver.rb', line 35

def add_template_only_nodes
  @add_template_only_nodes
end

#dest_analysisFileAnalysis (readonly)

Returns Analysis of the destination file.

Returns:



29
30
31
# File 'lib/prism/merge/conflict_resolver.rb', line 29

def dest_analysis
  @dest_analysis
end

#signature_match_preferenceSymbol (readonly)

Returns Preference for signature matches (:template or :destination).

Returns:

  • (Symbol)

    Preference for signature matches (:template or :destination)



32
33
34
# File 'lib/prism/merge/conflict_resolver.rb', line 32

def signature_match_preference
  @signature_match_preference
end

#template_analysisFileAnalysis (readonly)

Returns Analysis of the template file.

Returns:



26
27
28
# File 'lib/prism/merge/conflict_resolver.rb', line 26

def template_analysis
  @template_analysis
end

Instance Method Details

#resolve(boundary, result) ⇒ Object

Resolve a boundary by deciding which content to keep. If the boundary contains a kettle-dev:freeze block, the entire block from the destination is preserved.

Parameters:



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/prism/merge/conflict_resolver.rb', line 79

def resolve(boundary, result)
  # Extract content from both sides
  template_content = extract_boundary_content(@template_analysis, boundary.template_range)
  dest_content = extract_boundary_content(@dest_analysis, boundary.dest_range)

  # If both sides are empty, nothing to do
  return if template_content[:lines].empty? && dest_content[:lines].empty?

  # If one side is empty, use the other
  if template_content[:lines].empty?
    add_content_to_result(dest_content, result, :destination, MergeResult::DECISION_KEPT_DEST)
    return
  end

  if dest_content[:lines].empty?
    # Only add template-only content if the flag allows it
    if @add_template_only_nodes
      add_content_to_result(template_content, result, :template, MergeResult::DECISION_KEPT_TEMPLATE)
    end
    return
  end

  # Both sides have content - perform intelligent merge
  merge_boundary_content(template_content, dest_content, boundary, result)
end