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