1 /**
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "TSparser.h"
17
18 #include "parserFlags.h"
19 #include "util/helpers.h"
20 #include "varbinder/privateBinding.h"
21 #include "varbinder/scope.h"
22 #include "varbinder/tsBinding.h"
23 #include "lexer/TSLexer.h"
24 #include "ir/base/spreadElement.h"
25 #include "ir/base/decorator.h"
26 #include "ir/base/classElement.h"
27 #include "ir/base/classDefinition.h"
28 #include "ir/base/methodDefinition.h"
29 #include "ir/base/scriptFunction.h"
30 #include "ir/module/importDefaultSpecifier.h"
31 #include "ir/module/exportDefaultDeclaration.h"
32 #include "ir/module/exportAllDeclaration.h"
33 #include "ir/module/exportNamedDeclaration.h"
34 #include "ir/module/importDeclaration.h"
35 #include "ir/expressions/memberExpression.h"
36 #include "ir/expressions/sequenceExpression.h"
37 #include "ir/expressions/templateLiteral.h"
38 #include "ir/expressions/taggedTemplateExpression.h"
39 #include "ir/expressions/callExpression.h"
40 #include "ir/expressions/functionExpression.h"
41 #include "ir/expressions/arrowFunctionExpression.h"
42 #include "ir/expressions/yieldExpression.h"
43 #include "ir/expressions/assignmentExpression.h"
44 #include "ir/expressions/identifier.h"
45 #include "ir/expressions/objectExpression.h"
46 #include "ir/expressions/arrayExpression.h"
47 #include "ir/expressions/literals/bigIntLiteral.h"
48 #include "ir/expressions/literals/booleanLiteral.h"
49 #include "ir/expressions/literals/nullLiteral.h"
50 #include "ir/expressions/literals/numberLiteral.h"
51 #include "ir/expressions/literals/stringLiteral.h"
52 #include "ir/statements/emptyStatement.h"
53 #include "ir/statements/blockStatement.h"
54 #include "ir/statements/ifStatement.h"
55 #include "ir/statements/doWhileStatement.h"
56 #include "ir/statements/whileStatement.h"
57 #include "ir/statements/tryStatement.h"
58 #include "ir/statements/breakStatement.h"
59 #include "ir/statements/continueStatement.h"
60 #include "ir/statements/throwStatement.h"
61 #include "ir/statements/switchStatement.h"
62 #include "ir/statements/returnStatement.h"
63 #include "ir/statements/debuggerStatement.h"
64 #include "ir/statements/classDeclaration.h"
65 #include "ir/statements/labelledStatement.h"
66 #include "ir/statements/variableDeclarator.h"
67 #include "ir/statements/functionDeclaration.h"
68 #include "ir/ts/tsLiteralType.h"
69 #include "ir/ts/tsMappedType.h"
70 #include "ir/ts/tsImportType.h"
71 #include "ir/ts/tsThisType.h"
72 #include "ir/ts/tsConditionalType.h"
73 #include "ir/ts/tsTypeOperator.h"
74 #include "ir/ts/tsInferType.h"
75 #include "ir/ts/tsTupleType.h"
76 #include "ir/ts/tsNamedTupleMember.h"
77 #include "ir/ts/tsQualifiedName.h"
78 #include "ir/ts/tsIndexedAccessType.h"
79 #include "ir/ts/tsTypeQuery.h"
80 #include "ir/ts/tsTypeReference.h"
81 #include "ir/ts/tsTypePredicate.h"
82 #include "ir/ts/tsTypeLiteral.h"
83 #include "ir/ts/tsArrayType.h"
84 #include "ir/ts/tsUnionType.h"
85 #include "ir/ts/tsIntersectionType.h"
86 #include "ir/ts/tsAnyKeyword.h"
87 #include "ir/ts/tsUndefinedKeyword.h"
88 #include "ir/ts/tsVoidKeyword.h"
89 #include "ir/ts/tsNumberKeyword.h"
90 #include "ir/ts/tsStringKeyword.h"
91 #include "ir/ts/tsBooleanKeyword.h"
92 #include "ir/ts/tsBigintKeyword.h"
93 #include "ir/ts/tsUnknownKeyword.h"
94 #include "ir/ts/tsNullKeyword.h"
95 #include "ir/ts/tsNeverKeyword.h"
96 #include "ir/ts/tsObjectKeyword.h"
97 #include "ir/ts/tsFunctionType.h"
98 #include "ir/ts/tsConstructorType.h"
99 #include "ir/ts/tsParenthesizedType.h"
100 #include "ir/ts/tsTypeAssertion.h"
101 #include "ir/ts/tsAsExpression.h"
102 #include "ir/ts/tsNonNullExpression.h"
103 #include "ir/ts/tsEnumDeclaration.h"
104 #include "ir/ts/tsInterfaceDeclaration.h"
105 #include "ir/ts/tsTypeAliasDeclaration.h"
106 #include "ir/ts/tsModuleDeclaration.h"
107 #include "ir/ts/tsTypeParameterInstantiation.h"
108 #include "ir/ts/tsInterfaceHeritage.h"
109 #include "ir/base/tsSignatureDeclaration.h"
110 #include "ir/base/tsIndexSignature.h"
111 #include "ir/base/tsMethodSignature.h"
112 #include "ir/base/tsPropertySignature.h"
113 #include "ir/ts/tsParameterProperty.h"
114 #include "ir/ts/tsClassImplements.h"
115 #include "ir/ts/tsImportEqualsDeclaration.h"
116 #include "ir/ts/tsExternalModuleReference.h"
117
118 namespace ark::es2panda::parser {
ParsePotentialAsExpression(ir::Expression * expr)119 ir::Expression *TSParser::ParsePotentialAsExpression(ir::Expression *expr)
120 {
121 if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
122 return nullptr;
123 }
124
125 Lexer()->NextToken(); // eat 'as'
126 TypeAnnotationParsingOptions options =
127 TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_CONST;
128 ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
129
130 bool isConst = false;
131 if (typeAnnotation->IsTSTypeReference() && typeAnnotation->AsTSTypeReference()->TypeName()->IsIdentifier()) {
132 const util::StringView &refName = typeAnnotation->AsTSTypeReference()->TypeName()->AsIdentifier()->Name();
133 if (refName.Is("const")) {
134 isConst = true;
135 }
136 }
137
138 lexer::SourcePosition startLoc = expr->Start();
139 auto *asExpr = AllocNode<ir::TSAsExpression>(expr, typeAnnotation, isConst);
140 ES2PANDA_ASSERT(asExpr != nullptr);
141 asExpr->SetRange({startLoc, Lexer()->GetToken().End()});
142
143 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
144 return ParsePotentialAsExpression(asExpr);
145 }
146
147 return asExpr;
148 }
149
ParsePatternElementGetReturnNode(ExpressionParseFlags & flags,bool & isOptional)150 ir::AnnotatedExpression *TSParser::ParsePatternElementGetReturnNode(ExpressionParseFlags &flags, bool &isOptional)
151 {
152 switch (Lexer()->GetToken().Type()) {
153 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
154 ir::AnnotatedExpression *returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
155 isOptional = returnNode->AsArrayPattern()->IsOptional();
156 return returnNode;
157 }
158 case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
159 if ((flags & ExpressionParseFlags::IN_REST) != 0) {
160 ThrowSyntaxError("Unexpected token");
161 }
162
163 return ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
164 }
165 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
166 ir::AnnotatedExpression *returnNode =
167 ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
168 isOptional = returnNode->AsObjectPattern()->IsOptional();
169 return returnNode;
170 }
171 case lexer::TokenType::LITERAL_IDENT: {
172 ir::AnnotatedExpression *returnNode = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
173 ES2PANDA_ASSERT(returnNode != nullptr);
174
175 if (returnNode->AsIdentifier()->Decorators().empty()) {
176 returnNode->SetRange(Lexer()->GetToken().Loc());
177 } else {
178 returnNode->SetRange(
179 {returnNode->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()});
180 }
181
182 Lexer()->NextToken();
183
184 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
185 isOptional = true;
186
187 if ((flags & ExpressionParseFlags::IN_REST) != 0) {
188 ThrowSyntaxError("A rest parameter cannot be optional");
189 }
190
191 returnNode->AsIdentifier()->SetOptional(true);
192 Lexer()->NextToken();
193 }
194
195 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
196 Lexer()->NextToken(); // eat ':'
197 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
198 returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
199 }
200 return returnNode;
201 }
202 default: {
203 ThrowSyntaxError("Unexpected token, expected an identifier.");
204 }
205 }
206 }
207 // NOLINTNEXTLINE(google-default-arguments)
ParsePatternElement(ExpressionParseFlags flags,bool allowDefault)208 ir::Expression *TSParser::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault)
209 {
210 bool isOptional = false;
211 ir::AnnotatedExpression *returnNode = ParsePatternElementGetReturnNode(flags, isOptional);
212
213 if ((returnNode->IsObjectPattern() || returnNode->IsArrayPattern()) && !InAmbientContext() &&
214 ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && isOptional) {
215 ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.");
216 }
217
218 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
219 return returnNode;
220 }
221
222 if ((flags & ExpressionParseFlags::IN_REST) != 0) {
223 ThrowSyntaxError("A rest parameter cannot have an initializer.");
224 }
225
226 if (!allowDefault) {
227 ThrowSyntaxError("Invalid destructuring assignment target");
228 }
229
230 if (isOptional) {
231 ThrowSyntaxError("Parameter cannot have question mark and initializer");
232 }
233
234 Lexer()->NextToken();
235
236 if (((GetContext().Status() & ParserStatus::GENERATOR_FUNCTION) != 0) &&
237 Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD) {
238 ThrowSyntaxError("Yield is not allowed in generator parameters");
239 }
240
241 ir::Expression *rightNode = ParseExpression();
242
243 auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
244 ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
245 assignmentExpression->SetRange({returnNode->Start(), rightNode->End()});
246
247 return assignmentExpression;
248 }
249
CreateParameterProperty(ir::Expression * parameter,ir::ModifierFlags modifiers)250 ir::TSParameterProperty *TSParser::CreateParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
251 {
252 auto accessibilityOption = ir::AccessibilityOption::NO_OPTS;
253 bool readonly = false;
254 bool isStatic = false;
255 bool isExport = false;
256
257 if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) {
258 accessibilityOption = ir::AccessibilityOption::PRIVATE;
259 } else if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) {
260 accessibilityOption = ir::AccessibilityOption::PUBLIC;
261 } else if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) {
262 accessibilityOption = ir::AccessibilityOption::PROTECTED;
263 }
264
265 if ((modifiers & ir::ModifierFlags::READONLY) != 0) {
266 readonly = true;
267 }
268
269 if ((modifiers & ir::ModifierFlags::STATIC) != 0) {
270 isStatic = true;
271 }
272
273 // NOTE(Csaba Repasi): Handle export property of TSParameterProperty
274
275 return AllocNode<ir::TSParameterProperty>(accessibilityOption, parameter, readonly, isStatic, isExport);
276 }
277
ParseFunctionParameter()278 ir::Expression *TSParser::ParseFunctionParameter()
279 {
280 if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) {
281 Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
282 Lexer()->GetToken().SetTokenStr(ERROR_LITERAL);
283 }
284
285 lexer::SourcePosition parameterStart = Lexer()->GetToken().Start();
286 ir::ModifierFlags modifiers = ParseModifiers();
287 // NOTE(Csaba Repasi): throw error if using strick mode reserved keyword here
288 if (((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) && modifiers != ir::ModifierFlags::NONE) {
289 ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
290 }
291
292 if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
293 CheckRestrictedBinding();
294 }
295
296 ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
297
298 if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
299 ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
300 }
301
302 if (modifiers != ir::ModifierFlags::NONE &&
303 (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
304 (functionParameter->IsAssignmentPattern() &&
305 (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
306 functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
307 ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
308 }
309
310 if (modifiers != ir::ModifierFlags::NONE) {
311 functionParameter = CreateParameterProperty(functionParameter, modifiers);
312 functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
313 }
314
315 return functionParameter;
316 }
317
ParseModuleReference()318 ir::Expression *TSParser::ParseModuleReference()
319 {
320 ir::Expression *result = nullptr;
321
322 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE &&
323 Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_PAREN) {
324 lexer::SourcePosition start = Lexer()->GetToken().Start();
325 Lexer()->NextToken(); // eat 'require'
326 Lexer()->NextToken(); // eat '('
327
328 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
329 ThrowSyntaxError("String literal expected.");
330 }
331
332 result = AllocNode<ir::StringLiteral>(Lexer()->GetToken().String());
333 ES2PANDA_ASSERT(result != nullptr);
334 result->SetRange(Lexer()->GetToken().Loc());
335 Lexer()->NextToken();
336
337 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
338 ThrowSyntaxError("')' expected.");
339 }
340
341 result = AllocNode<ir::TSExternalModuleReference>(result);
342 result->SetRange({start, Lexer()->GetToken().End()});
343 Lexer()->NextToken(); // eat ')'
344 } else {
345 result = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
346 ES2PANDA_ASSERT(result != nullptr);
347 result->SetRange(Lexer()->GetToken().Loc());
348 Lexer()->NextToken();
349
350 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
351 result = ParseQualifiedReference(result);
352 }
353 }
354
355 return result;
356 }
357
ParseConstExpression()358 ir::TSTypeReference *TSParser::ParseConstExpression()
359 {
360 auto *identRef = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
361 ES2PANDA_ASSERT(identRef != nullptr);
362 identRef->SetRange(Lexer()->GetToken().Loc());
363
364 auto *typeReference = AllocNode<ir::TSTypeReference>(identRef, nullptr, Allocator());
365 ES2PANDA_ASSERT(typeReference);
366 typeReference->SetRange(Lexer()->GetToken().Loc());
367
368 Lexer()->NextToken();
369
370 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
371 Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
372 Lexer()->GetToken().Type() != lexer::TokenType::EOS &&
373 Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
374 ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0)) {
375 ThrowSyntaxError("Unexpected token.");
376 }
377
378 return typeReference;
379 }
380
ParsePotentialNonNullExpression(ir::Expression ** returnExpression,lexer::SourcePosition startLoc)381 bool TSParser::ParsePotentialNonNullExpression(ir::Expression **returnExpression, lexer::SourcePosition startLoc)
382 {
383 if (returnExpression == nullptr || Lexer()->GetToken().NewLine()) {
384 return true;
385 }
386
387 *returnExpression = AllocNode<ir::TSNonNullExpression>(*returnExpression);
388 ES2PANDA_ASSERT(*returnExpression != nullptr);
389 // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
390 (*returnExpression)->SetRange({startLoc, Lexer()->GetToken().End()});
391 Lexer()->NextToken();
392 return false;
393 }
394
395 // NOLINTNEXTLINE(google-default-arguments)
ParseObjectExpression(ExpressionParseFlags flags)396 ir::ObjectExpression *TSParser::ParseObjectExpression(ExpressionParseFlags flags)
397 {
398 ir::ObjectExpression *objExpression = ParserImpl::ParseObjectExpression(flags);
399 ParsePotentialOptionalFunctionParameter(objExpression);
400 return objExpression;
401 }
402
403 // NOLINTNEXTLINE(google-default-arguments)
ParseArrayExpression(ExpressionParseFlags flags)404 ir::ArrayExpression *TSParser::ParseArrayExpression(ExpressionParseFlags flags)
405 {
406 ir::ArrayExpression *arrayExpression = ParserImpl::ParseArrayExpression(flags);
407 ParsePotentialOptionalFunctionParameter(arrayExpression);
408 return arrayExpression;
409 }
410 class TSParser::ParsePotentialArrowExpressionHelper {
411 friend ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression,
412 const lexer::SourcePosition &startLoc);
413
414 private:
CreateCallExpression(TSParser * parser,lexer::Lexer * lexer,ir::Expression ** returnExpression,ir::TSTypeParameterDeclaration * typeParamDecl,const lexer::SourcePosition & startLoc)415 static ir::ArrowFunctionExpression *CreateCallExpression(TSParser *parser, lexer::Lexer *lexer,
416 ir::Expression **returnExpression,
417 ir::TSTypeParameterDeclaration *typeParamDecl,
418 const lexer::SourcePosition &startLoc)
419 {
420 ir::CallExpression *callExpression = parser->ParseCallExpression(*returnExpression, false);
421
422 ir::TypeNode *returnTypeAnnotation = nullptr;
423 if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
424 lexer->NextToken(); // eat ':'
425 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
426 returnTypeAnnotation = parser->ParseTypeAnnotation(&options);
427 }
428
429 if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
430 ir::ArrowFunctionExpression *arrowFuncExpr =
431 parser->ParseArrowFunctionExpression(callExpression, typeParamDecl, returnTypeAnnotation, true);
432 arrowFuncExpr->SetStart(startLoc);
433
434 return arrowFuncExpr;
435 }
436
437 if (returnTypeAnnotation != nullptr || typeParamDecl != nullptr) {
438 parser->ThrowSyntaxError("'=>' expected");
439 }
440
441 *returnExpression = callExpression;
442 return nullptr;
443 }
444 };
445
446 // NOLINTNEXTLINE(readability-function-size)
447 // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP) solid logic
ParsePotentialArrowExpression(ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc)448 ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression,
449 const lexer::SourcePosition &startLoc)
450 {
451 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
452
453 switch (Lexer()->GetToken().Type()) {
454 case lexer::TokenType::KEYW_FUNCTION: {
455 *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION);
456 ES2PANDA_ASSERT(*returnExpression != nullptr);
457 (*returnExpression)->SetStart(startLoc);
458 break;
459 }
460 case lexer::TokenType::LITERAL_IDENT: {
461 ir::Expression *identRef = ParsePrimaryExpression();
462 if (identRef == nullptr) {
463 return nullptr;
464 }
465 ES2PANDA_ASSERT(identRef->IsIdentifier());
466
467 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
468 ThrowSyntaxError("Unexpected token, expected '=>'");
469 }
470
471 ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true);
472 arrowFuncExpr->SetStart(startLoc);
473
474 return arrowFuncExpr;
475 }
476 case lexer::TokenType::PUNCTUATOR_ARROW: {
477 ir::ArrowFunctionExpression *arrowFuncExpr =
478 ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true);
479 arrowFuncExpr->SetStart(startLoc);
480 return arrowFuncExpr;
481 }
482 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
483 const auto savedPos = Lexer()->Save();
484
485 auto options = TypeAnnotationParsingOptions::NO_OPTS;
486 typeParamDecl = ParseTypeParameterDeclaration(&options);
487 if (typeParamDecl == nullptr) {
488 Lexer()->Rewind(savedPos);
489 return nullptr;
490 }
491
492 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
493 ThrowSyntaxError("'(' expected");
494 }
495
496 [[fallthrough]];
497 }
498 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
499 return ParsePotentialArrowExpressionHelper::CreateCallExpression(this, Lexer(), returnExpression,
500 typeParamDecl, startLoc);
501 }
502 default: {
503 break;
504 }
505 }
506
507 return nullptr;
508 }
509
ParseVariableDeclaratorKey(VariableParsingFlags flags)510 ir::AnnotatedExpression *TSParser::ParseVariableDeclaratorKey(VariableParsingFlags flags)
511 {
512 ir::AnnotatedExpression *init = ParserImpl::ParseVariableDeclaratorKey(flags);
513
514 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
515 Lexer()->NextToken(); // eat ':'
516 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
517 init->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
518 }
519
520 return init;
521 }
522
ParseOptionalFunctionParameter(ir::AnnotatedExpression * returnNode,bool isRest)523 void TSParser::ParseOptionalFunctionParameter(ir::AnnotatedExpression *returnNode, bool isRest)
524 {
525 bool isOptional = false;
526
527 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
528 if (isRest) {
529 ThrowSyntaxError("A rest parameter cannot be optional");
530 }
531
532 switch (returnNode->Type()) {
533 case ir::AstNodeType::IDENTIFIER: {
534 returnNode->AsIdentifier()->SetOptional(true);
535 break;
536 }
537 case ir::AstNodeType::OBJECT_PATTERN:
538 case ir::AstNodeType::ARRAY_PATTERN: {
539 if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0)) {
540 ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.");
541 }
542
543 if (returnNode->IsObjectPattern()) {
544 returnNode->AsObjectPattern()->SetOptional(true);
545 break;
546 }
547
548 returnNode->AsArrayPattern()->SetOptional(true);
549 break;
550 }
551 case ir::AstNodeType::REST_ELEMENT: {
552 returnNode->AsRestElement()->SetOptional(true);
553 break;
554 }
555 default: {
556 ES2PANDA_UNREACHABLE();
557 }
558 }
559
560 isOptional = true;
561 Lexer()->NextToken(); // eat '?'
562 }
563
564 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
565 Lexer()->NextToken(); // eat ':'
566 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
567 returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
568 }
569
570 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
571 return;
572 }
573
574 if (isRest) {
575 ThrowSyntaxError("A rest parameter cannot have an initializer");
576 }
577
578 if (returnNode->IsIdentifier() && isOptional) {
579 ThrowSyntaxError("Parameter cannot have question mark and initializer");
580 }
581 }
582
ValidateArrowFunctionRestParameter(ir::SpreadElement * restElement)583 bool TSParser::ValidateArrowFunctionRestParameter(ir::SpreadElement *restElement)
584 {
585 ParseOptionalFunctionParameter(restElement, true);
586
587 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
588 ThrowSyntaxError("')' expected");
589 }
590
591 return true;
592 }
593
ParseArrowFunctionRestParameter(lexer::SourcePosition start)594 ir::Expression *TSParser::ParseArrowFunctionRestParameter(lexer::SourcePosition start)
595 {
596 ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
597
598 restElement->SetGrouped();
599 restElement->SetStart(start);
600
601 ValidateArrowFunctionRestParameter(restElement);
602
603 Lexer()->NextToken();
604
605 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
606 ir::TypeNode *returnTypeAnnotation = nullptr;
607 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
608 Lexer()->NextToken(); // eat ':'
609 returnTypeAnnotation = ParseTypeAnnotation(&options);
610 }
611
612 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
613 ThrowSyntaxError("Unexpected token");
614 }
615
616 return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false);
617 }
618
ParseArrowFunctionNoParameter(lexer::SourcePosition start)619 ir::Expression *TSParser::ParseArrowFunctionNoParameter(lexer::SourcePosition start)
620 {
621 Lexer()->NextToken();
622
623 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
624 ir::TypeNode *returnTypeAnnotation = nullptr;
625 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
626 Lexer()->NextToken(); // eat ':'
627 returnTypeAnnotation = ParseTypeAnnotation(&options);
628 }
629
630 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
631 ThrowSyntaxError("Unexpected token");
632 }
633
634 auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false);
635 arrowExpr->SetStart(start);
636 arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start);
637
638 return arrowExpr;
639 }
640
641 // NOLINTNEXTLINE(google-default-arguments)
ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)642 ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(
643 [[maybe_unused]] ExpressionParseFlags flags) // CC-OFF(G.FMT.06-CPP) project code style
644 {
645 ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
646 lexer::SourcePosition start = Lexer()->GetToken().Start();
647 Lexer()->NextToken();
648 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
649
650 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
651 return ParseArrowFunctionRestParameter(start);
652 }
653
654 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
655 return ParseArrowFunctionNoParameter(start);
656 }
657
658 ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST |
659 ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
660
661 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
662 ThrowSyntaxError("Unexpected token, expected ')'");
663 }
664
665 expr->SetGrouped();
666 expr->SetRange({start, Lexer()->GetToken().End()});
667 Lexer()->NextToken();
668
669 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
670 auto savedPos = Lexer()->Save();
671 Lexer()->NextToken(); // eat ':'
672 options = TypeAnnotationParsingOptions::NO_OPTS;
673 ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options);
674
675 if (returnTypeAnnotation == nullptr) {
676 Lexer()->Rewind(savedPos);
677 return expr;
678 }
679
680 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
681 Lexer()->Rewind(savedPos);
682 return expr;
683 }
684
685 return ParseArrowFunctionExpression(expr, nullptr, returnTypeAnnotation, false);
686 }
687
688 return expr;
689 }
690
691 } // namespace ark::es2panda::parser
692