[ruby/yarp] Add implicit nodes for ommitted hash values

https://github.com/ruby/yarp/commit/22130b3491
This commit is contained in:
Kevin Newton 2023-09-13 09:39:20 -04:00 committed by git
parent 5a6eae0b0a
commit 5f9f2fd72e
8 changed files with 171 additions and 10 deletions

View File

@ -410,6 +410,20 @@ module YARP
assert_location(ImaginaryNode, "1ri")
end
def test_ImplicitNode
assert_location(ImplicitNode, "{ foo: }", 2...6) do |node|
node.elements.first.value
end
assert_location(ImplicitNode, "{ Foo: }", 2..6) do |node|
node.elements.first.value
end
assert_location(ImplicitNode, "foo = 1; { foo: }", 11..15) do |node|
node.elements.first.value
end
end
def test_InNode
assert_location(InNode, "case foo; in bar; end", 10...16) do |node|
node.conditions.first

View File

@ -240,7 +240,19 @@
│ │ │ │ ├── value_loc: (248...249) = "b"
│ │ │ │ ├── closing_loc: (249...250) = ":"
│ │ │ │ └── unescaped: "b"
│ │ │ ├── value: ∅
│ │ │ ├── value:
│ │ │ │ @ ImplicitNode (location: (248...250))
│ │ │ │ └── value:
│ │ │ │ @ CallNode (location: (248...250))
│ │ │ │ ├── receiver: ∅
│ │ │ │ ├── call_operator_loc: ∅
│ │ │ │ ├── message_loc: (248...249) = "b"
│ │ │ │ ├── opening_loc: ∅
│ │ │ │ ├── arguments: ∅
│ │ │ │ ├── closing_loc: ∅
│ │ │ │ ├── block: ∅
│ │ │ │ ├── flags: ∅
│ │ │ │ └── name: "b"
│ │ │ └── operator_loc: ∅
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅

View File

@ -340,7 +340,19 @@
│ │ │ │ ├── value_loc: (303...304) = "b"
│ │ │ │ ├── closing_loc: (304...305) = ":"
│ │ │ │ └── unescaped: "b"
│ │ │ ├── value: ∅
│ │ │ ├── value:
│ │ │ │ @ ImplicitNode (location: (303...305))
│ │ │ │ └── value:
│ │ │ │ @ CallNode (location: (303...305))
│ │ │ │ ├── receiver: ∅
│ │ │ │ ├── call_operator_loc: ∅
│ │ │ │ ├── message_loc: (303...304) = "b"
│ │ │ │ ├── opening_loc: ∅
│ │ │ │ ├── arguments: ∅
│ │ │ │ ├── closing_loc: ∅
│ │ │ │ ├── block: ∅
│ │ │ │ ├── flags: ∅
│ │ │ │ └── name: "b"
│ │ │ └── operator_loc: ∅
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅

View File

@ -13,6 +13,18 @@
│ │ ├── value_loc: (2...3) = "y"
│ │ ├── closing_loc: (3...4) = ":"
│ │ └── unescaped: "y"
│ ├── value: ∅
│ ├── value:
│ │ @ ImplicitNode (location: (2...4))
│ │ └── value:
│ │ @ CallNode (location: (2...4))
│ │ ├── receiver: ∅
│ │ ├── call_operator_loc: ∅
│ │ ├── message_loc: (2...3) = "y"
│ │ ├── opening_loc: ∅
│ │ ├── arguments: ∅
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅
│ │ ├── flags: ∅
│ │ └── name: "y"
│ └── operator_loc: ∅
└── closing_loc: (5...6) = "}"

View File

@ -13,7 +13,11 @@
│ │ │ ├── value_loc: (1...4) = "BAR"
│ │ │ ├── closing_loc: (4...5) = ":"
│ │ │ └── unescaped: "BAR"
│ │ ├── value: ∅
│ │ ├── value:
│ │ │ @ ImplicitNode (location: (1...5))
│ │ │ └── value:
│ │ │ @ ConstantReadNode (location: (1...5))
│ │ │ └── name: :BAR
│ │ └── operator_loc: ∅
│ └── closing_loc: (5...6) = "}"
├── @ HashNode (location: (8...16))
@ -26,7 +30,19 @@
│ │ │ │ ├── value_loc: (9...10) = "a"
│ │ │ │ ├── closing_loc: (10...11) = ":"
│ │ │ │ └── unescaped: "a"
│ │ │ ├── value: ∅
│ │ │ ├── value:
│ │ │ │ @ ImplicitNode (location: (9...11))
│ │ │ │ └── value:
│ │ │ │ @ CallNode (location: (9...11))
│ │ │ │ ├── receiver: ∅
│ │ │ │ ├── call_operator_loc: ∅
│ │ │ │ ├── message_loc: (9...10) = "a"
│ │ │ │ ├── opening_loc: ∅
│ │ │ │ ├── arguments: ∅
│ │ │ │ ├── closing_loc: ∅
│ │ │ │ ├── block: ∅
│ │ │ │ ├── flags: ∅
│ │ │ │ └── name: "a"
│ │ │ └── operator_loc: ∅
│ │ └── @ AssocNode (location: (13...15))
│ │ ├── key:
@ -35,7 +51,19 @@
│ │ │ ├── value_loc: (13...14) = "b"
│ │ │ ├── closing_loc: (14...15) = ":"
│ │ │ └── unescaped: "b"
│ │ ├── value: ∅
│ │ ├── value:
│ │ │ @ ImplicitNode (location: (13...15))
│ │ │ └── value:
│ │ │ @ CallNode (location: (13...15))
│ │ │ ├── receiver: ∅
│ │ │ ├── call_operator_loc: ∅
│ │ │ ├── message_loc: (13...14) = "b"
│ │ │ ├── opening_loc: ∅
│ │ │ ├── arguments: ∅
│ │ │ ├── closing_loc: ∅
│ │ │ ├── block: ∅
│ │ │ ├── flags: ∅
│ │ │ └── name: "b"
│ │ └── operator_loc: ∅
│ └── closing_loc: (15...16) = "}"
└── @ HashNode (location: (18...25))
@ -48,6 +76,18 @@
│ │ ├── value_loc: (19...23) = "puts"
│ │ ├── closing_loc: (23...24) = ":"
│ │ └── unescaped: "puts"
│ ├── value: ∅
│ ├── value:
│ │ @ ImplicitNode (location: (19...24))
│ │ └── value:
│ │ @ CallNode (location: (19...24))
│ │ ├── receiver: ∅
│ │ ├── call_operator_loc: ∅
│ │ ├── message_loc: (19...23) = "puts"
│ │ ├── opening_loc: ∅
│ │ ├── arguments: ∅
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅
│ │ ├── flags: ∅
│ │ └── name: "puts"
│ └── operator_loc: ∅
└── closing_loc: (24...25) = "}"

View File

@ -20,7 +20,19 @@
│ │ │ ├── value_loc: (4...5) = "a"
│ │ │ ├── closing_loc: (5...6) = ":"
│ │ │ └── unescaped: "a"
│ │ ├── value: ∅
│ │ ├── value:
│ │ │ @ ImplicitNode (location: (4...6))
│ │ │ └── value:
│ │ │ @ CallNode (location: (4...6))
│ │ │ ├── receiver: ∅
│ │ │ ├── call_operator_loc: ∅
│ │ │ ├── message_loc: (4...5) = "a"
│ │ │ ├── opening_loc: ∅
│ │ │ ├── arguments: ∅
│ │ │ ├── closing_loc: ∅
│ │ │ ├── block: ∅
│ │ │ ├── flags: ∅
│ │ │ └── name: "a"
│ │ └── operator_loc: ∅
│ └── @ AssocNode (location: (8...10))
│ ├── key:
@ -29,7 +41,19 @@
│ │ ├── value_loc: (8...9) = "b"
│ │ ├── closing_loc: (9...10) = ":"
│ │ └── unescaped: "b"
│ ├── value: ∅
│ ├── value:
│ │ @ ImplicitNode (location: (8...10))
│ │ └── value:
│ │ @ CallNode (location: (8...10))
│ │ ├── receiver: ∅
│ │ ├── call_operator_loc: ∅
│ │ ├── message_loc: (8...9) = "b"
│ │ ├── opening_loc: ∅
│ │ ├── arguments: ∅
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅
│ │ ├── flags: ∅
│ │ └── name: "b"
│ └── operator_loc: ∅
├── closing_loc: (10...11) = ")"
├── block: ∅

View File

@ -1413,6 +1413,19 @@ nodes:
1.0i
^^^^
- name: ImplicitNode
fields:
- name: value
type: node
comment: |
Represents a node that is implicitly being added to the tree but doesn't
correspond directly to a node in the source.
{ foo: }
^^^^
{ Foo: }
^^^^
- name: InNode
fields:
- name: pattern

View File

@ -2737,6 +2737,22 @@ yp_else_node_end_keyword_loc_set(yp_else_node_t *node, const yp_token_t *keyword
node->end_keyword_loc = YP_LOCATION_TOKEN_VALUE(keyword);
}
// Allocate and initialize a new ImplicitNode node.
static yp_implicit_node_t *
yp_implicit_node_create(yp_parser_t *parser, yp_node_t *value) {
yp_implicit_node_t *node = YP_ALLOC_NODE(parser, yp_implicit_node_t);
*node = (yp_implicit_node_t) {
{
.type = YP_IMPLICIT_NODE,
.location = value->location
},
.value = value
};
return node;
}
// Allocate and initialize a new IntegerNode node.
static yp_integer_node_t *
yp_integer_node_create(yp_parser_t *parser, yp_node_flags_t base, const yp_token_t *token) {
@ -8715,14 +8731,32 @@ parse_assocs(yp_parser_t *parser, yp_node_t *node) {
break;
}
case YP_TOKEN_LABEL: {
yp_token_t label = parser->current;
parser_lex(parser);
yp_node_t *key = (yp_node_t *) yp_symbol_node_label_create(parser, &parser->previous);
yp_node_t *key = (yp_node_t *) yp_symbol_node_label_create(parser, &label);
yp_token_t operator = not_provided(parser);
yp_node_t *value = NULL;
if (token_begins_expression_p(parser->current.type)) {
value = parse_expression(parser, YP_BINDING_POWER_DEFINED, YP_ERR_HASH_EXPRESSION_AFTER_LABEL);
} else {
if (parser->encoding.isupper_char(label.start, (label.end - 1) - label.start)) {
yp_token_t constant = { .type = YP_TOKEN_CONSTANT, .start = label.start, .end = label.end - 1 };
value = (yp_node_t *) yp_constant_read_node_create(parser, &constant);
} else {
int depth = yp_parser_local_depth(parser, &((yp_token_t) { .type = YP_TOKEN_IDENTIFIER, .start = label.start, .end = label.end - 1 }));
yp_token_t identifier = { .type = YP_TOKEN_IDENTIFIER, .start = label.start, .end = label.end - 1 };
if (depth == -1) {
value = (yp_node_t *) yp_call_node_variable_call_create(parser, &identifier);
} else {
value = (yp_node_t *) yp_local_variable_read_node_create(parser, &identifier, (uint32_t) depth);
}
}
value->location.end++;
value = (yp_node_t *) yp_implicit_node_create(parser, value);
}
element = (yp_node_t *) yp_assoc_node_create(parser, key, &operator, value);