# frozen_string_literal: true require File.expand_path('../../test_helper.rb', File.dirname(__FILE__)) describe RipperRubyParser::Parser do describe '#parse' do describe 'for regular if' do it 'works with a single statement' do 'if foo; bar; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), nil) end it 'works with multiple statements' do 'if foo; bar; baz; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:block, s(:call, nil, :bar), s(:call, nil, :baz)), nil) end it 'works with zero statements' do 'if foo; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), nil, nil) end it 'works with a begin..end block' do 'if foo; begin; bar; end; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), nil) end it 'works with an else clause' do 'if foo; bar; else; baz; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:call, nil, :baz)) end it 'works with an empty main clause' do 'if foo; else; bar; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), nil, s(:call, nil, :bar)) end it 'works with an empty else clause' do 'if foo; bar; else; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), nil) end it 'handles a negative condition correctly' do 'if not foo; bar; end'. must_be_parsed_as s(:if, s(:call, s(:call, nil, :foo), :!), s(:call, nil, :bar), nil) end it 'handles bare integer literal in condition' do 'if 1; bar; end'. must_be_parsed_as s(:if, s(:lit, 1), s(:call, nil, :bar), nil) end it 'handles bare regex literal in condition' do 'if /foo/; bar; end'. must_be_parsed_as s(:if, s(:match, s(:lit, /foo/)), s(:call, nil, :bar), nil) end it 'handles interpolated regex in condition' do 'if /#{foo}/; bar; end'. must_be_parsed_as s(:if, s(:dregx, '', s(:evstr, s(:call, nil, :foo))), s(:call, nil, :bar), nil) end it 'handles block conditions' do 'if (foo; bar); baz; end'. must_be_parsed_as s(:if, s(:block, s(:call, nil, :foo), s(:call, nil, :bar)), s(:call, nil, :baz), nil) end it 'converts :dot2 to :flip2' do 'if foo..bar; baz; end'. must_be_parsed_as s(:if, s(:flip2, s(:call, nil, :foo), s(:call, nil, :bar)), s(:call, nil, :baz), nil) end it 'converts :dot3 to :flip3' do 'if foo...bar; baz; end'. must_be_parsed_as s(:if, s(:flip3, s(:call, nil, :foo), s(:call, nil, :bar)), s(:call, nil, :baz), nil) end it 'handles negative match operator' do 'if foo !~ bar; baz; else; qux; end'. must_be_parsed_as s(:if, s(:call, s(:call, nil, :foo), :=~, s(:call, nil, :bar)), s(:call, nil, :qux), s(:call, nil, :baz)) end it 'cleans up begin..end block in condition' do 'if begin foo end; bar; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), nil) end it 'handles special conditions inside begin..end block' do 'if begin foo..bar end; baz; end'. must_be_parsed_as s(:if, s(:flip2, s(:call, nil, :foo), s(:call, nil, :bar)), s(:call, nil, :baz), nil) end it 'works with assignment in the condition' do 'if foo = bar; baz; end'. must_be_parsed_as s(:if, s(:lasgn, :foo, s(:call, nil, :bar)), s(:call, nil, :baz), nil) end it 'works with bracketed assignment in the condition' do 'if (foo = bar); baz; end'. must_be_parsed_as s(:if, s(:lasgn, :foo, s(:call, nil, :bar)), s(:call, nil, :baz), nil) end end describe 'for postfix if' do it 'works with a simple condition' do 'foo if bar'. must_be_parsed_as s(:if, s(:call, nil, :bar), s(:call, nil, :foo), nil) end it 'handles negative conditions' do 'foo if not bar'. must_be_parsed_as s(:if, s(:call, s(:call, nil, :bar), :!), s(:call, nil, :foo), nil) end it 'handles bare regex literal in condition' do 'foo if /bar/'. must_be_parsed_as s(:if, s(:match, s(:lit, /bar/)), s(:call, nil, :foo), nil) end it 'handles interpolated regex in condition' do 'foo if /#{bar}/'. must_be_parsed_as s(:if, s(:dregx, '', s(:evstr, s(:call, nil, :bar))), s(:call, nil, :foo), nil) end it 'handles negative match operator' do 'baz if foo !~ bar'. must_be_parsed_as s(:if, s(:call, s(:call, nil, :foo), :=~, s(:call, nil, :bar)), nil, s(:call, nil, :baz)) end it 'cleans up begin..end block in condition' do 'foo if begin bar end'. must_be_parsed_as s(:if, s(:call, nil, :bar), s(:call, nil, :foo), nil) end end describe 'for regular unless' do it 'works with a single statement' do 'unless bar; foo; end'. must_be_parsed_as s(:if, s(:call, nil, :bar), nil, s(:call, nil, :foo)) end it 'works with multiple statements' do 'unless foo; bar; baz; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), nil, s(:block, s(:call, nil, :bar), s(:call, nil, :baz))) end it 'works with zero statements' do 'unless foo; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), nil, nil) end it 'works with an else clause' do 'unless foo; bar; else; baz; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :baz), s(:call, nil, :bar)) end it 'works with an empty main clause' do 'unless foo; else; bar; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), nil) end it 'works with an empty else block' do 'unless foo; bar; else; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), nil, s(:call, nil, :bar)) end it 'handles bare regex literal in condition' do 'unless /foo/; bar; end'. must_be_parsed_as s(:if, s(:match, s(:lit, /foo/)), nil, s(:call, nil, :bar)) end it 'handles interpolated regex in condition' do 'unless /#{foo}/; bar; end'. must_be_parsed_as s(:if, s(:dregx, '', s(:evstr, s(:call, nil, :foo))), nil, s(:call, nil, :bar)) end it 'handles negative match operator' do 'unless foo !~ bar; baz; else; qux; end'. must_be_parsed_as s(:if, s(:call, s(:call, nil, :foo), :=~, s(:call, nil, :bar)), s(:call, nil, :baz), s(:call, nil, :qux)) end end describe 'for postfix unless' do it 'works with a simple condition' do 'foo unless bar'. must_be_parsed_as s(:if, s(:call, nil, :bar), nil, s(:call, nil, :foo)) end it 'handles bare regex literal in condition' do 'foo unless /bar/'. must_be_parsed_as s(:if, s(:match, s(:lit, /bar/)), nil, s(:call, nil, :foo)) end it 'handles interpolated regex in condition' do 'foo unless /#{bar}/'. must_be_parsed_as s(:if, s(:dregx, '', s(:evstr, s(:call, nil, :bar))), nil, s(:call, nil, :foo)) end it 'handles negative match operator' do 'baz unless foo !~ bar'. must_be_parsed_as s(:if, s(:call, s(:call, nil, :foo), :=~, s(:call, nil, :bar)), s(:call, nil, :baz), nil) end end describe 'for elsif' do it 'works with a single statement' do 'if foo; bar; elsif baz; qux; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:if, s(:call, nil, :baz), s(:call, nil, :qux), nil)) end it 'works with an empty consequesnt' do 'if foo; bar; elsif baz; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:if, s(:call, nil, :baz), nil, nil)) end it 'works with an else' do 'if foo; bar; elsif baz; qux; else; quuz; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:if, s(:call, nil, :baz), s(:call, nil, :qux), s(:call, nil, :quuz))) end it 'works with an empty else' do 'if foo; bar; elsif baz; qux; else; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:if, s(:call, nil, :baz), s(:call, nil, :qux), nil)) end it 'handles a negative condition correctly' do 'if foo; bar; elsif not baz; qux; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:if, s(:call, s(:call, nil, :baz), :!), s(:call, nil, :qux), nil)) end it 'does not replace :dot2 with :flip2' do 'if foo; bar; elsif baz..qux; quuz; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:if, s(:dot2, s(:call, nil, :baz), s(:call, nil, :qux)), s(:call, nil, :quuz), nil)) end it 'does not rewrite the negative match operator' do 'if foo; bar; elsif baz !~ qux; quuz; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:if, s(:not, s(:call, s(:call, nil, :baz), :=~, s(:call, nil, :qux))), s(:call, nil, :quuz), nil)) end it 'cleans up begin..end block in condition' do 'if foo; bar; elsif begin baz end; qux; end'. must_be_parsed_as s(:if, s(:call, nil, :foo), s(:call, nil, :bar), s(:if, s(:call, nil, :baz), s(:call, nil, :qux), nil)) end end describe 'for case block' do it 'works with a single when clause' do 'case foo; when bar; baz; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz)), nil) end it 'works with multiple when clauses' do 'case foo; when bar; baz; when qux; quux; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz)), s(:when, s(:array, s(:call, nil, :qux)), s(:call, nil, :quux)), nil) end it 'works with multiple statements in the when block' do 'case foo; when bar; baz; qux; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz), s(:call, nil, :qux)), nil) end it 'works with an else clause' do 'case foo; when bar; baz; else; qux; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz)), s(:call, nil, :qux)) end it 'works with multiple statements in the else block' do 'case foo; when bar; baz; else; qux; quuz end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz)), s(:block, s(:call, nil, :qux), s(:call, nil, :quuz))) end it 'works with an empty when block' do 'case foo; when bar; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), nil), nil) end it 'works with an empty else block' do 'case foo; when bar; baz; else; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz)), nil) end it 'works with a splat in the when clause' do 'case foo; when *bar; baz; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:splat, s(:call, nil, :bar))), s(:call, nil, :baz)), nil) end it 'cleans up a multi-statement begin..end in the when clause' do 'case foo; when bar; begin; baz; qux; end; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz), s(:call, nil, :qux)), nil) end it 'cleans up a multi-statement begin..end at start of the when clause' do 'case foo; when bar; begin; baz; qux; end; quuz; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz), s(:call, nil, :qux), s(:call, nil, :quuz)), nil) end it 'keeps up a multi-statement begin..end in the else clause' do 'case foo; when bar; baz; else; begin; qux; quuz; end; end'. must_be_parsed_as s(:case, s(:call, nil, :foo), s(:when, s(:array, s(:call, nil, :bar)), s(:call, nil, :baz)), s(:block, s(:call, nil, :qux), s(:call, nil, :quuz))) end end end end