diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2020-06-25 01:14:26 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2020-06-25 01:14:26 +0900 |
commit | 3d8705dcfdd567278c833c252ea11c018c0d3890 (patch) | |
tree | 03cfb2e8bc1e37bb1dc51079355c8e7e5bf780df | |
parent | 419b0596a2ada720ae1b3f2c1bd3ab5e12819ac8 (diff) | |
download | ruby-3d8705dcfdd567278c833c252ea11c018c0d3890.tar.gz |
Drop token info for endless method definition
Because it does not have closing `end`.
-rw-r--r-- | parse.y | 23 | ||||
-rw-r--r-- | test/ripper/test_parser_events.rb | 20 | ||||
-rw-r--r-- | test/ruby/test_rubyoptions.rb | 11 |
3 files changed, 45 insertions, 9 deletions
@@ -1053,6 +1053,7 @@ static void token_info_setup(token_info *ptinfo, const char *ptr, const rb_code_ static void token_info_push(struct parser_params*, const char *token, const rb_code_location_t *loc); static void token_info_pop(struct parser_params*, const char *token, const rb_code_location_t *loc); static void token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc); +static void token_info_drop(struct parser_params *p, const char *token, rb_code_position_t beg_pos); #define WARN_EOL(tok) \ (looking_at_eol_p(p) ? \ @@ -2493,6 +2494,7 @@ arg : lhs '=' arg_rhs } | defn_head f_paren_args '=' arg { + token_info_drop(p, "def", @1.beg_pos); restore_defun(p, $<node>1->nd_defn); /*%%%*/ $$ = set_defun_body(p, $1, $2, $4, &@$); @@ -2502,6 +2504,7 @@ arg : lhs '=' arg_rhs } | defn_head f_paren_args '=' arg modifier_rescue arg { + token_info_drop(p, "def", @1.beg_pos); restore_defun(p, $<node>1->nd_defn); /*%%%*/ $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6); @@ -5767,6 +5770,26 @@ token_info_pop(struct parser_params *p, const char *token, const rb_code_locatio } static void +token_info_drop(struct parser_params *p, const char *token, rb_code_position_t beg_pos) +{ + token_info *ptinfo_beg = p->token_info; + + if (!ptinfo_beg) return; + p->token_info = ptinfo_beg->next; + + if (ptinfo_beg->beg.lineno != beg_pos.lineno || + ptinfo_beg->beg.column != beg_pos.column || + strcmp(ptinfo_beg->token, token)) { + compile_error(p, "token position mismatch: %d:%d:%s expected but %d:%d:%s", + beg_pos.lineno, beg_pos.column, token, + ptinfo_beg->beg.lineno, ptinfo_beg->beg.column, + ptinfo_beg->token); + } + + ruby_sized_xfree(ptinfo_beg, sizeof(*ptinfo_beg)); +} + +static void token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc) { token_info ptinfo_end_body, *ptinfo_end = &ptinfo_end_body; diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb index 5b05624683..13064c2bc8 100644 --- a/test/ripper/test_parser_events.rb +++ b/test/ripper/test_parser_events.rb @@ -26,13 +26,21 @@ class TestRipper::ParserEvents < Test::Unit::TestCase end def warning(str) - parse(str, :warning) {|e, *args| return args} - assert(false, "warning expected") + tree = parse(str, :warning) {|e, *args| return args} + if block_given? + yield tree + else + assert(false, "warning expected") + end end def warn(str) - parse(str, :warn) {|e, *args| return args} - assert(false, "warning expected") + tree = parse(str, :warn) {|e, *args| return args} + if block_given? + yield tree + else + assert(false, "warning expected") + end end def test_program @@ -1552,6 +1560,10 @@ class TestRipper::ParserEvents < Test::Unit::TestCase fmt, tokend, tokbeg, line = assert_warning("") {break warn("if true\n end\n")} assert_match(/mismatched indentations/, fmt) assert_equal(["if", "end", 1], [tokbeg, tokend, line]) + result = assert_warning("") { + warn("begin\n" " def f() = nil\n" "end\n") {break :ok} + } + assert_equal(:ok, result) end def test_in diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 890f4c9b4e..754918d17c 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -494,16 +494,17 @@ class TestRubyOptions < Test::Unit::TestCase ["case nil; when true", "end"], ["if false;", "end", "if true\nelse ", "end"], ["else", " end", "_ = if true\n"], + ["begin\n def f() = nil", "end"], ].each do |b, e = 'end', pre = nil, post = nil| src = ["#{pre}#{b}\n", " #{e}\n#{post}"] k = b[/\A\s*(\S+)/, 1] e = e[/\A\s*(\S+)/, 1] - n = 2 - n += pre.count("\n") if pre + n = 1 + src[0].count("\n") + n1 = 1 + (pre ? pre.count("\n") : 0) a.for("no directives with #{src}") do - err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n-1}"] + err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"] t.rewind t.truncate(0) t.puts src @@ -522,7 +523,7 @@ class TestRubyOptions < Test::Unit::TestCase end a.for("false and true directives with #{src}") do - err = ["#{t.path}:#{n+2}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n+1}"] + err = ["#{t.path}:#{n+2}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1+2}"] t.rewind t.truncate(0) t.puts "# -*- warn-indent: false -*-" @@ -544,7 +545,7 @@ class TestRubyOptions < Test::Unit::TestCase end a.for("BOM with #{src}") do - err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n-1}"] + err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"] t.rewind t.truncate(0) t.print "\u{feff}" |