[ruby/prism] Allow writing to keywords with named captures if they are already locals

https://github.com/ruby/prism/commit/418318e1c8
This commit is contained in:
Kevin Newton 2024-03-28 15:48:44 -04:00 коммит произвёл git
Родитель 8780059c38
Коммит a8ec347ca2
3 изменённых файлов: 97 добавлений и 37 удалений

Просмотреть файл

@ -18107,9 +18107,6 @@ parse_regular_expression_named_capture(pm_parser_t *parser, const uint8_t *sourc
cursor += width;
}
// Finally, validate that the identifier is not a keywor.
if (pm_local_is_keyword((const char *) source, length)) return false;
return cursor == source + length;
}
@ -18170,16 +18167,19 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *
if (pm_constant_id_list_includes(&names, name)) continue;
pm_constant_id_list_append(&names, name);
int depth;
if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) {
// If the identifier is not already a local, then we'll add
// it to the local table unless it's a keyword.
if (pm_local_is_keyword((const char *) source, length)) continue;
pm_parser_local_add(parser, name);
}
// Here we lazily create the MatchWriteNode since we know we're
// about to add a target.
if (match == NULL) match = pm_match_write_node_create(parser, call);
// First, find the depth of the local that is being assigned.
int depth;
if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) {
pm_parser_local_add(parser, name);
}
// Next, create the local variable target and add it to the
// list of targets for the match.
pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create_values(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth);

Просмотреть файл

@ -41,4 +41,6 @@ tap { /(?<a>)/ =~ to_s }
/(?<foo>)/ =~ ""
/(?<Foo>)/ =~ ""
/(?<nil>)/ =~ ""
def foo(nil:) = /(?<nil>)/ =~ ""

Просмотреть файл

@ -1,8 +1,8 @@
@ ProgramNode (location: (1,0)-(44,16))
@ ProgramNode (location: (1,0)-(46,32))
├── locals: [:foo, :ab, :abc, :a]
└── statements:
@ StatementsNode (location: (1,0)-(44,16))
└── body: (length: 24)
@ StatementsNode (location: (1,0)-(46,32))
└── body: (length: 25)
├── @ CallNode (location: (1,0)-(1,9))
│ ├── flags: ignore_visibility
│ ├── receiver: ∅
@ -425,28 +425,86 @@
│ │ └── unescaped: ""
│ ├── closing_loc: ∅
│ └── block: ∅
└── @ CallNode (location: (44,0)-(44,16))
├── flags: ∅
├── receiver:
│ @ RegularExpressionNode (location: (44,0)-(44,10))
│ ├── flags: forced_us_ascii_encoding
│ ├── opening_loc: (44,0)-(44,1) = "/"
│ ├── content_loc: (44,1)-(44,9) = "(?<nil>)"
│ ├── closing_loc: (44,9)-(44,10) = "/"
│ └── unescaped: "(?<nil>)"
├── call_operator_loc: ∅
├── name: :=~
├── message_loc: (44,11)-(44,13) = "=~"
├── opening_loc: ∅
├── arguments:
│ @ ArgumentsNode (location: (44,14)-(44,16))
│ ├── flags: ∅
│ └── arguments: (length: 1)
│ └── @ StringNode (location: (44,14)-(44,16))
│ ├── flags: ∅
│ ├── opening_loc: (44,14)-(44,15) = "\""
│ ├── content_loc: (44,15)-(44,15) = ""
│ ├── closing_loc: (44,15)-(44,16) = "\""
│ └── unescaped: ""
├── closing_loc: ∅
└── block: ∅
├── @ CallNode (location: (45,0)-(45,16))
│ ├── flags: ∅
│ ├── receiver:
│ │ @ RegularExpressionNode (location: (45,0)-(45,10))
│ │ ├── flags: forced_us_ascii_encoding
│ │ ├── opening_loc: (45,0)-(45,1) = "/"
│ │ ├── content_loc: (45,1)-(45,9) = "(?<nil>)"
│ │ ├── closing_loc: (45,9)-(45,10) = "/"
│ │ └── unescaped: "(?<nil>)"
│ ├── call_operator_loc: ∅
│ ├── name: :=~
│ ├── message_loc: (45,11)-(45,13) = "=~"
│ ├── opening_loc: ∅
│ ├── arguments:
│ │ @ ArgumentsNode (location: (45,14)-(45,16))
│ │ ├── flags: ∅
│ │ └── arguments: (length: 1)
│ │ └── @ StringNode (location: (45,14)-(45,16))
│ │ ├── flags: ∅
│ │ ├── opening_loc: (45,14)-(45,15) = "\""
│ │ ├── content_loc: (45,15)-(45,15) = ""
│ │ ├── closing_loc: (45,15)-(45,16) = "\""
│ │ └── unescaped: ""
│ ├── closing_loc: ∅
│ └── block: ∅
└── @ DefNode (location: (46,0)-(46,32))
├── name: :foo
├── name_loc: (46,4)-(46,7) = "foo"
├── receiver: ∅
├── parameters:
│ @ ParametersNode (location: (46,8)-(46,12))
│ ├── requireds: (length: 0)
│ ├── optionals: (length: 0)
│ ├── rest: ∅
│ ├── posts: (length: 0)
│ ├── keywords: (length: 1)
│ │ └── @ RequiredKeywordParameterNode (location: (46,8)-(46,12))
│ │ ├── flags: ∅
│ │ ├── name: :nil
│ │ └── name_loc: (46,8)-(46,12) = "nil:"
│ ├── keyword_rest: ∅
│ └── block: ∅
├── body:
│ @ StatementsNode (location: (46,16)-(46,32))
│ └── body: (length: 1)
│ └── @ MatchWriteNode (location: (46,16)-(46,32))
│ ├── call:
│ │ @ CallNode (location: (46,16)-(46,32))
│ │ ├── flags: ∅
│ │ ├── receiver:
│ │ │ @ RegularExpressionNode (location: (46,16)-(46,26))
│ │ │ ├── flags: forced_us_ascii_encoding
│ │ │ ├── opening_loc: (46,16)-(46,17) = "/"
│ │ │ ├── content_loc: (46,17)-(46,25) = "(?<nil>)"
│ │ │ ├── closing_loc: (46,25)-(46,26) = "/"
│ │ │ └── unescaped: "(?<nil>)"
│ │ ├── call_operator_loc: ∅
│ │ ├── name: :=~
│ │ ├── message_loc: (46,27)-(46,29) = "=~"
│ │ ├── opening_loc: ∅
│ │ ├── arguments:
│ │ │ @ ArgumentsNode (location: (46,30)-(46,32))
│ │ │ ├── flags: ∅
│ │ │ └── arguments: (length: 1)
│ │ │ └── @ StringNode (location: (46,30)-(46,32))
│ │ │ ├── flags: ∅
│ │ │ ├── opening_loc: (46,30)-(46,31) = "\""
│ │ │ ├── content_loc: (46,31)-(46,31) = ""
│ │ │ ├── closing_loc: (46,31)-(46,32) = "\""
│ │ │ └── unescaped: ""
│ │ ├── closing_loc: ∅
│ │ └── block: ∅
│ └── targets: (length: 1)
│ └── @ LocalVariableTargetNode (location: (46,20)-(46,23))
│ ├── name: :nil
│ └── depth: 0
├── locals: [:nil]
├── def_keyword_loc: (46,0)-(46,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (46,7)-(46,8) = "("
├── rparen_loc: (46,12)-(46,13) = ")"
├── equal_loc: (46,14)-(46,15) = "="
└── end_keyword_loc: ∅