• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 "parser/parserStatusContext.h"
19 #include "util/es2pandaMacros.h"
20 #include "parserFlags.h"
21 #include "util/helpers.h"
22 #include "varbinder/privateBinding.h"
23 #include "varbinder/scope.h"
24 #include "varbinder/tsBinding.h"
25 #include "lexer/TSLexer.h"
26 #include "ir/base/spreadElement.h"
27 #include "ir/base/decorator.h"
28 #include "ir/base/classElement.h"
29 #include "ir/base/classDefinition.h"
30 #include "ir/base/methodDefinition.h"
31 #include "ir/base/scriptFunction.h"
32 #include "ir/module/importDefaultSpecifier.h"
33 #include "ir/module/exportDefaultDeclaration.h"
34 #include "ir/module/exportAllDeclaration.h"
35 #include "ir/module/exportNamedDeclaration.h"
36 #include "ir/module/importDeclaration.h"
37 #include "ir/expressions/memberExpression.h"
38 #include "ir/expressions/sequenceExpression.h"
39 #include "ir/expressions/templateLiteral.h"
40 #include "ir/expressions/taggedTemplateExpression.h"
41 #include "ir/expressions/callExpression.h"
42 #include "ir/expressions/functionExpression.h"
43 #include "ir/expressions/arrowFunctionExpression.h"
44 #include "ir/expressions/yieldExpression.h"
45 #include "ir/expressions/assignmentExpression.h"
46 #include "ir/expressions/identifier.h"
47 #include "ir/expressions/objectExpression.h"
48 #include "ir/expressions/arrayExpression.h"
49 #include "ir/expressions/literals/bigIntLiteral.h"
50 #include "ir/expressions/literals/booleanLiteral.h"
51 #include "ir/expressions/literals/nullLiteral.h"
52 #include "ir/expressions/literals/numberLiteral.h"
53 #include "ir/expressions/literals/stringLiteral.h"
54 #include "ir/statements/emptyStatement.h"
55 #include "ir/statements/blockStatement.h"
56 #include "ir/statements/ifStatement.h"
57 #include "ir/statements/doWhileStatement.h"
58 #include "ir/statements/whileStatement.h"
59 #include "ir/statements/tryStatement.h"
60 #include "ir/statements/breakStatement.h"
61 #include "ir/statements/continueStatement.h"
62 #include "ir/statements/throwStatement.h"
63 #include "ir/statements/switchStatement.h"
64 #include "ir/statements/returnStatement.h"
65 #include "ir/statements/debuggerStatement.h"
66 #include "ir/statements/classDeclaration.h"
67 #include "ir/statements/labelledStatement.h"
68 #include "ir/statements/variableDeclarator.h"
69 #include "ir/statements/functionDeclaration.h"
70 #include "ir/ts/tsLiteralType.h"
71 #include "ir/ts/tsMappedType.h"
72 #include "ir/ts/tsImportType.h"
73 #include "ir/ts/tsThisType.h"
74 #include "ir/ts/tsConditionalType.h"
75 #include "ir/ts/tsTypeOperator.h"
76 #include "ir/ts/tsInferType.h"
77 #include "ir/ts/tsTupleType.h"
78 #include "ir/ts/tsNamedTupleMember.h"
79 #include "ir/ts/tsQualifiedName.h"
80 #include "ir/ts/tsIndexedAccessType.h"
81 #include "ir/ts/tsTypeQuery.h"
82 #include "ir/ts/tsTypeReference.h"
83 #include "ir/ts/tsTypePredicate.h"
84 #include "ir/ts/tsTypeLiteral.h"
85 #include "ir/ts/tsArrayType.h"
86 #include "ir/ts/tsUnionType.h"
87 #include "ir/ts/tsIntersectionType.h"
88 #include "ir/ts/tsAnyKeyword.h"
89 #include "ir/ts/tsUndefinedKeyword.h"
90 #include "ir/ts/tsVoidKeyword.h"
91 #include "ir/ts/tsNumberKeyword.h"
92 #include "ir/ts/tsStringKeyword.h"
93 #include "ir/ts/tsBooleanKeyword.h"
94 #include "ir/ts/tsBigintKeyword.h"
95 #include "ir/ts/tsUnknownKeyword.h"
96 #include "ir/ts/tsNullKeyword.h"
97 #include "ir/ts/tsNeverKeyword.h"
98 #include "ir/ts/tsObjectKeyword.h"
99 #include "ir/ts/tsFunctionType.h"
100 #include "ir/ts/tsConstructorType.h"
101 #include "ir/ts/tsParenthesizedType.h"
102 #include "ir/ts/tsTypeAssertion.h"
103 #include "ir/ts/tsAsExpression.h"
104 #include "ir/ts/tsNonNullExpression.h"
105 #include "ir/ts/tsEnumDeclaration.h"
106 #include "ir/ts/tsInterfaceDeclaration.h"
107 #include "ir/ts/tsTypeAliasDeclaration.h"
108 #include "ir/ts/tsModuleDeclaration.h"
109 #include "ir/ts/tsTypeParameterInstantiation.h"
110 #include "ir/ts/tsInterfaceHeritage.h"
111 #include "ir/base/tsSignatureDeclaration.h"
112 #include "ir/base/tsIndexSignature.h"
113 #include "ir/base/tsMethodSignature.h"
114 #include "ir/base/tsPropertySignature.h"
115 #include "ir/ts/tsParameterProperty.h"
116 #include "ir/ts/tsClassImplements.h"
117 #include "ir/ts/tsImportEqualsDeclaration.h"
118 #include "ir/ts/tsExternalModuleReference.h"
119 
120 namespace ark::es2panda::parser {
InitLexer(const SourceFile & sourceFile)121 std::unique_ptr<lexer::Lexer> TSParser::InitLexer(const SourceFile &sourceFile)
122 {
123     GetProgram()->SetSource(sourceFile);
124     auto lexer = std::make_unique<lexer::TSLexer>(&GetContext(), DiagnosticEngine());
125     SetLexer(lexer.get());
126     return lexer;
127 }
128 
ParseDecorator()129 ir::Decorator *TSParser::ParseDecorator()
130 {
131     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT);
132 
133     lexer::SourcePosition start = Lexer()->GetToken().Start();
134     Lexer()->NextToken();  // eat '@'
135 
136     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
137         ThrowSyntaxError("Identifier expected");
138     }
139 
140     ir::Expression *expr = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
141     expr->SetRange(Lexer()->GetToken().Loc());
142     Lexer()->NextToken();
143 
144     while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
145         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
146 
147         if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
148             ThrowSyntaxError("Identifier expected");
149         }
150 
151         auto *identNode = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
152         ES2PANDA_ASSERT(identNode != nullptr);
153         identNode->SetRange(Lexer()->GetToken().Loc());
154 
155         expr =
156             AllocNode<ir::MemberExpression>(expr, identNode, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
157         Lexer()->NextToken();
158     }
159 
160     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
161         expr = ParseCallExpression(expr);
162     }
163 
164     auto *result = AllocNode<ir::Decorator>(expr);
165     ES2PANDA_ASSERT(result != nullptr);
166     result->SetRange({start, expr->End()});
167 
168     return result;
169 }
170 
AddDecorators(ir::AstNode * node,ArenaVector<ir::Decorator * > & decorators)171 void TSParser::AddDecorators(ir::AstNode *node, ArenaVector<ir::Decorator *> &decorators)
172 {
173     if (decorators.empty()) {
174         return;
175     }
176 
177     if (!node->CanHaveDecorator(true)) {
178         ThrowSyntaxError("Decorators are not valid here", decorators.front()->Start());
179     }
180 
181     node->AddDecorators(std::move(decorators));
182 }
183 
ParseTypeAliasDeclaration()184 ir::TSTypeAliasDeclaration *TSParser::ParseTypeAliasDeclaration()
185 {
186     ES2PANDA_ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE);
187     lexer::SourcePosition typeStart = Lexer()->GetToken().Start();
188     Lexer()->NextToken();  // eat type keyword
189 
190     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
191         ThrowSyntaxError("Identifier expected");
192     }
193 
194     if (Lexer()->GetToken().IsReservedTypeName()) {
195         std::string errMsg("Type alias name cannot be '");
196         errMsg.append(TokenToString(Lexer()->GetToken().KeywordType()));
197         errMsg.append("'");
198         ThrowSyntaxError(errMsg.c_str());
199     }
200 
201     const util::StringView &ident = Lexer()->GetToken().Ident();
202 
203     auto *id = AllocNode<ir::Identifier>(ident, Allocator());
204     ES2PANDA_ASSERT(id != nullptr);
205     id->SetRange(Lexer()->GetToken().Loc());
206     Lexer()->NextToken();
207 
208     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
209     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
210         auto options = TypeAnnotationParsingOptions::REPORT_ERROR;
211         typeParamDecl = ParseTypeParameterDeclaration(&options);
212     }
213 
214     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
215         ThrowSyntaxError("'=' expected");
216     }
217 
218     Lexer()->NextToken();  // eat '='
219 
220     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
221     ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
222 
223     auto *typeAliasDecl = AllocNode<ir::TSTypeAliasDeclaration>(Allocator(), id, typeParamDecl, typeAnnotation);
224     typeAliasDecl->SetRange({typeStart, Lexer()->GetToken().End()});
225 
226     return typeAliasDecl;
227 }
228 
CurrentLiteralIsBasicType() const229 bool TSParser::CurrentLiteralIsBasicType() const
230 {
231     switch (Lexer()->GetToken().KeywordType()) {
232         case lexer::TokenType::KEYW_ANY:
233         case lexer::TokenType::KEYW_BOOLEAN:
234         case lexer::TokenType::KEYW_NUMBER:
235         case lexer::TokenType::KEYW_STRING:
236         case lexer::TokenType::KEYW_UNKNOWN:
237         case lexer::TokenType::KEYW_UNDEFINED:
238         case lexer::TokenType::KEYW_NEVER:
239         case lexer::TokenType::KEYW_OBJECT:
240         case lexer::TokenType::KEYW_BIGINT: {
241             return true;
242         }
243         default: {
244             break;
245         }
246     }
247 
248     return false;
249 }
250 
CurrentIsBasicType()251 bool TSParser::CurrentIsBasicType()
252 {
253     switch (Lexer()->GetToken().Type()) {
254         case lexer::TokenType::LITERAL_NUMBER:
255         case lexer::TokenType::LITERAL_STRING:
256         case lexer::TokenType::LITERAL_FALSE:
257         case lexer::TokenType::LITERAL_TRUE:
258         case lexer::TokenType::LITERAL_NULL:
259         case lexer::TokenType::KEYW_THIS:
260         case lexer::TokenType::KEYW_VOID: {
261             return true;
262         }
263         case lexer::TokenType::LITERAL_IDENT: {
264             return CurrentLiteralIsBasicType();
265         }
266         default: {
267             break;
268         }
269     }
270 
271     return false;
272 }
273 
ParseTypeAnnotation(TypeAnnotationParsingOptions * options)274 ir::TypeNode *TSParser::ParseTypeAnnotation(TypeAnnotationParsingOptions *options)
275 {
276     ir::TypeNode *typeAnnotation = nullptr;
277 
278     while (true) {
279         ir::TypeNode *element = ParseTypeAnnotationElement(typeAnnotation, options);
280 
281         *options &= ~TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
282 
283         if (element == nullptr) {
284             break;
285         }
286 
287         typeAnnotation = element;
288 
289         if ((((*options) & TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE) != 0) && Lexer()->GetToken().NewLine()) {
290             break;
291         }
292     }
293 
294     return typeAnnotation;
295 }
296 
ParseIdentifierReference()297 ir::TypeNode *TSParser::ParseIdentifierReference()
298 {
299     if (CurrentLiteralIsBasicType() && Lexer()->Lookahead() != lexer::LEX_CHAR_DOT) {
300         return ParseBasicType();
301     }
302 
303     return ParseTypeReferenceOrQuery();
304 }
305 
IsStartOfMappedType() const306 bool TSParser::IsStartOfMappedType() const
307 {
308     auto pos = Lexer()->Save();
309     Lexer()->NextToken();
310     bool result = false;
311 
312     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
313         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
314         Lexer()->NextToken();
315         result = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY;
316         Lexer()->Rewind(pos);
317         return result;
318     }
319 
320     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
321         Lexer()->NextToken();
322     }
323 
324     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
325         Lexer()->Rewind(pos);
326         return false;
327     }
328 
329     Lexer()->NextToken();
330 
331     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
332         Lexer()->Rewind(pos);
333         return false;
334     }
335 
336     Lexer()->NextToken();
337 
338     result = Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IN;
339 
340     Lexer()->Rewind(pos);
341     return result;
342 }
343 
IsStartOfTypePredicate() const344 bool TSParser::IsStartOfTypePredicate() const
345 {
346     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
347                     Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS);
348 
349     auto pos = Lexer()->Save();
350     bool isAsserts = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
351     if (isAsserts) {
352         Lexer()->NextToken();
353     }
354 
355     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
356         Lexer()->GetToken().Type() != lexer::TokenType::KEYW_THIS) {
357         Lexer()->Rewind(pos);
358         return false;
359     }
360 
361     if (isAsserts) {
362         Lexer()->Rewind(pos);
363         return true;
364     }
365 
366     Lexer()->NextToken();
367 
368     bool result = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_IS;
369     Lexer()->Rewind(pos);
370     return result;
371 }
372 
IsStartOfAbstractConstructorType() const373 bool TSParser::IsStartOfAbstractConstructorType() const
374 {
375     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_ABSTRACT) {
376         return false;
377     }
378 
379     lexer::LexerPosition pos = Lexer()->Save();
380     Lexer()->NextToken();  // eat 'abstract'
381     bool result = Lexer()->GetToken().Type() == lexer::TokenType::KEYW_NEW;
382 
383     Lexer()->Rewind(pos);
384 
385     return result;
386 }
387 
ParseImportType(const lexer::SourcePosition & startLoc,bool isTypeof)388 ir::TSImportType *TSParser::ParseImportType(const lexer::SourcePosition &startLoc, bool isTypeof)
389 {
390     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPORT);
391 
392     Lexer()->NextToken();
393 
394     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
395         ThrowSyntaxError("'(' expected");
396     }
397 
398     Lexer()->NextToken();
399 
400     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
401     ir::TypeNode *param = ParseTypeAnnotation(&options);
402 
403     if (!param->IsTSLiteralType() || !param->AsTSLiteralType()->Literal()->IsStringLiteral()) {
404         ThrowSyntaxError("String literal expected");
405     }
406 
407     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
408         ThrowSyntaxError("')' expected");
409     }
410 
411     Lexer()->NextToken();
412 
413     ir::Expression *qualifier = nullptr;
414     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
415         Lexer()->NextToken();
416         qualifier = ParseQualifiedName();
417     }
418 
419     ir::TSTypeParameterInstantiation *typeParams = nullptr;
420     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT ||
421         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
422         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
423             Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
424         }
425 
426         typeParams = ParseTypeParameterInstantiation(&options);
427     }
428 
429     auto *importType = AllocNode<ir::TSImportType>(param, typeParams, qualifier, isTypeof, Allocator());
430 
431     importType->SetRange({startLoc, Lexer()->GetToken().End()});
432 
433     return importType;
434 }
435 
ParseThisType(bool throwError)436 ir::TypeNode *TSParser::ParseThisType(bool throwError)
437 {
438     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS);
439 
440     if (throwError && ((GetContext().Status() & ParserStatus::ALLOW_THIS_TYPE) == 0)) {
441         ThrowSyntaxError(
442             "A 'this' type is available only in a non-static member "
443             "of a class or interface.");
444     }
445 
446     auto *returnType = AllocNode<ir::TSThisType>(Allocator());
447     ES2PANDA_ASSERT(returnType != nullptr);
448     returnType->SetRange(Lexer()->GetToken().Loc());
449 
450     Lexer()->NextToken();
451 
452     return returnType;
453 }
454 
ParseConditionalType(ir::Expression * checkType,bool restrictExtends)455 ir::TypeNode *TSParser::ParseConditionalType(ir::Expression *checkType, bool restrictExtends)
456 {
457     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
458     if (restrictExtends) {
459         ThrowSyntaxError("'?' expected.");
460     }
461 
462     lexer::SourcePosition startLoc = checkType->Start();
463 
464     Lexer()->NextToken();  // eat 'extends'
465 
466     ParserStatus savedStatus = GetContext().Status();
467     GetContext().Status() |= ParserStatus::IN_EXTENDS;
468 
469     TypeAnnotationParsingOptions options =
470         TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
471     auto *extendsType = ParseTypeAnnotation(&options);
472 
473     GetContext().Status() = savedStatus;
474 
475     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
476         ThrowSyntaxError("'?' expected.");
477     }
478 
479     Lexer()->NextToken();  // eat '?'
480 
481     options &= ~TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
482     auto *trueType = ParseTypeAnnotation(&options);
483 
484     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
485         ThrowSyntaxError("':' expected.");
486     }
487 
488     Lexer()->NextToken();  // eat ':'
489 
490     auto *falseType = ParseTypeAnnotation(&options);
491 
492     lexer::SourcePosition endLoc = falseType->End();
493 
494     auto *conditionalType = AllocNode<ir::TSConditionalType>(checkType, extendsType, trueType, falseType, Allocator());
495 
496     conditionalType->SetRange({startLoc, endLoc});
497 
498     return conditionalType;
499 }
500 
ParseTypeOperatorOrTypeReference()501 ir::TypeNode *TSParser::ParseTypeOperatorOrTypeReference()
502 {
503     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
504 
505     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
506         lexer::SourcePosition typeOperatorStart = Lexer()->GetToken().Start();
507         Lexer()->NextToken();
508 
509         ir::TypeNode *type = ParseTypeAnnotation(&options);
510 
511         if (!type->IsTSArrayType() && !type->IsTSTupleType()) {
512             ThrowSyntaxError(
513                 "'readonly' type modifier is only permitted on array "
514                 "and tuple literal types.");
515         }
516 
517         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::READONLY, Allocator());
518         ES2PANDA_ASSERT(typeOperator != nullptr);
519         typeOperator->SetRange({typeOperatorStart, type->End()});
520 
521         return typeOperator;
522     }
523 
524     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_KEYOF) {
525         lexer::SourcePosition typeOperatorStart = Lexer()->GetToken().Start();
526         Lexer()->NextToken();
527 
528         ir::TypeNode *type = ParseTypeAnnotation(&options);
529 
530         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::KEYOF, Allocator());
531         ES2PANDA_ASSERT(typeOperator != nullptr);
532         typeOperator->SetRange({typeOperatorStart, type->End()});
533 
534         return typeOperator;
535     }
536 
537     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_INFER) {
538         if ((GetContext().Status() & ParserStatus::IN_EXTENDS) == 0) {
539             ThrowSyntaxError(
540                 "'infer' declarations are only permitted in the "
541                 "'extends' clause of a conditional type.");
542         }
543 
544         lexer::SourcePosition inferStart = Lexer()->GetToken().Start();
545         Lexer()->NextToken();
546 
547         ir::TSTypeParameter *typeParam = ParseTypeParameter(&options);
548 
549         auto *inferType = AllocNode<ir::TSInferType>(typeParam, Allocator());
550 
551         ES2PANDA_ASSERT(inferType != nullptr);
552         inferType->SetRange({inferStart, Lexer()->GetToken().End()});
553 
554         return inferType;
555     }
556 
557     return ParseIdentifierReference();
558 }
559 
ParseTupleElement(ir::TSTupleKind * kind,bool * seenOptional)560 ir::TypeNode *TSParser::ParseTupleElement(ir::TSTupleKind *kind, bool *seenOptional)
561 {
562     lexer::SourcePosition elementStart = Lexer()->GetToken().Start();
563     ir::TypeNode *element = nullptr;
564     bool isOptional = false;
565     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
566 
567     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && !CurrentLiteralIsBasicType()) {
568         auto *elementIdent = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
569         elementIdent->SetRange(Lexer()->GetToken().Loc());
570 
571         if (Lexer()->Lookahead() == lexer::LEX_CHAR_COLON || Lexer()->Lookahead() == lexer::LEX_CHAR_QUESTION) {
572             if (*kind == ir::TSTupleKind::DEFAULT) {
573                 ThrowSyntaxError("Tuple members must all have names or all not have names");
574             }
575 
576             Lexer()->NextToken();  // eat ident
577 
578             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
579                 Lexer()->NextToken();  // eat '?'
580                 isOptional = true;
581                 *seenOptional = true;
582             } else if (*seenOptional) {
583                 ThrowSyntaxError("A required element cannot follow an optional element");
584             }
585 
586             if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
587                 ThrowSyntaxError("':' expected");
588             }
589 
590             Lexer()->NextToken();  // eat ':'
591             auto *elementType = ParseTypeAnnotation(&options);
592             *kind = ir::TSTupleKind::NAMED;
593 
594             element = AllocNode<ir::TSNamedTupleMember>(elementIdent, elementType, isOptional, Allocator());
595         } else {
596             element = ParseTypeReferenceOrQuery();
597         }
598         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
599             Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
600             element = ParseTypeAnnotationElement(element, &options);
601         }
602     } else {
603         if (*kind == ir::TSTupleKind::NAMED) {
604             ThrowSyntaxError("Tuple members must all have names or all not have names");
605         }
606 
607         *kind = ir::TSTupleKind::DEFAULT;
608         element = ParseTypeAnnotation(&options);
609     }
610 
611     if (element != nullptr) {
612         element->SetRange({elementStart, Lexer()->GetToken().End()});
613     }
614     return element;
615 }
616 
ParseTupleType()617 ir::TSTupleType *TSParser::ParseTupleType()
618 {
619     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
620     lexer::SourcePosition tupleStart = Lexer()->GetToken().Start();
621     ArenaVector<ir::TypeNode *> elements(Allocator()->Adapter());
622     ir::TSTupleKind kind = ir::TSTupleKind::NONE;
623     bool seenOptional = false;
624 
625     Lexer()->NextToken();  // eat '['
626 
627     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
628         ir::TypeNode *element = ParseTupleElement(&kind, &seenOptional);
629         elements.push_back(element);
630 
631         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
632             break;
633         }
634 
635         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
636             ThrowSyntaxError("',' expected.");
637         }
638 
639         Lexer()->NextToken();  // eat ','
640     }
641 
642     lexer::SourcePosition tupleEnd = Lexer()->GetToken().End();
643     Lexer()->NextToken();  // eat ']'
644 
645     auto *tupleType = AllocNode<ir::TSTupleType>(std::move(elements), Allocator());
646     ES2PANDA_ASSERT(tupleType != nullptr);
647     tupleType->SetRange({tupleStart, tupleEnd});
648     return tupleType;
649 }
650 
ParseIndexAccessType(ir::TypeNode * typeName)651 ir::TypeNode *TSParser::ParseIndexAccessType(ir::TypeNode *typeName)
652 {
653     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
654 
655     do {
656         Lexer()->NextToken();  // eat '['
657 
658         ir::TypeNode *indexType = ParseTypeAnnotation(&options);
659 
660         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
661             ThrowSyntaxError("']' expected");
662         }
663 
664         Lexer()->NextToken();  // eat ']'
665 
666         typeName = AllocNode<ir::TSIndexedAccessType>(typeName, indexType, Allocator());
667         typeName->SetRange({typeName->AsTSIndexedAccessType()->ObjectType()->Start(), Lexer()->GetToken().End()});
668     } while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
669              Lexer()->Lookahead() != lexer::LEX_CHAR_RIGHT_SQUARE);
670 
671     return typeName;
672 }
673 
ParseTypeReferenceOrQuery(bool parseQuery)674 ir::TypeNode *TSParser::ParseTypeReferenceOrQuery(bool parseQuery)
675 {
676     lexer::SourcePosition referenceStartLoc = Lexer()->GetToken().Start();
677 
678     if (parseQuery) {
679         ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_TYPEOF);
680         Lexer()->NextToken();  // eat 'typeof'
681 
682         if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) {
683             lexer::SourcePosition &startLoc = referenceStartLoc;
684             return ParseImportType(startLoc, true);
685         }
686 
687         if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
688             ThrowSyntaxError("Identifier expected.");
689         }
690     }
691 
692     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
693                     Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
694 
695     ir::Expression *typeName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
696     ES2PANDA_ASSERT(typeName != nullptr);
697     typeName->SetRange(Lexer()->GetToken().Loc());
698 
699     if (Lexer()->Lookahead() == lexer::LEX_CHAR_LESS_THAN) {
700         Lexer()->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
701     } else {
702         Lexer()->NextToken();
703     }
704 
705     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
706         typeName = ParseQualifiedReference(typeName);
707     }
708 
709     ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
710     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
711         if (parseQuery) {
712             ThrowSyntaxError("Unexpected token.");
713         }
714 
715         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
716         typeParamInst = ParseTypeParameterInstantiation(&options);
717     }
718 
719     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
720         Lexer()->Lookahead() != lexer::LEX_CHAR_RIGHT_SQUARE) {
721         ir::TypeNode *typeRef =
722             parseQuery ? AllocNode<ir::TSTypeQuery>(typeName, Allocator())->AsTypeNode()
723                        : AllocNode<ir::TSTypeReference>(typeName, typeParamInst, Allocator())->AsTypeNode();
724 
725         typeRef->SetRange({referenceStartLoc, Lexer()->GetToken().End()});
726 
727         return ParseIndexAccessType(typeRef);
728     }
729 
730     ir::TypeNode *returnNode = parseQuery
731                                    ? AllocNode<ir::TSTypeQuery>(typeName, Allocator())->AsTypeNode()
732                                    : AllocNode<ir::TSTypeReference>(typeName, typeParamInst, Allocator())->AsTypeNode();
733 
734     returnNode->SetRange({referenceStartLoc, typeName->End()});
735 
736     return returnNode;
737 }
738 
ParseMappedTypeParameter()739 ir::TSTypeParameter *TSParser::ParseMappedTypeParameter()
740 {
741     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
742 
743     auto *paramName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
744     ES2PANDA_ASSERT(paramName != nullptr);
745     paramName->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()});
746 
747     Lexer()->NextToken();
748 
749     Lexer()->NextToken();  // eat 'in'
750 
751     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
752     ir::TypeNode *constraint = ParseTypeAnnotation(&options);
753 
754     lexer::SourcePosition endLoc = constraint->End();
755 
756     auto *typeParameter = AllocNode<ir::TSTypeParameter>(paramName, constraint, nullptr, Allocator());
757 
758     typeParameter->SetRange({startLoc, endLoc});
759 
760     return typeParameter;
761 }
762 
ParseMappedOption(lexer::TokenType tokenType)763 ir::MappedOption TSParser::ParseMappedOption(lexer::TokenType tokenType)
764 {
765     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MINUS &&
766         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PLUS &&
767         Lexer()->GetToken().KeywordType() != tokenType && Lexer()->GetToken().Type() != tokenType) {
768         return ir::MappedOption::NO_OPTS;
769     }
770 
771     auto result = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ? ir::MappedOption::MINUS
772                                                                                    : ir::MappedOption::PLUS;
773 
774     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
775         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
776         Lexer()->NextToken();
777     }
778 
779     if (Lexer()->GetToken().KeywordType() != tokenType && Lexer()->GetToken().Type() != tokenType) {
780         ThrowSyntaxError({"'", TokenToString(tokenType), "' expected."});
781     }
782 
783     Lexer()->NextToken();
784 
785     return result;
786 }
787 
ParseMappedType()788 ir::TSMappedType *TSParser::ParseMappedType()
789 {
790     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
791 
792     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
793     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
794 
795     ir::MappedOption readonly = ParseMappedOption(lexer::TokenType::KEYW_READONLY);
796 
797     Lexer()->NextToken();  // eat '['
798 
799     ir::TSTypeParameter *typeParameter = ParseMappedTypeParameter();
800 
801     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
802         ThrowSyntaxError("']' expected");
803     }
804 
805     Lexer()->NextToken();  // eat ']'
806 
807     ir::MappedOption optional = ParseMappedOption(lexer::TokenType::PUNCTUATOR_QUESTION_MARK);
808 
809     ir::TypeNode *typeAnnotation = nullptr;
810     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
811         Lexer()->NextToken();  // eat ':'
812         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
813         typeAnnotation = ParseTypeAnnotation(&options);
814     }
815 
816     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
817         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
818         ThrowSyntaxError("';' expected");
819     }
820 
821     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
822         Lexer()->NextToken();  // eat ';'
823     }
824 
825     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
826         ThrowSyntaxError("'}' expected");
827     }
828 
829     auto *mappedType = AllocNode<ir::TSMappedType>(typeParameter, typeAnnotation, readonly, optional, Allocator());
830 
831     mappedType->SetRange({startLoc, Lexer()->GetToken().End()});
832 
833     Lexer()->NextToken();  // eat '}'
834 
835     return mappedType;
836 }
837 
ParseTypePredicate()838 ir::TSTypePredicate *TSParser::ParseTypePredicate()
839 {
840     auto pos = Lexer()->Save();
841     lexer::SourcePosition startPos = Lexer()->GetToken().Start();
842     bool isAsserts = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
843     if (isAsserts) {
844         Lexer()->NextToken();  // eat 'asserts'
845         if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_IS) {
846             isAsserts = false;
847             Lexer()->Rewind(pos);
848         }
849     }
850 
851     ir::Expression *parameterName = nullptr;
852     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
853         parameterName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
854     } else {
855         parameterName = AllocNode<ir::TSThisType>(Allocator());
856     }
857 
858     parameterName->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()});
859 
860     Lexer()->NextToken();
861 
862     ir::TypeNode *typeAnnotation = nullptr;
863     lexer::SourcePosition endPos;
864     ir::TSTypePredicate *result = nullptr;
865 
866     if (isAsserts && Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_IS) {
867         endPos = parameterName->End();
868         result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts, Allocator());
869         ES2PANDA_ASSERT(result != nullptr);
870         result->SetRange({startPos, endPos});
871         return result;
872     }
873 
874     Lexer()->NextToken();  // eat 'is'
875 
876     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
877     typeAnnotation = ParseTypeAnnotation(&options);
878     endPos = typeAnnotation->End();
879 
880     result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts, Allocator());
881     ES2PANDA_ASSERT(result != nullptr);
882     result->SetRange({startPos, endPos});
883 
884     return result;
885 }
886 
ParseTypeLiteralOrMappedType(ir::TypeNode * typeAnnotation)887 ir::TypeNode *TSParser::ParseTypeLiteralOrMappedType(ir::TypeNode *typeAnnotation)
888 {
889     if (typeAnnotation != nullptr) {
890         return nullptr;
891     }
892 
893     if (IsStartOfMappedType()) {
894         return ParseMappedType();
895     }
896 
897     lexer::SourcePosition bodyStart = Lexer()->GetToken().Start();
898     auto members = ParseTypeLiteralOrInterface();
899     lexer::SourcePosition bodyEnd = Lexer()->GetToken().End();
900     Lexer()->NextToken();
901 
902     auto *literalType = AllocNode<ir::TSTypeLiteral>(std::move(members), Allocator());
903     ES2PANDA_ASSERT(literalType != nullptr);
904     auto *typeVar = varbinder::Scope::CreateVar(Allocator(), "__type", varbinder::VariableFlags::TYPE, literalType);
905     literalType->SetVariable(typeVar);
906     literalType->SetRange({bodyStart, bodyEnd});
907     return literalType;
908 }
909 
ParseTypeReferenceOrTypePredicate(ir::TypeNode * typeAnnotation,bool canBeTsTypePredicate)910 ir::TypeNode *TSParser::ParseTypeReferenceOrTypePredicate(ir::TypeNode *typeAnnotation, bool canBeTsTypePredicate)
911 {
912     if (typeAnnotation != nullptr) {
913         return nullptr;
914     }
915 
916     if (canBeTsTypePredicate && IsStartOfTypePredicate()) {
917         return ParseTypePredicate();
918     }
919 
920     return ParseTypeOperatorOrTypeReference();
921 }
922 
ParseThisTypeOrTypePredicate(ir::TypeNode * typeAnnotation,bool canBeTsTypePredicate,bool throwError)923 ir::TypeNode *TSParser::ParseThisTypeOrTypePredicate(ir::TypeNode *typeAnnotation, bool canBeTsTypePredicate,
924                                                      bool throwError)
925 {
926     if (typeAnnotation != nullptr) {
927         return nullptr;
928     }
929 
930     if (canBeTsTypePredicate && IsStartOfTypePredicate()) {
931         return ParseTypePredicate();
932     }
933 
934     return ParseThisType(throwError);
935 }
936 
ParseArrayType(ir::TypeNode * elementType)937 ir::TSArrayType *TSParser::ParseArrayType(ir::TypeNode *elementType)
938 {
939     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
940     Lexer()->NextToken();  // eat '['
941 
942     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
943         ThrowSyntaxError("']' expected");
944     }
945 
946     lexer::SourcePosition endLoc = Lexer()->GetToken().End();
947     Lexer()->NextToken();  // eat ']'
948 
949     lexer::SourcePosition startLoc = elementType->Start();
950     auto *arrayType = AllocNode<ir::TSArrayType>(elementType, Allocator());
951     ES2PANDA_ASSERT(arrayType != nullptr);
952     arrayType->SetRange({startLoc, endLoc});
953 
954     return arrayType;
955 }
956 
ParseUnionType(ir::TypeNode * type,bool restrictExtends)957 ir::TSUnionType *TSParser::ParseUnionType(ir::TypeNode *type, bool restrictExtends)
958 {
959     ArenaVector<ir::TypeNode *> types(Allocator()->Adapter());
960     lexer::SourcePosition startLoc;
961 
962     TypeAnnotationParsingOptions options =
963         TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::IN_UNION;
964 
965     if (restrictExtends) {
966         options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
967     }
968 
969     if (type != nullptr) {
970         startLoc = type->Start();
971         types.push_back(type);
972     } else {
973         startLoc = Lexer()->GetToken().Start();
974     }
975 
976     while (true) {
977         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
978             break;
979         }
980 
981         Lexer()->NextToken();  // eat '|'
982 
983         types.push_back(ParseTypeAnnotation(&options));
984     }
985 
986     lexer::SourcePosition endLoc = types.back()->End();
987 
988     auto *unionType = AllocNode<ir::TSUnionType>(std::move(types), Allocator());
989     auto *typeVar = varbinder::Scope::CreateVar(Allocator(), "__type", varbinder::VariableFlags::TYPE, unionType);
990     ES2PANDA_ASSERT(unionType != nullptr);
991     unionType->SetVariable(typeVar);
992     unionType->SetRange({startLoc, endLoc});
993 
994     return unionType;
995 }
996 
ParseIntersectionType(ir::Expression * type,bool inUnion,bool restrictExtends)997 ir::TSIntersectionType *TSParser::ParseIntersectionType(ir::Expression *type, bool inUnion, bool restrictExtends)
998 {
999     ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1000     lexer::SourcePosition startLoc;
1001 
1002     TypeAnnotationParsingOptions options =
1003         TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::IN_INTERSECTION;
1004 
1005     if (restrictExtends) {
1006         options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1007     }
1008 
1009     if (inUnion) {
1010         options |= TypeAnnotationParsingOptions::IN_UNION;
1011     }
1012 
1013     if (type != nullptr) {
1014         startLoc = type->Start();
1015         types.push_back(type);
1016     } else {
1017         startLoc = Lexer()->GetToken().Start();
1018     }
1019 
1020     while (true) {
1021         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_AND) {
1022             break;
1023         }
1024 
1025         Lexer()->NextToken();  // eat '&'
1026 
1027         types.push_back(ParseTypeAnnotation(&options));
1028     }
1029 
1030     lexer::SourcePosition endLoc = types.back()->End();
1031 
1032     auto *intersectionType = AllocNode<ir::TSIntersectionType>(std::move(types), Allocator());
1033     auto *typeVar =
1034         varbinder::Scope::CreateVar(Allocator(), "__type", varbinder::VariableFlags::TYPE, intersectionType);
1035     ES2PANDA_ASSERT(intersectionType != nullptr);
1036     intersectionType->SetVariable(typeVar);
1037     intersectionType->SetRange({startLoc, endLoc});
1038 
1039     return intersectionType;
1040 }
1041 
1042 class TSParser::ParseBasicTypeHelper {
1043     friend ir::TypeNode *TSParser::ParseBasicType();
1044 
1045 private:
GetTypeAnnotationFromLiteral(TSParser * parser,lexer::Lexer * lexer)1046     static ir::TypeNode *GetTypeAnnotationFromLiteral(TSParser *parser, lexer::Lexer *lexer)
1047     {
1048         switch (lexer->GetToken().KeywordType()) {
1049             case lexer::TokenType::LITERAL_NUMBER: {
1050                 if ((lexer->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
1051                     auto *bigintNode = parser->AllocNode<ir::BigIntLiteral>(lexer->GetToken().BigInt());
1052                     bigintNode->SetRange(lexer->GetToken().Loc());
1053 
1054                     return parser->AllocNode<ir::TSLiteralType>(bigintNode, parser->Allocator());
1055                 }
1056                 auto *numberNode = parser->AllocNode<ir::NumberLiteral>(lexer->GetToken().GetNumber());
1057                 CHECK_NOT_NULL(numberNode);
1058                 numberNode->SetRange(lexer->GetToken().Loc());
1059 
1060                 return parser->AllocNode<ir::TSLiteralType>(numberNode, parser->Allocator());
1061             }
1062             case lexer::TokenType::LITERAL_STRING: {
1063                 auto *stringNode = parser->AllocNode<ir::StringLiteral>(lexer->GetToken().String());
1064                 stringNode->SetRange(lexer->GetToken().Loc());
1065 
1066                 return parser->AllocNode<ir::TSLiteralType>(stringNode, parser->Allocator());
1067             }
1068             case lexer::TokenType::LITERAL_TRUE: {
1069                 auto *booleanLiteral = parser->AllocNode<ir::BooleanLiteral>(true);
1070                 booleanLiteral->SetRange(lexer->GetToken().Loc());
1071 
1072                 return parser->AllocNode<ir::TSLiteralType>(booleanLiteral, parser->Allocator());
1073             }
1074             case lexer::TokenType::LITERAL_FALSE: {
1075                 auto *booleanLiteral = parser->AllocNode<ir::BooleanLiteral>(false);
1076                 booleanLiteral->SetRange(lexer->GetToken().Loc());
1077 
1078                 return parser->AllocNode<ir::TSLiteralType>(booleanLiteral, parser->Allocator());
1079             }
1080             case lexer::TokenType::LITERAL_NULL: {
1081                 return parser->AllocNode<ir::TSNullKeyword>(parser->Allocator());
1082             }
1083             default: {
1084                 return nullptr;
1085             }
1086         }
1087     }
1088 
GetTypeAnnotation(TSParser * parser,lexer::Lexer * lexer)1089     static ir::TypeNode *GetTypeAnnotation(TSParser *parser, lexer::Lexer *lexer)
1090     {
1091         switch (lexer->GetToken().KeywordType()) {
1092             case lexer::TokenType::LITERAL_NUMBER:
1093             case lexer::TokenType::LITERAL_STRING:
1094             case lexer::TokenType::LITERAL_TRUE:
1095             case lexer::TokenType::LITERAL_FALSE:
1096             case lexer::TokenType::LITERAL_NULL: {
1097                 return GetTypeAnnotationFromLiteral(parser, lexer);
1098             }
1099             case lexer::TokenType::KEYW_ANY: {
1100                 return parser->AllocNode<ir::TSAnyKeyword>(parser->Allocator());
1101             }
1102             case lexer::TokenType::KEYW_BOOLEAN: {
1103                 return parser->AllocNode<ir::TSBooleanKeyword>(parser->Allocator());
1104             }
1105             case lexer::TokenType::KEYW_NUMBER: {
1106                 return parser->AllocNode<ir::TSNumberKeyword>(parser->Allocator());
1107             }
1108             case lexer::TokenType::KEYW_STRING: {
1109                 return parser->AllocNode<ir::TSStringKeyword>(parser->Allocator());
1110             }
1111             case lexer::TokenType::KEYW_UNKNOWN: {
1112                 return parser->AllocNode<ir::TSUnknownKeyword>(parser->Allocator());
1113             }
1114             case lexer::TokenType::KEYW_VOID: {
1115                 return parser->AllocNode<ir::TSVoidKeyword>(parser->Allocator());
1116             }
1117             case lexer::TokenType::KEYW_UNDEFINED: {
1118                 return parser->AllocNode<ir::TSUndefinedKeyword>(parser->Allocator());
1119             }
1120             case lexer::TokenType::KEYW_NEVER: {
1121                 return parser->AllocNode<ir::TSNeverKeyword>(parser->Allocator());
1122             }
1123             case lexer::TokenType::KEYW_OBJECT: {
1124                 return parser->AllocNode<ir::TSObjectKeyword>(parser->Allocator());
1125             }
1126             case lexer::TokenType::KEYW_BIGINT: {
1127                 return parser->AllocNode<ir::TSBigintKeyword>(parser->Allocator());
1128             }
1129             default: {
1130                 parser->ThrowSyntaxError("Unexpected type");
1131             }
1132         }
1133     }
1134 };
ParseBasicType()1135 ir::TypeNode *TSParser::ParseBasicType()
1136 {
1137     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) {
1138         Lexer()->NextToken();
1139 
1140         if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) {
1141             ThrowSyntaxError("Type expected");
1142         }
1143     }
1144 
1145     ir::TypeNode *typeAnnotation = ParseBasicTypeHelper::GetTypeAnnotation(this, Lexer());
1146 
1147     typeAnnotation->SetRange(Lexer()->GetToken().Loc());
1148 
1149     Lexer()->NextToken();
1150     return typeAnnotation;
1151 }
1152 
1153 // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP) solid logic
ParseParenthesizedOrFunctionType(ir::TypeNode * typeAnnotation,bool throwError)1154 ir::TypeNode *TSParser::ParseParenthesizedOrFunctionType(ir::TypeNode *typeAnnotation, bool throwError)
1155 {
1156     if (typeAnnotation != nullptr) {
1157         return nullptr;
1158     }
1159 
1160     lexer::SourcePosition typeStart = Lexer()->GetToken().Start();
1161 
1162     bool abstractConstructor = false;
1163 
1164     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) {
1165         abstractConstructor = true;
1166         Lexer()->NextToken();  // eat 'abstract'
1167     }
1168 
1169     bool isConstructionType = false;
1170 
1171     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_NEW) {
1172         Lexer()->NextToken();  // eat 'new'
1173         isConstructionType = true;
1174 
1175         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1176             Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1177             ThrowSyntaxError("'(' expected");
1178         }
1179     }
1180 
1181     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || isConstructionType) {
1182         return ParseFunctionType(typeStart, isConstructionType, throwError, abstractConstructor);
1183     }
1184 
1185     const auto startPos = Lexer()->Save();
1186     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1187     Lexer()->NextToken();  // eat '('
1188 
1189     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
1190     ir::TypeNode *type = ParseTypeAnnotation(&options);
1191 
1192     if (type == nullptr) {
1193         Lexer()->Rewind(startPos);
1194         return ParseFunctionType(typeStart, false, throwError);
1195     }
1196 
1197     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ||
1198         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK ||
1199         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1200         Lexer()->Rewind(startPos);
1201         return ParseFunctionType(typeStart, false, throwError);
1202     }
1203 
1204     if (throwError && Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1205         ThrowSyntaxError("')' expected");
1206     }
1207 
1208     lexer::SourcePosition endLoc = Lexer()->GetToken().End();
1209     Lexer()->NextToken();  // eat ')'
1210 
1211     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1212         Lexer()->Rewind(startPos);
1213 
1214         return ParseFunctionType(typeStart, false, throwError);
1215     }
1216 
1217     auto *result = AllocNode<ir::TSParenthesizedType>(type, Allocator());
1218     ES2PANDA_ASSERT(result != nullptr);
1219     result->SetRange({typeStart, endLoc});
1220 
1221     return result;
1222 }
1223 
ParseFunctionType(lexer::SourcePosition startLoc,bool isConstructionType,bool throwError,bool abstractConstructor)1224 ir::TypeNode *TSParser::ParseFunctionType(lexer::SourcePosition startLoc, bool isConstructionType, bool throwError,
1225                                           bool abstractConstructor)
1226 {
1227     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1228     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1229         auto options = throwError ? TypeAnnotationParsingOptions::REPORT_ERROR : TypeAnnotationParsingOptions::NO_OPTS;
1230         typeParamDecl = ParseTypeParameterDeclaration(&options);
1231 
1232         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1233             if (!throwError) {
1234                 return nullptr;
1235             }
1236 
1237             ThrowSyntaxError("'(' expected");
1238         }
1239     }
1240 
1241     auto params = ParseFunctionParams();
1242 
1243     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1244         ThrowSyntaxError("'=>' expected");
1245     }
1246 
1247     Lexer()->NextToken();  // eat '=>'
1248 
1249     TypeAnnotationParsingOptions options =
1250         TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1251     ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options);
1252 
1253     ir::TypeNode *funcType = nullptr;
1254 
1255     ir::FunctionSignature signature(typeParamDecl, std::move(params), returnTypeAnnotation);
1256 
1257     if (isConstructionType) {
1258         funcType = AllocNode<ir::TSConstructorType>(std::move(signature), abstractConstructor, Allocator());
1259     } else {
1260         funcType = AllocNode<ir::TSFunctionType>(std::move(signature), Allocator());
1261     }
1262 
1263     funcType->SetRange({startLoc, returnTypeAnnotation->End()});
1264 
1265     return funcType;
1266 }
1267 
1268 class TSParser::ParseTypeAnnotationElementHelper {
1269     friend ir::TypeNode *TSParser::ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation,
1270                                                               TypeAnnotationParsingOptions *options);
1271 
1272 private:
ParseKeywordTokens(TSParser * parser,lexer::Lexer * lexer,ir::TypeNode * typeAnnotation,TypeAnnotationParsingOptions * options)1273     static ir::TypeNode *ParseKeywordTokens(TSParser *parser, lexer::Lexer *lexer, ir::TypeNode *typeAnnotation,
1274                                             TypeAnnotationParsingOptions *options)
1275     {
1276         switch (lexer->GetToken().Type()) {
1277             case lexer::TokenType::KEYW_NEW: {
1278                 return parser->ParseParenthesizedOrFunctionType(
1279                     typeAnnotation, ((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0);
1280             }
1281             case lexer::TokenType::KEYW_TYPEOF: {
1282                 if (typeAnnotation != nullptr) {
1283                     break;
1284                 }
1285 
1286                 return parser->ParseTypeReferenceOrQuery(true);
1287             }
1288             case lexer::TokenType::KEYW_IMPORT: {
1289                 if (typeAnnotation != nullptr) {
1290                     break;
1291                 }
1292                 return parser->ParseImportType(lexer->GetToken().Start());
1293             }
1294             case lexer::TokenType::KEYW_CONST: {
1295                 if (((*options) & TypeAnnotationParsingOptions::ALLOW_CONST) == 0) {
1296                     break;
1297                 }
1298 
1299                 (*options) &= ~TypeAnnotationParsingOptions::ALLOW_CONST;
1300                 return parser->ParseConstExpression();
1301             }
1302             case lexer::TokenType::KEYW_EXTENDS: {
1303                 if (((*options) &
1304                      (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) != 0) {
1305                     break;
1306                 }
1307 
1308                 if (typeAnnotation == nullptr) {
1309                     return parser->ParseIdentifierReference();
1310                 }
1311 
1312                 return parser->ParseConditionalType(typeAnnotation,
1313                                                     ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0);
1314             }
1315             case lexer::TokenType::KEYW_THIS: {
1316                 return parser->ParseThisTypeOrTypePredicate(
1317                     typeAnnotation, ((*options) & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE) != 0,
1318                     ((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0);
1319             }
1320             default: {
1321                 break;
1322             }
1323         }
1324         return nullptr;
1325     }
1326 
ParsePunctuatorTokens(TSParser * parser,lexer::Lexer * lexer,ir::TypeNode * typeAnnotation,TypeAnnotationParsingOptions * options)1327     static ir::TypeNode *ParsePunctuatorTokens(TSParser *parser, lexer::Lexer *lexer, ir::TypeNode *typeAnnotation,
1328                                                TypeAnnotationParsingOptions *options)
1329     {
1330         switch (lexer->GetToken().Type()) {
1331             case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
1332                 if (((*options) &
1333                      (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) != 0) {
1334                     break;
1335                 }
1336 
1337                 return parser->ParseUnionType(typeAnnotation,
1338                                               ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0);
1339             }
1340             case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
1341                 if (((*options) & TypeAnnotationParsingOptions::IN_INTERSECTION) != 0) {
1342                     break;
1343                 }
1344 
1345                 return parser->ParseIntersectionType(
1346                     typeAnnotation, ((*options) & TypeAnnotationParsingOptions::IN_UNION) != 0,
1347                     ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0);
1348             }
1349             case lexer::TokenType::PUNCTUATOR_LESS_THAN:
1350             case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1351                 return parser->ParseParenthesizedOrFunctionType(
1352                     typeAnnotation, ((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0);
1353             }
1354             case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1355                 if (typeAnnotation != nullptr) {
1356                     if (lexer->Lookahead() == lexer::LEX_CHAR_RIGHT_SQUARE) {
1357                         return parser->ParseArrayType(typeAnnotation);
1358                     }
1359 
1360                     return parser->ParseIndexAccessType(typeAnnotation);
1361                 }
1362 
1363                 return parser->ParseTupleType();
1364             }
1365             case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1366                 return parser->ParseTypeLiteralOrMappedType(typeAnnotation);
1367             }
1368             default: {
1369                 break;
1370             }
1371         }
1372 
1373         return nullptr;
1374     }
1375 };
1376 
ParseTypeAnnotationElement(ir::TypeNode * typeAnnotation,TypeAnnotationParsingOptions * options)1377 ir::TypeNode *TSParser::ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation, TypeAnnotationParsingOptions *options)
1378 {
1379     switch (Lexer()->GetToken().Type()) {
1380         case lexer::TokenType::PUNCTUATOR_MINUS:
1381         case lexer::TokenType::LITERAL_NUMBER:
1382         case lexer::TokenType::LITERAL_STRING:
1383         case lexer::TokenType::LITERAL_FALSE:
1384         case lexer::TokenType::LITERAL_TRUE:
1385         case lexer::TokenType::LITERAL_NULL:
1386         case lexer::TokenType::KEYW_VOID: {
1387             if (typeAnnotation != nullptr) {
1388                 break;
1389             }
1390 
1391             return ParseBasicType();
1392         }
1393         case lexer::TokenType::LITERAL_IDENT: {
1394             if (IsStartOfAbstractConstructorType()) {
1395                 return ParseParenthesizedOrFunctionType(typeAnnotation,
1396                                                         ((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0);
1397             }
1398 
1399             return ParseTypeReferenceOrTypePredicate(
1400                 typeAnnotation, ((*options) & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE) != 0);
1401         }
1402         default: {
1403             ir::TypeNode *parsedValue =
1404                 ParseTypeAnnotationElementHelper::ParseKeywordTokens(this, Lexer(), typeAnnotation, options);
1405             if (parsedValue != nullptr) {
1406                 return parsedValue;
1407             }
1408 
1409             parsedValue =
1410                 ParseTypeAnnotationElementHelper::ParsePunctuatorTokens(this, Lexer(), typeAnnotation, options);
1411             if (parsedValue != nullptr) {
1412                 return parsedValue;
1413             }
1414 
1415             break;
1416         }
1417     }
1418 
1419     if (typeAnnotation == nullptr && (((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0)) {
1420         ThrowSyntaxError("Type expected");
1421     }
1422 
1423     return nullptr;
1424 }
1425 
ParsePotentialGenericFunctionCall(ir::Expression * primaryExpr,ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc,bool ignoreCallExpression)1426 bool TSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir::Expression **returnExpression,
1427                                                  const lexer::SourcePosition &startLoc, bool ignoreCallExpression)
1428 {
1429     if (Lexer()->Lookahead() == lexer::LEX_CHAR_LESS_THAN ||
1430         (!primaryExpr->IsIdentifier() && !primaryExpr->IsMemberExpression())) {
1431         return true;
1432     }
1433 
1434     const auto savedPos = Lexer()->Save();
1435 
1436     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
1437         Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
1438     }
1439 
1440     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
1441     ir::TSTypeParameterInstantiation *typeParams = ParseTypeParameterInstantiation(&options);
1442 
1443     if (typeParams == nullptr) {
1444         Lexer()->Rewind(savedPos);
1445         return true;
1446     }
1447 
1448     if (Lexer()->GetToken().Type() == lexer::TokenType::EOS) {
1449         ThrowSyntaxError("'(' or '`' expected");
1450     }
1451 
1452     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1453         if (!ignoreCallExpression) {
1454             *returnExpression = ParseCallExpression(*returnExpression, false);
1455             (*returnExpression)->AsCallExpression()->SetTypeParams(typeParams);
1456             return false;
1457         }
1458 
1459         return true;
1460     }
1461 
1462     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) {
1463         ir::TemplateLiteral *propertyNode = ParseTemplateLiteral();
1464         lexer::SourcePosition endLoc = propertyNode->End();
1465 
1466         *returnExpression = AllocNode<ir::TaggedTemplateExpression>(*returnExpression, propertyNode, typeParams);
1467         // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
1468         (*returnExpression)->SetRange({startLoc, endLoc});
1469         return false;
1470     }
1471 
1472     Lexer()->Rewind(savedPos);
1473     return true;
1474 }
1475 
IsNamedFunctionExpression()1476 bool TSParser::IsNamedFunctionExpression()
1477 {
1478     return Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1479            Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN;
1480 }
1481 
ParsePrimaryExpressionIdent(ExpressionParseFlags flags)1482 ir::Identifier *TSParser::ParsePrimaryExpressionIdent([[maybe_unused]] ExpressionParseFlags flags)
1483 {
1484     auto *identNode = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1485     ES2PANDA_ASSERT(identNode != nullptr);
1486     identNode->SetRange(Lexer()->GetToken().Loc());
1487 
1488     Lexer()->NextToken();
1489 
1490     ParsePotentialOptionalFunctionParameter(identNode);
1491 
1492     return identNode;
1493 }
1494 
ParseSignatureMember(bool isCallSignature)1495 ir::TSSignatureDeclaration *TSParser::ParseSignatureMember(bool isCallSignature)
1496 {
1497     lexer::SourcePosition memberStartLoc = Lexer()->GetToken().Start();
1498 
1499     if (!isCallSignature) {
1500         Lexer()->NextToken();  // eat 'new' keyword
1501     }
1502 
1503     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1504     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1505         auto options = TypeAnnotationParsingOptions::REPORT_ERROR;
1506         typeParamDecl = ParseTypeParameterDeclaration(&options);
1507 
1508         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1509             ThrowSyntaxError("'(' expected");
1510         }
1511     }
1512 
1513     FunctionParameterContext funcParamContext(&GetContext());
1514     auto params = ParseFunctionParams();
1515 
1516     ir::TypeNode *typeAnnotation = nullptr;
1517     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1518         Lexer()->NextToken();  // eat ':'
1519         TypeAnnotationParsingOptions options =
1520             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1521         typeAnnotation = ParseTypeAnnotation(&options);
1522     }
1523 
1524     auto kind = isCallSignature ? ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE
1525                                 : ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CONSTRUCT_SIGNATURE;
1526     auto *signatureMember = AllocNode<ir::TSSignatureDeclaration>(
1527         kind, ir::FunctionSignature(typeParamDecl, std::move(params), typeAnnotation));
1528     ES2PANDA_ASSERT(signatureMember != nullptr);
1529     signatureMember->SetRange({memberStartLoc, Lexer()->GetToken().End()});
1530 
1531     return signatureMember;
1532 }
1533 
IsPotentiallyIndexSignature()1534 bool TSParser::IsPotentiallyIndexSignature()
1535 {
1536     const auto savedPos = Lexer()->Save();
1537 
1538     Lexer()->NextToken();  // eat '['
1539 
1540     bool isIndexSignature =
1541         Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && Lexer()->Lookahead() == lexer::LEX_CHAR_COLON;
1542 
1543     Lexer()->Rewind(savedPos);
1544 
1545     return isIndexSignature;
1546 }
1547 
1548 // NOLINTNEXTLINE(google-default-arguments)
ParseIndexSignature(const lexer::SourcePosition & startLoc,bool isReadonly)1549 ir::TSIndexSignature *TSParser::ParseIndexSignature(const lexer::SourcePosition &startLoc, bool isReadonly)
1550 {
1551     Lexer()->NextToken();  // eat '['
1552 
1553     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
1554     auto *key = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1555     ES2PANDA_ASSERT(key != nullptr);
1556     key->SetRange(Lexer()->GetToken().Loc());
1557 
1558     Lexer()->NextToken();  // eat key
1559 
1560     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON);
1561 
1562     Lexer()->NextToken();  // eat ':'
1563 
1564     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
1565     ir::TypeNode *keyType = ParseTypeAnnotation(&options);
1566 
1567     if (!keyType->IsTSNumberKeyword() && !keyType->IsTSStringKeyword()) {
1568         ThrowSyntaxError(
1569             "An index signature parameter type must be either "
1570             "'string' or 'number'");
1571     }
1572 
1573     key->SetTsTypeAnnotation(keyType);
1574 
1575     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1576         ThrowSyntaxError("']' expected.");
1577     }
1578 
1579     Lexer()->NextToken();  // eat ']'
1580 
1581     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1582         ThrowSyntaxError("An index signature must have a type annotation.");
1583     }
1584 
1585     Lexer()->NextToken();  // eat ':'
1586 
1587     ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
1588 
1589     auto *indexSignature = AllocNode<ir::TSIndexSignature>(key, typeAnnotation, isReadonly);
1590     indexSignature->SetRange({startLoc, Lexer()->GetToken().End()});
1591     return indexSignature;
1592 }
1593 
ParseInterfacePropertyKey()1594 std::tuple<ir::Expression *, bool> TSParser::ParseInterfacePropertyKey()
1595 {
1596     ir::Expression *key = nullptr;
1597     bool isComputed = false;
1598 
1599     switch (Lexer()->GetToken().Type()) {
1600         case lexer::TokenType::LITERAL_IDENT: {
1601             const util::StringView &ident = Lexer()->GetToken().Ident();
1602             key = AllocNode<ir::Identifier>(ident, Allocator());
1603             ES2PANDA_ASSERT(key != nullptr);
1604             key->SetRange(Lexer()->GetToken().Loc());
1605             break;
1606         }
1607         case lexer::TokenType::LITERAL_STRING: {
1608             const util::StringView &string = Lexer()->GetToken().String();
1609             key = AllocNode<ir::StringLiteral>(string);
1610             ES2PANDA_ASSERT(key != nullptr);
1611             key->SetRange(Lexer()->GetToken().Loc());
1612             break;
1613         }
1614         case lexer::TokenType::LITERAL_NUMBER: {
1615             if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
1616                 key = AllocNode<ir::BigIntLiteral>(Lexer()->GetToken().BigInt());
1617             } else {
1618                 key = AllocNode<ir::NumberLiteral>(Lexer()->GetToken().GetNumber());
1619             }
1620 
1621             ES2PANDA_ASSERT(key != nullptr);
1622             key->SetRange(Lexer()->GetToken().Loc());
1623             break;
1624         }
1625         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1626             Lexer()->NextToken();  // eat left square bracket
1627 
1628             key = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1629             isComputed = true;
1630 
1631             if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1632                 ThrowSyntaxError("Unexpected token, expected ']'");
1633             }
1634             break;
1635         }
1636         default: {
1637             ThrowSyntaxError("Unexpected token in property key");
1638         }
1639     }
1640 
1641     Lexer()->NextToken();
1642     return {key, isComputed};
1643 }
1644 
CreateTSVariableForProperty(ir::AstNode * node,const ir::Expression * key,varbinder::VariableFlags flags)1645 void TSParser::CreateTSVariableForProperty(ir::AstNode *node, const ir::Expression *key, varbinder::VariableFlags flags)
1646 {
1647     varbinder::Variable *propVar = nullptr;
1648     bool isMethod = (flags & varbinder::VariableFlags::METHOD) != 0;
1649     util::StringView propName = "__computed";
1650 
1651     switch (key->Type()) {
1652         case ir::AstNodeType::IDENTIFIER: {
1653             propName = key->AsIdentifier()->Name();
1654             break;
1655         }
1656         case ir::AstNodeType::NUMBER_LITERAL: {
1657             propName = key->AsNumberLiteral()->Str();
1658             flags |= varbinder::VariableFlags::NUMERIC_NAME;
1659             break;
1660         }
1661         case ir::AstNodeType::STRING_LITERAL: {
1662             propName = key->AsStringLiteral()->Str();
1663             break;
1664         }
1665         default: {
1666             flags |= varbinder::VariableFlags::COMPUTED;
1667             break;
1668         }
1669     }
1670 
1671     propVar = isMethod ? varbinder::Scope::CreateVar<varbinder::MethodDecl>(Allocator(), propName, flags, node)
1672                        : varbinder::Scope::CreateVar<varbinder::PropertyDecl>(Allocator(), propName, flags, node);
1673 
1674     node->SetVariable(propVar);
1675 }
1676 
ParsePropertyOrMethodSignature(const lexer::SourcePosition & startLoc,bool isReadonly)1677 ir::AstNode *TSParser::ParsePropertyOrMethodSignature(const lexer::SourcePosition &startLoc, bool isReadonly)
1678 {
1679     auto [key, isComputed] = ParseInterfacePropertyKey();
1680     varbinder::VariableFlags flags = isReadonly ? varbinder::VariableFlags::READONLY : varbinder::VariableFlags::NONE;
1681 
1682     bool isOptional = false;
1683     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1684         isOptional = true;
1685         flags |= varbinder::VariableFlags::OPTIONAL;
1686         Lexer()->NextToken();  // eat '?'
1687     }
1688 
1689     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
1690         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1691         if (isReadonly) {
1692             ThrowSyntaxError("'readonly' modifier can only appear on a property declaration or index signature.",
1693                              startLoc);
1694         }
1695 
1696         ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1697         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1698             auto options = TypeAnnotationParsingOptions::REPORT_ERROR;
1699             typeParamDecl = ParseTypeParameterDeclaration(&options);
1700         }
1701 
1702         ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS, false);
1703 
1704         FunctionParameterContext funcParamContext(&GetContext());
1705         auto params = ParseFunctionParams();
1706 
1707         ir::TypeNode *returnType = nullptr;
1708         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1709             Lexer()->NextToken();  // eat ':'
1710             TypeAnnotationParsingOptions options =
1711                 TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1712             returnType = ParseTypeAnnotation(&options);
1713         }
1714 
1715         auto *methodSignature = AllocNode<ir::TSMethodSignature>(
1716             key, ir::FunctionSignature(typeParamDecl, std::move(params), returnType), isComputed, isOptional);
1717         CreateTSVariableForProperty(methodSignature, key, flags | varbinder::VariableFlags::METHOD);
1718         methodSignature->SetRange({startLoc, Lexer()->GetToken().End()});
1719         return methodSignature;
1720     }
1721 
1722     ir::TypeNode *typeAnnotation = nullptr;
1723     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1724         Lexer()->NextToken();  // eat ':'
1725         TypeAnnotationParsingOptions options =
1726             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
1727         typeAnnotation = ParseTypeAnnotation(&options);
1728     }
1729 
1730     auto *propertySignature =
1731         AllocNode<ir::TSPropertySignature>(key, typeAnnotation, isComputed, isOptional, isReadonly);
1732     CreateTSVariableForProperty(propertySignature, key, flags | varbinder::VariableFlags::PROPERTY);
1733     propertySignature->SetRange({startLoc, Lexer()->GetToken().End()});
1734     return propertySignature;
1735 }
1736 
ParseTypeLiteralOrInterfaceMember()1737 ir::AstNode *TSParser::ParseTypeLiteralOrInterfaceMember()
1738 {
1739     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
1740         ThrowSyntaxError("Decorators are not allowed here");
1741     }
1742 
1743     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
1744         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1745         return ParseSignatureMember(true);
1746     }
1747 
1748     char32_t nextCp = Lexer()->Lookahead();
1749     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_NEW &&
1750         (nextCp == lexer::LEX_CHAR_LEFT_PAREN || nextCp == lexer::LEX_CHAR_LESS_THAN)) {
1751         return ParseSignatureMember(false);
1752     }
1753 
1754     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1755     bool isReadonly = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY &&
1756                       nextCp != lexer::LEX_CHAR_LEFT_PAREN && nextCp != lexer::LEX_CHAR_COLON &&
1757                       nextCp != lexer::LEX_CHAR_COMMA;
1758     if (isReadonly) {
1759         Lexer()->NextToken();  // eat 'readonly"
1760     }
1761 
1762     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
1763         IsPotentiallyIndexSignature()) {
1764         return ParseIndexSignature(startLoc, isReadonly);
1765     }
1766 
1767     return ParsePropertyOrMethodSignature(startLoc, isReadonly);
1768 }
1769 
ValidateFunctionParam(const ArenaVector<ir::Expression * > & params,const ir::Expression * parameter,bool * seenOptional)1770 void TSParser::ValidateFunctionParam(const ArenaVector<ir::Expression *> &params, const ir::Expression *parameter,
1771                                      bool *seenOptional)
1772 {
1773     if (!parameter->IsIdentifier()) {
1774         GetContext().Status() |= ParserStatus::HAS_COMPLEX_PARAM;
1775         if (!parameter->IsRestElement()) {
1776             return;
1777         }
1778 
1779         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1780             ThrowSyntaxError("A rest parameter must be last in parameter list");
1781         }
1782         return;
1783     }
1784 
1785     bool currentIsOptional = parameter->AsIdentifier()->IsOptional();
1786     if (*seenOptional && !currentIsOptional) {
1787         ThrowSyntaxError("A required parameter cannot follow an optional parameter");
1788     }
1789 
1790     *seenOptional |= currentIsOptional;
1791     const util::StringView &paramName = parameter->AsIdentifier()->Name();
1792 
1793     if (paramName.Is("this")) {
1794         if (!params.empty()) {
1795             ThrowSyntaxError("A 'this' parameter must be the first parameter");
1796         }
1797 
1798         if ((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) != 0) {
1799             ThrowSyntaxError("A constructor cannot have a 'this' parameter");
1800         }
1801 
1802         if ((GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0) {
1803             ThrowSyntaxError("An arrow function cannot have a 'this' parameter");
1804         }
1805 
1806         if ((GetContext().Status() & ParserStatus::ACCESSOR_FUNCTION) != 0) {
1807             ThrowSyntaxError("'get' and 'set' accessors cannot declare 'this' parameters");
1808         }
1809     }
1810 
1811     if (paramName.Is("constructor") && ((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) != 0)) {
1812         ThrowSyntaxError("'constructor' cannot be used as a parameter property name");
1813     }
1814 }
1815 
ParseFunctionParams()1816 ArenaVector<ir::Expression *> TSParser::ParseFunctionParams()
1817 {
1818     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1819     Lexer()->NextToken();
1820 
1821     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1822     bool seenOptional = false;
1823 
1824     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1825         ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
1826 
1827         ParseDecorators(decorators);
1828 
1829         if (!decorators.empty() && ((GetContext().Status() & ParserStatus::IN_CLASS_BODY) == 0)) {
1830             ThrowSyntaxError("Decorators are not valid here", decorators.front()->Start());
1831         }
1832 
1833         ir::Expression *parameter = ParseFunctionParameter();
1834         ValidateFunctionParam(params, parameter, &seenOptional);
1835 
1836         if (!decorators.empty()) {
1837             parameter->AddDecorators(std::move(decorators));
1838         }
1839 
1840         params.push_back(parameter);
1841 
1842         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1843             Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1844             ThrowSyntaxError(", expected");
1845         }
1846 
1847         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1848             Lexer()->NextToken();
1849         }
1850     }
1851 
1852     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
1853     Lexer()->NextToken();
1854 
1855     return params;
1856 }
1857 
ParseClassKeyAnnotation()1858 ir::TypeNode *TSParser::ParseClassKeyAnnotation()
1859 {
1860     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1861         Lexer()->NextToken();  // eat ':'
1862         TypeAnnotationParsingOptions options =
1863             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
1864         return ParseTypeAnnotation(&options);
1865     }
1866 
1867     return nullptr;
1868 }
1869 
ValidateClassMethodStart(ClassElementDescriptor * desc,ir::TypeNode * typeAnnotation)1870 void TSParser::ValidateClassMethodStart(ClassElementDescriptor *desc, ir::TypeNode *typeAnnotation)
1871 {
1872     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && desc->isPrivateIdent) {
1873         ThrowSyntaxError("A method cannot be named with a private identifier");
1874     }
1875 
1876     if (typeAnnotation == nullptr && (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
1877                                       Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN)) {
1878         if (((desc->modifiers & (ir::ModifierFlags::DECLARE | ir::ModifierFlags::READONLY)) != 0)) {
1879             ThrowSyntaxError("Class method can not be declare nor readonly");
1880         }
1881         desc->classMethod = true;
1882     } else {
1883         if (((desc->modifiers & ir::ModifierFlags::ASYNC) != 0) || desc->isGenerator) {
1884             ThrowSyntaxError("Expected '('");
1885         }
1886         desc->classField = true;
1887 
1888         if (desc->invalidComputedProperty) {
1889             ThrowSyntaxError(
1890                 "Computed property name must refer to a symbol or "
1891                 "literal expression whose value is "
1892                 "number or string");
1893         }
1894     }
1895 
1896     if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0) {
1897         desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
1898     }
1899 
1900     if (desc->isGenerator) {
1901         desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
1902     }
1903 }
1904 
ParseClassMethod(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd)1905 ir::MethodDefinition *TSParser::ParseClassMethod(ClassElementDescriptor *desc,
1906                                                  const ArenaVector<ir::AstNode *> &properties, ir::Expression *propName,
1907                                                  lexer::SourcePosition *propEnd)
1908 {
1909     if (desc->methodKind == ir::MethodDefinitionKind::SET || desc->methodKind == ir::MethodDefinitionKind::GET) {
1910         desc->newStatus |= ParserStatus::ACCESSOR_FUNCTION;
1911     }
1912 
1913     desc->newStatus |= ParserStatus::IN_METHOD_DEFINITION;
1914 
1915     if (InAmbientContext() && (desc->newStatus & ParserStatus::ASYNC_FUNCTION) != 0) {
1916         ThrowSyntaxError("'async' modifier cannot be used in an ambient context.");
1917     }
1918 
1919     if (InAmbientContext() && desc->isGenerator) {
1920         ThrowSyntaxError("Generators are not allowed in an ambient context.");
1921     }
1922 
1923     if (desc->methodKind != ir::MethodDefinitionKind::SET &&
1924         ((desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0)) {
1925         desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
1926     }
1927 
1928     ir::ScriptFunction *func = ParseFunction(desc->newStatus);
1929 
1930     ES2PANDA_ASSERT(func != nullptr);
1931     if (func->IsOverload() && !desc->decorators.empty()) {
1932         ThrowSyntaxError("A decorator can only decorate a method implementation, not an overload.",
1933                          desc->decorators.front()->Start());
1934     }
1935 
1936     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
1937     ES2PANDA_ASSERT(funcExpr != nullptr);
1938     funcExpr->SetRange(func->Range());
1939 
1940     if (desc->methodKind == ir::MethodDefinitionKind::SET) {
1941         ValidateClassSetter(desc, properties, propName, func);
1942     } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
1943         ValidateClassGetter(desc, properties, propName, func);
1944     }
1945 
1946     *propEnd = func->End();
1947     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
1948     auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(),
1949                                                    desc->isComputed);
1950     ES2PANDA_ASSERT(method != nullptr);
1951     method->SetRange(funcExpr->Range());
1952 
1953     return method;
1954 }
1955 
ValidateClassSetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)1956 void TSParser::ValidateClassSetter(ClassElementDescriptor *desc, const ArenaVector<ir::AstNode *> &properties,
1957                                    ir::Expression *propName, ir::ScriptFunction *func)
1958 {
1959     ValidateGetterSetter(ir::MethodDefinitionKind::SET, func->Params().size());
1960 
1961     if ((desc->modifiers & ir::ModifierFlags::STATIC) == 0) {
1962         ir::ModifierFlags access = GetAccessability(desc->modifiers);
1963         CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::GET, access);
1964     }
1965 }
1966 
ValidateClassGetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)1967 void TSParser::ValidateClassGetter(ClassElementDescriptor *desc, const ArenaVector<ir::AstNode *> &properties,
1968                                    ir::Expression *propName, ir::ScriptFunction *func)
1969 {
1970     ValidateGetterSetter(ir::MethodDefinitionKind::GET, func->Params().size());
1971 
1972     if ((desc->modifiers & ir::ModifierFlags::STATIC) == 0) {
1973         ir::ModifierFlags access = GetAccessability(desc->modifiers);
1974 
1975         CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::SET, access);
1976     }
1977 }
1978 
ValidateIndexSignatureTypeAnnotation(ir::TypeNode * typeAnnotation)1979 void TSParser::ValidateIndexSignatureTypeAnnotation(ir::TypeNode *typeAnnotation)
1980 {
1981     if (typeAnnotation == nullptr) {
1982         ThrowSyntaxError("An index signature must have a type annotation");
1983     }
1984 }
1985 
IsModifierKind(const lexer::Token & token)1986 bool TSParser::IsModifierKind(const lexer::Token &token)
1987 {
1988     switch (token.KeywordType()) {
1989         case lexer::TokenType::KEYW_PUBLIC:
1990         case lexer::TokenType::KEYW_PRIVATE:
1991         case lexer::TokenType::KEYW_PROTECTED:
1992         case lexer::TokenType::KEYW_STATIC:
1993         case lexer::TokenType::KEYW_ASYNC:
1994         case lexer::TokenType::KEYW_ABSTRACT:
1995         case lexer::TokenType::KEYW_DECLARE:
1996         case lexer::TokenType::KEYW_READONLY:
1997             return true;
1998         default:
1999             break;
2000     }
2001 
2002     return false;
2003 }
2004 
CheckIfTypeParameterNameIsReserved()2005 void TSParser::CheckIfTypeParameterNameIsReserved()
2006 {
2007     if (Lexer()->GetToken().IsReservedTypeName()) {
2008         ThrowSyntaxError("Invalid type parameter name");
2009     }
2010 }
2011 
CheckIfStaticConstructor(ir::ModifierFlags flags)2012 void TSParser::CheckIfStaticConstructor(ir::ModifierFlags flags)
2013 {
2014     if ((flags & ir::ModifierFlags::STATIC) != 0) {
2015         ThrowSyntaxError("Static modifier can not appear on a constructor");
2016     }
2017 }
2018 
ParseComputedClassFieldOrIndexSignature(ir::Expression ** propName)2019 std::tuple<bool, bool, bool> TSParser::ParseComputedClassFieldOrIndexSignature(ir::Expression **propName)
2020 {
2021     Lexer()->NextToken();  // eat left square bracket
2022 
2023     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2024         Lexer()->Lookahead() == lexer::LEX_CHAR_COLON) {
2025         auto id = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
2026         ES2PANDA_ASSERT(id != nullptr);
2027         id->SetRange(Lexer()->GetToken().Loc());
2028 
2029         Lexer()->NextToken();  // eat param
2030 
2031         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2032             ThrowSyntaxError("':' expected");
2033         }
2034 
2035         Lexer()->NextToken();  // eat ':'
2036         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
2037         ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
2038 
2039         if (!typeAnnotation->IsTSNumberKeyword() && !typeAnnotation->IsTSStringKeyword()) {
2040             ThrowSyntaxError(
2041                 "An index signature parameter type must be either "
2042                 "'string' or 'number'");
2043         }
2044 
2045         id->SetTsTypeAnnotation(typeAnnotation);
2046 
2047         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2048             ThrowSyntaxError("']' expected");
2049         }
2050 
2051         *propName = id;
2052         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
2053 
2054         return {false, false, true};
2055     }
2056 
2057     *propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2058 
2059     bool invalidComputedProperty =
2060         !(*propName)->IsNumberLiteral() && !(*propName)->IsStringLiteral() &&
2061         !((*propName)->IsMemberExpression() && (*propName)->AsMemberExpression()->Object()->IsIdentifier() &&
2062           (*propName)->AsMemberExpression()->Object()->AsIdentifier()->Name().Is("Symbol"));
2063 
2064     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2065         ThrowSyntaxError("Unexpected token, expected ']'");
2066     }
2067 
2068     return {true, invalidComputedProperty, false};
2069 }
2070 
ParseFunctionReturnType(ParserStatus status)2071 ir::TypeNode *TSParser::ParseFunctionReturnType([[maybe_unused]] ParserStatus status)
2072 {
2073     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2074         Lexer()->NextToken();  // eat ':'
2075         TypeAnnotationParsingOptions options =
2076             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
2077         return ParseTypeAnnotation(&options);
2078     }
2079 
2080     return nullptr;
2081 }
2082 
ValidateFunctionOverloadParams(const ArenaVector<ir::Expression * > & params)2083 void TSParser::ValidateFunctionOverloadParams(const ArenaVector<ir::Expression *> &params)
2084 {
2085     for (auto *it : params) {
2086         if (it->IsAssignmentPattern()) {
2087             ThrowSyntaxError(
2088                 "A parameter initializer is only allowed in a function "
2089                 "or constructor implementation.",
2090                 it->Start());
2091         }
2092     }
2093 }
2094 
ParseFunctionBody(const ArenaVector<ir::Expression * > & params,ParserStatus newStatus,ParserStatus contextStatus)2095 std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> TSParser::ParseFunctionBody(
2096     const ArenaVector<ir::Expression *> &params, ParserStatus newStatus, ParserStatus contextStatus)
2097 {
2098     bool isDeclare = InAmbientContext();
2099     bool isOverload = false;
2100     bool letDeclare = true;
2101     ir::BlockStatement *body = nullptr;
2102     lexer::SourcePosition endLoc = Lexer()->GetToken().End();
2103 
2104     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2105         if ((newStatus & ParserStatus::FUNCTION_DECLARATION) != 0) {
2106             ValidateFunctionOverloadParams(params);
2107         } else if (!isDeclare && ((contextStatus & ParserStatus::IN_METHOD_DEFINITION) == 0)) {
2108             ThrowSyntaxError("Unexpected token, expected '{'");
2109         } else {
2110             letDeclare = false;
2111         }
2112 
2113         isOverload = true;
2114     } else if (isDeclare) {
2115         ThrowSyntaxError("An implementation cannot be declared in ambient contexts.");
2116     } else {
2117         body = ParseBlockStatement();
2118         ES2PANDA_ASSERT(body != nullptr);
2119         endLoc = body->End();
2120     }
2121 
2122     return {letDeclare, body, endLoc, isOverload};
2123 }
2124 
ParseImportDefaultSpecifier(ArenaVector<ir::AstNode * > * specifiers)2125 ir::AstNode *TSParser::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers)
2126 {
2127     ir::Identifier *local = ParseNamedImport(&Lexer()->GetToken());
2128     Lexer()->NextToken();  // eat local name
2129 
2130     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2131         Lexer()->NextToken();  // eat substitution
2132         if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2133             ThrowSyntaxError("identifier expected");
2134         }
2135 
2136         return AllocNode<ir::TSImportEqualsDeclaration>(local, ParseModuleReference(), false);
2137     }
2138 
2139     auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local);
2140     ES2PANDA_ASSERT(specifier != nullptr);
2141     specifier->SetRange(specifier->Local()->Range());
2142     specifiers->push_back(specifier);
2143 
2144     Lexer()->NextToken();  // eat specifier name
2145 
2146     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2147         Lexer()->NextToken();  // eat comma
2148     }
2149 
2150     return nullptr;
2151 }
2152 
ParseCatchParamTypeAnnotation(ir::AnnotatedExpression * param)2153 void TSParser::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param)
2154 {
2155     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2156         Lexer()->NextToken();  // eat ':'
2157 
2158         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
2159         param->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
2160     }
2161 
2162     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2163         ThrowSyntaxError("Catch clause variable cannot have an initializer");
2164     }
2165 }
2166 
ReportPossibleOutOfBoundaryJumpError(bool allowBreak)2167 void TSParser::ReportPossibleOutOfBoundaryJumpError(bool allowBreak)
2168 {
2169     if (((GetContext().Status() & ParserStatus::FUNCTION) != 0) && !allowBreak) {
2170         ThrowSyntaxError("Jump target cannot cross function boundary");
2171     }
2172 }
2173 
ReportIllegalBreakError(const lexer::SourcePosition & pos)2174 void TSParser::ReportIllegalBreakError(const lexer::SourcePosition &pos)
2175 {
2176     ThrowSyntaxError("A 'break' statement can only be used within an enclosing iteration or switch statement", pos);
2177 }
2178 
ReportIllegalContinueError()2179 void TSParser::ReportIllegalContinueError()
2180 {
2181     ThrowSyntaxError("A 'continue' statement can only be used within an enclosing iteration statement");
2182 }
2183 
ReportMultipleDefaultError()2184 void TSParser::ReportMultipleDefaultError()
2185 {
2186     ThrowSyntaxError("A 'default' clause cannot appear more than once in a 'switch' statement");
2187 }
2188 
ReportIllegalNewLineErrorAfterThrow()2189 void TSParser::ReportIllegalNewLineErrorAfterThrow()
2190 {
2191     ThrowSyntaxError("Line break not permitted here");
2192 }
2193 
ReportIfBodyEmptyError(ir::Statement * consequent)2194 void TSParser::ReportIfBodyEmptyError(ir::Statement *consequent)
2195 {
2196     if (consequent->IsEmptyStatement()) {
2197         ThrowSyntaxError("The body of an if statement cannot be the empty statement");
2198     }
2199 }
2200 
2201 }  // namespace ark::es2panda::parser
2202