diff --git a/lib/syntax_tree/translation/parser.rb b/lib/syntax_tree/translation/parser.rb index ad889478..4f32c933 100644 --- a/lib/syntax_tree/translation/parser.rb +++ b/lib/syntax_tree/translation/parser.rb @@ -1287,35 +1287,13 @@ def visit_ident(node) # Visit an IfNode node. def visit_if(node) - predicate = - case node.predicate - when RangeNode - type = - node.predicate.operator.value == ".." ? :iflipflop : :eflipflop - s(type, visit(node.predicate).children, nil) - when RegexpLiteral - s(:match_current_line, [visit(node.predicate)], nil) - when Unary - if node.predicate.operator.value == "!" && - node.predicate.statement.is_a?(RegexpLiteral) - s( - :send, - [ - s(:match_current_line, [visit(node.predicate.statement)]), - :! - ], - nil - ) - else - visit(node.predicate) - end - else - visit(node.predicate) - end - s( :if, - [predicate, visit(node.statements), visit(node.consequent)], + [ + visit_predicate(node.predicate), + visit(node.statements), + visit(node.consequent) + ], if node.modifier? smap_keyword_bare( srange_find_between(node.statements, node.predicate, "if"), @@ -1577,28 +1555,20 @@ def visit_massign(node) # Visit a MethodAddBlock node. def visit_method_add_block(node) case node.call - when Break, Next, ReturnNode - type, arguments = block_children(node.block) - call = visit(node.call) - - s( - call.type, - [ - s( - type, - [*call.children, arguments, visit(node.block.bodystmt)], - nil - ) - ], - nil - ) when ARef, Super, ZSuper type, arguments = block_children(node.block) s( type, [visit(node.call), arguments, visit(node.block.bodystmt)], - nil + smap_collection( + srange_node(node.block.opening), + srange_length( + node.block.end_char, + node.block.opening.is_a?(Kw) ? -3 : -1 + ), + srange_node(node) + ) ) else visit_command_call( @@ -2376,22 +2346,58 @@ def visit_tstring_content(node) # Visit a Unary node. def visit_unary(node) # Special handling here for flipflops - if node.statement.is_a?(Paren) && - node.statement.contents.is_a?(Statements) && - node.statement.contents.body.length == 1 && - (range = node.statement.contents.body.first).is_a?(RangeNode) && + if (paren = node.statement).is_a?(Paren) && + paren.contents.is_a?(Statements) && + paren.contents.body.length == 1 && + (range = paren.contents.body.first).is_a?(RangeNode) && node.operator == "!" - type = range.operator.value == ".." ? :iflipflop : :eflipflop - return( - s( - :send, - [s(:begin, [s(type, visit(range).children, nil)], nil), :!], - nil + s( + :send, + [ + s( + :begin, + [ + s( + range.operator.value == ".." ? :iflipflop : :eflipflop, + visit(range).children, + smap_operator( + srange_node(range.operator), + srange_node(range) + ) + ) + ], + smap_collection( + srange_length(paren.start_char, 1), + srange_length(paren.end_char, -1), + srange_node(paren) + ) + ), + :! + ], + smap_send_bare( + srange_length(node.start_char, 1), + srange_node(node) ) ) + elsif node.operator == "!" && node.statement.is_a?(RegexpLiteral) + s( + :send, + [ + s( + :match_current_line, + [visit(node.statement)], + smap(srange_node(node.statement)) + ), + :! + ], + smap_send_bare( + srange_length(node.start_char, 1), + srange_node(node) + ) + ) + else + visit(canonical_unary(node)) end - - visit(canonical_unary(node)) end # Visit an Undef node. @@ -2408,40 +2414,37 @@ def visit_undef(node) # Visit an UnlessNode node. def visit_unless(node) - predicate = - case node.predicate - when RegexpLiteral - s(:match_current_line, [visit(node.predicate)], nil) - when Unary - if node.predicate.operator.value == "!" && - node.predicate.statement.is_a?(RegexpLiteral) - s( - :send, - [ - s(:match_current_line, [visit(node.predicate.statement)]), - :! - ], - nil - ) - else - visit(node.predicate) - end - else - visit(node.predicate) - end - s( :if, - [predicate, visit(node.consequent), visit(node.statements)], + [ + visit_predicate(node.predicate), + visit(node.consequent), + visit(node.statements) + ], if node.modifier? smap_keyword_bare( srange_find_between(node.statements, node.predicate, "unless"), srange_node(node) ) else + begin_start = node.predicate.end_char + begin_end = + if node.statements.empty? + node.statements.end_char + else + node.statements.body.first.start_char + end + + begin_token = + if buffer.source[begin_start...begin_end].include?("then") + srange_find(begin_start, begin_end, "then") + elsif buffer.source[begin_start...begin_end].include?(";") + srange_find(begin_start, begin_end, ";") + end + smap_condition( srange_length(node.start_char, 6), - srange_search_between(node.predicate, node.statements, "then"), + begin_token, nil, srange_length(node.end_char, -3), srange_node(node) @@ -3014,6 +3017,31 @@ def srange_node(node) location = node.location srange(location.start_char, location.end_char) end + + def visit_predicate(node) + case node + when RangeNode + s( + node.operator.value == ".." ? :iflipflop : :eflipflop, + visit(node).children, + smap_operator(srange_node(node.operator), srange_node(node)) + ) + when RegexpLiteral + s(:match_current_line, [visit(node)], smap(srange_node(node))) + when Unary + if node.operator.value == "!" && node.statement.is_a?(RegexpLiteral) + s( + :send, + [s(:match_current_line, [visit(node.statement)]), :!], + smap_send_bare(srange_node(node.operator), srange_node(node)) + ) + else + visit(node) + end + else + visit(node) + end + end end end end diff --git a/test/translation/parser_test.rb b/test/translation/parser_test.rb index ad87d8c6..1df98f47 100644 --- a/test/translation/parser_test.rb +++ b/test/translation/parser_test.rb @@ -55,7 +55,6 @@ class ParserTest < Minitest::Test "test_dedenting_heredoc:399", "test_slash_newline_in_heredocs:7194", "test_parser_slash_slash_n_escaping_in_literals:*", - "test_cond_match_current_line:4801", "test_forwarded_restarg:*", "test_forwarded_kwrestarg:*", "test_forwarded_argument_with_restarg:*",