Skip to content

Commit d023e10

Browse files
nicolo-ribaudoJLHwung
authored andcommitted
[TS] Parse calls with type args in optional chains (#10631)
* [TS] Parse calls with type args in optional chains * Test output
1 parent abce0ef commit d023e10

6 files changed

Lines changed: 204 additions & 29 deletions

File tree

packages/babel-parser/src/parser/expression.js

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ export default class ExpressionParser extends LValParser {
628628
node.callee = base;
629629
node.arguments = this.parseCallExpressionArguments(tt.parenR, false);
630630
node.optional = true;
631-
return this.finishNode(node, "OptionalCallExpression");
631+
return this.finishCallExpression(node, /* optional */ true);
632632
} else {
633633
node.object = base;
634634
node.property = this.parseIdentifier(true);
@@ -683,11 +683,7 @@ export default class ExpressionParser extends LValParser {
683683
base.type !== "Super",
684684
node,
685685
);
686-
if (!state.optionalChainMember) {
687-
this.finishCallExpression(node);
688-
} else {
689-
this.finishOptionalCallExpression(node);
690-
}
686+
this.finishCallExpression(node, state.optionalChainMember);
691687

692688
if (state.maybeAsyncArrow && this.shouldParseAsyncArrow()) {
693689
state.stop = true;
@@ -783,21 +779,10 @@ export default class ExpressionParser extends LValParser {
783779
);
784780
}
785781

786-
finishCallExpression(node: N.CallExpression): N.CallExpression {
787-
if (node.callee.type === "Import") {
788-
if (node.arguments.length !== 1) {
789-
this.raise(node.start, "import() requires exactly one argument");
790-
}
791-
792-
const importArg = node.arguments[0];
793-
if (importArg && importArg.type === "SpreadElement") {
794-
this.raise(importArg.start, "... is not allowed in import()");
795-
}
796-
}
797-
return this.finishNode(node, "CallExpression");
798-
}
799-
800-
finishOptionalCallExpression(node: N.CallExpression): N.CallExpression {
782+
finishCallExpression<T: N.CallExpression | N.OptionalCallExpression>(
783+
node: T,
784+
optional: boolean,
785+
): T {
801786
if (node.callee.type === "Import") {
802787
if (node.arguments.length !== 1) {
803788
this.raise(node.start, "import() requires exactly one argument");
@@ -808,7 +793,10 @@ export default class ExpressionParser extends LValParser {
808793
this.raise(importArg.start, "... is not allowed in import()");
809794
}
810795
}
811-
return this.finishNode(node, "OptionalCallExpression");
796+
return this.finishNode(
797+
node,
798+
optional ? "OptionalCallExpression" : "CallExpression",
799+
);
812800
}
813801

814802
parseCallExpressionArguments(

packages/babel-parser/src/plugins/flow.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,7 +2709,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
27092709
// $FlowFixMe
27102710
node.arguments = this.parseCallExpressionArguments(tt.parenR, false);
27112711
node.optional = true;
2712-
return this.finishNode(node, "OptionalCallExpression");
2712+
return this.finishCallExpression(node, /* optional */ true);
27132713
} else if (
27142714
!noCalls &&
27152715
this.shouldParseTypes() &&
@@ -2722,11 +2722,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
27222722
node.typeArguments = this.flowParseTypeParameterInstantiationCallOrNew();
27232723
this.expect(tt.parenL);
27242724
node.arguments = this.parseCallExpressionArguments(tt.parenR, false);
2725-
if (subscriptState.optionalChainMember) {
2726-
node.optional = false;
2727-
return this.finishNode(node, "OptionalCallExpression");
2728-
}
2729-
return this.finishNode(node, "CallExpression");
2725+
if (subscriptState.optionalChainMember) node.optional = false;
2726+
return this.finishCallExpression(
2727+
node,
2728+
subscriptState.optionalChainMember,
2729+
);
27302730
} catch (e) {
27312731
if (e instanceof SyntaxError) {
27322732
this.state = state;

packages/babel-parser/src/plugins/typescript/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
16551655
/* possibleAsync */ false,
16561656
);
16571657
node.typeParameters = typeArguments;
1658-
return this.finishCallExpression(node);
1658+
return this.finishCallExpression(node, state.optionalChainMember);
16591659
} else if (this.match(tt.backQuote)) {
16601660
return this.parseTaggedTemplateExpression(
16611661
startPos,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example.inner?.greet<string>()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"sourceType": "module",
3+
"plugins": ["typescript", "optionalChaining"]
4+
}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
{
2+
"type": "File",
3+
"start": 0,
4+
"end": 30,
5+
"loc": {
6+
"start": {
7+
"line": 1,
8+
"column": 0
9+
},
10+
"end": {
11+
"line": 1,
12+
"column": 30
13+
}
14+
},
15+
"program": {
16+
"type": "Program",
17+
"start": 0,
18+
"end": 30,
19+
"loc": {
20+
"start": {
21+
"line": 1,
22+
"column": 0
23+
},
24+
"end": {
25+
"line": 1,
26+
"column": 30
27+
}
28+
},
29+
"sourceType": "module",
30+
"interpreter": null,
31+
"body": [
32+
{
33+
"type": "ExpressionStatement",
34+
"start": 0,
35+
"end": 30,
36+
"loc": {
37+
"start": {
38+
"line": 1,
39+
"column": 0
40+
},
41+
"end": {
42+
"line": 1,
43+
"column": 30
44+
}
45+
},
46+
"expression": {
47+
"type": "OptionalCallExpression",
48+
"start": 0,
49+
"end": 30,
50+
"loc": {
51+
"start": {
52+
"line": 1,
53+
"column": 0
54+
},
55+
"end": {
56+
"line": 1,
57+
"column": 30
58+
}
59+
},
60+
"callee": {
61+
"type": "OptionalMemberExpression",
62+
"start": 0,
63+
"end": 20,
64+
"loc": {
65+
"start": {
66+
"line": 1,
67+
"column": 0
68+
},
69+
"end": {
70+
"line": 1,
71+
"column": 20
72+
}
73+
},
74+
"object": {
75+
"type": "MemberExpression",
76+
"start": 0,
77+
"end": 13,
78+
"loc": {
79+
"start": {
80+
"line": 1,
81+
"column": 0
82+
},
83+
"end": {
84+
"line": 1,
85+
"column": 13
86+
}
87+
},
88+
"object": {
89+
"type": "Identifier",
90+
"start": 0,
91+
"end": 7,
92+
"loc": {
93+
"start": {
94+
"line": 1,
95+
"column": 0
96+
},
97+
"end": {
98+
"line": 1,
99+
"column": 7
100+
},
101+
"identifierName": "example"
102+
},
103+
"name": "example"
104+
},
105+
"property": {
106+
"type": "Identifier",
107+
"start": 8,
108+
"end": 13,
109+
"loc": {
110+
"start": {
111+
"line": 1,
112+
"column": 8
113+
},
114+
"end": {
115+
"line": 1,
116+
"column": 13
117+
},
118+
"identifierName": "inner"
119+
},
120+
"name": "inner"
121+
},
122+
"computed": false
123+
},
124+
"property": {
125+
"type": "Identifier",
126+
"start": 15,
127+
"end": 20,
128+
"loc": {
129+
"start": {
130+
"line": 1,
131+
"column": 15
132+
},
133+
"end": {
134+
"line": 1,
135+
"column": 20
136+
},
137+
"identifierName": "greet"
138+
},
139+
"name": "greet"
140+
},
141+
"computed": false,
142+
"optional": true
143+
},
144+
"arguments": [],
145+
"typeParameters": {
146+
"type": "TSTypeParameterInstantiation",
147+
"start": 20,
148+
"end": 28,
149+
"loc": {
150+
"start": {
151+
"line": 1,
152+
"column": 20
153+
},
154+
"end": {
155+
"line": 1,
156+
"column": 28
157+
}
158+
},
159+
"params": [
160+
{
161+
"type": "TSStringKeyword",
162+
"start": 21,
163+
"end": 27,
164+
"loc": {
165+
"start": {
166+
"line": 1,
167+
"column": 21
168+
},
169+
"end": {
170+
"line": 1,
171+
"column": 27
172+
}
173+
}
174+
}
175+
]
176+
}
177+
}
178+
}
179+
],
180+
"directives": []
181+
}
182+
}

0 commit comments

Comments
 (0)