mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Treat "end" as reserved word with consideration of indent
"end" after "." or "::" is treated as local variable or method, see `EXPR_DOT_bit` for detail. However this "changes" where `bar` method is defined. In the example below it is not module Z but class Foo. ``` module Z class Foo foo. end def bar end end ``` [Feature #19013]
This commit is contained in:
parent
342d4c16d9
commit
4f24f3ea94
Notes:
git
2022-10-08 17:59:34 +09:00
2 changed files with 87 additions and 1 deletions
37
parse.y
37
parse.y
|
@ -438,6 +438,13 @@ pop_end_expect_token_localtions(struct parser_params *p)
|
||||||
rb_ary_pop(p->end_expect_token_localtions);
|
rb_ary_pop(p->end_expect_token_localtions);
|
||||||
debug_end_expect_token_localtions(p, "pop_end_expect_token_localtions");
|
debug_end_expect_token_localtions(p, "pop_end_expect_token_localtions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
peek_end_expect_token_localtions(struct parser_params *p)
|
||||||
|
{
|
||||||
|
if(NIL_P(p->end_expect_token_localtions)) return Qnil;
|
||||||
|
return rb_ary_last(0, 0, p->end_expect_token_localtions);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RBIMPL_ATTR_NONNULL((1, 2, 3))
|
RBIMPL_ATTR_NONNULL((1, 2, 3))
|
||||||
|
@ -9285,6 +9292,7 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
|
||||||
int mb = ENC_CODERANGE_7BIT;
|
int mb = ENC_CODERANGE_7BIT;
|
||||||
const enum lex_state_e last_state = p->lex.state;
|
const enum lex_state_e last_state = p->lex.state;
|
||||||
ID ident;
|
ID ident;
|
||||||
|
int enforce_keyword_end = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
|
if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
|
||||||
|
@ -9314,7 +9322,34 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
|
||||||
return tLABEL;
|
return tLABEL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mb == ENC_CODERANGE_7BIT && !IS_lex_state(EXPR_DOT)) {
|
|
||||||
|
#ifndef RIPPER
|
||||||
|
if (!NIL_P(peek_end_expect_token_localtions(p))) {
|
||||||
|
VALUE end_loc;
|
||||||
|
int lineno, column;
|
||||||
|
int beg_pos = (int)(p->lex.ptok - p->lex.pbeg);
|
||||||
|
|
||||||
|
end_loc = peek_end_expect_token_localtions(p);
|
||||||
|
lineno = NUM2INT(rb_ary_entry(end_loc, 0));
|
||||||
|
column = NUM2INT(rb_ary_entry(end_loc, 1));
|
||||||
|
|
||||||
|
if (p->debug) {
|
||||||
|
rb_parser_printf(p, "enforce_keyword_end check. current: (%d, %d), peek: (%d, %d)\n",
|
||||||
|
p->ruby_sourceline, beg_pos, lineno, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p->ruby_sourceline > lineno) && (beg_pos <= column)) {
|
||||||
|
const struct kwtable *kw;
|
||||||
|
|
||||||
|
if ((IS_lex_state(EXPR_DOT)) && (kw = rb_reserved_word(tok(p), toklen(p))) && (kw && kw->id[0] == keyword_end)) {
|
||||||
|
if (p->debug) rb_parser_printf(p, "enforce_keyword_end is enabled\n");
|
||||||
|
enforce_keyword_end = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (mb == ENC_CODERANGE_7BIT && (!IS_lex_state(EXPR_DOT) || enforce_keyword_end)) {
|
||||||
const struct kwtable *kw;
|
const struct kwtable *kw;
|
||||||
|
|
||||||
/* See if it is a reserved word. */
|
/* See if it is a reserved word. */
|
||||||
|
|
|
@ -956,4 +956,55 @@ dummy
|
||||||
body: (VCALL@2:2-2:3 :a))))
|
body: (VCALL@2:2-2:3 :a))))
|
||||||
EXP
|
EXP
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_error_tolerant_treat_end_as_keyword_based_on_indent
|
||||||
|
node = RubyVM::AbstractSyntaxTree.parse(<<~STR, error_tolerant: true)
|
||||||
|
module Z
|
||||||
|
class Foo
|
||||||
|
foo.
|
||||||
|
end
|
||||||
|
|
||||||
|
def bar
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STR
|
||||||
|
|
||||||
|
str = ""
|
||||||
|
PP.pp(node, str)
|
||||||
|
assert_equal(<<~EXP, str)
|
||||||
|
(SCOPE@1:0-8:3
|
||||||
|
tbl: []
|
||||||
|
args: nil
|
||||||
|
body:
|
||||||
|
(MODULE@1:0-8:3 (COLON2@1:7-1:8 nil :Z)
|
||||||
|
(SCOPE@1:0-8:3
|
||||||
|
tbl: []
|
||||||
|
args: nil
|
||||||
|
body:
|
||||||
|
(BLOCK@1:8-8:3 (BEGIN@1:8-1:8 nil)
|
||||||
|
(CLASS@2:2-8:3 (COLON2@2:8-2:11 nil :Foo) nil
|
||||||
|
(SCOPE@2:2-8:3
|
||||||
|
tbl: []
|
||||||
|
args: nil
|
||||||
|
body:
|
||||||
|
(DEFN@6:2-7:5
|
||||||
|
mid: :bar
|
||||||
|
body:
|
||||||
|
(SCOPE@6:2-7:5
|
||||||
|
tbl: []
|
||||||
|
args:
|
||||||
|
(ARGS@6:9-6:9
|
||||||
|
pre_num: 0
|
||||||
|
pre_init: nil
|
||||||
|
opt: nil
|
||||||
|
first_post: nil
|
||||||
|
post_num: 0
|
||||||
|
post_init: nil
|
||||||
|
rest: nil
|
||||||
|
kw: nil
|
||||||
|
kwrest: nil
|
||||||
|
block: nil)
|
||||||
|
body: nil))))))))
|
||||||
|
EXP
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue