eslint-parser: ES2020 features (#11815)

* chore: update espree test on nullish coalescing

* feat: add optional chaining support

* fix: adapt to estree AST shape

* chore: update lockfile

* add estree optional-chaining test fixtures

* address review comments

* chore: simplify smoke test

* export * support

Co-authored-by: Brian Ng <bng412@gmail.com>
This commit is contained in:
Huáng Jùnliàng
2020-07-29 16:46:29 -04:00
committed by GitHub
parent 059e9124ff
commit d7347fb8bd
36 changed files with 690 additions and 60 deletions

View File

@@ -388,8 +388,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
delete node.arguments;
// $FlowIgnore - callee isn't optional in the type definition
delete node.callee;
} else if (node.type === "CallExpression") {
(node: N.Node).optional = false;
}
return node;
@@ -431,10 +429,38 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return node;
}
parseSubscript(...args) {
const node = super.parseSubscript(...args);
parseSubscript(
base: N.Expression,
startPos: number,
startLoc: Position,
noCalls: ?boolean,
state: N.ParseSubscriptState,
) {
const node = super.parseSubscript(
base,
startPos,
startLoc,
noCalls,
state,
);
if (node.type === "MemberExpression") {
if (state.optionalChainMember) {
// https://github.com/estree/estree/blob/master/es2020.md#chainexpression
if (
node.type === "OptionalMemberExpression" ||
node.type === "OptionalCallExpression"
) {
node.type = node.type.substring(8); // strip Optional prefix
}
if (state.stop) {
const chain = this.startNodeAtNode(node);
chain.expression = node;
return this.finishNode(chain, "ChainExpression");
}
} else if (
node.type === "MemberExpression" ||
node.type === "CallExpression"
) {
node.optional = false;
}

View File

@@ -0,0 +1 @@
(foo?.())()

View File

@@ -0,0 +1,41 @@
{
"type": "File",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"program": {
"type": "Program",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"expression": {
"type": "CallExpression",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"callee": {
"type": "ChainExpression",
"start":1,"end":8,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":8}},
"expression": {
"type": "CallExpression",
"start":1,"end":8,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":8}},
"callee": {
"type": "Identifier",
"start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4},"identifierName":"foo"},
"name": "foo"
},
"optional": true,
"arguments": []
},
"extra": {
"parenthesized": true,
"parenStart": 0
}
},
"arguments": [],
"optional": false
}
}
]
}
}

View File

@@ -0,0 +1,37 @@
{
"type": "File",
"start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}},
"program": {
"type": "Program",
"start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}},
"expression": {
"type": "ChainExpression",
"start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}},
"expression": {
"type": "CallExpression",
"start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}},
"callee": {
"type": "CallExpression",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"callee": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"optional": true,
"arguments": []
},
"optional": false,
"arguments": []
}
}
}
]
}
}

View File

@@ -0,0 +1,42 @@
{
"type": "File",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"program": {
"type": "Program",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"expression": {
"type": "ChainExpression",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"expression": {
"type": "MemberExpression",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"object": {
"type": "CallExpression",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"callee": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"optional": true,
"arguments": []
},
"property": {
"type": "Identifier",
"start":8,"end":11,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":11},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": false
}
}
}
]
}
}

View File

@@ -0,0 +1 @@
(foo?.()).bar

View File

@@ -0,0 +1,46 @@
{
"type": "File",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"program": {
"type": "Program",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"expression": {
"type": "MemberExpression",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"object": {
"type": "ChainExpression",
"start":1,"end":8,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":8}},
"expression": {
"type": "CallExpression",
"start":1,"end":8,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":8}},
"callee": {
"type": "Identifier",
"start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4},"identifierName":"foo"},
"name": "foo"
},
"optional": true,
"arguments": []
},
"extra": {
"parenthesized": true,
"parenStart": 0
}
},
"property": {
"type": "Identifier",
"start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": false
}
}
]
}
}

View File

@@ -0,0 +1,37 @@
{
"type": "File",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"program": {
"type": "Program",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"expression": {
"type": "ChainExpression",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"expression": {
"type": "CallExpression",
"start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}},
"callee": {
"type": "CallExpression",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"callee": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"optional": true,
"arguments": []
},
"optional": true,
"arguments": []
}
}
}
]
}
}

View File

@@ -0,0 +1,42 @@
{
"type": "File",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"program": {
"type": "Program",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"expression": {
"type": "ChainExpression",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"expression": {
"type": "MemberExpression",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"object": {
"type": "CallExpression",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"callee": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"optional": true,
"arguments": []
},
"property": {
"type": "Identifier",
"start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": true
}
}
}
]
}
}

View File

@@ -0,0 +1 @@
foo?.()

View File

@@ -0,0 +1,31 @@
{
"type": "File",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"program": {
"type": "Program",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"expression": {
"type": "ChainExpression",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"expression": {
"type": "CallExpression",
"start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}},
"callee": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"optional": true,
"arguments": []
}
}
}
]
}
}

View File

@@ -0,0 +1 @@
(foo?.bar)()

View File

@@ -0,0 +1,46 @@
{
"type": "File",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"program": {
"type": "Program",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"expression": {
"type": "CallExpression",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"callee": {
"type": "ChainExpression",
"start":1,"end":9,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":9}},
"expression": {
"type": "MemberExpression",
"start":1,"end":9,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":9}},
"object": {
"type": "Identifier",
"start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4},"identifierName":"foo"},
"name": "foo"
},
"property": {
"type": "Identifier",
"start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": true
},
"extra": {
"parenthesized": true,
"parenStart": 0
}
},
"arguments": [],
"optional": false
}
}
]
}
}

View File

@@ -0,0 +1,42 @@
{
"type": "File",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"program": {
"type": "Program",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"expression": {
"type": "ChainExpression",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"expression": {
"type": "CallExpression",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"callee": {
"type": "MemberExpression",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"object": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"property": {
"type": "Identifier",
"start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": true
},
"optional": false,
"arguments": []
}
}
}
]
}
}

View File

@@ -0,0 +1,47 @@
{
"type": "File",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"program": {
"type": "Program",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"expression": {
"type": "ChainExpression",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"expression": {
"type": "MemberExpression",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"object": {
"type": "MemberExpression",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"object": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"property": {
"type": "Identifier",
"start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": true
},
"property": {
"type": "Identifier",
"start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"qux"},
"name": "qux"
},
"computed": false,
"optional": false
}
}
}
]
}
}

View File

@@ -0,0 +1 @@
(foo?.bar).qux

View File

@@ -0,0 +1,51 @@
{
"type": "File",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"program": {
"type": "Program",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"expression": {
"type": "MemberExpression",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"object": {
"type": "ChainExpression",
"start":1,"end":9,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":9}},
"expression": {
"type": "MemberExpression",
"start":1,"end":9,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":9}},
"object": {
"type": "Identifier",
"start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4},"identifierName":"foo"},
"name": "foo"
},
"property": {
"type": "Identifier",
"start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": true
},
"extra": {
"parenthesized": true,
"parenStart": 0
}
},
"property": {
"type": "Identifier",
"start":11,"end":14,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":14},"identifierName":"qux"},
"name": "qux"
},
"computed": false,
"optional": false
}
}
]
}
}

View File

@@ -0,0 +1,42 @@
{
"type": "File",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"program": {
"type": "Program",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"expression": {
"type": "ChainExpression",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"expression": {
"type": "CallExpression",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}},
"callee": {
"type": "MemberExpression",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"object": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"property": {
"type": "Identifier",
"start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": true
},
"optional": true,
"arguments": []
}
}
}
]
}
}

View File

@@ -0,0 +1,47 @@
{
"type": "File",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"program": {
"type": "Program",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"expression": {
"type": "ChainExpression",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"expression": {
"type": "MemberExpression",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"object": {
"type": "MemberExpression",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"object": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"property": {
"type": "Identifier",
"start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": true
},
"property": {
"type": "Identifier",
"start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13},"identifierName":"qux"},
"name": "qux"
},
"computed": false,
"optional": true
}
}
}
]
}
}

View File

@@ -0,0 +1 @@
foo?.bar

View File

@@ -0,0 +1,36 @@
{
"type": "File",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"program": {
"type": "Program",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"expression": {
"type": "ChainExpression",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"expression": {
"type": "MemberExpression",
"start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}},
"object": {
"type": "Identifier",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"},
"name": "foo"
},
"property": {
"type": "Identifier",
"start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"},
"name": "bar"
},
"computed": false,
"optional": true
}
}
}
]
}
}