tree-sitter-javascript
tree-sitter-javascript copied to clipboard
Use new reserved words API to improve error recovery
⚠️ Depends on https://github.com/tree-sitter/tree-sitter/pull/1635. Don't merge yet. ⚠️
This PR makes use of Tree-sitter's upcoming "reserved words" feature in order to provide better error recovery in many common cases.
For example, the following code contains an error on line 2.
var a = {if: 1}; // <- valid
b = // <- incomplete
if (c) { // <- error should be detected at this "if"
a.if(); // <- valid
}
Previously, the parser would correctly allow the word if to be used as a property name on lines 1 and 4, but it would incorrectly allow the word if on line 3, which would prevent it from finding a good error recovery for the incomplete code on line 2.
Old Parse Tree - It would interpret the word if as an identifier, preventing it from correctly recognizing the if_statement below the error:
(program [0, 0] - [5, 0]
(variable_declaration [0, 0] - [0, 16]
(variable_declarator [0, 4] - [0, 15]
name: (identifier [0, 4] - [0, 5])
value: (object [0, 8] - [0, 15]
(pair [0, 9] - [0, 14]
key: (property_identifier [0, 9] - [0, 11])
value: (number [0, 13] - [0, 14])))))
(comment [0, 17] - [0, 28])
(expression_statement [1, 0] - [2, 6]
(assignment_expression [1, 0] - [2, 6]
left: (identifier [1, 0] - [1, 1])
(comment [1, 17] - [1, 33])
right: (call_expression [2, 0] - [2, 6]
function: (identifier [2, 0] - [2, 2])
arguments: (arguments [2, 3] - [2, 6]
(identifier [2, 4] - [2, 5])))))
(statement_block [2, 7] - [4, 1]
(comment [2, 17] - [2, 60])
(expression_statement [3, 2] - [3, 9]
(call_expression [3, 2] - [3, 8]
function: (member_expression [3, 2] - [3, 6]
object: (identifier [3, 2] - [3, 3])
property: (property_identifier [3, 4] - [3, 6]))
arguments: (arguments [3, 6] - [3, 8])))
(comment [3, 17] - [3, 28])))
test.js 0 ms (MISSING ";" [2, 6] - [2, 6])
New Parse Tree - On this branch, the if_statement is still parsed correctly, despite the error on the preceding line.
(program [0, 0] - [5, 0]
(variable_declaration [0, 0] - [0, 19]
(variable_declarator [0, 4] - [0, 18]
name: (identifier [0, 4] - [0, 5])
value: (object [0, 8] - [0, 18]
(pair [0, 9] - [0, 17]
key: (property_identifier [0, 9] - [0, 11])
value: (true [0, 13] - [0, 17])))))
(comment [0, 20] - [0, 31])
(ERROR [1, 0] - [1, 3]
(identifier [1, 0] - [1, 1]))
(comment [1, 20] - [1, 36])
(if_statement [2, 0] - [4, 1]
condition: (parenthesized_expression [2, 3] - [2, 10]
(member_expression [2, 4] - [2, 9]
object: (identifier [2, 4] - [2, 5])
property: (property_identifier [2, 6] - [2, 9])))
consequence: (statement_block [2, 11] - [4, 1]
(comment [2, 24] - [2, 67])
(expression_statement [3, 2] - [3, 9]
(call_expression [3, 2] - [3, 8]
function: (member_expression [3, 2] - [3, 6]
object: (identifier [3, 2] - [3, 3])
property: (property_identifier [3, 4] - [3, 6]))
arguments: (arguments [3, 6] - [3, 8])))
(comment [3, 20] - [3, 31]))))