• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 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     asExpr->SetRange({startLoc, Lexer()->GetToken().End()});
141 
142     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
143         return ParsePotentialAsExpression(asExpr);
144     }
145 
146     return asExpr;
147 }
148 
ParsePatternElementGetReturnNode(ExpressionParseFlags & flags,bool & isOptional)149 ir::AnnotatedExpression *TSParser::ParsePatternElementGetReturnNode(ExpressionParseFlags &flags, bool &isOptional)
150 {
151     switch (Lexer()->GetToken().Type()) {
152         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
153             ir::AnnotatedExpression *returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
154             isOptional = returnNode->AsArrayPattern()->IsOptional();
155             return returnNode;
156         }
157         case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
158             if ((flags & ExpressionParseFlags::IN_REST) != 0) {
159                 ThrowSyntaxError("Unexpected token");
160             }
161 
162             return ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
163         }
164         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
165             ir::AnnotatedExpression *returnNode =
166                 ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
167             isOptional = returnNode->AsObjectPattern()->IsOptional();
168             return returnNode;
169         }
170         case lexer::TokenType::LITERAL_IDENT: {
171             ir::AnnotatedExpression *returnNode = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
172 
173             if (returnNode->AsIdentifier()->Decorators().empty()) {
174                 returnNode->SetRange(Lexer()->GetToken().Loc());
175             } else {
176                 returnNode->SetRange(
177                     {returnNode->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()});
178             }
179 
180             Lexer()->NextToken();
181 
182             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
183                 isOptional = true;
184 
185                 if ((flags & ExpressionParseFlags::IN_REST) != 0) {
186                     ThrowSyntaxError("A rest parameter cannot be optional");
187                 }
188 
189                 returnNode->AsIdentifier()->SetOptional(true);
190                 Lexer()->NextToken();
191             }
192 
193             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
194                 Lexer()->NextToken();  // eat ':'
195                 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
196                 returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
197             }
198             return returnNode;
199         }
200         default: {
201             ThrowSyntaxError("Unexpected token, expected an identifier.");
202         }
203     }
204 }
205 // NOLINTNEXTLINE(google-default-arguments)
ParsePatternElement(ExpressionParseFlags flags,bool allowDefault)206 ir::Expression *TSParser::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault)
207 {
208     bool isOptional = false;
209     ir::AnnotatedExpression *returnNode = ParsePatternElementGetReturnNode(flags, isOptional);
210 
211     if ((returnNode->IsObjectPattern() || returnNode->IsArrayPattern()) && !InAmbientContext() &&
212         ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && isOptional) {
213         ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.");
214     }
215 
216     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
217         return returnNode;
218     }
219 
220     if ((flags & ExpressionParseFlags::IN_REST) != 0) {
221         ThrowSyntaxError("A rest parameter cannot have an initializer.");
222     }
223 
224     if (!allowDefault) {
225         ThrowSyntaxError("Invalid destructuring assignment target");
226     }
227 
228     if (isOptional) {
229         ThrowSyntaxError("Parameter cannot have question mark and initializer");
230     }
231 
232     Lexer()->NextToken();
233 
234     if (((GetContext().Status() & ParserStatus::GENERATOR_FUNCTION) != 0) &&
235         Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD) {
236         ThrowSyntaxError("Yield is not allowed in generator parameters");
237     }
238 
239     ir::Expression *rightNode = ParseExpression();
240 
241     auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
242         ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
243     assignmentExpression->SetRange({returnNode->Start(), rightNode->End()});
244 
245     return assignmentExpression;
246 }
247 
CreateParameterProperty(ir::Expression * parameter,ir::ModifierFlags modifiers)248 ir::TSParameterProperty *TSParser::CreateParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
249 {
250     auto accessibilityOption = ir::AccessibilityOption::NO_OPTS;
251     bool readonly = false;
252     bool isStatic = false;
253     bool isExport = false;
254 
255     if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) {
256         accessibilityOption = ir::AccessibilityOption::PRIVATE;
257     } else if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) {
258         accessibilityOption = ir::AccessibilityOption::PUBLIC;
259     } else if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) {
260         accessibilityOption = ir::AccessibilityOption::PROTECTED;
261     }
262 
263     if ((modifiers & ir::ModifierFlags::READONLY) != 0) {
264         readonly = true;
265     }
266 
267     if ((modifiers & ir::ModifierFlags::STATIC) != 0) {
268         isStatic = true;
269     }
270 
271     // NOTE(Csaba Repasi): Handle export property of TSParameterProperty
272 
273     return AllocNode<ir::TSParameterProperty>(accessibilityOption, parameter, readonly, isStatic, isExport);
274 }
275 
ParseFunctionParameter()276 ir::Expression *TSParser::ParseFunctionParameter()
277 {
278     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) {
279         Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
280         Lexer()->GetToken().SetTokenStr(ERROR_LITERAL);
281     }
282 
283     lexer::SourcePosition parameterStart = Lexer()->GetToken().Start();
284     ir::ModifierFlags modifiers = ParseModifiers();
285     // NOTE(Csaba Repasi): throw error if using strick mode reserved keyword here
286     if (((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) && modifiers != ir::ModifierFlags::NONE) {
287         ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
288     }
289 
290     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
291         CheckRestrictedBinding();
292     }
293 
294     ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
295 
296     if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
297         ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
298     }
299 
300     if (modifiers != ir::ModifierFlags::NONE &&
301         (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
302          (functionParameter->IsAssignmentPattern() &&
303           (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
304            functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
305         ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
306     }
307 
308     if (modifiers != ir::ModifierFlags::NONE) {
309         functionParameter = CreateParameterProperty(functionParameter, modifiers);
310         functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
311     }
312 
313     return functionParameter;
314 }
315 
ParseModuleReference()316 ir::Expression *TSParser::ParseModuleReference()
317 {
318     ir::Expression *result = nullptr;
319 
320     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE &&
321         Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_PAREN) {
322         lexer::SourcePosition start = Lexer()->GetToken().Start();
323         Lexer()->NextToken();  // eat 'require'
324         Lexer()->NextToken();  // eat '('
325 
326         if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
327             ThrowSyntaxError("String literal expected.");
328         }
329 
330         result = AllocNode<ir::StringLiteral>(Lexer()->GetToken().String());
331         result->SetRange(Lexer()->GetToken().Loc());
332         Lexer()->NextToken();
333 
334         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
335             ThrowSyntaxError("')' expected.");
336         }
337 
338         result = AllocNode<ir::TSExternalModuleReference>(result);
339         result->SetRange({start, Lexer()->GetToken().End()});
340         Lexer()->NextToken();  // eat ')'
341     } else {
342         result = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
343         result->SetRange(Lexer()->GetToken().Loc());
344         Lexer()->NextToken();
345 
346         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
347             result = ParseQualifiedReference(result);
348         }
349     }
350 
351     return result;
352 }
353 
ParseConstExpression()354 ir::TSTypeReference *TSParser::ParseConstExpression()
355 {
356     auto *identRef = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
357     identRef->SetRange(Lexer()->GetToken().Loc());
358 
359     auto *typeReference = AllocNode<ir::TSTypeReference>(identRef, nullptr);
360     typeReference->SetRange(Lexer()->GetToken().Loc());
361 
362     Lexer()->NextToken();
363 
364     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
365         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
366         Lexer()->GetToken().Type() != lexer::TokenType::EOS &&
367         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
368         ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0)) {
369         ThrowSyntaxError("Unexpected token.");
370     }
371 
372     return typeReference;
373 }
374 
ParsePotentialNonNullExpression(ir::Expression ** returnExpression,lexer::SourcePosition startLoc)375 bool TSParser::ParsePotentialNonNullExpression(ir::Expression **returnExpression, lexer::SourcePosition startLoc)
376 {
377     if (returnExpression == nullptr || Lexer()->GetToken().NewLine()) {
378         return true;
379     }
380 
381     *returnExpression = AllocNode<ir::TSNonNullExpression>(*returnExpression);
382     (*returnExpression)->SetRange({startLoc, Lexer()->GetToken().End()});
383     Lexer()->NextToken();
384     return false;
385 }
386 
387 // NOLINTNEXTLINE(google-default-arguments)
ParseObjectExpression(ExpressionParseFlags flags)388 ir::ObjectExpression *TSParser::ParseObjectExpression(ExpressionParseFlags flags)
389 {
390     ir::ObjectExpression *objExpression = ParserImpl::ParseObjectExpression(flags);
391     ParsePotentialOptionalFunctionParameter(objExpression);
392     return objExpression;
393 }
394 
395 // NOLINTNEXTLINE(google-default-arguments)
ParseArrayExpression(ExpressionParseFlags flags)396 ir::ArrayExpression *TSParser::ParseArrayExpression(ExpressionParseFlags flags)
397 {
398     ir::ArrayExpression *arrayExpression = ParserImpl::ParseArrayExpression(flags);
399     ParsePotentialOptionalFunctionParameter(arrayExpression);
400     return arrayExpression;
401 }
402 class TSParser::ParsePotentialArrowExpressionHelper {
403     friend ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression,
404                                                                                 const lexer::SourcePosition &startLoc);
405 
406 private:
CreateCallExpression(TSParser * parser,lexer::Lexer * lexer,ir::Expression ** returnExpression,ir::TSTypeParameterDeclaration * typeParamDecl,const lexer::SourcePosition & startLoc)407     static ir::ArrowFunctionExpression *CreateCallExpression(TSParser *parser, lexer::Lexer *lexer,
408                                                              ir::Expression **returnExpression,
409                                                              ir::TSTypeParameterDeclaration *typeParamDecl,
410                                                              const lexer::SourcePosition &startLoc)
411     {
412         ir::CallExpression *callExpression = parser->ParseCallExpression(*returnExpression, false);
413 
414         ir::TypeNode *returnTypeAnnotation = nullptr;
415         if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
416             lexer->NextToken();  // eat ':'
417             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
418             returnTypeAnnotation = parser->ParseTypeAnnotation(&options);
419         }
420 
421         if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
422             ir::ArrowFunctionExpression *arrowFuncExpr =
423                 parser->ParseArrowFunctionExpression(callExpression, typeParamDecl, returnTypeAnnotation, true);
424             arrowFuncExpr->SetStart(startLoc);
425 
426             return arrowFuncExpr;
427         }
428 
429         if (returnTypeAnnotation != nullptr || typeParamDecl != nullptr) {
430             parser->ThrowSyntaxError("'=>' expected");
431         }
432 
433         *returnExpression = callExpression;
434         return nullptr;
435     }
436 };
437 
ParsePotentialArrowExpression(ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc)438 ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression,
439                                                                      const lexer::SourcePosition &startLoc)
440 {
441     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
442 
443     switch (Lexer()->GetToken().Type()) {
444         case lexer::TokenType::KEYW_FUNCTION: {
445             *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION);
446             (*returnExpression)->SetStart(startLoc);
447             break;
448         }
449         case lexer::TokenType::LITERAL_IDENT: {
450             ir::Expression *identRef = ParsePrimaryExpression();
451             if (identRef == nullptr) {
452                 return nullptr;
453             }
454             ASSERT(identRef->IsIdentifier());
455 
456             if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
457                 ThrowSyntaxError("Unexpected token, expected '=>'");
458             }
459 
460             ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true);
461             arrowFuncExpr->SetStart(startLoc);
462 
463             return arrowFuncExpr;
464         }
465         case lexer::TokenType::PUNCTUATOR_ARROW: {
466             ir::ArrowFunctionExpression *arrowFuncExpr =
467                 ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true);
468             arrowFuncExpr->SetStart(startLoc);
469             return arrowFuncExpr;
470         }
471         case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
472             const auto savedPos = Lexer()->Save();
473 
474             auto options = TypeAnnotationParsingOptions::NO_OPTS;
475             typeParamDecl = ParseTypeParameterDeclaration(&options);
476             if (typeParamDecl == nullptr) {
477                 Lexer()->Rewind(savedPos);
478                 return nullptr;
479             }
480 
481             if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
482                 ThrowSyntaxError("'(' expected");
483             }
484 
485             [[fallthrough]];
486         }
487         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
488             return ParsePotentialArrowExpressionHelper::CreateCallExpression(this, Lexer(), returnExpression,
489                                                                              typeParamDecl, startLoc);
490         }
491         default: {
492             break;
493         }
494     }
495 
496     return nullptr;
497 }
498 
ParseVariableDeclaratorKey(VariableParsingFlags flags)499 ir::AnnotatedExpression *TSParser::ParseVariableDeclaratorKey(VariableParsingFlags flags)
500 {
501     ir::AnnotatedExpression *init = ParserImpl::ParseVariableDeclaratorKey(flags);
502 
503     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
504         Lexer()->NextToken();  // eat ':'
505         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
506         init->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
507     }
508 
509     return init;
510 }
511 
ParseOptionalFunctionParameter(ir::AnnotatedExpression * returnNode,bool isRest)512 void TSParser::ParseOptionalFunctionParameter(ir::AnnotatedExpression *returnNode, bool isRest)
513 {
514     bool isOptional = false;
515 
516     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
517         if (isRest) {
518             ThrowSyntaxError("A rest parameter cannot be optional");
519         }
520 
521         switch (returnNode->Type()) {
522             case ir::AstNodeType::IDENTIFIER: {
523                 returnNode->AsIdentifier()->SetOptional(true);
524                 break;
525             }
526             case ir::AstNodeType::OBJECT_PATTERN:
527             case ir::AstNodeType::ARRAY_PATTERN: {
528                 if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0)) {
529                     ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.");
530                 }
531 
532                 if (returnNode->IsObjectPattern()) {
533                     returnNode->AsObjectPattern()->SetOptional(true);
534                     break;
535                 }
536 
537                 returnNode->AsArrayPattern()->SetOptional(true);
538                 break;
539             }
540             case ir::AstNodeType::REST_ELEMENT: {
541                 returnNode->AsRestElement()->SetOptional(true);
542                 break;
543             }
544             default: {
545                 UNREACHABLE();
546             }
547         }
548 
549         isOptional = true;
550         Lexer()->NextToken();  // eat '?'
551     }
552 
553     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
554         Lexer()->NextToken();  // eat ':'
555         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
556         returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
557     }
558 
559     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
560         return;
561     }
562 
563     if (isRest) {
564         ThrowSyntaxError("A rest parameter cannot have an initializer");
565     }
566 
567     if (returnNode->IsIdentifier() && isOptional) {
568         ThrowSyntaxError("Parameter cannot have question mark and initializer");
569     }
570 }
571 
ValidateArrowFunctionRestParameter(ir::SpreadElement * restElement)572 bool TSParser::ValidateArrowFunctionRestParameter(ir::SpreadElement *restElement)
573 {
574     ParseOptionalFunctionParameter(restElement, true);
575 
576     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
577         ThrowSyntaxError("')' expected");
578     }
579 
580     return true;
581 }
582 
ParseArrowFunctionRestParameter(lexer::SourcePosition start)583 ir::Expression *TSParser::ParseArrowFunctionRestParameter(lexer::SourcePosition start)
584 {
585     ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
586 
587     restElement->SetGrouped();
588     restElement->SetStart(start);
589 
590     ValidateArrowFunctionRestParameter(restElement);
591 
592     Lexer()->NextToken();
593 
594     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
595     ir::TypeNode *returnTypeAnnotation = nullptr;
596     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
597         Lexer()->NextToken();  // eat ':'
598         returnTypeAnnotation = ParseTypeAnnotation(&options);
599     }
600 
601     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
602         ThrowSyntaxError("Unexpected token");
603     }
604 
605     return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false);
606 }
607 
ParseArrowFunctionNoParameter(lexer::SourcePosition start)608 ir::Expression *TSParser::ParseArrowFunctionNoParameter(lexer::SourcePosition start)
609 {
610     Lexer()->NextToken();
611 
612     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
613     ir::TypeNode *returnTypeAnnotation = nullptr;
614     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
615         Lexer()->NextToken();  // eat ':'
616         returnTypeAnnotation = ParseTypeAnnotation(&options);
617     }
618 
619     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
620         ThrowSyntaxError("Unexpected token");
621     }
622 
623     auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false);
624     arrowExpr->SetStart(start);
625     arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start);
626 
627     return arrowExpr;
628 }
629 
630 // NOLINTNEXTLINE(google-default-arguments)
ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)631 ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(
632     [[maybe_unused]] ExpressionParseFlags flags)  // CC-OFF(G.FMT.06-CPP) project code style
633 {
634     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
635     lexer::SourcePosition start = Lexer()->GetToken().Start();
636     Lexer()->NextToken();
637     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
638 
639     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
640         return ParseArrowFunctionRestParameter(start);
641     }
642 
643     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
644         return ParseArrowFunctionNoParameter(start);
645     }
646 
647     ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST |
648                                            ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
649 
650     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
651         ThrowSyntaxError("Unexpected token, expected ')'");
652     }
653 
654     expr->SetGrouped();
655     expr->SetRange({start, Lexer()->GetToken().End()});
656     Lexer()->NextToken();
657 
658     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
659         auto savedPos = Lexer()->Save();
660         Lexer()->NextToken();  // eat ':'
661         options = TypeAnnotationParsingOptions::NO_OPTS;
662         ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options);
663 
664         if (returnTypeAnnotation == nullptr) {
665             Lexer()->Rewind(savedPos);
666             return expr;
667         }
668 
669         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
670             Lexer()->Rewind(savedPos);
671             return expr;
672         }
673 
674         return ParseArrowFunctionExpression(expr, nullptr, returnTypeAnnotation, false);
675     }
676 
677     return expr;
678 }
679 
680 }  // namespace ark::es2panda::parser
681