diff options
| author | TSUYUSATO Kitsune <make.just.on@gmail.com> | 2023-11-29 10:32:26 +0900 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2023-11-29 02:03:06 +0000 |
| commit | a908cef53f4c647c7fe7c9e808b501c3bb3cc70f (patch) | |
| tree | 5bcade9747f23bde3587ee114c4611800f82cecc | |
| parent | fcabe2df39b892458cb1f67437852c4acbb245a6 (diff) | |
[ruby/prism] Reject class/module defs in method params/rescue/ensure/else
Fix https://github.com/ruby/prism/pull/1936
https://github.com/ruby/prism/commit/232e77a003
| -rw-r--r-- | prism/diagnostic.c | 4 | ||||
| -rw-r--r-- | prism/parser.h | 9 | ||||
| -rw-r--r-- | prism/prism.c | 43 | ||||
| -rw-r--r-- | test/prism/errors_test.rb | 34 | ||||
| -rw-r--r-- | test/prism/fixtures/methods.txt | 2 | ||||
| -rw-r--r-- | test/prism/snapshots/methods.txt | 153 |
6 files changed, 174 insertions, 71 deletions
diff --git a/prism/diagnostic.c b/prism/diagnostic.c index e2181151c2..443ad35c6a 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -90,7 +90,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_CASE_MATCH_MISSING_PREDICATE] = "expected a predicate for a case matching statement", [PM_ERR_CASE_MISSING_CONDITIONS] = "expected a `when` or `in` clause after `case`", [PM_ERR_CASE_TERM] = "expected an `end` to close the `case` statement", - [PM_ERR_CLASS_IN_METHOD] = "unexpected class definition in a method body", + [PM_ERR_CLASS_IN_METHOD] = "unexpected class definition in a method definition", [PM_ERR_CLASS_NAME] = "expected a constant name after `class`", [PM_ERR_CLASS_SUPERCLASS] = "expected a superclass after `<`", [PM_ERR_CLASS_TERM] = "expected an `end` to close the `class` statement", @@ -185,7 +185,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_LIST_W_UPPER_ELEMENT] = "expected a string in a `%W` list", [PM_ERR_LIST_W_UPPER_TERM] = "expected a closing delimiter for the `%W` list", [PM_ERR_MALLOC_FAILED] = "failed to allocate memory", - [PM_ERR_MODULE_IN_METHOD] = "unexpected module definition in a method body", + [PM_ERR_MODULE_IN_METHOD] = "unexpected module definition in a method definition", [PM_ERR_MODULE_NAME] = "expected a constant name after `module`", [PM_ERR_MODULE_TERM] = "expected an `end` to close the `module` statement", [PM_ERR_MULTI_ASSIGN_MULTI_SPLATS] = "multiple splats in multiple assignment", diff --git a/prism/parser.h b/prism/parser.h index fec1036229..c1f9e0f663 100644 --- a/prism/parser.h +++ b/prism/parser.h @@ -297,6 +297,9 @@ typedef enum { /** an ensure statement */ PM_CONTEXT_ENSURE, + /** an ensure statement within a method definition */ + PM_CONTEXT_ENSURE_DEF, + /** a for loop */ PM_CONTEXT_FOR, @@ -333,9 +336,15 @@ typedef enum { /** a rescue else statement */ PM_CONTEXT_RESCUE_ELSE, + /** a rescue else statement within a method definition */ + PM_CONTEXT_RESCUE_ELSE_DEF, + /** a rescue statement */ PM_CONTEXT_RESCUE, + /** a rescue statement within a method definition */ + PM_CONTEXT_RESCUE_DEF, + /** a singleton class definition */ PM_CONTEXT_SCLASS, diff --git a/prism/prism.c b/prism/prism.c index 03b6204a78..41ed44e9c1 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -6603,6 +6603,7 @@ context_terminator(pm_context_t context, pm_token_t *token) { case PM_CONTEXT_ELSE: case PM_CONTEXT_FOR: case PM_CONTEXT_ENSURE: + case PM_CONTEXT_ENSURE_DEF: return token->type == PM_TOKEN_KEYWORD_END; case PM_CONTEXT_FOR_INDEX: return token->type == PM_TOKEN_KEYWORD_IN; @@ -6623,8 +6624,10 @@ context_terminator(pm_context_t context, pm_token_t *token) { return token->type == PM_TOKEN_PARENTHESIS_RIGHT; case PM_CONTEXT_BEGIN: case PM_CONTEXT_RESCUE: + case PM_CONTEXT_RESCUE_DEF: return token->type == PM_TOKEN_KEYWORD_ENSURE || token->type == PM_TOKEN_KEYWORD_RESCUE || token->type == PM_TOKEN_KEYWORD_ELSE || token->type == PM_TOKEN_KEYWORD_END; case PM_CONTEXT_RESCUE_ELSE: + case PM_CONTEXT_RESCUE_ELSE_DEF: return token->type == PM_TOKEN_KEYWORD_ENSURE || token->type == PM_TOKEN_KEYWORD_END; case PM_CONTEXT_LAMBDA_BRACES: return token->type == PM_TOKEN_BRACE_RIGHT; @@ -6690,6 +6693,10 @@ context_def_p(pm_parser_t *parser) { while (context_node != NULL) { switch (context_node->context) { case PM_CONTEXT_DEF: + case PM_CONTEXT_DEF_PARAMS: + case PM_CONTEXT_ENSURE_DEF: + case PM_CONTEXT_RESCUE_DEF: + case PM_CONTEXT_RESCUE_ELSE_DEF: return true; case PM_CONTEXT_CLASS: case PM_CONTEXT_MODULE: @@ -11837,7 +11844,7 @@ parse_parameters( * nodes pointing to each other from the top. */ static inline void -parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) { +parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, bool def_p) { pm_rescue_node_t *current = NULL; while (accept1(parser, PM_TOKEN_KEYWORD_RESCUE)) { @@ -11900,7 +11907,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) { if (!match3(parser, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_RESCUE); + pm_statements_node_t *statements = parse_statements(parser, def_p ? PM_CONTEXT_RESCUE_DEF : PM_CONTEXT_RESCUE); if (statements) { pm_rescue_node_statements_set(rescue, statements); } @@ -11936,7 +11943,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) { pm_statements_node_t *else_statements = NULL; if (!match2(parser, PM_TOKEN_KEYWORD_END, PM_TOKEN_KEYWORD_ENSURE)) { pm_accepts_block_stack_push(parser, true); - else_statements = parse_statements(parser, PM_CONTEXT_RESCUE_ELSE); + else_statements = parse_statements(parser, def_p ? PM_CONTEXT_RESCUE_ELSE_DEF : PM_CONTEXT_RESCUE_ELSE); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); } @@ -11952,7 +11959,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) { pm_statements_node_t *ensure_statements = NULL; if (!match1(parser, PM_TOKEN_KEYWORD_END)) { pm_accepts_block_stack_push(parser, true); - ensure_statements = parse_statements(parser, PM_CONTEXT_ENSURE); + ensure_statements = parse_statements(parser, def_p ? PM_CONTEXT_ENSURE_DEF : PM_CONTEXT_ENSURE); pm_accepts_block_stack_pop(parser); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); } @@ -11970,10 +11977,10 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) { } static inline pm_begin_node_t * -parse_rescues_as_begin(pm_parser_t *parser, pm_statements_node_t *statements) { +parse_rescues_as_begin(pm_parser_t *parser, pm_statements_node_t *statements, bool def_p) { pm_token_t no_begin_token = not_provided(parser); pm_begin_node_t *begin_node = pm_begin_node_create(parser, &no_begin_token, statements); - parse_rescues(parser, begin_node); + parse_rescues(parser, begin_node, def_p); // All nodes within a begin node are optional, so we look // for the earliest possible node that we can use to set @@ -12078,7 +12085,7 @@ parse_block(pm_parser_t *parser) { if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements); + statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false); } } @@ -14547,7 +14554,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { } pm_begin_node_t *begin_node = pm_begin_node_create(parser, &begin_keyword, begin_statements); - parse_rescues(parser, begin_node); + parse_rescues(parser, begin_node, false); expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BEGIN_TERM); begin_node->base.location.end = parser->previous.end; @@ -14665,7 +14672,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements); + statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false); } expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM); @@ -14717,7 +14724,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements); + statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false); } expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM); @@ -14744,6 +14751,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { pm_token_t operator = not_provided(parser); pm_token_t name = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = def_keyword.end, .end = def_keyword.end }; + // This context is necessary for lexing `...` in a bare params correctly. + // It must be pushed before lexing the first param, so it is here. context_push(parser, PM_CONTEXT_DEF_PARAMS); parser_lex(parser); pm_constant_id_t old_param_name = parser->current_param_name; @@ -14844,7 +14853,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { break; } case PM_TOKEN_PARENTHESIS_LEFT: { + // The current context is `PM_CONTEXT_DEF_PARAMS`, however the inner expression + // of this parenthesis should not be processed under this context. + // Thus, the context is popped here. + context_pop(parser); parser_lex(parser); + pm_token_t lparen = parser->previous; pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_DEF_RECEIVER); @@ -14859,6 +14873,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { pm_parser_scope_push(parser, true); parser->current_param_name = 0; + + // To push `PM_CONTEXT_DEF_PARAMS` again is for the same reason as described the above. + context_push(parser, PM_CONTEXT_DEF_PARAMS); name = parse_method_definition_name(parser); break; } @@ -14967,7 +14984,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements); + statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, true); } pm_accepts_block_stack_pop(parser); @@ -15222,7 +15239,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE)); - statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements); + statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false); } pm_constant_id_list_t locals = parser->current_scope->locals; @@ -15893,7 +15910,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { assert(body == NULL || PM_NODE_TYPE_P(body, PM_STATEMENTS_NODE)); - body = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) body); + body = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) body, false); } expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_LAMBDA_TERM_END); diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 871caa7475..4b745d31f8 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -428,7 +428,7 @@ module Prism ) assert_errors expected, "def foo;module A;end;end", [ - ["unexpected module definition in a method body", 8..14] + ["unexpected module definition in a method definition", 8..14] ] end @@ -467,7 +467,7 @@ module Prism Location() ) - assert_errors expected, <<~RUBY, [["unexpected module definition in a method body", 21..27]] + assert_errors expected, <<~RUBY, [["unexpected module definition in a method definition", 21..27]] def foo bar do module Foo;end @@ -476,6 +476,20 @@ module Prism RUBY end + def test_module_definition_in_method_defs + source = <<~RUBY + def foo(bar = module A;end);end + def foo;rescue;module A;end;end + def foo;ensure;module A;end;end + RUBY + message = "unexpected module definition in a method definition" + assert_errors expression(source), source, [ + [message, 14..20], + [message, 47..53], + [message, 79..85], + ] + end + def test_class_definition_in_method_body expected = DefNode( :foo, @@ -504,7 +518,21 @@ module Prism ) assert_errors expected, "def foo;class A;end;end", [ - ["unexpected class definition in a method body", 8..13] + ["unexpected class definition in a method definition", 8..13] + ] + end + + def test_class_definition_in_method_defs + source = <<~RUBY + def foo(bar = class A;end);end + def foo;rescue;class A;end;end + def foo;ensure;class A;end;end + RUBY + message = "unexpected class definition in a method definition" + assert_errors expression(source), source, [ + [message, 14..19], + [message, 46..51], + [message, 77..82], ] end diff --git a/test/prism/fixtures/methods.txt b/test/prism/fixtures/methods.txt index 3c382d07f0..703527f2de 100644 --- a/test/prism/fixtures/methods.txt +++ b/test/prism/fixtures/methods.txt @@ -182,3 +182,5 @@ def foo(...) end def foo(bar = (def baz(bar) = bar; 1)) = 2 + +def (class Foo; end).foo(bar = 1) = 2 diff --git a/test/prism/snapshots/methods.txt b/test/prism/snapshots/methods.txt index b0981f1202..960264f6a8 100644 --- a/test/prism/snapshots/methods.txt +++ b/test/prism/snapshots/methods.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(184,42)) +@ ProgramNode (location: (1,0)-(186,37)) ├── locals: [:a, :c, :foo] └── statements: - @ StatementsNode (location: (1,0)-(184,42)) - └── body: (length: 69) + @ StatementsNode (location: (1,0)-(186,37)) + └── body: (length: 70) ├── @ DefNode (location: (1,0)-(2,3)) │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" @@ -1888,69 +1888,116 @@ │ ├── rparen_loc: (180,11)-(180,12) = ")" │ ├── equal_loc: ∅ │ └── end_keyword_loc: (182,0)-(182,3) = "end" - └── @ DefNode (location: (184,0)-(184,42)) + ├── @ DefNode (location: (184,0)-(184,42)) + │ ├── name: :foo + │ ├── name_loc: (184,4)-(184,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (184,8)-(184,37)) + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 1) + │ │ │ └── @ OptionalParameterNode (location: (184,8)-(184,37)) + │ │ │ ├── name: :bar + │ │ │ ├── name_loc: (184,8)-(184,11) = "bar" + │ │ │ ├── operator_loc: (184,12)-(184,13) = "=" + │ │ │ └── value: + │ │ │ @ ParenthesesNode (location: (184,14)-(184,37)) + │ │ │ ├── body: + │ │ │ │ @ StatementsNode (location: (184,15)-(184,36)) + │ │ │ │ └── body: (length: 2) + │ │ │ │ ├── @ DefNode (location: (184,15)-(184,33)) + │ │ │ │ │ ├── name: :baz + │ │ │ │ │ ├── name_loc: (184,19)-(184,22) = "baz" + │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ ├── parameters: + │ │ │ │ │ │ @ ParametersNode (location: (184,23)-(184,26)) + │ │ │ │ │ │ ├── requireds: (length: 1) + │ │ │ │ │ │ │ └── @ RequiredParameterNode (location: (184,23)-(184,26)) + │ │ │ │ │ │ │ └── name: :bar + │ │ │ │ │ │ ├── optionals: (length: 0) + │ │ │ │ │ │ ├── rest: ∅ + │ │ │ │ │ │ ├── posts: (length: 0) + │ │ │ │ │ │ ├── keywords: (length: 0) + │ │ │ │ │ │ ├── keyword_rest: ∅ + │ │ │ │ │ │ └── block: ∅ + │ │ │ │ │ ├── body: + │ │ │ │ │ │ @ StatementsNode (location: (184,30)-(184,33)) + │ │ │ │ │ │ └── body: (length: 1) + │ │ │ │ │ │ └── @ LocalVariableReadNode (location: (184,30)-(184,33)) + │ │ │ │ │ │ ├── name: :bar + │ │ │ │ │ │ └── depth: 0 + │ │ │ │ │ ├── locals: [:bar] + │ │ │ │ │ ├── def_keyword_loc: (184,15)-(184,18) = "def" + │ │ │ │ │ ├── operator_loc: ∅ + │ │ │ │ │ ├── lparen_loc: (184,22)-(184,23) = "(" + │ │ │ │ │ ├── rparen_loc: (184,26)-(184,27) = ")" + │ │ │ │ │ ├── equal_loc: (184,28)-(184,29) = "=" + │ │ │ │ │ └── end_keyword_loc: ∅ + │ │ │ │ └── @ IntegerNode (location: (184,35)-(184,36)) + │ │ │ │ └── flags: decimal + │ │ │ ├── opening_loc: (184,14)-(184,15) = "(" + │ │ │ └── closing_loc: (184,36)-(184,37) = ")" + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (184,41)-(184,42)) + │ │ └── body: (length: 1) + │ │ └── @ IntegerNode (location: (184,41)-(184,42)) + │ │ └── flags: decimal + │ ├── locals: [:bar] + │ ├── def_keyword_loc: (184,0)-(184,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (184,7)-(184,8) = "(" + │ ├── rparen_loc: (184,37)-(184,38) = ")" + │ ├── equal_loc: (184,39)-(184,40) = "=" + │ └── end_keyword_loc: ∅ + └── @ DefNode (location: (186,0)-(186,37)) ├── name: :foo - ├── name_loc: (184,4)-(184,7) = "foo" - ├── receiver: ∅ + ├── name_loc: (186,21)-(186,24) = "foo" + ├── receiver: + │ @ ParenthesesNode (location: (186,4)-(186,20)) + │ ├── body: + │ │ @ ClassNode (location: (186,5)-(186,19)) + │ │ ├── locals: [] + │ │ ├── class_keyword_loc: (186,5)-(186,10) = "class" + │ │ ├── constant_path: + │ │ │ @ ConstantReadNode (location: (186,11)-(186,14)) + │ │ │ └── name: :Foo + │ │ ├── inheritance_operator_loc: ∅ + │ │ ├── superclass: ∅ + │ │ ├── body: ∅ + │ │ ├── end_keyword_loc: (186,16)-(186,19) = "end" + │ │ └── name: :Foo + │ ├── opening_loc: (186,4)-(186,5) = "(" + │ └── closing_loc: (186,19)-(186,20) = ")" ├── parameters: - │ @ ParametersNode (location: (184,8)-(184,37)) + │ @ ParametersNode (location: (186,25)-(186,32)) │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) - │ │ └── @ OptionalParameterNode (location: (184,8)-(184,37)) + │ │ └── @ OptionalParameterNode (location: (186,25)-(186,32)) │ │ ├── name: :bar - │ │ ├── name_loc: (184,8)-(184,11) = "bar" - │ │ ├── operator_loc: (184,12)-(184,13) = "=" + │ │ ├── name_loc: (186,25)-(186,28) = "bar" + │ │ ├── operator_loc: (186,29)-(186,30) = "=" │ │ └── value: - │ │ @ ParenthesesNode (location: (184,14)-(184,37)) - │ │ ├── body: - │ │ │ @ StatementsNode (location: (184,15)-(184,36)) - │ │ │ └── body: (length: 2) - │ │ │ ├── @ DefNode (location: (184,15)-(184,33)) - │ │ │ │ ├── name: :baz - │ │ │ │ ├── name_loc: (184,19)-(184,22) = "baz" - │ │ │ │ ├── receiver: ∅ - │ │ │ │ ├── parameters: - │ │ │ │ │ @ ParametersNode (location: (184,23)-(184,26)) - │ │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ │ └── @ RequiredParameterNode (location: (184,23)-(184,26)) - │ │ │ │ │ │ └── name: :bar - │ │ │ │ │ ├── optionals: (length: 0) - │ │ │ │ │ ├── rest: ∅ - │ │ │ │ │ ├── posts: (length: 0) - │ │ │ │ │ ├── keywords: (length: 0) - │ │ │ │ │ ├── keyword_rest: ∅ - │ │ │ │ │ └── block: ∅ - │ │ │ │ ├── body: - │ │ │ │ │ @ StatementsNode (location: (184,30)-(184,33)) - │ │ │ │ │ └── body: (length: 1) - │ │ │ │ │ └── @ LocalVariableReadNode (location: (184,30)-(184,33)) - │ │ │ │ │ ├── name: :bar - │ │ │ │ │ └── depth: 0 - │ │ │ │ ├── locals: [:bar] - │ │ │ │ ├── def_keyword_loc: (184,15)-(184,18) = "def" - │ │ │ │ ├── operator_loc: ∅ - │ │ │ │ ├── lparen_loc: (184,22)-(184,23) = "(" - │ │ │ │ ├── rparen_loc: (184,26)-(184,27) = ")" - │ │ │ │ ├── equal_loc: (184,28)-(184,29) = "=" - │ │ │ │ └── end_keyword_loc: ∅ - │ │ │ └── @ IntegerNode (location: (184,35)-(184,36)) - │ │ │ └── flags: decimal - │ │ ├── opening_loc: (184,14)-(184,15) = "(" - │ │ └── closing_loc: (184,36)-(184,37) = ")" + │ │ @ IntegerNode (location: (186,31)-(186,32)) + │ │ └── flags: decimal │ ├── rest: ∅ │ ├── posts: (length: 0) │ ├── keywords: (length: 0) │ ├── keyword_rest: ∅ │ └── block: ∅ ├── body: - │ @ StatementsNode (location: (184,41)-(184,42)) + │ @ StatementsNode (location: (186,36)-(186,37)) │ └── body: (length: 1) - │ └── @ IntegerNode (location: (184,41)-(184,42)) + │ └── @ IntegerNode (location: (186,36)-(186,37)) │ └── flags: decimal ├── locals: [:bar] - ├── def_keyword_loc: (184,0)-(184,3) = "def" - ├── operator_loc: ∅ - ├── lparen_loc: (184,7)-(184,8) = "(" - ├── rparen_loc: (184,37)-(184,38) = ")" - ├── equal_loc: (184,39)-(184,40) = "=" + ├── def_keyword_loc: (186,0)-(186,3) = "def" + ├── operator_loc: (186,20)-(186,21) = "." + ├── lparen_loc: (186,24)-(186,25) = "(" + ├── rparen_loc: (186,32)-(186,33) = ")" + ├── equal_loc: (186,34)-(186,35) = "=" └── end_keyword_loc: ∅ |
