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
120namespace ark::es2panda::parser {
121std::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
129ir::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
169void 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
182ir::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 =
221        AllocNode<ir::TSTypeAliasDeclaration>(Allocator(), id, typeParamDecl, typeAnnotation, InAmbientContext());
222    typeAliasDecl->SetRange({typeStart, Lexer()->GetToken().End()});
223
224    return typeAliasDecl;
225}
226
227bool 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
249bool 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
272ir::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
295ir::TypeNode *TSParser::ParseIdentifierReference()
296{
297    if (CurrentLiteralIsBasicType() && Lexer()->Lookahead() != lexer::LEX_CHAR_DOT) {
298        return ParseBasicType();
299    }
300
301    return ParseTypeReferenceOrQuery();
302}
303
304bool 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
342bool 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
371bool 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
386ir::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::REPORT_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
434ir::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
452ir::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::REPORT_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
498ir::TypeNode *TSParser::ParseTypeOperatorOrTypeReference()
499{
500    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_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
556ir::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::REPORT_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
613ir::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
646ir::TypeNode *TSParser::ParseIndexAccessType(ir::TypeNode *typeName)
647{
648    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_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
669ir::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::REPORT_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
732ir::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::REPORT_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
755ir::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
780ir::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::REPORT_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
830ir::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::REPORT_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
878ir::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
900ir::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
913ir::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
927ir::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
946ir::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::REPORT_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
985ir::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::REPORT_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
1029class TSParser::ParseBasicTypeHelper {
1030    friend ir::TypeNode *TSParser::ParseBasicType();
1031
1032private:
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
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};
1121ir::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
1139ir::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
1208ir::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::REPORT_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::REPORT_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
1252class TSParser::ParseTypeAnnotationElementHelper {
1253    friend ir::TypeNode *TSParser::ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation,
1254                                                              TypeAnnotationParsingOptions *options);
1255
1256private:
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::REPORT_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::REPORT_ERROR) != 0);
1303            }
1304            default: {
1305                break;
1306            }
1307        }
1308        return nullptr;
1309    }
1310
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::REPORT_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
1361ir::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::REPORT_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::REPORT_ERROR) != 0)) {
1404        ThrowSyntaxError("Type expected");
1405    }
1406
1407    return nullptr;
1408}
1409
1410bool 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
1459bool TSParser::IsNamedFunctionExpression()
1460{
1461    return Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1462           Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN;
1463}
1464
1465ir::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
1478ir::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::REPORT_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::REPORT_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
1516bool 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)
1531ir::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::REPORT_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
1575std::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
1623void 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
1655ir::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::REPORT_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::REPORT_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::REPORT_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
1715ir::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
1748void TSParser::ValidateFunctionParam(const ArenaVector<ir::Expression *> &params, 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 &paramName = 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
1794ArenaVector<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
1836ir::TypeNode *TSParser::ParseClassKeyAnnotation()
1837{
1838    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1839        Lexer()->NextToken();  // eat ':'
1840        TypeAnnotationParsingOptions options =
1841            TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
1842        return ParseTypeAnnotation(&options);
1843    }
1844
1845    return nullptr;
1846}
1847
1848void 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
1883ir::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
1931void 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
1944void 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
1958void TSParser::ValidateIndexSignatureTypeAnnotation(ir::TypeNode *typeAnnotation)
1959{
1960    if (typeAnnotation == nullptr) {
1961        ThrowSyntaxError("An index signature must have a type annotation");
1962    }
1963}
1964
1965bool 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
1984void TSParser::CheckIfTypeParameterNameIsReserved()
1985{
1986    if (Lexer()->GetToken().IsReservedTypeName()) {
1987        ThrowSyntaxError("Invalid type parameter name");
1988    }
1989}
1990
1991void 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
1998std::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::REPORT_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
2049ir::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::REPORT_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
2055        return ParseTypeAnnotation(&options);
2056    }
2057
2058    return nullptr;
2059}
2060
2061void TSParser::ValidateFunctionOverloadParams(const ArenaVector<ir::Expression *> &params)
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
2073std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> TSParser::ParseFunctionBody(
2074    const ArenaVector<ir::Expression *> &params, 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
2102ir::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
2131void 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::REPORT_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
2145void TSParser::ThrowPossibleOutOfBoundaryJumpError(bool allowBreak)
2146{
2147    if (((GetContext().Status() & ParserStatus::FUNCTION) != 0) && !allowBreak) {
2148        ThrowSyntaxError("Jump target cannot cross function boundary");
2149    }
2150}
2151
2152void TSParser::ThrowIllegalBreakError()
2153{
2154    ThrowSyntaxError("A 'break' statement can only be used within an enclosing iteration or switch statement");
2155}
2156
2157void TSParser::ThrowIllegalContinueError()
2158{
2159    ThrowSyntaxError("A 'continue' statement can only be used within an enclosing iteration statement");
2160}
2161
2162void TSParser::ThrowMultipleDefaultError()
2163{
2164    ThrowSyntaxError("A 'default' clause cannot appear more than once in a 'switch' statement");
2165}
2166
2167void TSParser::ThrowIllegalNewLineErrorAfterThrow()
2168{
2169    ThrowSyntaxError("Line break not permitted here");
2170}
2171
2172void 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