From d34bc779a7f8fc9d8820a8cdeb4a3b5e75958be2 Mon Sep 17 00:00:00 2001 From: nobu Date: Mon, 19 Mar 2018 08:21:26 +0000 Subject: [PATCH] parse.y: mismatched indentations at middle * parse.y (k_rescue, k_ensure, k_when, k_else, k_elsif): warn mismatched indentations at keywords in middle of blocks. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62836 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- parse.y | 64 ++++++++++++++++++++++++++++------- test/ruby/test_rubyoptions.rb | 7 ++++ 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/parse.y b/parse.y index 19a4189264..6acfb6a5a3 100644 --- a/parse.y +++ b/parse.y @@ -738,6 +738,7 @@ PRINTF_ARGS(static void parser_compile_error(struct parser_params*, const char * 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, const rb_code_location_t *loc); %} %pure-parser @@ -2718,6 +2719,36 @@ k_def : keyword_def } ; +k_rescue : keyword_rescue + { + token_info_warn(p, "rescue", p->token_info, &@$); + } + ; + +k_ensure : keyword_ensure + { + token_info_warn(p, "ensure", p->token_info, &@$); + } + ; + +k_when : keyword_when + { + token_info_warn(p, "when", p->token_info, &@$); + } + ; + +k_else : keyword_else + { + token_info_warn(p, "else", p->token_info, &@$); + } + ; + +k_elsif : keyword_elsif + { + token_info_warn(p, "elsif", p->token_info, &@$); + } + ; + k_end : keyword_end { token_info_pop(p, "end", &@$); @@ -2741,7 +2772,7 @@ do : term ; if_tail : opt_else - | keyword_elsif expr_value then + | k_elsif expr_value then compstmt if_tail { @@ -2754,7 +2785,7 @@ if_tail : opt_else ; opt_else : none - | keyword_else compstmt + | k_else compstmt { /*%%%*/ $$ = $2; @@ -3236,7 +3267,7 @@ do_body : {$$ = dyna_push(p);} } ; -case_body : keyword_when args then +case_body : k_when args then compstmt cases { @@ -3252,7 +3283,7 @@ cases : opt_else | case_body ; -opt_rescue : keyword_rescue exc_list exc_var then +opt_rescue : k_rescue exc_list exc_var then compstmt opt_rescue { @@ -3291,7 +3322,7 @@ exc_var : tASSOC lhs | none ; -opt_ensure : keyword_ensure compstmt +opt_ensure : k_ensure compstmt { /*%%%*/ $$ = $2; @@ -4488,22 +4519,29 @@ token_info_push(struct parser_params *p, const char *token, const rb_code_locati static void token_info_pop(struct parser_params *p, const char *token, const rb_code_location_t *loc) { - token_info *ptinfo_beg = p->token_info, ptinfo_end_body, *ptinfo_end = &ptinfo_end_body; - setup_token_info(ptinfo_end, p->lex.pbeg, loc); + token_info *ptinfo_beg = p->token_info; if (!ptinfo_beg) return; p->token_info = ptinfo_beg->next; /* indentation check of matched keywords (begin..end, if..end, etc.) */ - if (!p->token_info_enabled) goto ok; /* the check is off */ - if (ptinfo_beg->linenum == ptinfo_end->linenum) goto ok; /* ignore one-line block */ - if (ptinfo_beg->nonspc || ptinfo_end->nonspc) goto ok; /* ignore keyword in the middle of a line */ - if (ptinfo_beg->column == ptinfo_end->column) goto ok; /* the indents are matched */ + token_info_warn(p, token, ptinfo_beg, loc); + xfree(ptinfo_beg); +} + +static void +token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, const rb_code_location_t *loc) +{ + token_info ptinfo_end_body, *ptinfo_end = &ptinfo_end_body; + if (!p->token_info_enabled) return; + if (!ptinfo_beg) return; + setup_token_info(ptinfo_end, p->lex.pbeg, loc); + if (ptinfo_beg->linenum == ptinfo_end->linenum) return; /* ignore one-line block */ + if (ptinfo_beg->nonspc || ptinfo_end->nonspc) return; /* ignore keyword in the middle of a line */ + if (ptinfo_beg->column == ptinfo_end->column) return; /* the indents are matched */ rb_warn3L(ptinfo_end->linenum, "mismatched indentations at '%s' with '%s' at %d", WARN_S(token), WARN_S(ptinfo_beg->token), WARN_I(ptinfo_beg->linenum)); -ok: - xfree(ptinfo_beg); } static int diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 7c733a4d8e..4479bd5d9b 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -445,10 +445,17 @@ class TestRubyOptions < Test::Unit::TestCase "begin", "if false", "for _ in []", "while false", "def foo", "class X", "module M", ["-> do", "end"], ["-> {", "}"], + ["if false;", "else ; end"], + ["if false;", "elsif false ; end"], + ["begin", "rescue ; end"], + ["begin rescue", "else ; end"], + ["begin", "ensure ; end"], + ["case nil", "when true; end"], ].each do |b, e = 'end'| src = ["#{b}\n", " #{e}\n"] k = b[/\A\S+/] + e = e[/\A\S+/] a.for("no directives with #{b}") do err = ["#{t.path}:2: warning: mismatched indentations at '#{e}' with '#{k}' at 1"]