• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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