• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "TypedParser.h"
17 
18 #include "parser/parserImpl.h"
19 #include "parser/parserStatusContext.h"
20 #include "varbinder/privateBinding.h"
21 #include "lexer/lexer.h"
22 #include "ir/base/classDefinition.h"
23 #include "ir/base/decorator.h"
24 #include "ir/base/spreadElement.h"
25 #include "ir/base/tsPropertySignature.h"
26 #include "ir/base/tsMethodSignature.h"
27 #include "ir/base/methodDefinition.h"
28 #include "ir/base/tsIndexSignature.h"
29 #include "ir/base/scriptFunction.h"
30 #include "ir/expressions/identifier.h"
31 #include "ir/expressions/yieldExpression.h"
32 #include "ir/expressions/objectExpression.h"
33 #include "ir/expressions/arrayExpression.h"
34 #include "ir/expressions/assignmentExpression.h"
35 #include "ir/expressions/arrowFunctionExpression.h"
36 #include "ir/expressions/sequenceExpression.h"
37 #include "ir/expressions/callExpression.h"
38 #include "ir/expressions/literals/stringLiteral.h"
39 #include "ir/expressions/literals/numberLiteral.h"
40 #include "ir/expressions/functionExpression.h"
41 #include "ir/statement.h"
42 #include "ir/statements/classDeclaration.h"
43 #include "ir/statements/variableDeclarator.h"
44 #include "ir/ts/tsModuleDeclaration.h"
45 #include "ir/ts/tsModuleBlock.h"
46 #include "ir/ts/tsInterfaceBody.h"
47 #include "ir/ts/tsInterfaceDeclaration.h"
48 #include "ir/ts/tsEnumMember.h"
49 #include "ir/ts/tsEnumDeclaration.h"
50 #include "ir/ts/tsTypeParameterInstantiation.h"
51 #include "ir/ts/tsTypeParameterDeclaration.h"
52 #include "ir/ts/tsTypeParameter.h"
53 #include "ir/ts/tsQualifiedName.h"
54 #include "ir/ts/tsTypeReference.h"
55 #include "ir/ts/tsTypeAliasDeclaration.h"
56 #include "ir/ts/tsInterfaceHeritage.h"
57 #include "ir/ts/tsClassImplements.h"
58 #include "ir/ts/tsTypeAssertion.h"
59 #include "util/errorRecovery.h"
60 #include "generated/diagnostic.h"
61 
62 namespace ark::es2panda::parser {
63 
ParsePotentialAsExpression(ir::Expression * primaryExpression)64 ir::Expression *TypedParser::ParsePotentialAsExpression([[maybe_unused]] ir::Expression *primaryExpression)
65 {
66     return nullptr;
67 }
68 
69 // NOLINTNEXTLINE(google-default-arguments)
ParseExpression(ExpressionParseFlags flags)70 ir::Expression *TypedParser::ParseExpression(ExpressionParseFlags flags)
71 {
72     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD &&
73         ((flags & ExpressionParseFlags::DISALLOW_YIELD) == 0)) {
74         ir::YieldExpression *yieldExpr = ParseYieldExpression();
75 
76         return ParsePotentialExpressionSequence(yieldExpr, flags);
77     }
78 
79     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
80         const auto startPos = Lexer()->Save();
81 
82         // NOTE(rsipka): ParseTsGenericArrowFunction and ParseTsTypeAssertion might be in a common function
83         ir::Expression *expr = ParseGenericArrowFunction();
84         // NOTE(rsipka): negative cases are not covered, probably this is not a complete solution yet
85         if (expr == nullptr) {
86             Lexer()->Rewind(startPos);
87             expr = ParseTypeAssertion();
88         }
89 
90         return expr;
91     }
92 
93     ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags);
94     if (unaryExpressionNode->IsArrowFunctionExpression()) {
95         return unaryExpressionNode;
96     }
97 
98     ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags);
99 
100     if (Lexer()->GetToken().NewLine()) {
101         return assignmentExpression;
102     }
103 
104     switch (Lexer()->GetToken().Type()) {
105         case lexer::TokenType::LITERAL_IDENT: {
106             if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
107                 return ParsePotentialAsExpression(assignmentExpression);
108             }
109             break;
110         }
111         case lexer::TokenType::PUNCTUATOR_COMMA: {
112             if ((flags & ExpressionParseFlags::ACCEPT_COMMA) != 0) {
113                 return ParseSequenceExpression(assignmentExpression,
114                                                ((flags & ExpressionParseFlags::ACCEPT_REST) != 0));
115             }
116             break;
117         }
118         default: {
119             break;
120         }
121     }
122 
123     return assignmentExpression;
124 }
125 
IsNamespaceDecl()126 bool TypedParser::IsNamespaceDecl()
127 {
128     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_NAMESPACE) {
129         return false;
130     }
131     auto savedPos = Lexer()->Save();
132     Lexer()->NextToken();
133     bool isNamespaceDecl = Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT;
134     Lexer()->Rewind(savedPos);
135     return isNamespaceDecl;
136 }
137 
ParsePotentialExpressionStatement(StatementParsingFlags flags)138 ir::Statement *TypedParser::ParsePotentialExpressionStatement(StatementParsingFlags flags)
139 {
140     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
141 
142     switch (Lexer()->GetToken().KeywordType()) {
143         case lexer::TokenType::KEYW_TYPE: {
144             const auto maybeAlias = ParseTypeAliasDeclaration();
145             if (maybeAlias != nullptr) {
146                 return maybeAlias;
147             }
148             break;
149         }
150         case lexer::TokenType::KEYW_ABSTRACT: {
151             Lexer()->NextToken();  // eat abstract keyword
152 
153             if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
154                 LogError(diagnostic::ABSTRACT_METHODS_ONLY_IN_ABSTRACT_CLASS);
155                 if (Lexer()->GetToken().IsKeyword()) {
156                     return ParseExpressionStatement(flags);
157                 }
158                 Lexer()->GetToken().SetTokenType(lexer::TokenType::KEYW_CLASS);
159             }
160 
161             return ParseClassStatement(flags, ir::ClassDefinitionModifiers::NONE, ir::ModifierFlags::ABSTRACT);
162         }
163         case lexer::TokenType::KEYW_GLOBAL:
164         case lexer::TokenType::KEYW_MODULE: {
165             return ParseModuleDeclaration();
166         }
167         case lexer::TokenType::KEYW_NAMESPACE: {
168             if (((GetContext().Status() & ParserStatus::IN_AMBIENT_CONTEXT) != 0U) || IsNamespaceDecl()) {
169                 return ParseNamespace(ir::ModifierFlags::NONE);
170             }
171             [[fallthrough]];
172         }
173         default: {
174             break;
175         }
176     }
177     return ParseExpressionStatement(flags);
178 }
179 
ParseTypeAssertion()180 ir::TSTypeAssertion *TypedParser::ParseTypeAssertion()
181 {
182     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
183     lexer::SourcePosition start = Lexer()->GetToken().Start();
184     Lexer()->NextToken();  // eat '<'
185 
186     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
187     ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
188 
189     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
190         return nullptr;
191     }
192 
193     Lexer()->NextToken();  // eat '>'
194     ir::Expression *expression = ParseExpression();
195     auto *typeAssertion = AllocNode<ir::TSTypeAssertion>(typeAnnotation, expression);
196     ES2PANDA_ASSERT(typeAssertion != nullptr);
197     typeAssertion->SetRange({start, Lexer()->GetToken().End()});
198 
199     return typeAssertion;
200 }
201 
202 // NOLINTNEXTLINE(google-default-arguments)
ParseModuleDeclaration(StatementParsingFlags flags)203 ir::Statement *TypedParser::ParseModuleDeclaration([[maybe_unused]] StatementParsingFlags flags)
204 {
205     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
206     GetContext().Status() |= ParserStatus::MODULE;
207 
208     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) {
209         return ParseAmbientExternalModuleDeclaration(startLoc);
210     }
211 
212     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) {
213         Lexer()->NextToken();
214     } else {
215         ES2PANDA_ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE);
216         Lexer()->NextToken();
217         if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
218             return ParseAmbientExternalModuleDeclaration(startLoc);
219         }
220     }
221 
222     return ParseModuleOrNamespaceDeclaration(startLoc);
223 }
224 
ParseNamespace(ir::ModifierFlags flags)225 ir::Statement *TypedParser::ParseNamespace([[maybe_unused]] ir::ModifierFlags flags)
226 {
227     return ParseModuleDeclaration();
228 }
229 
ParseGenericArrowFunction()230 ir::ArrowFunctionExpression *TypedParser::ParseGenericArrowFunction()
231 {
232     ArrowFunctionContext arrowFunctionContext(this, false);
233 
234     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
235     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
236 
237     auto typeParamDeclOptions = TypeAnnotationParsingOptions::NO_OPTS;
238     ir::TSTypeParameterDeclaration *typeParamDecl = ParseTypeParameterDeclaration(&typeParamDeclOptions);
239 
240     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
241         return nullptr;
242     }
243 
244     FunctionParameterContext funcParamContext(&GetContext());
245     auto params = ParseFunctionParams();
246 
247     ParserStatus arrowStatus = ParserStatus::NO_OPTS;
248     if (std::any_of(params.begin(), params.end(), [](const auto *param) { return !param->IsIdentifier(); })) {
249         arrowStatus = ParserStatus::HAS_COMPLEX_PARAM;
250     }
251 
252     ir::TypeNode *returnTypeAnnotation = nullptr;
253     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
254         Lexer()->NextToken();  // eat ':'
255         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
256         returnTypeAnnotation = ParseTypeAnnotation(&options);
257     }
258 
259     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
260         return nullptr;
261     }
262 
263     ArrowFunctionDescriptor desc(std::move(params), startLoc, arrowStatus);
264 
265     return ParseArrowFunctionExpressionBody(&arrowFunctionContext, &desc, typeParamDecl, returnTypeAnnotation);
266 }
267 
ParseAmbientExternalModuleDeclaration(const lexer::SourcePosition & startLoc)268 ir::TSModuleDeclaration *TypedParser::ParseAmbientExternalModuleDeclaration(const lexer::SourcePosition &startLoc)
269 {
270     bool isGlobal = false;
271     ir::Expression *name = nullptr;
272 
273     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) {
274         isGlobal = true;
275         name = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
276     } else {
277         ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
278 
279         if (!InAmbientContext()) {
280             LogError(diagnostic::ONLY_AMBIENT_MODULES_QUOTED_NAMES);
281         }
282 
283         name = AllocNode<ir::StringLiteral>(Lexer()->GetToken().String());
284     }
285 
286     name->SetRange(Lexer()->GetToken().Loc());
287 
288     Lexer()->NextToken();
289 
290     ir::Statement *body = nullptr;
291     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
292         body = ParseTsModuleBlock();
293     } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
294         Lexer()->NextToken();
295     } else {
296         // test exists for ts extension only
297         LogExpectedToken(lexer::TokenType::PUNCTUATOR_SEMI_COLON);
298         Lexer()->NextToken();
299     }
300 
301     auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(Allocator(), name, body,
302                                                           ir::TSModuleDeclaration::ConstructorFlags {isGlobal, true});
303     ES2PANDA_ASSERT(moduleDecl != nullptr);
304     moduleDecl->SetRange({startLoc, Lexer()->GetToken().End()});
305 
306     return moduleDecl;
307 }
308 
ParseModuleOrNamespaceDeclaration(const lexer::SourcePosition & startLoc)309 ir::TSModuleDeclaration *TypedParser::ParseModuleOrNamespaceDeclaration(const lexer::SourcePosition &startLoc)
310 {
311     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
312         LogExpectedToken(lexer::TokenType::LITERAL_IDENT);
313     }
314 
315     auto *identNode = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
316     ES2PANDA_ASSERT(identNode != nullptr);
317     identNode->SetRange(Lexer()->GetToken().Loc());
318 
319     Lexer()->NextToken();
320 
321     ir::Statement *body = nullptr;
322 
323     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
324         Lexer()->NextToken();
325         lexer::SourcePosition moduleStart = Lexer()->GetToken().Start();
326         body = ParseModuleOrNamespaceDeclaration(moduleStart);
327     } else {
328         body = ParseTsModuleBlock();
329     }
330 
331     auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(Allocator(), identNode, body,
332                                                           ir::TSModuleDeclaration::ConstructorFlags {false, false});
333     ES2PANDA_ASSERT(moduleDecl != nullptr);
334     moduleDecl->SetRange({startLoc, Lexer()->GetToken().End()});
335 
336     return moduleDecl;
337 }
338 
ParseTsModuleBlock()339 ir::TSModuleBlock *TypedParser::ParseTsModuleBlock()
340 {
341     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
342         LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
343     }
344 
345     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
346     Lexer()->NextToken();
347     auto statements = ParseStatementList();
348 
349     auto *blockNode = AllocNode<ir::TSModuleBlock>(std::move(statements));
350     ES2PANDA_ASSERT(blockNode != nullptr);
351     blockNode->SetRange({startLoc, Lexer()->GetToken().End()});
352 
353     ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE);
354     return blockNode;
355 }
356 
CheckDeclare()357 void TypedParser::CheckDeclare()
358 {
359     ES2PANDA_ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE);
360 
361     if (InAmbientContext()) {
362         LogError(diagnostic::DECALRE_IN_AMBIENT_CONTEXT);
363     }
364 
365     GetContext().Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
366 
367     Lexer()->NextToken();  // eat 'declare'
368 
369     switch (Lexer()->GetToken().KeywordType()) {
370         case lexer::TokenType::KEYW_VAR:
371         case lexer::TokenType::KEYW_LET:
372         case lexer::TokenType::KEYW_CONST:
373         case lexer::TokenType::KEYW_FUNCTION:
374         case lexer::TokenType::KEYW_CLASS:
375         case lexer::TokenType::KEYW_TYPE:
376         case lexer::TokenType::KEYW_MODULE:
377         case lexer::TokenType::KEYW_GLOBAL:
378         case lexer::TokenType::KEYW_NAMESPACE:
379         case lexer::TokenType::KEYW_ENUM:
380         case lexer::TokenType::KEYW_ABSTRACT:
381         case lexer::TokenType::KEYW_INTERFACE: {
382             return;
383         }
384         default: {
385             LogUnexpectedToken(Lexer()->GetToken());
386         }
387     }
388 }
389 
ParseDecorators(ArenaVector<ir::Decorator * > & decorators)390 void TypedParser::ParseDecorators(ArenaVector<ir::Decorator *> &decorators)
391 {
392     while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
393         decorators.push_back(ParseDecorator());
394     }
395 }
396 
ParseFunctionReturnType(ParserStatus status)397 ir::TypeNode *TypedParser::ParseFunctionReturnType(ParserStatus status)
398 {
399     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
400         Lexer()->NextToken();  // eat ':'
401         TypeAnnotationParsingOptions options =
402             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::RETURN_TYPE;
403         return ParseTypeAnnotation(&options);
404     }
405 
406     if ((status & ParserStatus::NEED_RETURN_TYPE) != 0) {
407         LogError(diagnostic::TYPE_EXPECTED);
408     }
409 
410     return nullptr;
411 }
412 
ParseInterfaceExtendsElement()413 ir::TypeNode *TypedParser::ParseInterfaceExtendsElement()
414 {
415     const lexer::SourcePosition &heritageStart = Lexer()->GetToken().Start();
416     lexer::SourcePosition heritageEnd = Lexer()->GetToken().End();
417     ir::Expression *expr = ParseQualifiedName();
418 
419     if (Lexer()->Lookahead() == lexer::LEX_CHAR_LESS_THAN) {
420         Lexer()->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
421     }
422 
423     ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
424     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
425         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
426         typeParamInst = ParseTypeParameterInstantiation(&options);
427         ES2PANDA_ASSERT(typeParamInst != nullptr);
428         heritageEnd = typeParamInst->End();
429     }
430 
431     auto *typeReference = AllocNode<ir::TSTypeReference>(expr, typeParamInst, Allocator());
432     ES2PANDA_ASSERT(typeReference != nullptr);
433     typeReference->SetRange({heritageStart, heritageEnd});
434     return typeReference;
435 }
436 
ParseInterfaceExtendsClause()437 ArenaVector<ir::TSInterfaceHeritage *> TypedParser::ParseInterfaceExtendsClause()
438 {
439     Lexer()->NextToken();  // eat extends keyword
440 
441     ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
442 
443     while (true) {
444         auto *typeReference = ParseInterfaceExtendsElement();
445         ES2PANDA_ASSERT(typeReference != nullptr);
446         auto *heritage = AllocNode<ir::TSInterfaceHeritage>(typeReference);
447         ES2PANDA_ASSERT(heritage != nullptr);
448         heritage->SetRange(typeReference->Range());
449         extends.push_back(heritage);
450 
451         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE ||
452             Lexer()->GetToken().Type() == lexer::TokenType::EOS) {
453             break;
454         }
455 
456         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
457             LogExpectedToken(lexer::TokenType::PUNCTUATOR_COMMA);
458         }
459 
460         Lexer()->NextToken();
461     }
462 
463     return extends;
464 }
465 
ParseFunctionTypeParameters()466 ir::TSTypeParameterDeclaration *TypedParser::ParseFunctionTypeParameters()
467 {
468     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
469         auto options = TypeAnnotationParsingOptions::REPORT_ERROR;
470         return ParseTypeParameterDeclaration(&options);
471     }
472 
473     return nullptr;
474 }
475 
ParseInterfaceDeclaration(bool isStatic)476 ir::Statement *TypedParser::ParseInterfaceDeclaration(bool isStatic)
477 {
478     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_INTERFACE);
479     GetContext().Status() |= ParserStatus::ALLOW_THIS_TYPE;
480     lexer::SourcePosition interfaceStart = Lexer()->GetToken().Start();
481     Lexer()->NextToken();  // eat interface keyword
482 
483     auto id = ExpectIdentifier(true);
484 
485     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
486     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
487         auto options = TypeAnnotationParsingOptions::REPORT_ERROR;
488         typeParamDecl = ParseTypeParameterDeclaration(&options);
489     }
490 
491     ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
492     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
493         extends = ParseInterfaceExtendsClause();
494     }
495 
496     lexer::SourcePosition bodyStart = Lexer()->GetToken().Start();
497     auto members = ParseTypeLiteralOrInterface();
498 
499     auto *body = AllocNode<ir::TSInterfaceBody>(std::move(members));
500     body->SetRange({bodyStart, Lexer()->GetToken().End()});
501 
502     const auto isExternal = IsExternal();
503     auto *interfaceDecl = AllocNode<ir::TSInterfaceDeclaration>(
504         Allocator(), std::move(extends),
505         ir::TSInterfaceDeclaration::ConstructorData {id, typeParamDecl, body, isStatic, isExternal,
506                                                      GetContext().GetLanguage()});
507     ES2PANDA_ASSERT(interfaceDecl != nullptr);
508     interfaceDecl->SetRange({interfaceStart, Lexer()->GetToken().End()});
509 
510     Lexer()->NextToken();
511     GetContext().Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
512 
513     return interfaceDecl;
514 }
515 
GetTSPropertyName(ir::Expression * key)516 static util::StringView GetTSPropertyName(ir::Expression *key)
517 {
518     switch (key->Type()) {
519         case ir::AstNodeType::IDENTIFIER: {
520             return key->AsIdentifier()->Name();
521         }
522         case ir::AstNodeType::NUMBER_LITERAL: {
523             return key->AsNumberLiteral()->Str();
524         }
525         case ir::AstNodeType::STRING_LITERAL: {
526             return key->AsStringLiteral()->Str();
527         }
528         default: {
529             ES2PANDA_UNREACHABLE();
530         }
531     }
532 }
533 
CheckObjectTypeForDuplicatedProperties(ir::Expression * key,ArenaVector<ir::AstNode * > & members)534 void TypedParser::CheckObjectTypeForDuplicatedProperties(ir::Expression *key, ArenaVector<ir::AstNode *> &members)
535 {
536     if (!key->IsIdentifier() && !key->IsNumberLiteral() && !key->IsStringLiteral()) {
537         return;
538     }
539 
540     for (auto *it : members) {
541         ir::Expression *compare = nullptr;
542 
543         switch (it->Type()) {
544             case ir::AstNodeType::TS_PROPERTY_SIGNATURE: {
545                 compare = it->AsTSPropertySignature()->Key();
546                 break;
547             }
548             case ir::AstNodeType::TS_METHOD_SIGNATURE: {
549                 compare = it->AsTSMethodSignature()->Key();
550                 break;
551             }
552             default: {
553                 continue;
554             }
555         }
556 
557         if (!compare->IsIdentifier() && !compare->IsNumberLiteral() && !compare->IsStringLiteral()) {
558             continue;
559         }
560 
561         if (GetTSPropertyName(key) == GetTSPropertyName(compare)) {
562             LogError(diagnostic::DUPLICATED_IDENTIFIER, {}, key->Start());
563         }
564     }
565 }
566 
ParseTypeLiteralOrInterfaceBody()567 ArenaVector<ir::AstNode *> TypedParser::ParseTypeLiteralOrInterfaceBody()
568 {
569     ArenaVector<ir::AstNode *> members(Allocator()->Adapter());
570 
571     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
572            Lexer()->GetToken().Type() != lexer::TokenType::EOS) {
573         util::ErrorRecursionGuard infiniteLoopBlocker(Lexer());
574 
575         ir::AstNode *member = ParseTypeLiteralOrInterfaceMember();
576         if (member == nullptr) {
577             break;
578         }
579 
580         if (member->IsMethodDefinition() && member->AsMethodDefinition()->Function() != nullptr &&
581             member->AsMethodDefinition()->Function()->IsOverload() &&
582             member->AsMethodDefinition()->Function()->Body() != nullptr) {
583             continue;
584         }
585 
586         if (member->IsTSPropertySignature()) {
587             CheckObjectTypeForDuplicatedProperties(member->AsTSPropertySignature()->Key(), members);
588         } else if (member->IsTSMethodSignature()) {
589             CheckObjectTypeForDuplicatedProperties(member->AsTSMethodSignature()->Key(), members);
590         }
591 
592         members.push_back(member);
593 
594         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
595             break;
596         }
597 
598         if (Lexer()->GetToken().Type() == lexer::TokenType::JS_DOC_START) {
599             continue;
600         }
601 
602         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
603             Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
604             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
605                 LogError(diagnostic::INTERFACE_MEMBER_INIT_NOT_ALLOWED);
606                 Lexer()->NextToken();
607             }
608             if (!Lexer()->GetToken().NewLine()) {
609                 LogExpectedToken(lexer::TokenType::PUNCTUATOR_COMMA);
610             }
611 
612             if (Lexer()->GetToken().IsKeyword() && ((Lexer()->GetToken().Type() != lexer::TokenType::KEYW_STATIC) &&
613                                                     (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_PRIVATE))) {
614                 Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
615                 Lexer()->GetToken().SetTokenStr(ERROR_LITERAL);
616             }
617 
618             continue;
619         }
620 
621         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
622     }
623 
624     return members;
625 }
626 
ParseTypeLiteralOrInterface()627 ArenaVector<ir::AstNode *> TypedParser::ParseTypeLiteralOrInterface()
628 {
629     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPLEMENTS) {
630         LogError(diagnostic::INTERFACE_DEC_IMPLEMENTS);
631         Lexer()->NextToken();         // eat 'implements'
632         ParseClassImplementClause();  // Try to parse implements, but drop the result;
633     }
634 
635     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
636         LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
637     }
638 
639     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
640 
641     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_OVERRIDE) {
642         LogError(diagnostic::OVERRIDE_IN_INTERFACE);
643         Lexer()->NextToken();  // eat 'override'
644     }
645 
646     bool const formattedParsing = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
647                                   Lexer()->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE);
648 
649     ArenaVector<ir::AstNode *> members =
650         !formattedParsing ? ParseTypeLiteralOrInterfaceBody() : std::move(ParseAstNodesArrayFormatPlaceholder());
651 
652     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
653         // redundant check since we have the same check
654         // in ParseTypeLiteralOrInterfaceBody() above
655         LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE);
656     }
657 
658     return members;
659 }
660 
ParseEnumMembers(ir::Identifier * key,const lexer::SourcePosition & enumStart,bool isConst,bool isStatic)661 ir::TSEnumDeclaration *TypedParser::ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart,
662                                                      bool isConst, [[maybe_unused]] bool isStatic)
663 {
664     ArenaVector<ir::AstNode *> members(Allocator()->Adapter());
665     ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
666     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
667 
668     lexer::SourcePosition endLoc;
669     ParseList(
670         lexer::TokenType::PUNCTUATOR_RIGHT_BRACE, lexer::NextTokenFlags::KEYWORD_TO_IDENT,
671         [this, &members]() {
672             ir::Expression *memberKey = nullptr;
673 
674             if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
675                 memberKey = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
676                 memberKey->SetRange(Lexer()->GetToken().Loc());
677             } else if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
678                 memberKey = AllocNode<ir::StringLiteral>(Lexer()->GetToken().String());
679                 memberKey->SetRange(Lexer()->GetToken().Loc());
680             } else {
681                 LogError(diagnostic::UNEXPECTED_TOKEN_ENUM);
682                 memberKey = AllocBrokenExpression(Lexer()->GetToken().Loc());
683                 // Consider that the current token is a memberKey and skip it.
684             }
685 
686             Lexer()->NextToken();  // eat memberKey
687 
688             ir::Expression *memberInit = nullptr;
689             lexer::SourcePosition initStart = Lexer()->GetToken().Start();
690 
691             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
692                 Lexer()->NextToken();  // eat '='
693                 initStart = Lexer()->GetToken().Start();
694                 memberInit = ParseExpression();
695             }
696 
697             auto *member = AllocNode<ir::TSEnumMember>(memberKey, memberInit);
698             member->SetRange({initStart, Lexer()->GetToken().End()});
699             members.push_back(member);
700             return true;
701         },
702         &endLoc, true);
703 
704     auto *enumDeclaration = AllocNode<ir::TSEnumDeclaration>(Allocator(), key, std::move(members),
705                                                              ir::TSEnumDeclaration::ConstructorFlags {isConst});
706     ES2PANDA_ASSERT(enumDeclaration != nullptr);
707     enumDeclaration->SetRange({enumStart, endLoc});
708 
709     return enumDeclaration;
710 }
711 
712 // NOLINTNEXTLINE(google-default-arguments)
ParseEnumDeclaration(bool isConst,bool isStatic)713 ir::Statement *TypedParser::ParseEnumDeclaration(bool isConst, [[maybe_unused]] bool isStatic)
714 {
715     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_ENUM);
716     lexer::SourcePosition enumStart = Lexer()->GetToken().Start();
717     Lexer()->NextToken();  // eat enum keyword
718     auto *key = ExpectIdentifier(true);
719     auto *declNode = ParseEnumMembers(key, enumStart, isConst, false);
720     return declNode;
721 }
722 
ParseTypeParameter(TypeAnnotationParsingOptions * options)723 ir::TSTypeParameter *TypedParser::ParseTypeParameter(TypeAnnotationParsingOptions *options)
724 {
725     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
726     bool reportError = ((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0;
727 
728     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || Lexer()->GetToken().IsDefinableTypeName()) {
729         if (!reportError) {
730             return nullptr;
731         }
732 
733         LogError(diagnostic::TYPE_PARAM_DEC_EXPECTED);
734         return nullptr;
735     }
736 
737     if (reportError) {
738         CheckIfTypeParameterNameIsReserved();
739     }
740 
741     const auto &ident = Lexer()->GetToken().Ident();
742     auto *paramIdent = AllocNode<ir::Identifier>(ident, Allocator());
743     ES2PANDA_ASSERT(paramIdent != nullptr);
744     paramIdent->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()});
745 
746     Lexer()->NextToken();
747 
748     TypeAnnotationParsingOptions newOptions = TypeAnnotationParsingOptions::NO_OPTS;
749 
750     if (reportError) {
751         newOptions |= TypeAnnotationParsingOptions::REPORT_ERROR;
752     }
753 
754     ir::TypeNode *constraint = nullptr;
755     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
756         Lexer()->NextToken();
757         constraint = ParseTypeAnnotation(&newOptions);
758     }
759 
760     ir::TypeNode *defaultType = nullptr;
761     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
762         Lexer()->NextToken();
763         defaultType = ParseTypeAnnotation(&newOptions);
764     }
765 
766     auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType, Allocator());
767     ES2PANDA_ASSERT(typeParam != nullptr);
768     typeParam->SetRange({startLoc, Lexer()->GetToken().End()});
769 
770     return typeParam;
771 }
772 
773 //  Auxiliary method to reduce the size of functions.
ParseTypeParameterDeclarationImpl(TypeAnnotationParsingOptions * options)774 ir::AstNode *TypedParser::ParseTypeParameterDeclarationImpl(TypeAnnotationParsingOptions *options)
775 {
776     ArenaVector<ir::TSTypeParameter *> params(Allocator()->Adapter());
777     bool seenDefault = false;
778     size_t requiredParams = 0U;
779 
780     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
781         auto newOptions = *options | TypeAnnotationParsingOptions::ADD_TYPE_PARAMETER_BINDING;
782         ir::TSTypeParameter *currentParam = ParseTypeParameter(&newOptions);
783 
784         if (currentParam == nullptr) {
785             // Maybe error processing.
786             return nullptr;
787         }
788 
789         if (currentParam->DefaultType() != nullptr) {
790             seenDefault = true;
791         } else if (seenDefault) {
792             LogError(diagnostic::REQUIRED_TYPE_PARAM_AFTER_OPTIONAL);
793         } else {
794             requiredParams++;
795         }
796 
797         params.push_back(currentParam);
798 
799         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
800             break;
801         }
802 
803         Lexer()->NextToken();
804     }
805 
806     if (params.empty()) {
807         LogError(diagnostic::TYPE_PARAM_LIST_EMPTY);
808     }
809 
810     return AllocNode<ir::TSTypeParameterDeclaration>(std::move(params), requiredParams);
811 }
812 
ParseTypeParameterDeclaration(TypeAnnotationParsingOptions * options)813 ir::TSTypeParameterDeclaration *TypedParser::ParseTypeParameterDeclaration(TypeAnnotationParsingOptions *options)
814 {
815     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
816 
817     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
818     Lexer()->NextToken();  // eat '<'
819 
820     ir::AstNode *typeParamDecl;
821 
822     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
823         Lexer()->Lookahead() == static_cast<char32_t>(EXPRESSION_FORMAT_NODE)) {
824         typeParamDecl = ParseTypeParametersFormatPlaceholder();
825     } else {
826         typeParamDecl = ParseTypeParameterDeclarationImpl(options);
827     }
828 
829     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
830         if ((*options & TypeAnnotationParsingOptions::REPORT_ERROR) == 0) {
831             return nullptr;
832         }
833         LogExpectedToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN);
834     }
835 
836     lexer::SourcePosition endLoc = Lexer()->GetToken().End();
837     Lexer()->NextToken();  // eat '>'
838 
839     if (typeParamDecl != nullptr) {
840         typeParamDecl->SetRange({startLoc, endLoc});
841         return typeParamDecl->AsTSTypeParameterDeclaration();
842     }
843 
844     return nullptr;
845 }
846 
ParseSuperClassReference()847 ir::Expression *TypedParser::ParseSuperClassReference()
848 {
849     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
850         Lexer()->NextToken();
851 
852         return ParseLeftHandSideExpression();
853     }
854 
855     return nullptr;
856 }
857 
ParseSuperClass()858 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> TypedParser::ParseSuperClass()
859 {
860     ir::Expression *superClass = ParseSuperClassReference();
861 
862     ir::TSTypeParameterInstantiation *superTypeParams = nullptr;
863     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
864         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
865         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
866             Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
867         }
868 
869         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
870         superTypeParams = ParseTypeParameterInstantiation(&options);
871     }
872 
873     return {superClass, superTypeParams};
874 }
875 
ParseClassImplementsElement()876 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> TypedParser::ParseClassImplementsElement()
877 {
878     ir::Expression *expr = ParseQualifiedName();
879 
880     ir::TSTypeParameterInstantiation *implTypeParams = nullptr;
881     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
882         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
883         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
884             Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
885         }
886 
887         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
888         implTypeParams = ParseTypeParameterInstantiation(&options);
889     }
890 
891     return {expr, implTypeParams};
892 }
893 
ParseClassImplementClause()894 ArenaVector<ir::TSClassImplements *> TypedParser::ParseClassImplementClause()
895 {
896     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
897 
898     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
899         lexer::SourcePosition implStart = Lexer()->GetToken().Start();
900         auto [expr, implTypeParams] = ParseClassImplementsElement();
901         auto *impl = AllocNode<ir::TSClassImplements>(expr, implTypeParams);
902         ES2PANDA_ASSERT(impl != nullptr);
903         impl->SetRange({implStart, Lexer()->GetToken().End()});
904         implements.push_back(impl);
905 
906         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
907             Lexer()->NextToken();
908             continue;
909         }
910 
911         if (InAmbientContext()) {
912             break;
913         }
914 
915         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
916             LogExpectedToken(lexer::TokenType::PUNCTUATOR_COMMA);
917             break;  // Force to leave the 'implements' context.
918         }
919     }
920 
921     if (implements.empty()) {
922         LogError(diagnostic::IMPLEMENTS_CLAUSE_EMPTY);
923     }
924 
925     return implements;
926 }
927 
CheckClassElementInterfaceBody(ir::AstNode * property,ArenaVector<ir::AstNode * > & properties)928 bool TypedParser::CheckClassElementInterfaceBody(ir::AstNode *property, ArenaVector<ir::AstNode *> &properties)
929 {
930     for (auto *it : property->AsTSInterfaceBody()->Body()) {
931         properties.push_back(it);
932     }
933 
934     return true;
935 }
936 
CheckClassElement(ir::AstNode * property,ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties)937 bool TypedParser::CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor,
938                                     [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
939 {
940     if (property->IsTSInterfaceBody()) {
941         return CheckClassElementInterfaceBody(property, properties);
942     }
943 
944     return ParserImpl::CheckClassElement(property, ctor, properties);
945 }
946 
947 // NOLINTNEXTLINE(google-default-arguments)
ParseClassDefinition(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)948 ir::ClassDefinition *TypedParser::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
949 {
950     Lexer()->NextToken();
951 
952     ir::Identifier *identNode = ParseClassIdent(modifiers);
953 
954     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
955     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
956         auto options = TypeAnnotationParsingOptions::REPORT_ERROR;
957         typeParamDecl = ParseTypeParameterDeclaration(&options);
958     }
959 
960     varbinder::PrivateBinding privateBinding(Allocator(), ClassId()++);
961 
962     // Parse SuperClass
963     auto [superClass, superTypeParams] = ParseSuperClass();
964 
965     if (superClass != nullptr) {
966         modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
967     }
968 
969     // Parse implements clause
970     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
971     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
972         Lexer()->NextToken();
973         implements = ParseClassImplementClause();
974     }
975 
976     ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
977 
978     // Parse ClassBody
979     auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags);
980 
981     if (InAmbientContext()) {
982         flags |= ir::ModifierFlags::DECLARE;
983     }
984 
985     auto *classDefinition =
986         AllocNode<ir::ClassDefinition>(identNode, typeParamDecl, superTypeParams, std::move(implements), ctor,
987                                        superClass, std::move(properties), modifiers, flags, GetContext().GetLanguage());
988     ES2PANDA_ASSERT(classDefinition != nullptr);
989     classDefinition->SetInternalName(privateBinding.View());
990 
991     classDefinition->SetRange(bodyRange);
992 
993     return classDefinition;
994 }
995 
ValidateIndexSignatureTypeAnnotation(ir::TypeNode * typeAnnotation)996 void TypedParser::ValidateIndexSignatureTypeAnnotation(ir::TypeNode *typeAnnotation)
997 {
998     if (typeAnnotation == nullptr) {
999         LogError(diagnostic::INDEX_MISSING_TYPE);
1000     }
1001 }
1002 
ParseProperty(const ArenaVector<ir::AstNode * > & properties,ClassElementDescriptor & desc,ir::Expression * propName)1003 ir::AstNode *TypedParser::ParseProperty(const ArenaVector<ir::AstNode *> &properties, ClassElementDescriptor &desc,
1004                                         ir::Expression *propName)
1005 {
1006     ir::AstNode *property = nullptr;
1007     ir::TypeNode *typeAnnotation = ParseClassKeyAnnotation();
1008 
1009     if (desc.isIndexSignature) {
1010         if (!desc.decorators.empty()) {
1011             LogError(diagnostic::DECORATORS_INVALID, {}, desc.decorators.front()->Start());
1012         }
1013 
1014         ValidateIndexSignatureTypeAnnotation(typeAnnotation);
1015 
1016         if ((desc.modifiers & ir::ModifierFlags::DECLARE) != 0) {
1017             LogError(diagnostic::DECALRE_IN_AMBIENT_CONTEXT);
1018         }
1019 
1020         property =
1021             AllocNode<ir::TSIndexSignature>(propName, typeAnnotation, desc.modifiers & ir::ModifierFlags::READONLY);
1022         ES2PANDA_ASSERT(property != nullptr);
1023         property->SetRange({property->AsTSIndexSignature()->Param()->Start(),
1024                             property->AsTSIndexSignature()->TypeAnnotation()->End()});
1025     } else {
1026         ValidateClassMethodStart(&desc, typeAnnotation);
1027         property = ParseClassProperty(&desc, properties, propName, typeAnnotation);
1028 
1029         if (!desc.decorators.empty()) {
1030             if (desc.isPrivateIdent) {
1031                 LogError(diagnostic::DECORATORS_INVALID);
1032             }
1033             ES2PANDA_ASSERT(property != nullptr);
1034             property->AddDecorators(std::move(desc.decorators));
1035         }
1036     }
1037 
1038     ES2PANDA_ASSERT(property != nullptr);
1039     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1040         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
1041         ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0) &&
1042         !(property->IsMethodDefinition() &&
1043           property->AsMethodDefinition()->Value()->AsFunctionExpression()->Function()->Body() != nullptr)) {
1044         LogExpectedToken(lexer::TokenType::PUNCTUATOR_SEMI_COLON);
1045     }
1046 
1047     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1048         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1049     }
1050 
1051     GetContext().Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
1052 
1053     if (desc.isPrivateIdent) {
1054         AddPrivateElement(property->AsClassElement());
1055     }
1056 
1057     return property;
1058 }
1059 
ParseClassElement(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)1060 ir::AstNode *TypedParser::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
1061                                             ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
1062 {
1063     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
1064         Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
1065         return ParseClassStaticBlock();
1066     }
1067 
1068     ClassElementDescriptor desc(Allocator());
1069 
1070     desc.methodKind = ir::MethodDefinitionKind::METHOD;
1071     desc.newStatus = ParserStatus::ALLOW_SUPER;
1072     desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0;
1073     desc.propStart = Lexer()->GetToken().Start();
1074 
1075     ParseDecorators(desc.decorators);
1076 
1077     desc.modifiers = ParseModifiers();
1078 
1079     if (((desc.modifiers & ir::ModifierFlags::ABSTRACT) != 0) && ((flags & ir::ModifierFlags::ABSTRACT) == 0)) {
1080         LogError(diagnostic::ABSTRACT_METHODS_ONLY_IN_ABSTRACT_CLASS);
1081     }
1082 
1083     char32_t nextCp = Lexer()->Lookahead();
1084     CheckClassGeneratorMethod(&desc, &nextCp);
1085     ParseClassAccessor(&desc, &nextCp);
1086 
1087     if ((desc.modifiers & ir::ModifierFlags::STATIC) == 0) {
1088         GetContext().Status() |= ParserStatus::ALLOW_THIS_TYPE;
1089     }
1090 
1091     ir::Expression *propName = ParseClassKey(&desc);
1092     if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR && !desc.decorators.empty()) {
1093         LogError(diagnostic::DECORATORS_INVALID, {}, desc.decorators.front()->Start());
1094     }
1095 
1096     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1097         ParseOptionalClassElement(&desc);
1098     } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
1099         if (desc.isIndexSignature || Lexer()->Lookahead() != lexer::LEX_CHAR_COLON) {
1100             // test exists for ts extension only
1101             LogExpectedToken(lexer::TokenType::PUNCTUATOR_SEMI_COLON);
1102         }
1103 
1104         desc.modifiers |= ir::ModifierFlags::DEFINITE;
1105         Lexer()->NextToken();
1106     }
1107 
1108     return ParseProperty(properties, desc, propName);
1109 }
1110 
ParseOptionalClassElement(ClassElementDescriptor * desc)1111 void TypedParser::ParseOptionalClassElement(ClassElementDescriptor *desc)
1112 {
1113     if (desc->isIndexSignature) {
1114         LogExpectedToken(lexer::TokenType::PUNCTUATOR_SEMI_COLON);  // no test
1115     }
1116 
1117     if (desc->methodKind == ir::MethodDefinitionKind::CONSTRUCTOR) {
1118         // test exists for ts extension only
1119         LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1120     }
1121 
1122     desc->modifiers |= ir::ModifierFlags::OPTIONAL;
1123     Lexer()->NextToken();
1124 }
1125 
ParseActualNextStatus(lexer::TokenType keywordType)1126 static std::pair<ir::ModifierFlags, ir::ModifierFlags> ParseActualNextStatus(lexer::TokenType keywordType)
1127 {
1128     constexpr auto ASYNC_STATIC_READONLY =
1129         ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY;
1130     constexpr auto ASYNC_STATIC_READONLY_AMBIENT_ABSTRACT =
1131         ASYNC_STATIC_READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1132 
1133     switch (keywordType) {
1134         case lexer::TokenType::KEYW_PUBLIC:
1135             return {ir::ModifierFlags::PUBLIC, ASYNC_STATIC_READONLY_AMBIENT_ABSTRACT};
1136         case lexer::TokenType::KEYW_PRIVATE:
1137             return {ir::ModifierFlags::PRIVATE, ASYNC_STATIC_READONLY_AMBIENT_ABSTRACT};
1138         case lexer::TokenType::KEYW_PROTECTED:
1139             return {ir::ModifierFlags::PROTECTED, ASYNC_STATIC_READONLY_AMBIENT_ABSTRACT};
1140         case lexer::TokenType::KEYW_INTERNAL:
1141             return {ir::ModifierFlags::INTERNAL, ASYNC_STATIC_READONLY_AMBIENT_ABSTRACT | ir::ModifierFlags::PROTECTED};
1142         case lexer::TokenType::KEYW_STATIC:
1143             return {ir::ModifierFlags::STATIC, ir::ModifierFlags::ASYNC | ir::ModifierFlags::READONLY |
1144                                                    ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT};
1145         case lexer::TokenType::KEYW_ASYNC:
1146             return {ir::ModifierFlags::ASYNC,
1147                     ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT};
1148         case lexer::TokenType::KEYW_ABSTRACT:
1149             return {ir::ModifierFlags::ABSTRACT,
1150                     ASYNC_STATIC_READONLY | ir::ModifierFlags::ACCESS | ir::ModifierFlags::DECLARE};
1151         case lexer::TokenType::KEYW_DECLARE:
1152             return {ir::ModifierFlags::DECLARE, ASYNC_STATIC_READONLY | ir::ModifierFlags::ACCESS};
1153         case lexer::TokenType::KEYW_READONLY:
1154             return {ir::ModifierFlags::READONLY,
1155                     ir::ModifierFlags::ASYNC | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT};
1156         default:
1157             ES2PANDA_UNREACHABLE();
1158     }
1159 }
1160 
ParseModifiers()1161 ir::ModifierFlags TypedParser::ParseModifiers()
1162 {
1163     ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
1164     ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
1165 
1166     while (IsModifierKind(Lexer()->GetToken())) {
1167         char32_t nextCp = Lexer()->Lookahead();
1168         if (!(nextCp != lexer::LEX_CHAR_EQUALS && nextCp != lexer::LEX_CHAR_SEMICOLON &&
1169               nextCp != lexer::LEX_CHAR_COMMA && nextCp != lexer::LEX_CHAR_LEFT_PAREN)) {
1170             break;
1171         }
1172 
1173         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
1174         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
1175             LogError(diagnostic::KEYWORD_CONTAINS_ESCAPED_CHARS);
1176         }
1177 
1178         auto [actualStatus, nextStatus] = ParseActualNextStatus(Lexer()->GetToken().KeywordType());
1179 
1180         nextCp = Lexer()->Lookahead();
1181         if (nextCp == lexer::LEX_CHAR_COLON || nextCp == lexer::LEX_CHAR_COMMA ||
1182             nextCp == lexer::LEX_CHAR_RIGHT_PAREN || nextCp == lexer::LEX_CHAR_QUESTION ||
1183             nextCp == lexer::LEX_CHAR_RIGHT_BRACE || nextCp == lexer::LEX_CHAR_LESS_THAN) {
1184             break;
1185         }
1186 
1187         if ((prevStatus & actualStatus) == 0) {
1188             LogError(diagnostic::UNEXPECTED_MODIFIER);
1189         }
1190 
1191         if ((resultStatus & actualStatus) != 0) {
1192             LogError(diagnostic::DUPLICATED_MODIFIER);
1193         }
1194 
1195         if ((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) != 0 &&
1196             (actualStatus & ~ir::ModifierFlags::ALLOWED_IN_CTOR_PARAMETER) != 0) {
1197             LogParameterModifierError(actualStatus);
1198         }
1199 
1200         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1201 
1202         resultStatus |= actualStatus;
1203         prevStatus = nextStatus;
1204     }
1205 
1206     return resultStatus;
1207 }
1208 
ParseQualifiedName(ExpressionParseFlags flags)1209 ir::Expression *TypedParser::ParseQualifiedName(ExpressionParseFlags flags)
1210 {
1211     ir::Expression *expr = nullptr;
1212 
1213     switch (Lexer()->GetToken().Type()) {
1214         case lexer::TokenType::PUNCTUATOR_FORMAT:
1215             expr = ParseIdentifierFormatPlaceholder(std::nullopt);
1216             break;
1217         case lexer::TokenType::LITERAL_IDENT:
1218             expr = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1219             ES2PANDA_ASSERT(expr != nullptr);
1220             expr->SetRange(Lexer()->GetToken().Loc());
1221             Lexer()->NextToken();
1222             break;
1223         default:
1224             LogError(diagnostic::ID_EXPECTED);
1225             return AllocBrokenExpression(Lexer()->GetToken().Loc());
1226     }
1227 
1228     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
1229         expr = ParseQualifiedReference(expr, flags);
1230     }
1231 
1232     return expr;
1233 }
1234 
ParseLiteralIndent(ir::Expression * typeName,ExpressionParseFlags flags,const lexer::SourcePosition & startLoc)1235 ir::Expression *TypedParser::ParseLiteralIndent(ir::Expression *typeName, ExpressionParseFlags flags,
1236                                                 const lexer::SourcePosition &startLoc)
1237 {
1238     if ((flags & ExpressionParseFlags::POTENTIAL_CLASS_LITERAL) != 0 &&
1239         Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS) {
1240         typeName->SetRange({startLoc, Lexer()->GetToken().End()});
1241         return typeName;
1242     }
1243 
1244     LogError(diagnostic::ID_EXPECTED);
1245     return AllocBrokenExpression(Lexer()->GetToken().Loc());
1246 }
1247 
ParseQualifiedReference(ir::Expression * typeName,ExpressionParseFlags flags)1248 ir::Expression *TypedParser::ParseQualifiedReference(ir::Expression *typeName, ExpressionParseFlags flags)
1249 {
1250     lexer::SourcePosition startLoc = typeName->Start();
1251 
1252     do {
1253         Lexer()->NextToken();  // eat '.'
1254 
1255         ir::Identifier *propName {};
1256         if ((flags & ExpressionParseFlags::IMPORT) != 0 &&
1257             Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1258             Lexer()->NextToken();  // eat '*'
1259             propName = AllocNode<ir::Identifier>(varbinder::VarBinder::STAR_IMPORT, Allocator());
1260         } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT) {
1261             propName = ParseIdentifierFormatPlaceholder(std::nullopt);
1262         } else if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1263             return ParseLiteralIndent(typeName, flags, startLoc);
1264         } else {
1265             propName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1266         }
1267 
1268         if (propName == nullptr) {
1269             return AllocBrokenExpression(Lexer()->GetToken().Loc());
1270         }
1271         propName->SetRange(Lexer()->GetToken().Loc());
1272 
1273         typeName = AllocNode<ir::TSQualifiedName>(typeName, propName, Allocator());
1274         ES2PANDA_ASSERT(typeName != nullptr);
1275         typeName->SetRange({typeName->AsTSQualifiedName()->Left()->Start(), Lexer()->GetToken().End()});
1276 
1277         if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1278             Lexer()->NextToken();
1279         }
1280     } while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD);
1281 
1282     typeName->SetRange({startLoc, Lexer()->GetToken().End()});
1283 
1284     return typeName;
1285 }
1286 
1287 //  Auxiliary method to reduce the size of functions.
ParseTypeParameterInstantiationImpl(TypeAnnotationParsingOptions * options)1288 ir::AstNode *TypedParser::ParseTypeParameterInstantiationImpl(TypeAnnotationParsingOptions *options)
1289 {
1290     ArenaVector<ir::TypeNode *> params(Allocator()->Adapter());
1291 
1292     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
1293         TypeAnnotationParsingOptions tmpOptions = *options &= ~TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE;
1294         // Need to parse correctly the cases like `x: T|C<T|U>`
1295         tmpOptions &= ~TypeAnnotationParsingOptions::DISALLOW_UNION;
1296         tmpOptions |= TypeAnnotationParsingOptions::ANNOTATION_NOT_ALLOW;
1297         ir::TypeNode *currentParam = ParseTypeAnnotation(&tmpOptions);
1298 
1299         if (currentParam == nullptr) {
1300             return nullptr;
1301         }
1302 
1303         params.push_back(currentParam);
1304 
1305         switch (Lexer()->GetToken().Type()) {
1306             case lexer::TokenType::PUNCTUATOR_COMMA: {
1307                 Lexer()->NextToken();
1308                 continue;
1309             }
1310             case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
1311             case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: {
1312                 Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 1);
1313                 break;
1314             }
1315             case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL:
1316             case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
1317                 Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 2U);
1318                 break;
1319             }
1320             case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: {
1321                 Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 3U);
1322                 break;
1323             }
1324             case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
1325                 break;
1326             }
1327             default: {
1328                 return nullptr;
1329             }
1330         }
1331     }
1332 
1333     return AllocNode<ir::TSTypeParameterInstantiation>(std::move(params));
1334 }
1335 
ParseTypeParameterInstantiation(TypeAnnotationParsingOptions * options)1336 ir::TSTypeParameterInstantiation *TypedParser::ParseTypeParameterInstantiation(TypeAnnotationParsingOptions *options)
1337 {
1338     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
1339 
1340     const bool inPotentialNewArray = (*options & TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY) != 0;
1341     *options &= ~TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY;
1342     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1343     Lexer()->NextToken();  // eat '<'
1344 
1345     ir::AstNode *typeParamInst;
1346     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
1347         Lexer()->Lookahead() == static_cast<char32_t>(EXPRESSION_FORMAT_NODE)) {
1348         typeParamInst = ParseTypeParametersFormatPlaceholder();
1349     } else {
1350         typeParamInst = ParseTypeParameterInstantiationImpl(options);
1351     }
1352 
1353     if (inPotentialNewArray) {
1354         *options |= TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY;
1355     }
1356 
1357     lexer::SourcePosition endLoc = Lexer()->GetToken().End();
1358     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
1359         if ((*options & TypeAnnotationParsingOptions::REPORT_ERROR) == 0) {
1360             return nullptr;
1361         }
1362         LogExpectedToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN);
1363     } else {
1364         Lexer()->NextToken();  // eat '>'
1365     }
1366     if (typeParamInst != nullptr) {
1367         typeParamInst->SetRange({startLoc, endLoc});
1368         return typeParamInst->AsTSTypeParameterInstantiation();
1369     }
1370 
1371     return nullptr;
1372 }
1373 
ParseDeclareAndDecorators(StatementParsingFlags flags)1374 ir::Statement *TypedParser::ParseDeclareAndDecorators(StatementParsingFlags flags)
1375 {
1376     ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
1377 
1378     ParseDecorators(decorators);
1379 
1380     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
1381         CheckDeclare();
1382     }
1383 
1384     ir::Statement *stmt = TypedParser::ParseStatement(flags);
1385 
1386     GetContext().Status() &= ~ParserStatus::IN_AMBIENT_CONTEXT;
1387     if (stmt != nullptr) {  // Error processing.
1388         AddDecorators(stmt, decorators);
1389     }
1390 
1391     return stmt;
1392 }
1393 
ConvertThisKeywordToIdentIfNecessary()1394 void TypedParser::ConvertThisKeywordToIdentIfNecessary()
1395 {
1396     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) {
1397         Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
1398         Lexer()->GetToken().SetTokenStr(ERROR_LITERAL);
1399     }
1400 }
1401 
ParseVariableDeclarator(ir::Expression * init,lexer::SourcePosition startLoc,VariableParsingFlags flags)1402 ir::VariableDeclarator *TypedParser::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc,
1403                                                              VariableParsingFlags flags)
1404 {
1405     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1406         return ParseVariableDeclaratorInitializer(init, flags, startLoc);
1407     }
1408 
1409     if (((flags & VariableParsingFlags::IN_FOR) == 0) && (init->IsArrayPattern() || init->IsObjectPattern())) {
1410         LogError(diagnostic::MISSING_INIT_IN_DEST_DEC);
1411     }
1412 
1413     lexer::SourcePosition endLoc = init->End();
1414     auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init);
1415     declarator->SetRange({startLoc, endLoc});
1416 
1417     return declarator;
1418 }
1419 
ParsePotentialOptionalFunctionParameter(ir::AnnotatedExpression * returnNode)1420 void TypedParser::ParsePotentialOptionalFunctionParameter(ir::AnnotatedExpression *returnNode)
1421 {
1422     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1423         switch (returnNode->Type()) {
1424             case ir::AstNodeType::IDENTIFIER: {
1425                 returnNode->AsIdentifier()->SetOptional(true);
1426                 break;
1427             }
1428             case ir::AstNodeType::OBJECT_PATTERN: {
1429                 returnNode->AsObjectPattern()->SetOptional(true);
1430                 break;
1431             }
1432             case ir::AstNodeType::ARRAY_PATTERN: {
1433                 returnNode->AsArrayPattern()->SetOptional(true);
1434                 break;
1435             }
1436             case ir::AstNodeType::REST_ELEMENT: {
1437                 returnNode->AsRestElement()->SetOptional(true);
1438                 break;
1439             }
1440             default: {
1441                 LogError(diagnostic::UNEXPECTED_TOKEN_FOR_PARAM);
1442             }
1443         }
1444 
1445         Lexer()->NextToken();  // eat '?'
1446     }
1447 
1448     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1449         Lexer()->NextToken();  // eat ':'
1450         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
1451         returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
1452     }
1453 }
1454 
ValidateArrowParameterAssignment(ir::AssignmentExpression * assignmentExpr)1455 ParserStatus TypedParser::ValidateArrowParameterAssignment(ir::AssignmentExpression *assignmentExpr)
1456 {
1457     if (assignmentExpr->Right()->IsYieldExpression()) {
1458         LogError(diagnostic::YIELD_IN_ARROW_FUN_PARAM);
1459     }
1460 
1461     if (assignmentExpr->Right()->IsAwaitExpression()) {
1462         LogError(diagnostic::AWAIT_IN_ARROW_FUN_PARAM);
1463     }
1464 
1465     if (!assignmentExpr->ConvertibleToAssignmentPattern()) {
1466         LogError(diagnostic::INVALID_DESTRUCTURING_TARGET);
1467     }
1468 
1469     if (assignmentExpr->Left()->IsIdentifier() && assignmentExpr->Left()->AsIdentifier()->IsOptional()) {
1470         LogError(diagnostic::PARAM_CANNOT_HAVE_QUESTION_MARK, {}, assignmentExpr->Start());
1471     }
1472 
1473     ValidateArrowParameterBindings(assignmentExpr);
1474     return ParserStatus::HAS_COMPLEX_PARAM;
1475 }
1476 
ValidateArrowParameterArray(ir::ArrayExpression * arrayPattern)1477 ParserStatus TypedParser::ValidateArrowParameterArray(ir::ArrayExpression *arrayPattern)
1478 {
1479     if (!arrayPattern->ConvertibleToArrayPattern()) {
1480         LogError(diagnostic::INVALID_DESTRUCTURING_TARGET);
1481     }
1482 
1483     if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && arrayPattern->IsOptional()) {
1484         LogError(diagnostic::BINDING_PATTERN_PARAM_CANNOT_BE_OPTIONAL, {}, arrayPattern->Start());
1485     }
1486 
1487     ValidateArrowParameterBindings(arrayPattern);
1488     return ParserStatus::HAS_COMPLEX_PARAM;
1489 }
1490 
ValidateArrowParameterObject(ir::ObjectExpression * objectPattern)1491 ParserStatus TypedParser::ValidateArrowParameterObject(ir::ObjectExpression *objectPattern)
1492 {
1493     if (!objectPattern->ConvertibleToObjectPattern()) {
1494         LogError(diagnostic::INVALID_DESTRUCTURING_TARGET);
1495     }
1496 
1497     if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && objectPattern->IsOptional()) {
1498         LogError(diagnostic::BINDING_PATTERN_PARAM_CANNOT_BE_OPTIONAL, {}, objectPattern->Start());
1499     }
1500 
1501     ValidateArrowParameterBindings(objectPattern);
1502     return ParserStatus::HAS_COMPLEX_PARAM;
1503 }
1504 
ValidateArrowParameter(ir::Expression * expr,bool * seenOptional)1505 ParserStatus TypedParser::ValidateArrowParameter(ir::Expression *expr, bool *seenOptional)
1506 {
1507     switch (expr->Type()) {
1508         case ir::AstNodeType::SPREAD_ELEMENT: {
1509             if (!expr->AsSpreadElement()->ConvertibleToRest(true)) {
1510                 LogError(diagnostic::INVALID_REST_ELEMENT);
1511             }
1512 
1513             [[fallthrough]];
1514         }
1515         case ir::AstNodeType::REST_ELEMENT: {
1516             if (expr->AsRestElement()->IsOptional()) {
1517                 LogError(diagnostic::REST_PARAM_CANNOT_BE_OPTIONAL, {}, expr->Start());
1518             }
1519 
1520             ValidateArrowParameterBindings(expr->AsRestElement()->Argument());
1521             return ParserStatus::HAS_COMPLEX_PARAM;
1522         }
1523         case ir::AstNodeType::IDENTIFIER: {
1524             const util::StringView &identifier = expr->AsIdentifier()->Name();
1525             bool isOptional = expr->AsIdentifier()->IsOptional();
1526             if ((*seenOptional) && !isOptional) {
1527                 LogError(diagnostic::REQUIRED_PARAM_AFTER_OPTIONAL, {}, expr->Start());
1528             }
1529 
1530             (*seenOptional) |= isOptional;
1531 
1532             if (identifier.Is("arguments")) {
1533                 LogError(diagnostic::BINDING_ARGS_INVALID);
1534             } else if (identifier.Is("eval")) {
1535                 LogError(diagnostic::BINDING_EVAL_INVALID);
1536             }
1537 
1538             ValidateArrowParameterBindings(expr);
1539             return ParserStatus::NO_OPTS;
1540         }
1541         case ir::AstNodeType::OBJECT_EXPRESSION:
1542             return ValidateArrowParameterObject(expr->AsObjectExpression());
1543         case ir::AstNodeType::ARRAY_EXPRESSION:
1544             return ValidateArrowParameterArray(expr->AsArrayExpression());
1545         case ir::AstNodeType::ASSIGNMENT_EXPRESSION:
1546             return ValidateArrowParameterAssignment(expr->AsAssignmentExpression());
1547         default:
1548             break;
1549     }
1550     LogError(diagnostic::INSUFFICIENT_PARAM_IN_ARROW_FUN);
1551     return ParserStatus::NO_OPTS;
1552 }
1553 
1554 }  // namespace ark::es2panda::parser
1555