Skip to content

Commit

Permalink
+ New methods as_nested_actions and as_replacements to output represe…
Browse files Browse the repository at this point in the history
…ntations of Source::TreeRewriter
  • Loading branch information
marcandre committed Jun 9, 2020
1 parent 733278c commit eed5b12
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
38 changes: 38 additions & 0 deletions lib/parser/source/tree_rewriter.rb
Expand Up @@ -260,6 +260,44 @@ def process
chunks.join
end

##
# Returns a representation of the rewriter as an ordered list of replacements.
#
# rewriter.as_replacements # => [ [1...1, '('],
# [2...4, 'foo'],
# [5...6, ''],
# [6...6, '!'],
# [10...10, ')'],
# ]
#
# This representation is sufficient to recreate the result of `process` but it is
# not sufficient to recreate completely the rewriter for further merging/actions.
# See `as_nested_actions`
#
# @return [Array<Range, String>] an ordered list of pairs of range & replacement
#
def as_replacements
@action_root.ordered_replacements
end

##
# Returns a representation of the rewriter as nested insertions (:wrap) and replacements.
#
# rewriter.as_actions # =>[ [:wrap, 1...10, '(', ')'],
# [:wrap, 2...6, '', '!'], # aka "insert_after"
# [:replace, 2...4, 'foo'],
# [:replace, 5...6, ''], # aka "removal"
# ],
#
# Contrary to `as_replacements`, this representation is sufficient to recreate exactly
# the rewriter.
#
# @return [Array<(Symbol, Range, String{, String})>]
#
def as_nested_actions
@action_root.nested_actions
end

##
# Provides a protected block where a sequence of multiple rewrite actions
# are handled atomically. If any of the actions failed by clobbering,
Expand Down
8 changes: 8 additions & 0 deletions lib/parser/source/tree_rewriter/action.rb
Expand Up @@ -46,6 +46,14 @@ def ordered_replacements
reps
end

def nested_actions
actions = []
actions << [:wrap, @range, @insert_before, @insert_after] if !@insert_before.empty? ||
!@insert_after.empty?
actions << [:replace, @range, @replacement] if @replacement
actions.concat(@children.flat_map(&:nested_actions))
end

def insertion?
!insert_before.empty? || !insert_after.empty? || (replacement && !replacement.empty?)
end
Expand Down
33 changes: 33 additions & 0 deletions test/test_source_tree_rewriter.rb
Expand Up @@ -265,6 +265,39 @@ def test_merge
[:wrap, @hello.join(@world), '@', '@'],
])
end

def representation_example
Parser::Source::TreeRewriter.new(@buf)
.wrap(range(1...10), '(', ')')
.insert_after(range(2...6), '!')
.replace(range(2...4), 'foo')
.remove(range(5...6))
end

def test_nested_actions
result = representation_example.as_nested_actions

assert_equal( [ [:wrap, 1...10, '(', ')'],
[:wrap, 2...6, '', '!'], # aka "insert_after"
[:replace, 2...4, 'foo'],
[:replace, 5...6, ''], # aka "removal"
],
result.each {|arr| arr[1] = arr[1].to_range }
)
end

def test_ordered_replacements
result = representation_example.as_replacements

assert_equal( [ [ 1...1, '('],
[ 2...4, 'foo'],
[ 5...6, ''],
[ 6...6, '!'],
[ 10...10, ')'],
],
result.map {|r, s| [r.to_range, s]}
)
end
end

class TestSourceTreeRewriterImport < Minitest::Test
Expand Down

0 comments on commit eed5b12

Please sign in to comment.