Skip to content

Fix: allow reserved words as property identifiers after optional chaining#378

Open
rbonestell wants to merge 2 commits intotree-sitter:masterfrom
rbonestell:bug/377-opt-chaining-res-words
Open

Fix: allow reserved words as property identifiers after optional chaining#378
rbonestell wants to merge 2 commits intotree-sitter:masterfrom
rbonestell:bug/377-opt-chaining-res-words

Conversation

@rbonestell
Copy link

Summary

Fixes #377.

Reserved words (delete, class, return, etc.) are correctly treated as property_identifier nodes after . but produce ERROR nodes after ?. (optional chaining). This is because the reserved('properties', ...) context is not propagated through the ?. token path — likely a tree-sitter core issue.

This PR works around it by explicitly listing all reserved words as valid alternatives in the member_expression property field via a new _keyword_identifier rule.

Before:

a?.delete(b);  →  ERROR
a?.class;      →  ERROR
a?.return;     →  ERROR

After:

a?.delete(b);  →  (call_expression (member_expression … (optional_chain) (property_identifier)) (arguments …))
a?.class;      →  (member_expression … (optional_chain) (property_identifier))
a?.return;     →  (member_expression … (optional_chain) (property_identifier))

Changes

  • grammar.js: Extract RESERVED_WORDS and CONTEXTUAL_KEYWORDS as shared constants to eliminate duplication across reserved.global, _reserved_identifier, and the new _keyword_identifier rule. Add _keyword_identifier (inlined) to the member_expression property field alongside $.identifier inside the existing reserved('properties', ...) wrapper.
  • test/corpus/expressions.txt: Add test case for optional chaining with reserved words.
  • package.json: Add tree-sitter to devDependencies (required by bindings/node/binding_test.js).
  • .github/workflows/ci.yml: Pin node-version: 22 for Node binding tests (tree-sitter@0.25.0 cannot compile with Node 24).
  • src/: Regenerated via tree-sitter generate.

Notes

  • Parser impact is minimal: +10 states (+0.5%), +2.9% file size. LARGE_STATE_COUNT unchanged.
  • The reserved('properties', ...) wrapper is retained for the . path and forward compatibility — when tree-sitter core fixes the propagation issue, the explicit alternatives become redundant but harmless.
  • No existing tests are affected. All 117 corpus tests pass on all platforms.

…ning

Reserved words like 'delete', 'class', 'return' were producing ERROR nodes when used as property identifiers after '?.' (optional chaining), while working correctly after '.'. This adds a '_keyword_identifier' rule that explicitly lists all reserved words as valid alternatives in the member_expression property field, working around a tree-sitter core issue where the 'reserved()' context wasn't propagated through the '?.' token path.

Also extracts RESERVED_WORDS and CONTEXTUAL_KEYWORDS as shared constants to eliminate keyword list duplication across reserved.global, _reserved_identifier, and _keyword_identifier.

Fixes tree-sitter#377
Add tree-sitter to devDependencies (required by bindings/node/binding_test.js) and pin node-version to 22 (tree-sitter@0.25.0 cannot compile with Node 24).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Reserved words not recognized as property identifiers after optional chaining (?.)

1 participant