[前][次][番号順一覧][スレッド一覧]

ruby-changes:73925

From: yui-knk <ko1@a...>
Date: Sat, 8 Oct 2022 17:59:31 +0900 (JST)
Subject: [ruby-changes:73925] 4f24f3ea94 (master): Treat "end" as reserved word with consideration of indent

https://git.ruby-lang.org/ruby.git/commit/?id=4f24f3ea94

From 4f24f3ea94e43d1021fdd8548480f130f5112b99 Mon Sep 17 00:00:00 2001
From: yui-knk <spiketeika@g...>
Date: Sat, 1 Oct 2022 17:19:34 +0900
Subject: 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]
---
 parse.y               | 37 ++++++++++++++++++++++++++++++++++++-
 test/ruby/test_ast.rb | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/parse.y b/parse.y
index a1b1e2ee46..c0959a5e81 100644
--- a/parse.y
+++ b/parse.y
@@ -438,6 +438,13 @@ pop_end_expect_token_localtions(struct parser_params *p) https://github.com/ruby/ruby/blob/trunk/parse.y#L438
     rb_ary_pop(p->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
 
 RBIMPL_ATTR_NONNULL((1, 2, 3))
@@ -9285,6 +9292,7 @@ parse_ident(struct parser_params *p, int c, int cmd_state) https://github.com/ruby/ruby/blob/trunk/parse.y#L9292
     int mb = ENC_CODERANGE_7BIT;
     const enum lex_state_e last_state = p->lex.state;
     ID ident;
+    int enforce_keyword_end = 0;
 
     do {
 	if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
@@ -9314,7 +9322,34 @@ parse_ident(struct parser_params *p, int c, int cmd_state) https://github.com/ruby/ruby/blob/trunk/parse.y#L9322
 	    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;
 
 	/* See if it is a reserved word.  */
diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb
index 2f05bf97a1..033a09b4c0 100644
--- a/test/ruby/test_ast.rb
+++ b/test/ruby/test_ast.rb
@@ -956,4 +956,55 @@ dummy https://github.com/ruby/ruby/blob/trunk/test/ruby/test_ast.rb#L956
              body: (VCALL@2:2-2:3 :a))))
     EXP
   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
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]