class Parser::Source::TreeRewriter::Action
@api private
Actions are arranged in a tree and get combined so that:
children are strictly contained by their parent sibblings all disjoint from one another only actions with replacement==nil may have children
Attributes
insert_after[R]
insert_before[R]
range[R]
replacement[R]
Public Class Methods
new(range, enforcer, insert_before: '', replacement: nil, insert_after: '', children: [] )
click to toggle source
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 14 def initialize(range, enforcer, insert_before: '', replacement: nil, insert_after: '', children: [] ) @range, @enforcer, @children, @insert_before, @replacement, @insert_after = range, enforcer, children.freeze, insert_before.freeze, replacement, insert_after.freeze freeze end
Public Instance Methods
combine(action)
click to toggle source
Assumes action.children.empty?
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 27 def combine(action) return self unless action.insertion? || action.replacement # Ignore empty action do_combine(action) end
insertion?()
click to toggle source
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 41 def insertion? !insert_before.empty? || !insert_after.empty? || (replacement && !replacement.empty?) end
ordered_replacements()
click to toggle source
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 32 def ordered_replacements reps = [] reps << [@range.begin, @insert_before] unless @insert_before.empty? reps << [@range, @replacement] if @replacement reps.concat(@children.sort_by(&:range).flat_map(&:ordered_replacements)) reps << [@range.end, @insert_after] unless @insert_after.empty? reps end
Protected Instance Methods
call_enforcer_for_merge(action)
click to toggle source
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 113 def call_enforcer_for_merge(action) @enforcer.call(:different_replacements) do if @replacement && action.replacement && @replacement != action.replacement {range: @range, replacement: action.replacement, other_replacement: @replacement} end end end
do_combine(action)
click to toggle source
Assumes range.contains?(action.range) && action.children.empty?
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 53 def do_combine(action) if action.range == @range merge(action) else place_in_hierachy(action) end end
fuse_deletions(action, fusible, other_sibblings)
click to toggle source
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 78 def fuse_deletions(action, fusible, other_sibblings) without_fusible = with(children: other_sibblings) fused_range = [action, *fusible].map(&:range).inject(:join) fused_deletion = action.with(range: fused_range) without_fusible.do_combine(fused_deletion) end
merge(action)
click to toggle source
Assumes action.range == range && action.children.empty?
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 104 def merge(action) call_enforcer_for_merge(action) with( insert_before: "#{action.insert_before}#{insert_before}", replacement: action.replacement || @replacement, insert_after: "#{insert_after}#{action.insert_after}", ) end
place_in_hierachy(action)
click to toggle source
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 61 def place_in_hierachy(action) family = @children.group_by { |child| child.relationship_with(action) } if family[:fusible] fuse_deletions(action, family[:fusible], [*family[:sibbling], *family[:child]]) else extra_sibbling = if family[:parent] # action should be a descendant of one of the children family[:parent][0].do_combine(action) elsif family[:child] # or it should become the parent of some of the children, action.with(children: family[:child]) else # or else it should become an additional child action end with(children: [*family[:sibbling], extra_sibbling]) end end
relationship_with(action)
click to toggle source
Returns what relationship self should have with `action`; either of
:sibbling, :parent, :child, :fusible or raises a CloberingError
In case of equal range, returns :parent
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 88 def relationship_with(action) if action.range == @range || @range.contains?(action.range) :parent elsif @range.contained?(action.range) :child elsif @range.disjoint?(action.range) :sibbling elsif !action.insertion? && !insertion? @enforcer.call(:crossing_deletions) { {range: action.range, conflict: @range} } :fusible else @enforcer.call(:crossing_insertions) { {range: action.range, conflict: @range} } end end
swallow(children)
click to toggle source
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 121 def swallow(children) @enforcer.call(:swallowed_insertions) do insertions = children.select(&:insertion?) {range: @range, conflict: insertions.map(&:range)} unless insertions.empty? end [] end
with(range: @range, children: @children, insert_before: @insert_before, replacement: @replacement, insert_after: @insert_after)
click to toggle source
# File lib/parser_tree_rewriter/source/tree_rewriter/action.rb, line 47 def with(range: @range, children: @children, insert_before: @insert_before, replacement: @replacement, insert_after: @insert_after) children = swallow(children) if replacement self.class.new(range, @enforcer, children: children, insert_before: insert_before, replacement: replacement, insert_after: insert_after) end