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