class RBI::Rewriters::Merge::TreeMerger

Attributes

conflicts[R]

Public Class Methods

new(output, left_name: "left", right_name: "right", keep: Keep::NONE) click to toggle source
Calls superclass method
# File lib/rbi/rewriters/merge_trees.rb, line 103
def initialize(output, left_name: "left", right_name: "right", keep: Keep::NONE)
  super()
  @tree = output
  @index = T.let(output.index, Index)
  @scope_stack = T.let([@tree], T::Array[Tree])
  @left_name = left_name
  @right_name = right_name
  @keep = keep
  @conflicts = T.let([], T::Array[Conflict])
end

Public Instance Methods

visit(node) click to toggle source
# File lib/rbi/rewriters/merge_trees.rb, line 115
def visit(node)
  return unless node

  case node
  when Scope
    prev = previous_definition(node)

    if prev.is_a?(Scope)
      if node.compatible_with?(prev)
        prev.merge_with(node)
      elsif @keep == Keep::LEFT
        # do nothing it's already merged
      elsif @keep == Keep::RIGHT
        prev = replace_scope_header(prev, node)
      else
        make_conflict_scope(prev, node)
      end
      @scope_stack << prev
    else
      copy = node.dup_empty
      current_scope << copy
      @scope_stack << copy
    end
    visit_all(node.nodes)
    @scope_stack.pop
  when Tree
    current_scope.merge_with(node)
    visit_all(node.nodes)
  when Indexable
    prev = previous_definition(node)
    if prev
      if node.compatible_with?(prev)
        prev.merge_with(node)
      elsif @keep == Keep::LEFT
        # do nothing it's already merged
      elsif @keep == Keep::RIGHT
        prev.replace(node)
      else
        make_conflict_tree(prev, node)
      end
    else
      current_scope << node.dup
    end
  end
end

Private Instance Methods

current_scope() click to toggle source
# File lib/rbi/rewriters/merge_trees.rb, line 164
def current_scope
  T.must(@scope_stack.last)
end
make_conflict_scope(left, right) click to toggle source
# File lib/rbi/rewriters/merge_trees.rb, line 181
def make_conflict_scope(left, right)
  @conflicts << Conflict.new(left: left, right: right, left_name: @left_name, right_name: @right_name)
  scope_conflict = ScopeConflict.new(left: left, right: right, left_name: @left_name, right_name: @right_name)
  left.replace(scope_conflict)
end
make_conflict_tree(left, right) click to toggle source
# File lib/rbi/rewriters/merge_trees.rb, line 188
def make_conflict_tree(left, right)
  @conflicts << Conflict.new(left: left, right: right, left_name: @left_name, right_name: @right_name)
  tree = left.parent_conflict_tree
  unless tree
    tree = ConflictTree.new(left_name: @left_name, right_name: @right_name)
    left.replace(tree)
    tree.left << left
  end
  tree.right << right
end
previous_definition(node) click to toggle source
# File lib/rbi/rewriters/merge_trees.rb, line 169
def previous_definition(node)
  case node
  when Indexable
    node.index_ids.each do |id|
      others = @index[id]
      return others.last unless others.empty?
    end
  end
  nil
end
replace_scope_header(left, right) click to toggle source
# File lib/rbi/rewriters/merge_trees.rb, line 200
def replace_scope_header(left, right)
  right_copy = right.dup_empty
  left.replace(right_copy)
  left.nodes.each do |node|
    right_copy << node
  end
  @index.index(right_copy)
  right_copy
end