1/**
2 * Copyright (c) 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 "parserFlags.h"
19#include "util/helpers.h"
20#include "varbinder/privateBinding.h"
21#include "varbinder/scope.h"
22#include "varbinder/tsBinding.h"
23#include "lexer/TSLexer.h"
24#include "ir/base/spreadElement.h"
25#include "ir/base/decorator.h"
26#include "ir/base/classElement.h"
27#include "ir/base/classDefinition.h"
28#include "ir/base/methodDefinition.h"
29#include "ir/base/scriptFunction.h"
30#include "ir/module/importDefaultSpecifier.h"
31#include "ir/module/exportDefaultDeclaration.h"
32#include "ir/module/exportAllDeclaration.h"
33#include "ir/module/exportNamedDeclaration.h"
34#include "ir/module/importDeclaration.h"
35#include "ir/expressions/memberExpression.h"
36#include "ir/expressions/sequenceExpression.h"
37#include "ir/expressions/templateLiteral.h"
38#include "ir/expressions/taggedTemplateExpression.h"
39#include "ir/expressions/callExpression.h"
40#include "ir/expressions/functionExpression.h"
41#include "ir/expressions/arrowFunctionExpression.h"
42#include "ir/expressions/yieldExpression.h"
43#include "ir/expressions/assignmentExpression.h"
44#include "ir/expressions/identifier.h"
45#include "ir/expressions/objectExpression.h"
46#include "ir/expressions/arrayExpression.h"
47#include "ir/expressions/literals/bigIntLiteral.h"
48#include "ir/expressions/literals/booleanLiteral.h"
49#include "ir/expressions/literals/nullLiteral.h"
50#include "ir/expressions/literals/numberLiteral.h"
51#include "ir/expressions/literals/stringLiteral.h"
52#include "ir/statements/emptyStatement.h"
53#include "ir/statements/blockStatement.h"
54#include "ir/statements/ifStatement.h"
55#include "ir/statements/doWhileStatement.h"
56#include "ir/statements/whileStatement.h"
57#include "ir/statements/tryStatement.h"
58#include "ir/statements/breakStatement.h"
59#include "ir/statements/continueStatement.h"
60#include "ir/statements/throwStatement.h"
61#include "ir/statements/switchStatement.h"
62#include "ir/statements/returnStatement.h"
63#include "ir/statements/debuggerStatement.h"
64#include "ir/statements/classDeclaration.h"
65#include "ir/statements/labelledStatement.h"
66#include "ir/statements/variableDeclarator.h"
67#include "ir/statements/functionDeclaration.h"
68#include "ir/ts/tsLiteralType.h"
69#include "ir/ts/tsMappedType.h"
70#include "ir/ts/tsImportType.h"
71#include "ir/ts/tsThisType.h"
72#include "ir/ts/tsConditionalType.h"
73#include "ir/ts/tsTypeOperator.h"
74#include "ir/ts/tsInferType.h"
75#include "ir/ts/tsTupleType.h"
76#include "ir/ts/tsNamedTupleMember.h"
77#include "ir/ts/tsQualifiedName.h"
78#include "ir/ts/tsIndexedAccessType.h"
79#include "ir/ts/tsTypeQuery.h"
80#include "ir/ts/tsTypeReference.h"
81#include "ir/ts/tsTypePredicate.h"
82#include "ir/ts/tsTypeLiteral.h"
83#include "ir/ts/tsArrayType.h"
84#include "ir/ts/tsUnionType.h"
85#include "ir/ts/tsIntersectionType.h"
86#include "ir/ts/tsAnyKeyword.h"
87#include "ir/ts/tsUndefinedKeyword.h"
88#include "ir/ts/tsVoidKeyword.h"
89#include "ir/ts/tsNumberKeyword.h"
90#include "ir/ts/tsStringKeyword.h"
91#include "ir/ts/tsBooleanKeyword.h"
92#include "ir/ts/tsBigintKeyword.h"
93#include "ir/ts/tsUnknownKeyword.h"
94#include "ir/ts/tsNullKeyword.h"
95#include "ir/ts/tsNeverKeyword.h"
96#include "ir/ts/tsObjectKeyword.h"
97#include "ir/ts/tsFunctionType.h"
98#include "ir/ts/tsConstructorType.h"
99#include "ir/ts/tsParenthesizedType.h"
100#include "ir/ts/tsTypeAssertion.h"
101#include "ir/ts/tsAsExpression.h"
102#include "ir/ts/tsNonNullExpression.h"
103#include "ir/ts/tsEnumDeclaration.h"
104#include "ir/ts/tsInterfaceDeclaration.h"
105#include "ir/ts/tsTypeAliasDeclaration.h"
106#include "ir/ts/tsModuleDeclaration.h"
107#include "ir/ts/tsTypeParameterInstantiation.h"
108#include "ir/ts/tsInterfaceHeritage.h"
109#include "ir/base/tsSignatureDeclaration.h"
110#include "ir/base/tsIndexSignature.h"
111#include "ir/base/tsMethodSignature.h"
112#include "ir/base/tsPropertySignature.h"
113#include "ir/ts/tsParameterProperty.h"
114#include "ir/ts/tsClassImplements.h"
115#include "ir/ts/tsImportEqualsDeclaration.h"
116#include "ir/ts/tsExternalModuleReference.h"
117
118namespace ark::es2panda::parser {
119ir::Expression *TSParser::ParsePotentialAsExpression(ir::Expression *expr)
120{
121    if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
122        return nullptr;
123    }
124
125    Lexer()->NextToken();  // eat 'as'
126    TypeAnnotationParsingOptions options =
127        TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_CONST;
128    ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
129
130    bool isConst = false;
131    if (typeAnnotation->IsTSTypeReference() && typeAnnotation->AsTSTypeReference()->TypeName()->IsIdentifier()) {
132        const util::StringView &refName = typeAnnotation->AsTSTypeReference()->TypeName()->AsIdentifier()->Name();
133        if (refName.Is("const")) {
134            isConst = true;
135        }
136    }
137
138    lexer::SourcePosition startLoc = expr->Start();
139    auto *asExpr = AllocNode<ir::TSAsExpression>(expr, typeAnnotation, isConst);
140    asExpr->SetRange({startLoc, Lexer()->GetToken().End()});
141
142    if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
143        return ParsePotentialAsExpression(asExpr);
144    }
145
146    return asExpr;
147}
148
149ir::AnnotatedExpression *TSParser::ParsePatternElementGetReturnNode(ExpressionParseFlags &flags, bool &isOptional)
150{
151    switch (Lexer()->GetToken().Type()) {
152        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
153            ir::AnnotatedExpression *returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
154            isOptional = returnNode->AsArrayPattern()->IsOptional();
155            return returnNode;
156        }
157        case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
158            if ((flags & ExpressionParseFlags::IN_REST) != 0) {
159                ThrowSyntaxError("Unexpected token");
160            }
161
162            return ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
163        }
164        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
165            ir::AnnotatedExpression *returnNode =
166                ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
167            isOptional = returnNode->AsObjectPattern()->IsOptional();
168            return returnNode;
169        }
170        case lexer::TokenType::LITERAL_IDENT: {
171            ir::AnnotatedExpression *returnNode = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
172            returnNode->AsIdentifier()->SetReference();
173
174            if (returnNode->AsIdentifier()->Decorators().empty()) {
175                returnNode->SetRange(Lexer()->GetToken().Loc());
176            } else {
177                returnNode->SetRange(
178                    {returnNode->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()});
179            }
180
181            Lexer()->NextToken();
182
183            if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
184                isOptional = true;
185
186                if ((flags & ExpressionParseFlags::IN_REST) != 0) {
187                    ThrowSyntaxError("A rest parameter cannot be optional");
188                }
189
190                returnNode->AsIdentifier()->SetOptional(true);
191                Lexer()->NextToken();
192            }
193
194            if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
195                Lexer()->NextToken();  // eat ':'
196                TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
197                returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
198            }
199            return returnNode;
200        }
201        default: {
202            ThrowSyntaxError("Unexpected token, expected an identifier.");
203        }
204    }
205}
206// NOLINTNEXTLINE(google-default-arguments)
207ir::Expression *TSParser::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault)
208{
209    bool isOptional = false;
210    ir::AnnotatedExpression *returnNode = ParsePatternElementGetReturnNode(flags, isOptional);
211
212    if ((returnNode->IsObjectPattern() || returnNode->IsArrayPattern()) && !InAmbientContext() &&
213        ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && isOptional) {
214        ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.");
215    }
216
217    if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
218        return returnNode;
219    }
220
221    if ((flags & ExpressionParseFlags::IN_REST) != 0) {
222        ThrowSyntaxError("A rest parameter cannot have an initializer.");
223    }
224
225    if (!allowDefault) {
226        ThrowSyntaxError("Invalid destructuring assignment target");
227    }
228
229    if (isOptional) {
230        ThrowSyntaxError("Parameter cannot have question mark and initializer");
231    }
232
233    Lexer()->NextToken();
234
235    if (((GetContext().Status() & ParserStatus::GENERATOR_FUNCTION) != 0) &&
236        Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD) {
237        ThrowSyntaxError("Yield is not allowed in generator parameters");
238    }
239
240    ir::Expression *rightNode = ParseExpression();
241
242    auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
243        ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
244    assignmentExpression->SetRange({returnNode->Start(), rightNode->End()});
245
246    return assignmentExpression;
247}
248
249ir::TSParameterProperty *TSParser::CreateParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
250{
251    auto accessibilityOption = ir::AccessibilityOption::NO_OPTS;
252    bool readonly = false;
253    bool isStatic = false;
254    bool isExport = false;
255
256    if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) {
257        accessibilityOption = ir::AccessibilityOption::PRIVATE;
258    } else if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) {
259        accessibilityOption = ir::AccessibilityOption::PUBLIC;
260    } else if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) {
261        accessibilityOption = ir::AccessibilityOption::PROTECTED;
262    }
263
264    if ((modifiers & ir::ModifierFlags::READONLY) != 0) {
265        readonly = true;
266    }
267
268    if ((modifiers & ir::ModifierFlags::STATIC) != 0) {
269        isStatic = true;
270    }
271
272    // NOTE(Csaba Repasi): Handle export property of TSParameterProperty
273
274    return AllocNode<ir::TSParameterProperty>(accessibilityOption, parameter, readonly, isStatic, isExport);
275}
276
277ir::Expression *TSParser::ParseFunctionParameter()
278{
279    if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) {
280        Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
281    }
282
283    lexer::SourcePosition parameterStart = Lexer()->GetToken().Start();
284    ir::ModifierFlags modifiers = ParseModifiers();
285    // NOTE(Csaba Repasi): throw error if using strick mode reserved keyword here
286    if (((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) && modifiers != ir::ModifierFlags::NONE) {
287        ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
288    }
289
290    if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
291        CheckRestrictedBinding();
292    }
293
294    ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
295
296    if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
297        ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
298    }
299
300    if (modifiers != ir::ModifierFlags::NONE &&
301        (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
302         (functionParameter->IsAssignmentPattern() &&
303          (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
304           functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
305        ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
306    }
307
308    if (modifiers != ir::ModifierFlags::NONE) {
309        functionParameter = CreateParameterProperty(functionParameter, modifiers);
310        functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
311    }
312
313    return functionParameter;
314}
315
316ir::Expression *TSParser::ParseModuleReference()
317{
318    ir::Expression *result = nullptr;
319
320    if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE &&
321        Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_PAREN) {
322        lexer::SourcePosition start = Lexer()->GetToken().Start();
323        Lexer()->NextToken();  // eat 'require'
324        Lexer()->NextToken();  // eat '('
325
326        if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
327            ThrowSyntaxError("String literal expected.");
328        }
329
330        result = AllocNode<ir::StringLiteral>(Lexer()->GetToken().String());
331        result->SetRange(Lexer()->GetToken().Loc());
332        Lexer()->NextToken();
333
334        if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
335            ThrowSyntaxError("')' expected.");
336        }
337
338        result = AllocNode<ir::TSExternalModuleReference>(result);
339        result->SetRange({start, Lexer()->GetToken().End()});
340        Lexer()->NextToken();  // eat ')'
341    } else {
342        result = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
343        result->SetRange(Lexer()->GetToken().Loc());
344        Lexer()->NextToken();
345
346        if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
347            result = ParseQualifiedReference(result);
348        }
349    }
350
351    return result;
352}
353
354ir::TSTypeReference *TSParser::ParseConstExpression()
355{
356    auto *identRef = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
357    identRef->SetReference();
358    identRef->SetRange(Lexer()->GetToken().Loc());
359
360    auto *typeReference = AllocNode<ir::TSTypeReference>(identRef, nullptr);
361    typeReference->SetRange(Lexer()->GetToken().Loc());
362
363    Lexer()->NextToken();
364
365    if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
366        Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
367        Lexer()->GetToken().Type() != lexer::TokenType::EOS &&
368        Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
369        ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0)) {
370        ThrowSyntaxError("Unexpected token.");
371    }
372
373    return typeReference;
374}
375
376bool TSParser::ParsePotentialNonNullExpression(ir::Expression **returnExpression, lexer::SourcePosition startLoc)
377{
378    if (returnExpression == nullptr || Lexer()->GetToken().NewLine()) {
379        return true;
380    }
381
382    *returnExpression = AllocNode<ir::TSNonNullExpression>(*returnExpression);
383    (*returnExpression)->SetRange({startLoc, Lexer()->GetToken().End()});
384    Lexer()->NextToken();
385    return false;
386}
387
388// NOLINTNEXTLINE(google-default-arguments)
389ir::ObjectExpression *TSParser::ParseObjectExpression(ExpressionParseFlags flags)
390{
391    ir::ObjectExpression *objExpression = ParserImpl::ParseObjectExpression(flags);
392    ParsePotentialOptionalFunctionParameter(objExpression);
393    return objExpression;
394}
395
396// NOLINTNEXTLINE(google-default-arguments)
397ir::ArrayExpression *TSParser::ParseArrayExpression(ExpressionParseFlags flags)
398{
399    ir::ArrayExpression *arrayExpression = ParserImpl::ParseArrayExpression(flags);
400    ParsePotentialOptionalFunctionParameter(arrayExpression);
401    return arrayExpression;
402}
403class TSParser::ParsePotentialArrowExpressionHelper {
404    friend ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression,
405                                                                                const lexer::SourcePosition &startLoc);
406
407private:
408    static ir::ArrowFunctionExpression *CreateCallExpression(TSParser *parser, lexer::Lexer *lexer,
409                                                             ir::Expression **returnExpression,
410                                                             ir::TSTypeParameterDeclaration *typeParamDecl,
411                                                             const lexer::SourcePosition &startLoc)
412    {
413        ir::CallExpression *callExpression = parser->ParseCallExpression(*returnExpression, false);
414
415        ir::TypeNode *returnTypeAnnotation = nullptr;
416        if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
417            lexer->NextToken();  // eat ':'
418            TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
419            returnTypeAnnotation = parser->ParseTypeAnnotation(&options);
420        }
421
422        if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
423            ir::ArrowFunctionExpression *arrowFuncExpr =
424                parser->ParseArrowFunctionExpression(callExpression, typeParamDecl, returnTypeAnnotation, true);
425            arrowFuncExpr->SetStart(startLoc);
426
427            return arrowFuncExpr;
428        }
429
430        if (returnTypeAnnotation != nullptr || typeParamDecl != nullptr) {
431            parser->ThrowSyntaxError("'=>' expected");
432        }
433
434        *returnExpression = callExpression;
435        return nullptr;
436    }
437};
438
439ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression,
440                                                                     const lexer::SourcePosition &startLoc)
441{
442    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
443
444    switch (Lexer()->GetToken().Type()) {
445        case lexer::TokenType::KEYW_FUNCTION: {
446            *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION);
447            (*returnExpression)->SetStart(startLoc);
448            break;
449        }
450        case lexer::TokenType::LITERAL_IDENT: {
451            ir::Expression *identRef = ParsePrimaryExpression();
452            ASSERT(identRef->IsIdentifier());
453
454            if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
455                ThrowSyntaxError("Unexpected token, expected '=>'");
456            }
457
458            ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true);
459            arrowFuncExpr->SetStart(startLoc);
460
461            return arrowFuncExpr;
462        }
463        case lexer::TokenType::PUNCTUATOR_ARROW: {
464            ir::ArrowFunctionExpression *arrowFuncExpr =
465                ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true);
466            arrowFuncExpr->SetStart(startLoc);
467            return arrowFuncExpr;
468        }
469        case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
470            const auto savedPos = Lexer()->Save();
471
472            auto options = TypeAnnotationParsingOptions::NO_OPTS;
473            typeParamDecl = ParseTypeParameterDeclaration(&options);
474            if (typeParamDecl == nullptr) {
475                Lexer()->Rewind(savedPos);
476                return nullptr;
477            }
478
479            if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
480                ThrowSyntaxError("'(' expected");
481            }
482
483            [[fallthrough]];
484        }
485        case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
486            return ParsePotentialArrowExpressionHelper::CreateCallExpression(this, Lexer(), returnExpression,
487                                                                             typeParamDecl, startLoc);
488        }
489        default: {
490            break;
491        }
492    }
493
494    return nullptr;
495}
496
497ir::AnnotatedExpression *TSParser::ParseVariableDeclaratorKey(VariableParsingFlags flags)
498{
499    ir::AnnotatedExpression *init = ParserImpl::ParseVariableDeclaratorKey(flags);
500
501    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
502        Lexer()->NextToken();  // eat ':'
503        TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
504        init->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
505    }
506
507    return init;
508}
509
510void TSParser::ParseOptionalFunctionParameter(ir::AnnotatedExpression *returnNode, bool isRest)
511{
512    bool isOptional = false;
513
514    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
515        if (isRest) {
516            ThrowSyntaxError("A rest parameter cannot be optional");
517        }
518
519        switch (returnNode->Type()) {
520            case ir::AstNodeType::IDENTIFIER: {
521                returnNode->AsIdentifier()->SetOptional(true);
522                break;
523            }
524            case ir::AstNodeType::OBJECT_PATTERN:
525            case ir::AstNodeType::ARRAY_PATTERN: {
526                if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0)) {
527                    ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.");
528                }
529
530                if (returnNode->IsObjectPattern()) {
531                    returnNode->AsObjectPattern()->SetOptional(true);
532                    break;
533                }
534
535                returnNode->AsArrayPattern()->SetOptional(true);
536                break;
537            }
538            case ir::AstNodeType::REST_ELEMENT: {
539                returnNode->AsRestElement()->SetOptional(true);
540                break;
541            }
542            default: {
543                UNREACHABLE();
544            }
545        }
546
547        isOptional = true;
548        Lexer()->NextToken();  // eat '?'
549    }
550
551    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
552        Lexer()->NextToken();  // eat ':'
553        TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
554        returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
555    }
556
557    if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
558        return;
559    }
560
561    if (isRest) {
562        ThrowSyntaxError("A rest parameter cannot have an initializer");
563    }
564
565    if (returnNode->IsIdentifier() && isOptional) {
566        ThrowSyntaxError("Parameter cannot have question mark and initializer");
567    }
568}
569
570void TSParser::ValidateArrowFunctionRestParameter(ir::SpreadElement *restElement)
571{
572    ParseOptionalFunctionParameter(restElement, true);
573
574    if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
575        ThrowSyntaxError("')' expected");
576    }
577}
578
579ir::Expression *TSParser::ParseArrowFunctionRestParameter(lexer::SourcePosition start)
580{
581    ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
582
583    restElement->SetGrouped();
584    restElement->SetStart(start);
585
586    ValidateArrowFunctionRestParameter(restElement);
587
588    Lexer()->NextToken();
589
590    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
591    ir::TypeNode *returnTypeAnnotation = nullptr;
592    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
593        Lexer()->NextToken();  // eat ':'
594        returnTypeAnnotation = ParseTypeAnnotation(&options);
595    }
596
597    if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
598        ThrowSyntaxError("Unexpected token");
599    }
600
601    return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false);
602}
603
604ir::Expression *TSParser::ParseArrowFunctionNoParameter(lexer::SourcePosition start)
605{
606    Lexer()->NextToken();
607
608    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
609    ir::TypeNode *returnTypeAnnotation = nullptr;
610    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
611        Lexer()->NextToken();  // eat ':'
612        returnTypeAnnotation = ParseTypeAnnotation(&options);
613    }
614
615    if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
616        ThrowSyntaxError("Unexpected token");
617    }
618
619    auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false);
620    arrowExpr->SetStart(start);
621    arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start);
622
623    return arrowExpr;
624}
625
626// NOLINTNEXTLINE(google-default-arguments)
627ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(
628    [[maybe_unused]] ExpressionParseFlags flags)
629{
630    ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
631    lexer::SourcePosition start = Lexer()->GetToken().Start();
632    Lexer()->NextToken();
633    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
634
635    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
636        return ParseArrowFunctionRestParameter(start);
637    }
638
639    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
640        return ParseArrowFunctionNoParameter(start);
641    }
642
643    ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST |
644                                           ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
645
646    if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
647        ThrowSyntaxError("Unexpected token, expected ')'");
648    }
649
650    expr->SetGrouped();
651    expr->SetRange({start, Lexer()->GetToken().End()});
652    Lexer()->NextToken();
653
654    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
655        auto savedPos = Lexer()->Save();
656        Lexer()->NextToken();  // eat ':'
657        options = TypeAnnotationParsingOptions::NO_OPTS;
658        ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options);
659
660        if (returnTypeAnnotation == nullptr) {
661            Lexer()->Rewind(savedPos);
662            return expr;
663        }
664
665        if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
666            Lexer()->Rewind(savedPos);
667            return expr;
668        }
669
670        return ParseArrowFunctionExpression(expr, nullptr, returnTypeAnnotation, false);
671    }
672
673    return expr;
674}
675
676}  // namespace ark::es2panda::parser