summaryrefslogtreecommitdiff
path: root/test/ripper
diff options
context:
space:
mode:
Diffstat (limited to 'test/ripper')
-rw-r--r--test/ripper/assert_parse_files.rb1
-rw-r--r--test/ripper/test_lexer.rb329
-rw-r--r--test/ripper/test_parser_events.rb120
-rw-r--r--test/ripper/test_ripper.rb37
-rw-r--r--test/ripper/test_scanner_events.rb6
-rw-r--r--test/ripper/test_sexp.rb15
6 files changed, 490 insertions, 18 deletions
diff --git a/test/ripper/assert_parse_files.rb b/test/ripper/assert_parse_files.rb
index 0d583a99e3..4f08589e41 100644
--- a/test/ripper/assert_parse_files.rb
+++ b/test/ripper/assert_parse_files.rb
@@ -40,6 +40,7 @@ class TestRipper::Generic < Test::Unit::TestCase
end
}
end
+ assert(true) if scripts.empty?
end;
end
end
diff --git a/test/ripper/test_lexer.rb b/test/ripper/test_lexer.rb
index 7d62a7ee28..4bc6fd7ced 100644
--- a/test/ripper/test_lexer.rb
+++ b/test/ripper/test_lexer.rb
@@ -253,18 +253,31 @@ world"
assert_equal(code, Ripper.tokenize(code).join(""), bug)
end
+ InvalidHeredocInsideBlockParam = <<~CODE
+ a do |b
+ <<-C
+ C
+ |
+ end
+ CODE
+
def test_heredoc_inside_block_param
bug = '[Bug #19399]'
- code = <<~CODE
- a do |b
- <<-C
- C
- |
- end
- CODE
+ code = InvalidHeredocInsideBlockParam
assert_equal(code, Ripper.tokenize(code).join(""), bug)
end
+ def test_heredoc_no_memory_leak
+ assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true)
+ require "ripper"
+ source = "" #{InvalidHeredocInsideBlockParam.dump}
+ begin;
+ 400_000.times do
+ Ripper.new(source).parse
+ end
+ end;
+ end
+
def test_heredoc_unterminated_interpolation
code = <<~'HEREDOC'
<<A+1
@@ -302,9 +315,8 @@ world"
[[6, 2], :on_tstring_content, "3\n", state(:EXPR_BEG)],
[[7, 0], :on_heredoc_end, "H1\n", state(:EXPR_BEG)],
]
- assert_equal(code, Ripper.tokenize(code).join(""))
- assert_equal(expected, result = Ripper.lex(code),
- proc {expected.zip(result) {|e, r| break diff(e, r) unless e == r}})
+
+ assert_lexer(expected, code)
code = <<~'HEREDOC'
<<-H1
@@ -330,6 +342,303 @@ world"
[[6, 0], :on_tstring_content, " 3\n", state(:EXPR_BEG)],
[[7, 0], :on_heredoc_end, "H1\n", state(:EXPR_BEG)],
]
+
+ assert_lexer(expected, code)
+
+ code = <<~'HEREDOC'
+ <<H1
+ #{<<H2}a
+ H2
+ b
+ HEREDOC
+
+ expected = [
+ [[1, 0], :on_heredoc_beg, "<<H1", state(:EXPR_BEG)],
+ [[1, 4], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_embexpr_beg, "\#{", state(:EXPR_BEG)],
+ [[2, 2], :on_heredoc_beg, "<<H2", state(:EXPR_BEG)],
+ [[2, 6], :on_embexpr_end, "}", state(:EXPR_END)],
+ [[2, 7], :on_tstring_content, "a\n", state(:EXPR_BEG)],
+ [[3, 0], :on_heredoc_end, "H2\n", state(:EXPR_BEG)],
+ [[4, 0], :on_tstring_content, "b\n", state(:EXPR_BEG)]
+ ]
+
+ assert_lexer(expected, code)
+
+ code = <<~'HEREDOC'
+ <<H1
+ #{<<H2}a
+ H2
+ b
+ c
+ HEREDOC
+
+ expected = [
+ [[1, 0], :on_heredoc_beg, "<<H1", state(:EXPR_BEG)],
+ [[1, 4], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_embexpr_beg, "\#{", state(:EXPR_BEG)],
+ [[2, 2], :on_heredoc_beg, "<<H2", state(:EXPR_BEG)],
+ [[2, 6], :on_embexpr_end, "}", state(:EXPR_END)],
+ [[2, 7], :on_tstring_content, "a\n", state(:EXPR_BEG)],
+ [[3, 0], :on_heredoc_end, "H2\n", state(:EXPR_BEG)],
+ [[4, 0], :on_tstring_content, "b\nc\n", state(:EXPR_BEG)]
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_ctrl_mbchar
+ code = %["\\C-\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\C-\u{3042}", state(:EXPR_BEG)],
+ [[1, 7], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+
+ code = %["\\C-\\\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\C-\\\u{3042}", state(:EXPR_BEG)],
+ [[1, 8], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_meta_mbchar
+ code = %["\\M-\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\M-\u{3042}", state(:EXPR_BEG)],
+ [[1, 7], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+
+ code = %["\\M-\\\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\M-\\\u{3042}", state(:EXPR_BEG)],
+ [[1, 8], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_meta_ctrl_mbchar
+ code = %["\\M-\\C-\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\M-\\C-\u{3042}", state(:EXPR_BEG)],
+ [[1, 10], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+
+ code = %["\\M-\\C-\\\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\M-\\C-\\\u{3042}", state(:EXPR_BEG)],
+ [[1, 11], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_ctrl_meta_mbchar
+ code = %["\\C-\\M-\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\C-\\M-\u{3042}", state(:EXPR_BEG)],
+ [[1, 10], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+
+ code = %["\\C-\\M-\\\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\C-\\M-\\\u{3042}", state(:EXPR_BEG)],
+ [[1, 11], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_string
+ code = "\"hello\\x world"
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "hello", state(:EXPR_BEG)],
+ [[1, 5], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[1, 7], :on_tstring_content, " world", state(:EXPR_BEG)],
+ ]
+
+ code = "\"\nhello\\x world"
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n" "hello", state(:EXPR_BEG)],
+ [[2, 5], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[2, 7], :on_tstring_content, " world", state(:EXPR_BEG)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\Cxx\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\Cx", state(:EXPR_BEG)],
+ [[2, 3], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\Mxx\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\Mx", state(:EXPR_BEG)],
+ [[2, 3], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\c\\cx\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\c\\c", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 5], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\ux\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\u", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 3], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\xx\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 3], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "<<A\n\n\\xyz"
+ expected = [
+ [[1, 0], :on_heredoc_beg, "<<A", state(:EXPR_BEG)],
+ [[1, 3], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[3, 0], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[3, 2], :on_tstring_content, "yz", state(:EXPR_BEG)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "%(\n\\xyz)"
+ expected = [
+ [[1, 0], :on_tstring_beg, "%(", state(:EXPR_BEG)],
+ [[1, 2], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "yz", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_end, ")", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "%Q(\n\\xyz)"
+ expected = [
+ [[1, 0], :on_tstring_beg, "%Q(", state(:EXPR_BEG)],
+ [[1, 3], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "yz", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_end, ")", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = ":\"\n\\xyz\""
+ expected = [
+ [[1, 0], :on_symbeg, ":\"", state(:EXPR_FNAME)],
+ [[1, 2], :on_tstring_content, "\n", state(:EXPR_FNAME)],
+ [[2, 0], :on_tstring_content, "\\x", state(:EXPR_FNAME)],
+ [[2, 2], :on_tstring_content, "yz", state(:EXPR_FNAME)],
+ [[2, 4], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+ end
+
+ def test_spaces_at_eof
+ code = "1\n\t \t"
+ expected = [
+ [[1, 0], :on_int, "1", state(:EXPR_END)],
+ [[1, 1], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_sp, "\t \t", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+ end
+
+ def test_fluent_and
+ code = "foo\n" "and"
+ expected = [
+ [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)],
+ [[1, 3], :on_ignored_nl, "\n", state(:EXPR_CMDARG)],
+ [[2, 0], :on_kw, "and", state(:EXPR_BEG)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "foo\n" "and?"
+ expected = [
+ [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)],
+ [[1, 3], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_ident, "and?", state(:EXPR_CMDARG)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "foo\n" "and!"
+ expected = [
+ [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)],
+ [[1, 3], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_ident, "and!", state(:EXPR_CMDARG)],
+ ]
+ assert_lexer(expected, code)
+ end
+
+ def test_fluent_or
+ code = "foo\n" "or"
+ expected = [
+ [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)],
+ [[1, 3], :on_ignored_nl, "\n", state(:EXPR_CMDARG)],
+ [[2, 0], :on_kw, "or", state(:EXPR_BEG)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "foo\n" "or?"
+ expected = [
+ [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)],
+ [[1, 3], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_ident, "or?", state(:EXPR_CMDARG)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "foo\n" "or!"
+ expected = [
+ [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)],
+ [[1, 3], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_ident, "or!", state(:EXPR_CMDARG)],
+ ]
+ assert_lexer(expected, code)
+ end
+
+ def assert_lexer(expected, code)
assert_equal(code, Ripper.tokenize(code).join(""))
assert_equal(expected, result = Ripper.lex(code),
proc {expected.zip(result) {|e, r| break diff(e, r) unless e == r}})
diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb
index 9283a4d343..3e72c7a331 100644
--- a/test/ripper/test_parser_events.rb
+++ b/test/ripper/test_parser_events.rb
@@ -267,17 +267,29 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def test_assign_error_backref
- thru_assign_error = false
+ errors = []
result =
- parse('$` = 1', :on_assign_error) {thru_assign_error = true}
- assert_equal true, thru_assign_error
- assert_equal '[assign(assign_error(var_field($`)),1)]', result
+ parse('$& = 1', %i[on_assign_error compile_error]) {|e, *| errors << e}
+ assert_equal %i[on_assign_error], errors
+ assert_equal '[assign(assign_error(var_field($&)),1)]', result
- thru_assign_error = false
+ errors = []
result =
- parse('$`, _ = 1', :on_assign_error) {thru_assign_error = true}
- assert_equal true, thru_assign_error
- assert_equal '[massign([assign_error(var_field($`)),var_field(_)],1)]', result
+ parse('$&, _ = 1', %i[on_assign_error compile_error]) {|e, *| errors << e}
+ assert_equal %i[on_assign_error], errors
+ assert_equal '[massign([assign_error(var_field($&)),var_field(_)],1)]', result
+
+ errors = []
+ result =
+ parse('$& += 1', %i[on_assign_error compile_error]) {|e, *| errors << e}
+ assert_equal %i[on_assign_error], errors
+ assert_equal '[assign_error(opassign(var_field($&),+=,1))]', result
+
+ errors = []
+ result =
+ parse('$& += cmd 1, 2', %i[on_assign_error compile_error]) {|e, *| errors << e}
+ assert_equal %i[on_assign_error], errors
+ assert_equal '[assign_error(opassign(var_field($&),+=,command(cmd,[1,2])))]', result
end
def test_assign_error_const_qualified
@@ -470,6 +482,13 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
thru_call = false
assert_nothing_raised {
+ tree = parse("a b do end.()", :on_call) {thru_call = true}
+ }
+ assert_equal true, thru_call
+ assert_equal "[call(command(a,[vcall(b)],&do_block(,bodystmt([void()]))),.,call,[])]", tree
+
+ thru_call = false
+ assert_nothing_raised {
tree = parse("self::foo", :on_call) {thru_call = true}
}
assert_equal true, thru_call
@@ -1672,6 +1691,26 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
assert_equal(%w"frozen_string_literal nottrue", args)
end
+ def test_warning_duplicated_when_clause
+ fmt, *args = warning(<<~STR)
+ a = 1
+ case a
+ when 1
+ when 1
+ when 2
+ else
+ end
+ STR
+ assert_match(/duplicates 'when' clause/, fmt)
+ assert_equal([4, 3], args)
+ end
+
+ def test_warn_duplicated_hash_keys
+ fmt, *args = warn("{ a: 1, a: 2 }")
+ assert_match(/is duplicated and overwritten on line/, fmt)
+ assert_equal([:a, 1], args)
+ end
+
def test_warn_cr_in_middle
fmt = nil
assert_warn("") {fmt, = warn("\r;")}
@@ -1711,4 +1750,69 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
parse('case 0; in {a:}; end', :on_hshptn) {thru_hshptn = true}
assert_equal true, thru_hshptn
end
+
+ def test_return_out_of_compile_error_no_memory_leak
+ assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
+ class MyRipper < Ripper
+ def initialize(src, &blk)
+ super(src)
+ @blk = blk
+ end
+
+ def compile_error(msg) = @blk.call(msg)
+ end
+
+ def call_parse = MyRipper.new("/") { |msg| return msg }.parse
+
+ # Check that call_parse does return a syntax error
+ raise "call_parse should return a syntax error" unless call_parse
+ begin;
+ 100_000.times do
+ call_parse
+ end
+ end;
+ end
+
+ def test_return_out_of_warn_no_memory_leak
+ assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
+ class MyRipper < Ripper
+ def initialize(src, &blk)
+ super(src)
+ @blk = blk
+ end
+
+ def warn(msg, *args) = @blk.call(msg)
+ end
+
+ def call_parse = MyRipper.new("{ a: 1, a: 2 }") { |msg| return msg }.parse
+
+ # Check that call_parse does warn
+ raise "call_parse should warn" unless call_parse
+ begin;
+ 500_000.times do
+ call_parse
+ end
+ end;
+
+ assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
+ class MyRipper < Ripper
+ def initialize(src, &blk)
+ super(src)
+ @blk = blk
+ end
+
+ def warn(msg, *args) = @blk.call(msg)
+ end
+
+ $VERBOSE = true
+ def call_parse = MyRipper.new("if true\n end\n") { |msg| return msg }.parse
+
+ # Check that call_parse does warn
+ raise "call_parse should warn" unless call_parse
+ begin;
+ 1_000_000.times do
+ call_parse
+ end
+ end;
+ end
end if ripper_test
diff --git a/test/ripper/test_ripper.rb b/test/ripper/test_ripper.rb
index 6061496d9c..2b3421d827 100644
--- a/test/ripper/test_ripper.rb
+++ b/test/ripper/test_ripper.rb
@@ -148,6 +148,25 @@ end
assert_nothing_raised { Ripper.lex src }
end
+ def test_assignable_in_regexp
+ assert_separately(%w(-rripper), "", "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_nil(Ripper.parse('/(?<_1>)/ =~ s'))
+ end;
+ end
+
+ def test_invalid_multibyte_character_in_regexp
+ lex = Ripper::Lexer.new(%q[/#{"\xcd"}/]).scan.map(&:to_a)
+ assert_equal([[1, 0], :on_regexp_beg, "/", state(:EXPR_BEG)], lex.shift)
+ assert_equal([[1, 1], :on_embexpr_beg, "\#{", state(:EXPR_BEG)], lex.shift)
+ assert_equal([[1, 3], :on_tstring_beg, "\"", state(:EXPR_BEG)], lex.shift)
+ assert_equal([[1, 4], :on_tstring_content, "\\xcd", state(:EXPR_BEG)], lex.shift)
+ assert_equal([[1, 8], :on_tstring_end, "\"", state(:EXPR_END)], lex.shift)
+ assert_equal([[1, 9], :on_embexpr_end, "}", state(:EXPR_END)], lex.shift)
+ assert_equal([[1, 10], :on_regexp_end, "/", state(:EXPR_BEG)], lex.shift)
+ assert_empty(lex)
+ end
+
def test_no_memory_leak
assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
2_000_000.times do
@@ -168,6 +187,21 @@ end
Ripper.parse("-> {")
end
end;
+
+ # [Bug #21004]
+ assert_no_memory_leak(%w(-rripper), "", <<~RUBY, rss: true)
+ 1_000_000.times do
+ Ripper.parse("-> do it end")
+ end
+ RUBY
+ end
+
+ def test_sexp_no_memory_leak
+ assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
+ 1_000_000.times do
+ Ripper.sexp("")
+ end
+ end;
end
class TestInput < self
@@ -187,4 +221,7 @@ end
end
end
+ def state(name)
+ Ripper::Lexer::State.new(Ripper.const_get(name))
+ end
end if ripper_test
diff --git a/test/ripper/test_scanner_events.rb b/test/ripper/test_scanner_events.rb
index 792f19ef1a..ed291c4384 100644
--- a/test/ripper/test_scanner_events.rb
+++ b/test/ripper/test_scanner_events.rb
@@ -53,6 +53,8 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
Ripper.tokenize("1 .foo\n")
assert_equal ["1", "\n", " ", ".", "foo", "\n"],
Ripper.tokenize("1\n .foo\n")
+ assert_equal ["def", " ", "f", ";", " ", "(", "x", ")", "::", "A", " ", "="],
+ Ripper.tokenize("def f; (x)::A =")
end
def test_lex
@@ -950,6 +952,10 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
scan('CHAR', "?\\u{41}")
err = nil
+ assert_equal [], scan('CHAR', '?\\') {|*e| err = e}
+ assert_equal([:on_parse_error, "Invalid escape character syntax", "?\\"], err)
+
+ err = nil
assert_equal [], scan('CHAR', '?\\M ') {|*e| err = e}
assert_equal([:on_parse_error, "Invalid escape character syntax", "?\\M "], err)
diff --git a/test/ripper/test_sexp.rb b/test/ripper/test_sexp.rb
index 32285be9ab..3ebcf3062e 100644
--- a/test/ripper/test_sexp.rb
+++ b/test/ripper/test_sexp.rb
@@ -123,6 +123,21 @@ eot
assert_equal(exp, named)
end
+ def test_command
+ sexp = Ripper.sexp("a::C {}")
+ assert_equal(
+ [:program,
+ [
+ [:method_add_block,
+ [:command_call,
+ [:vcall, [:@ident, "a", [1, 0]]],
+ [:@op, "::", [1, 1]],
+ [:@const, "C", [1, 3]],
+ nil],
+ [:brace_block, nil, [[:void_stmt]]]]]],
+ sexp)
+ end
+
def search_sexp(sym, sexp)
return sexp if !sexp or sexp[0] == sym
sexp.find do |e|