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