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