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 *> ¶ms, 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 ¶mName = 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 *> ¶ms)
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 *> ¶ms, 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