• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ETSparser.h"
17 #include "ETSNolintParser.h"
18 #include <utility>
19 
20 #include "macros.h"
21 #include "parser/parserFlags.h"
22 #include "parser/parserStatusContext.h"
23 #include "util/helpers.h"
24 #include "util/language.h"
25 #include "utils/arena_containers.h"
26 #include "varbinder/varbinder.h"
27 #include "varbinder/ETSBinder.h"
28 #include "lexer/lexer.h"
29 #include "lexer/ETSLexer.h"
30 #include "checker/types/ets/etsEnumType.h"
31 #include "ir/astNode.h"
32 #include "ir/base/classDefinition.h"
33 #include "ir/base/decorator.h"
34 #include "ir/base/catchClause.h"
35 #include "ir/base/classProperty.h"
36 #include "ir/base/scriptFunction.h"
37 #include "ir/base/methodDefinition.h"
38 #include "ir/base/classStaticBlock.h"
39 #include "ir/base/spreadElement.h"
40 #include "ir/expressions/identifier.h"
41 #include "ir/expressions/functionExpression.h"
42 #include "ir/expressions/dummyNode.h"
43 #include "ir/module/importDeclaration.h"
44 #include "ir/module/importDefaultSpecifier.h"
45 #include "ir/module/importSpecifier.h"
46 #include "ir/module/exportSpecifier.h"
47 #include "ir/module/exportNamedDeclaration.h"
48 #include "ir/statements/assertStatement.h"
49 #include "ir/statements/blockStatement.h"
50 #include "ir/statements/ifStatement.h"
51 #include "ir/statements/labelledStatement.h"
52 #include "ir/statements/namespaceDeclaration.h"
53 #include "ir/statements/switchStatement.h"
54 #include "ir/statements/throwStatement.h"
55 #include "ir/statements/tryStatement.h"
56 #include "ir/statements/whileStatement.h"
57 #include "ir/statements/forOfStatement.h"
58 #include "ir/statements/doWhileStatement.h"
59 #include "ir/statements/breakStatement.h"
60 #include "ir/statements/debuggerStatement.h"
61 #include "ir/ets/etsLaunchExpression.h"
62 #include "ir/ets/etsClassLiteral.h"
63 #include "ir/ets/etsPrimitiveType.h"
64 #include "ir/ets/etsPackageDeclaration.h"
65 #include "ir/ets/etsReExportDeclaration.h"
66 #include "ir/ets/etsWildcardType.h"
67 #include "ir/ets/etsNewArrayInstanceExpression.h"
68 #include "ir/ets/etsTuple.h"
69 #include "ir/ets/etsFunctionType.h"
70 #include "ir/ets/etsNewClassInstanceExpression.h"
71 #include "ir/ets/etsNewMultiDimArrayInstanceExpression.h"
72 #include "ir/ets/etsScript.h"
73 #include "ir/ets/etsTypeReference.h"
74 #include "ir/ets/etsTypeReferencePart.h"
75 #include "ir/ets/etsNullishTypes.h"
76 #include "ir/ets/etsUnionType.h"
77 #include "ir/ets/etsImportSource.h"
78 #include "ir/ets/etsImportDeclaration.h"
79 #include "ir/ets/etsStructDeclaration.h"
80 #include "ir/ets/etsParameterExpression.h"
81 #include "ir/module/importNamespaceSpecifier.h"
82 #include "ir/ts/tsAsExpression.h"
83 #include "ir/ts/tsInterfaceDeclaration.h"
84 #include "ir/ts/tsEnumDeclaration.h"
85 #include "ir/ts/tsTypeParameterInstantiation.h"
86 #include "ir/ts/tsInterfaceBody.h"
87 #include "ir/ts/tsImportEqualsDeclaration.h"
88 #include "ir/ts/tsArrayType.h"
89 #include "ir/ts/tsQualifiedName.h"
90 #include "ir/ts/tsTypeReference.h"
91 #include "ir/ts/tsTypeParameter.h"
92 #include "ir/ts/tsInterfaceHeritage.h"
93 #include "ir/ts/tsFunctionType.h"
94 #include "ir/ts/tsClassImplements.h"
95 #include "ir/ts/tsEnumMember.h"
96 #include "ir/ts/tsTypeAliasDeclaration.h"
97 #include "ir/ts/tsTypeParameterDeclaration.h"
98 #include "ir/ts/tsNonNullExpression.h"
99 #include "ir/ts/tsThisType.h"
100 #include "generated/signatures.h"
101 
102 namespace ark::es2panda::parser {
103 class FunctionContext;
104 
105 using namespace std::literals::string_literals;
106 
IsClassModifier(lexer::TokenType type)107 static bool IsClassModifier(lexer::TokenType type)
108 {
109     return type == lexer::TokenType::KEYW_STATIC || type == lexer::TokenType::KEYW_ABSTRACT ||
110            type == lexer::TokenType::KEYW_FINAL;
111 }
112 
ParseClassModifiers()113 ir::ModifierFlags ETSParser::ParseClassModifiers()
114 {
115     ir::ModifierFlags flags = ir::ModifierFlags::NONE;
116 
117     while (IsClassModifier(Lexer()->GetToken().KeywordType())) {
118         ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE;
119 
120         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
121         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
122             LogSyntaxError("Keyword must not contain escaped characters");  // Lexer will do it.
123         }
124 
125         switch (Lexer()->GetToken().KeywordType()) {
126             case lexer::TokenType::KEYW_STATIC: {
127                 currentFlag = ir::ModifierFlags::STATIC;
128                 break;
129             }
130             case lexer::TokenType::KEYW_FINAL: {
131                 currentFlag = ir::ModifierFlags::FINAL;
132                 break;
133             }
134             case lexer::TokenType::KEYW_ABSTRACT: {
135                 currentFlag = ir::ModifierFlags::ABSTRACT;
136                 break;
137             }
138             default: {
139                 UNREACHABLE();
140             }
141         }
142 
143         if ((flags & currentFlag) != 0) {
144             LogSyntaxError("Duplicated modifier is not allowed");
145         }
146 
147         Lexer()->NextToken();
148         flags |= currentFlag;
149     }
150 
151     return flags;
152 }
153 
ParseClassImplementsElement()154 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ETSParser::ParseClassImplementsElement()
155 {
156     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR |
157                                            TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
158                                            TypeAnnotationParsingOptions::ALLOW_WILDCARD;
159     return {ParseTypeReference(&options), nullptr};
160 }
161 
ParseSuperClassReference()162 ir::Expression *ETSParser::ParseSuperClassReference()
163 {
164     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
165         Lexer()->NextToken();
166 
167         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR |
168                                                TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
169                                                TypeAnnotationParsingOptions::ALLOW_WILDCARD;
170         return ParseTypeReference(&options);
171     }
172 
173     return nullptr;
174 }
175 
ParseInterfaceExtendsElement()176 ir::TypeNode *ETSParser::ParseInterfaceExtendsElement()
177 {
178     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR |
179                                            TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
180                                            TypeAnnotationParsingOptions::ALLOW_WILDCARD;
181     return ParseTypeReference(&options);
182 }
183 
IsClassMemberAccessModifier(lexer::TokenType type)184 static bool IsClassMemberAccessModifier(lexer::TokenType type)
185 {
186     return type == lexer::TokenType::KEYW_PUBLIC || type == lexer::TokenType::KEYW_PRIVATE ||
187            type == lexer::TokenType::KEYW_PROTECTED || type == lexer::TokenType::KEYW_INTERNAL;
188 }
189 
ParseClassMemberAccessModifiers()190 std::tuple<ir::ModifierFlags, bool> ETSParser::ParseClassMemberAccessModifiers()
191 {
192     if (!IsClassMemberAccessModifier(Lexer()->GetToken().Type())) {
193         return {ir::ModifierFlags::PUBLIC, false};
194     }
195 
196     char32_t nextCp = Lexer()->Lookahead();
197     if (!(nextCp != lexer::LEX_CHAR_EQUALS && nextCp != lexer::LEX_CHAR_COLON &&
198           nextCp != lexer::LEX_CHAR_LEFT_PAREN)) {
199         return {ir::ModifierFlags::NONE, false};
200     }
201 
202     lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
203     if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
204         LogSyntaxError("Keyword must not contain escaped characters");  // Lexer will do it.
205     }
206 
207     ir::ModifierFlags accessFlag = ir::ModifierFlags::NONE;
208 
209     switch (Lexer()->GetToken().KeywordType()) {
210         case lexer::TokenType::KEYW_PUBLIC: {
211             accessFlag = ir::ModifierFlags::PUBLIC;
212             break;
213         }
214         case lexer::TokenType::KEYW_PRIVATE: {
215             accessFlag = ir::ModifierFlags::PRIVATE;
216             break;
217         }
218         case lexer::TokenType::KEYW_PROTECTED: {
219             accessFlag = ir::ModifierFlags::PROTECTED;
220             break;
221         }
222         case lexer::TokenType::KEYW_INTERNAL: {
223             Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
224             if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_PROTECTED) {
225                 accessFlag = ir::ModifierFlags::INTERNAL;
226                 return {accessFlag, true};
227             }
228             accessFlag = ir::ModifierFlags::INTERNAL_PROTECTED;
229             break;
230         }
231         default: {
232             UNREACHABLE();
233         }
234     }
235     if (((GetContext().Status() & ParserStatus::FUNCTION) != 0) &&
236         (accessFlag == ir::ModifierFlags::PUBLIC || accessFlag == ir::ModifierFlags::PRIVATE ||
237          accessFlag == ir::ModifierFlags::PROTECTED)) {
238         LogSyntaxError("Local class declaration members can not have access modifies", Lexer()->GetToken().Start());
239     }
240 
241     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
242     return {accessFlag, true};
243 }
244 
IsClassFieldModifier(lexer::TokenType type)245 static bool IsClassFieldModifier(lexer::TokenType type)
246 {
247     return type == lexer::TokenType::KEYW_STATIC || type == lexer::TokenType::KEYW_READONLY;
248 }
249 
ParseClassFieldModifiers(bool seenStatic)250 ir::ModifierFlags ETSParser::ParseClassFieldModifiers(bool seenStatic)
251 {
252     ir::ModifierFlags flags = seenStatic ? ir::ModifierFlags::STATIC : ir::ModifierFlags::NONE;
253 
254     while (IsClassFieldModifier(Lexer()->GetToken().KeywordType())) {
255         char32_t nextCp = Lexer()->Lookahead();
256         if (!(nextCp != lexer::LEX_CHAR_EQUALS && nextCp != lexer::LEX_CHAR_COLON)) {
257             return flags;
258         }
259 
260         ir::ModifierFlags currentFlag;
261 
262         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
263         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
264             LogSyntaxError("Keyword must not contain escaped characters");  // Lexer will do it.
265         }
266 
267         switch (Lexer()->GetToken().KeywordType()) {
268             case lexer::TokenType::KEYW_STATIC: {
269                 currentFlag = ir::ModifierFlags::STATIC;
270                 break;
271             }
272             case lexer::TokenType::KEYW_READONLY: {
273                 currentFlag = ir::ModifierFlags::READONLY;
274                 break;
275             }
276             default: {
277                 UNREACHABLE();
278             }
279         }
280 
281         if ((flags & currentFlag) != 0) {
282             LogSyntaxError("Duplicated modifier is not allowed");
283         }
284 
285         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
286         flags |= currentFlag;
287     }
288 
289     return flags;
290 }
291 
IsClassMethodModifier(lexer::TokenType type)292 bool ETSParser::IsClassMethodModifier(lexer::TokenType type) noexcept
293 {
294     switch (type) {
295         case lexer::TokenType::KEYW_STATIC:
296         case lexer::TokenType::KEYW_FINAL:
297         case lexer::TokenType::KEYW_NATIVE:
298         case lexer::TokenType::KEYW_ASYNC:
299         case lexer::TokenType::KEYW_OVERRIDE:
300         case lexer::TokenType::KEYW_ABSTRACT: {
301             return true;
302         }
303         default: {
304             break;
305         }
306     }
307 
308     return false;
309 }
310 
311 // Helper method for ir::ModifierFlags ETSParser::ParseClassMethodModifiers(bool seenStatic)
ParseClassMethodModifierFlag()312 ir::ModifierFlags ETSParser::ParseClassMethodModifierFlag()
313 {
314     ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE;
315 
316     switch (Lexer()->GetToken().KeywordType()) {
317         case lexer::TokenType::KEYW_STATIC: {
318             currentFlag = ir::ModifierFlags::STATIC;
319             break;
320         }
321         case lexer::TokenType::KEYW_FINAL: {
322             currentFlag = ir::ModifierFlags::FINAL;
323             break;
324         }
325         case lexer::TokenType::KEYW_NATIVE: {
326             currentFlag = ir::ModifierFlags::NATIVE;
327             break;
328         }
329         case lexer::TokenType::KEYW_ASYNC: {
330             currentFlag = ir::ModifierFlags::ASYNC;
331             break;
332         }
333         case lexer::TokenType::KEYW_OVERRIDE: {
334             currentFlag = ir::ModifierFlags::OVERRIDE;
335             break;
336         }
337         case lexer::TokenType::KEYW_ABSTRACT: {
338             currentFlag = ir::ModifierFlags::ABSTRACT;
339             break;
340         }
341         case lexer::TokenType::KEYW_DECLARE: {
342             currentFlag = ir::ModifierFlags::DECLARE;
343             break;
344         }
345         default: {
346             UNREACHABLE();
347         }
348     }
349 
350     return currentFlag;
351 }
352 
ParseClassMethodModifiers(bool seenStatic)353 ir::ModifierFlags ETSParser::ParseClassMethodModifiers(bool seenStatic)
354 {
355     ir::ModifierFlags flags = seenStatic ? ir::ModifierFlags::STATIC : ir::ModifierFlags::NONE;
356 
357     while (IsClassMethodModifier(Lexer()->GetToken().KeywordType())) {
358         char32_t nextCp = Lexer()->Lookahead();
359         if (!(nextCp != lexer::LEX_CHAR_LEFT_PAREN)) {
360             return flags;
361         }
362 
363         ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE;
364 
365         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
366         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
367             LogSyntaxError("Keyword must not contain escaped characters");  // Lexer will do it.
368         }
369 
370         currentFlag = ParseClassMethodModifierFlag();
371         if ((flags & currentFlag) != 0) {
372             LogSyntaxError("Duplicated modifier is not allowed");
373         }
374 
375         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
376         flags |= currentFlag;
377         if ((flags & ir::ModifierFlags::ASYNC) != 0) {
378             if ((flags & ir::ModifierFlags::NATIVE) != 0) {
379                 LogSyntaxError("Native method cannot be async");
380             } else if ((flags & ir::ModifierFlags::ABSTRACT) != 0) {
381                 LogSyntaxError("Abstract method cannot be async");
382             }
383         }
384     }
385 
386     return flags;
387 }
388 
389 // NOLINTNEXTLINE(google-default-arguments)
ParseClassFieldDefinition(ir::Identifier * fieldName,ir::ModifierFlags modifiers,ArenaVector<ir::AstNode * > * declarations)390 void ETSParser::ParseClassFieldDefinition(ir::Identifier *fieldName, ir::ModifierFlags modifiers,
391                                           ArenaVector<ir::AstNode *> *declarations)
392 {
393     lexer::SourcePosition endLoc = fieldName->End();
394     ir::TypeNode *typeAnnotation = nullptr;
395     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
396     bool optionalField = false;
397 
398     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
399         Lexer()->NextToken();  // eat '?'
400         optionalField = true;
401     }
402     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
403         Lexer()->NextToken();  // eat ':'
404         typeAnnotation = ParseTypeAnnotation(&options);
405         endLoc = typeAnnotation->End();
406     }
407 
408     ir::Expression *initializer = nullptr;
409     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
410         Lexer()->NextToken();  // eat '='
411         initializer = ParseExpression();
412     } else if (typeAnnotation == nullptr) {
413         LogSyntaxError("Field type annotation expected");
414     }
415 
416     bool isDeclare = (modifiers & ir::ModifierFlags::DECLARE) != 0;
417 
418     if (isDeclare && initializer != nullptr) {
419         LogSyntaxError("Initializers are not allowed in ambient contexts.");
420     }
421 
422     auto *field = AllocNode<ir::ClassProperty>(fieldName, initializer, typeAnnotation, modifiers, Allocator(), false);
423     field->SetRange({fieldName->Start(), initializer != nullptr ? initializer->End() : endLoc});
424     if (optionalField) {
425         field->AddModifier(ir::ModifierFlags::OPTIONAL);
426     }
427 
428     declarations->push_back(field);
429 
430     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
431         Lexer()->NextToken();
432         ir::Identifier *nextName = ExpectIdentifier(false, true);
433         ParseClassFieldDefinition(nextName, modifiers, declarations);
434     }
435 }
436 
ParseClassMethodDefinition(ir::Identifier * methodName,ir::ModifierFlags modifiers,ir::Identifier * className)437 ir::MethodDefinition *ETSParser::ParseClassMethodDefinition(ir::Identifier *methodName, ir::ModifierFlags modifiers,
438                                                             ir::Identifier *className)
439 {
440     auto newStatus = ParserStatus::NEED_RETURN_TYPE | ParserStatus::ALLOW_SUPER;
441     auto methodKind = ir::MethodDefinitionKind::METHOD;
442 
443     if (className != nullptr) {
444         methodKind = ir::MethodDefinitionKind::EXTENSION_METHOD;
445         newStatus |= ParserStatus::IN_EXTENSION_FUNCTION;
446     }
447 
448     if ((modifiers & ir::ModifierFlags::CONSTRUCTOR) != 0) {
449         newStatus = ParserStatus::CONSTRUCTOR_FUNCTION | ParserStatus::ALLOW_SUPER | ParserStatus::ALLOW_SUPER_CALL;
450         methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
451     }
452 
453     if ((modifiers & ir::ModifierFlags::ASYNC) != 0) {
454         newStatus |= ParserStatus::ASYNC_FUNCTION;
455     }
456 
457     if ((modifiers & ir::ModifierFlags::STATIC) == 0) {
458         newStatus |= ParserStatus::ALLOW_THIS_TYPE;
459     }
460 
461     ir::ETSTypeReference *typeAnnotation = nullptr;
462     if (className != nullptr) {
463         auto *typeRefPart = AllocNode<ir::ETSTypeReferencePart>(className, nullptr, nullptr);
464         typeAnnotation = AllocNode<ir::ETSTypeReference>(typeRefPart);
465     }
466 
467     ir::ScriptFunction *func = ParseFunction(newStatus, typeAnnotation);
468     func->SetIdent(methodName);
469     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
470     funcExpr->SetRange(func->Range());
471     func->AddModifier(modifiers);
472 
473     if (typeAnnotation != nullptr) {
474         func->AddFlag(ir::ScriptFunctionFlags::INSTANCE_EXTENSION_METHOD);
475     }
476     auto *method = AllocNode<ir::MethodDefinition>(methodKind, methodName->Clone(Allocator(), nullptr)->AsExpression(),
477                                                    funcExpr, modifiers, Allocator(), false);
478     method->SetRange(funcExpr->Range());
479     return method;
480 }
481 
ParseClassMethod(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd)482 ir::MethodDefinition *ETSParser::ParseClassMethod(ClassElementDescriptor *desc,
483                                                   const ArenaVector<ir::AstNode *> &properties,
484                                                   ir::Expression *propName, lexer::SourcePosition *propEnd)
485 {
486     if (desc->methodKind != ir::MethodDefinitionKind::SET &&
487         (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) {
488         desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
489     }
490 
491     ir::ScriptFunction *func = ParseFunction(desc->newStatus);
492     if (propName->IsIdentifier()) {
493         func->SetIdent(propName->AsIdentifier()->Clone(Allocator(), nullptr));
494     }
495 
496     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
497     funcExpr->SetRange(func->Range());
498 
499     if (desc->methodKind == ir::MethodDefinitionKind::SET) {
500         ValidateClassSetter(desc, properties, propName, func);
501     } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
502         ValidateClassGetter(desc, properties, propName, func);
503     }
504 
505     *propEnd = func->End();
506     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
507     auto *method =
508         AllocNode<ir::MethodDefinition>(desc->methodKind, propName->Clone(Allocator(), nullptr)->AsExpression(),
509                                         funcExpr, desc->modifiers, Allocator(), desc->isComputed);
510     method->SetRange(funcExpr->Range());
511 
512     return method;
513 }
514 
UpdateMemberModifiers(ir::ModifierFlags & memberModifiers,bool & seenStatic)515 void ETSParser::UpdateMemberModifiers(ir::ModifierFlags &memberModifiers, bool &seenStatic)
516 {
517     if (InAmbientContext()) {
518         memberModifiers |= ir::ModifierFlags::DECLARE;
519     }
520 
521     char32_t nextCp = Lexer()->Lookahead();
522     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC && nextCp != lexer::LEX_CHAR_EQUALS &&
523         nextCp != lexer::LEX_CHAR_COLON && nextCp != lexer::LEX_CHAR_LEFT_PAREN &&
524         nextCp != lexer::LEX_CHAR_LESS_THAN) {
525         Lexer()->NextToken();
526         memberModifiers |= ir::ModifierFlags::STATIC;
527         seenStatic = true;
528     } else {
529         seenStatic = false;
530     }
531 
532     if (IsClassFieldModifier(Lexer()->GetToken().KeywordType())) {
533         memberModifiers |= ParseClassFieldModifiers(seenStatic);
534     } else if (IsClassMethodModifier(Lexer()->GetToken().Type())) {
535         memberModifiers |= ParseClassMethodModifiers(seenStatic);
536     }
537 }
538 
ApplyAnnotationsToNode(ir::AstNode * node,ArenaVector<ir::AnnotationUsage * > && annotations,lexer::SourcePosition pos)539 void ETSParser::ApplyAnnotationsToNode(ir::AstNode *node, ArenaVector<ir::AnnotationUsage *> &&annotations,
540                                        lexer::SourcePosition pos)
541 {
542     if (!annotations.empty()) {
543         if (node->IsAbstract() ||
544             (node->IsClassDeclaration() && node->AsClassDeclaration()->Definition()->IsAbstract())) {
545             LogSyntaxError("Annotations are not allowed on an abstract class or methods.", pos);
546         }
547 
548         if (node->IsMethodDefinition()) {
549             node->AsMethodDefinition()->Function()->SetAnnotations(std::move(annotations));
550         } else if (node->IsClassDeclaration()) {
551             node->AsClassDeclaration()->Definition()->SetAnnotations(std::move(annotations));
552         } else if (node->IsFunctionDeclaration()) {
553             node->AsFunctionDeclaration()->SetAnnotations(std::move(annotations));
554         } else {
555             LogSyntaxError("Annotations are not allowed on this type of declaration.", pos);
556         }
557     }
558 }
559 
ParseClassElement(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)560 ir::AstNode *ETSParser::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
561                                           ir::ClassDefinitionModifiers modifiers,
562                                           [[maybe_unused]] ir::ModifierFlags flags)
563 {
564     auto startLoc = Lexer()->GetToken().Start();
565 
566     ArenaVector<ir::AnnotationUsage *> annotations(Allocator()->Adapter());
567     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
568         Lexer()->NextToken();
569         annotations = ParseAnnotations(flags, false);
570     }
571 
572     ir::ModifierFlags memberModifiers = ir::ModifierFlags::NONE;
573     if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0 &&
574         Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXPORT) {
575         Lexer()->NextToken();  // eat exported
576         memberModifiers |= ir::ModifierFlags::EXPORTED;
577     }
578     auto savedPos = Lexer()->Save();  // NOLINT(clang-analyzer-deadcode.DeadStores)
579 
580     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
581         Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
582         return ParseClassStaticBlock();
583     }
584 
585     auto [modifierFlags, isStepToken] = ParseClassMemberAccessModifiers();
586     memberModifiers |= modifierFlags;
587 
588     bool seenStatic = false;
589     UpdateMemberModifiers(memberModifiers, seenStatic);
590 
591     if (!annotations.empty() && (memberModifiers & ir::ModifierFlags::ABSTRACT) != 0) {
592         LogSyntaxError("Annotations cannot be applied to an abstract class or method.", Lexer()->GetToken().Start());
593     }
594 
595     auto savePos = Lexer()->GetToken().Start();
596     switch (Lexer()->GetToken().Type()) {
597         case lexer::TokenType::KEYW_INTERFACE:
598         case lexer::TokenType::KEYW_CLASS:
599         case lexer::TokenType::KEYW_ENUM:
600             return ParseInnerTypeDeclaration(memberModifiers, savedPos, isStepToken, seenStatic);
601         case lexer::TokenType::KEYW_CONSTRUCTOR:
602             return ParseInnerConstructorDeclaration(memberModifiers, startLoc);
603         case lexer::TokenType::KEYW_NAMESPACE:
604             return ParseNamespaceDeclaration(memberModifiers);
605         case lexer::TokenType::KEYW_PUBLIC:
606         case lexer::TokenType::KEYW_PRIVATE:
607         case lexer::TokenType::KEYW_PROTECTED: {
608             LogSyntaxError("Access modifier must precede field and method modifiers.");
609             Lexer()->NextToken();
610             return nullptr;
611         }
612         default: {
613             auto *property = ParseInnerRest(properties, modifiers, memberModifiers, startLoc);
614             ApplyAnnotationsToNode(property, std::move(annotations), savePos);
615             return property;
616         }
617     }
618 }
619 
ParseClassGetterSetterMethod(const ArenaVector<ir::AstNode * > & properties,const ir::ClassDefinitionModifiers modifiers,const ir::ModifierFlags memberModifiers)620 ir::MethodDefinition *ETSParser::ParseClassGetterSetterMethod(const ArenaVector<ir::AstNode *> &properties,
621                                                               const ir::ClassDefinitionModifiers modifiers,
622                                                               const ir::ModifierFlags memberModifiers)
623 {
624     ClassElementDescriptor desc(Allocator());
625     desc.methodKind = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET
626                                                                                       : ir::MethodDefinitionKind::SET;
627     Lexer()->NextToken();  // eat get/set
628     auto *methodName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
629     if (desc.methodKind == ir::MethodDefinitionKind::GET) {
630         methodName->SetAccessor();
631     } else {
632         methodName->SetMutator();
633     }
634 
635     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
636 
637     desc.newStatus = ParserStatus::ALLOW_SUPER;
638     desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U;
639     desc.propStart = Lexer()->GetToken().Start();
640     desc.modifiers = memberModifiers;
641 
642     lexer::SourcePosition propEnd = methodName->End();
643     ir::MethodDefinition *method = ParseClassMethod(&desc, properties, methodName, &propEnd);
644     method->Function()->AddModifier(desc.modifiers);
645     method->SetRange({desc.propStart, propEnd});
646     if (desc.methodKind == ir::MethodDefinitionKind::GET) {
647         method->Function()->AddFlag(ir::ScriptFunctionFlags::GETTER);
648     } else {
649         method->Function()->AddFlag(ir::ScriptFunctionFlags::SETTER);
650     }
651 
652     return method;
653 }
654 
ParseInterfaceGetterSetterMethod(const ir::ModifierFlags modifiers)655 ir::MethodDefinition *ETSParser::ParseInterfaceGetterSetterMethod(const ir::ModifierFlags modifiers)
656 {
657     auto methodKind = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET
658                                                                                       : ir::MethodDefinitionKind::SET;
659     Lexer()->NextToken();  // eat get/set
660     ExpectToken(lexer::TokenType::LITERAL_IDENT, false);
661     ir::MethodDefinition *method = ParseInterfaceMethod(modifiers, methodKind);
662     method->AddModifier(ir::ModifierFlags::PUBLIC);
663     method->SetRange({Lexer()->GetToken().Start(), method->Id()->End()});
664     if (methodKind == ir::MethodDefinitionKind::GET) {
665         method->Id()->SetAccessor();
666         method->Function()->AddFlag(ir::ScriptFunctionFlags::GETTER);
667     } else {
668         method->Id()->SetMutator();
669         method->Function()->AddFlag(ir::ScriptFunctionFlags::SETTER);
670     }
671     method->AddModifier(ir::ModifierFlags::PUBLIC);
672 
673     method->Function()->SetIdent(method->Id()->Clone(Allocator(), nullptr));
674     method->Function()->AddModifier(method->Modifiers());
675 
676     return method;
677 }
678 
ParseInterfaceBody(ir::Identifier * name,bool isStatic)679 ir::TSInterfaceDeclaration *ETSParser::ParseInterfaceBody(ir::Identifier *name, bool isStatic)
680 {
681     GetContext().Status() |= ParserStatus::ALLOW_THIS_TYPE;
682 
683     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
684     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
685         auto options =
686             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE;
687         typeParamDecl = ParseTypeParameterDeclaration(&options);
688     }
689 
690     ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
691     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
692         extends = ParseInterfaceExtendsClause();
693     }
694 
695     lexer::SourcePosition bodyStart = Lexer()->GetToken().Start();
696     auto members = ParseTypeLiteralOrInterface();
697 
698     for (auto &member : members) {
699         if (member->Type() == ir::AstNodeType::CLASS_DECLARATION ||
700             member->Type() == ir::AstNodeType::STRUCT_DECLARATION ||
701             member->Type() == ir::AstNodeType::TS_ENUM_DECLARATION ||
702             member->Type() == ir::AstNodeType::TS_INTERFACE_DECLARATION) {
703             LogSyntaxError(
704                 "Local type declaration (class, struct, interface and enum) support is not yet implemented.");
705         }
706     }
707 
708     auto *body = AllocNode<ir::TSInterfaceBody>(std::move(members));
709     body->SetRange({bodyStart, Lexer()->GetToken().End()});
710 
711     const auto isExternal = IsExternal();
712     auto *interfaceDecl = AllocNode<ir::TSInterfaceDeclaration>(
713         Allocator(), std::move(extends),
714         ir::TSInterfaceDeclaration::ConstructorData {name, typeParamDecl, body, isStatic, isExternal,
715                                                      GetContext().GetLanguage()});
716 
717     Lexer()->NextToken();
718     GetContext().Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
719 
720     return interfaceDecl;
721 }
722 
ParseInterfaceDeclaration(bool isStatic)723 ir::Statement *ETSParser::ParseInterfaceDeclaration(bool isStatic)
724 {
725     lexer::SourcePosition interfaceStart = Lexer()->GetToken().Start();
726     Lexer()->NextToken();  // eat interface keyword
727 
728     auto *id = ExpectIdentifier(false, true);
729 
730     auto *declNode = ParseInterfaceBody(id, isStatic);
731 
732     declNode->SetRange({interfaceStart, Lexer()->GetToken().End()});
733     return declNode;
734 }
735 
736 // NOLINTNEXTLINE(google-default-arguments)
ParseClassDefinition(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)737 ir::ClassDefinition *ETSParser::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
738 {
739     Lexer()->NextToken();
740 
741     ir::Identifier *identNode = ParseClassIdent(modifiers);
742     if (identNode == nullptr && Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
743         Lexer()->NextToken();  // Error processing.
744     }
745 
746     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
747     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
748         auto options =
749             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE;
750         typeParamDecl = ParseTypeParameterDeclaration(&options);
751     }
752 
753     // Parse SuperClass
754     auto [superClass, superTypeParams] = ParseSuperClass();
755 
756     if (superClass != nullptr) {
757         modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
758         GetContext().Status() |= ParserStatus::ALLOW_SUPER;
759     }
760 
761     if (InAmbientContext()) {
762         flags |= ir::ModifierFlags::DECLARE;
763     }
764 
765     // Parse implements clause
766     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
767     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
768         Lexer()->NextToken();
769         implements = ParseClassImplementClause();
770     }
771 
772     ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
773     ir::MethodDefinition *ctor = nullptr;
774     lexer::SourceRange bodyRange;
775 
776     if ((flags & ir::ModifierFlags::DECLARE) != 0U &&
777         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
778         // without ClassBody
779         bodyRange = lexer::SourceRange {Lexer()->GetToken().Start(), Lexer()->GetToken().Start()};
780     } else {
781         ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
782 
783         // Parse ClassBody
784         std::tie(ctor, properties, bodyRange) = ParseClassBody(modifiers, flags);
785     }
786 
787     auto *classDefinition = AllocNode<ir::ClassDefinition>(
788         util::StringView(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass,
789         std::move(properties), modifiers, flags, GetContext().GetLanguage());
790 
791     classDefinition->SetRange(bodyRange);
792 
793     GetContext().Status() &= ~ParserStatus::ALLOW_SUPER;
794 
795     return classDefinition;
796 }
797 
ParseInterfaceMethodModifiers()798 ir::ModifierFlags ETSParser::ParseInterfaceMethodModifiers()
799 {
800     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
801         return ir::ModifierFlags::PUBLIC;
802     }
803 
804     if ((GetContext().Status() & ParserStatus::FUNCTION) != 0) {
805         if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_PRIVATE) {
806             LogSyntaxError("Local interface declaration members can not have access modifiers",
807                            Lexer()->GetToken().Start());
808         }
809     }
810 
811     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_PRIVATE) {
812         LogSyntaxError("Unexpected token, expected 'private' or identifier");
813     }
814 
815     Lexer()->NextToken();
816     return ir::ModifierFlags::PRIVATE;
817 }
818 
ParseInterfaceField()819 ir::ClassProperty *ETSParser::ParseInterfaceField()
820 {
821     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
822     auto *name = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
823     name->SetRange(Lexer()->GetToken().Loc());
824     Lexer()->NextToken();
825     bool optionalField = false;
826 
827     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
828         Lexer()->NextToken();  // eat '?'
829         optionalField = true;
830     }
831 
832     ir::TypeNode *typeAnnotation = nullptr;
833     if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_COLON)) {
834         // interfaces3.sts
835         LogSyntaxError("Interface fields must have type annotation.");
836 
837         Lexer()->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_COLON);
838         Lexer()->NextToken();  // additional check
839     }
840     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
841     typeAnnotation = ParseTypeAnnotation(&options);
842     if (typeAnnotation == nullptr) {  // Error processing.
843         return nullptr;
844     }
845 
846     name->SetTsTypeAnnotation(typeAnnotation);
847     typeAnnotation->SetParent(name);
848 
849     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) {
850         LogSyntaxError("Initializers are not allowed on interface properties.");
851         Lexer()->NextToken();  // Error processing: eat '='.
852     }
853 
854     ir::ModifierFlags fieldModifiers = ir::ModifierFlags::PUBLIC;
855 
856     if (InAmbientContext()) {
857         fieldModifiers |= ir::ModifierFlags::DECLARE;
858     }
859 
860     auto *field = AllocNode<ir::ClassProperty>(name, nullptr, typeAnnotation->Clone(Allocator(), nullptr),
861                                                fieldModifiers, Allocator(), false);
862     if (optionalField) {
863         field->AddModifier(ir::ModifierFlags::OPTIONAL);
864     }
865     field->SetEnd(Lexer()->GetToken().End());
866 
867     return field;
868 }
869 
GetEndLoc(ir::BlockStatement * body,ir::ScriptFunction * func,lexer::Lexer * lexer)870 static lexer::SourcePosition GetEndLoc(ir::BlockStatement *body, ir::ScriptFunction *func, lexer::Lexer *lexer)
871 {
872     if (body != nullptr) {
873         return body->End();
874     }
875 
876     if (func->ReturnTypeAnnotation() != nullptr) {
877         return func->ReturnTypeAnnotation()->End();
878     }
879 
880     if (!func->Params().empty()) {
881         return func->Params().back()->End();
882     }
883 
884     return lexer->GetToken().End();
885 }
886 
ParseInterfaceMethod(ir::ModifierFlags flags,ir::MethodDefinitionKind methodKind)887 ir::MethodDefinition *ETSParser::ParseInterfaceMethod(ir::ModifierFlags flags, ir::MethodDefinitionKind methodKind)
888 {
889     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
890         LogSyntaxError({"Expected method name, got '", lexer::TokenToString(Lexer()->GetToken().Type()), "'."});
891         return nullptr;
892     }
893 
894     auto *name = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
895     name->SetRange(Lexer()->GetToken().Loc());
896     Lexer()->NextToken();
897 
898     FunctionContext functionContext(this, ParserStatus::FUNCTION);
899 
900     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
901 
902     auto [signature, throwMarker] = ParseFunctionSignature(ParserStatus::NEED_RETURN_TYPE);
903 
904     ir::BlockStatement *body = nullptr;
905 
906     bool isDeclare = InAmbientContext();
907     if (isDeclare) {
908         flags |= ir::ModifierFlags::DECLARE;
909     }
910 
911     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
912         if (methodKind == ir::MethodDefinitionKind::SET || methodKind == ir::MethodDefinitionKind::GET) {
913             LogSyntaxError("Getter and setter methods must be abstracts in the interface body", startLoc);
914         }
915         body = ParseBlockStatement();
916     } else if ((flags & (ir::ModifierFlags::PRIVATE)) != 0 && !isDeclare) {
917         LogSyntaxError("Private interface methods must have body", startLoc);
918     }
919 
920     functionContext.AddFlag(throwMarker);
921 
922     if ((GetContext().Status() & ParserStatus::FUNCTION_HAS_RETURN_STATEMENT) != 0) {
923         functionContext.AddFlag(ir::ScriptFunctionFlags::HAS_RETURN);
924         GetContext().Status() ^= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT;
925     }
926 
927     auto *func = AllocNode<ir::ScriptFunction>(
928         Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(signature), functionContext.Flags(), flags,
929                                                              GetContext().GetLanguage()});
930 
931     if ((flags & ir::ModifierFlags::STATIC) == 0 && body == nullptr) {
932         func->AddModifier(ir::ModifierFlags::ABSTRACT);
933     }
934     ValidateGetterSetter(methodKind, func->Params().size());
935     func->SetRange({startLoc, GetEndLoc(body, func, Lexer())});
936 
937     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
938     funcExpr->SetRange(func->Range());
939     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
940 
941     func->SetIdent(name);
942     auto *method = AllocNode<ir::MethodDefinition>(methodKind, name->Clone(Allocator(), nullptr)->AsExpression(),
943                                                    funcExpr, flags, Allocator(), false);
944     method->SetRange(funcExpr->Range());
945 
946     ConsumeSemicolon(method);
947 
948     return method;
949 }
950 
ParseTypeLiteralOrInterfaceMember()951 ir::AstNode *ETSParser::ParseTypeLiteralOrInterfaceMember()
952 {
953     auto startLoc = Lexer()->GetToken().Start();
954 
955     if (Lexer()->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN && Lexer()->Lookahead() != lexer::LEX_CHAR_LESS_THAN &&
956         (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ||
957          Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_SET)) {
958         return ParseInterfaceGetterSetterMethod(ir::ModifierFlags::PUBLIC);
959     }
960 
961     if (Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_READONLY)) {
962         char32_t nextCp = Lexer()->Lookahead();
963         if (nextCp == lexer::LEX_CHAR_LEFT_PAREN || nextCp == lexer::LEX_CHAR_LESS_THAN) {
964             LogSyntaxError("Modifier 'readonly' cannot be applied to an interface method", startLoc);
965             return nullptr;  // Error processing.
966         }
967         auto *field = ParseInterfaceField();
968         field->SetStart(startLoc);
969         field->AddModifier(ir::ModifierFlags::READONLY);
970         return field;
971     }
972 
973     ir::ModifierFlags modfiers = ParseInterfaceMethodModifiers();
974     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
975         LogSyntaxError("Identifier expected");
976         return nullptr;  // Error processing.
977     }
978 
979     char32_t nextCp = Lexer()->Lookahead();
980     if (nextCp == lexer::LEX_CHAR_LEFT_PAREN || nextCp == lexer::LEX_CHAR_LESS_THAN) {
981         auto *method = ParseInterfaceMethod(modfiers, ir::MethodDefinitionKind::METHOD);
982         method->SetStart(startLoc);
983         return method;
984     }
985 
986     auto *field = ParseInterfaceField();
987     if (field != nullptr) {
988         field->SetStart(startLoc);
989         return field;
990     }
991 
992     return ParseTypeDeclaration(true);
993 }
994 
CheckClassElement(ir::AstNode * property,ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties)995 bool ETSParser::CheckClassElement(ir::AstNode *property, [[maybe_unused]] ir::MethodDefinition *&ctor,
996                                   [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
997 {
998     if (property->IsClassStaticBlock()) {
999         if (std::any_of(properties.cbegin(), properties.cend(),
1000                         [](const auto *prop) { return prop->IsClassStaticBlock(); })) {
1001             LogSyntaxError("Only one static block is allowed", property->Start());
1002         }
1003 
1004         auto *id = AllocNode<ir::Identifier>(compiler::Signatures::CCTOR, Allocator());
1005         property->AsClassStaticBlock()->Function()->SetIdent(id);
1006     }
1007 
1008     if (property->IsTSInterfaceBody()) {
1009         return CheckClassElementInterfaceBody(property, properties);
1010     }
1011 
1012     if (!property->IsMethodDefinition()) {
1013         return false;
1014     }
1015 
1016     auto const *const method = property->AsMethodDefinition();
1017     auto const *const function = method->Function();
1018 
1019     //  Check the special '$_get' and '$_set' methods using for object's index access
1020     if (method->Kind() == ir::MethodDefinitionKind::METHOD) {
1021         CheckPredefinedMethods(function, property->Start());
1022     }
1023 
1024     return false;  // resolve overloads later on scopes stage
1025 }
1026 
CheckPredefinedMethods(ir::ScriptFunction const * function,const lexer::SourcePosition & position)1027 void ETSParser::CheckPredefinedMethods(ir::ScriptFunction const *function, const lexer::SourcePosition &position)
1028 {
1029     auto const name = function->Id()->Name();
1030 
1031     auto const checkAsynchronous = [this, function, &name, &position]() -> void {
1032         if (function->IsAsyncFunc()) {
1033             LogSyntaxError({ir::PREDEFINED_METHOD, name.Utf8(), "' cannot be asynchronous."}, position);
1034         }
1035     };
1036 
1037     if (name.Is(compiler::Signatures::GET_INDEX_METHOD)) {
1038         checkAsynchronous();
1039 
1040         bool isValid = function->Params().size() == 1U;
1041         if (isValid) {
1042             auto const *const param = function->Params()[0]->AsETSParameterExpression();
1043             isValid = !param->IsDefault() && !param->IsRestParameter();
1044         }
1045 
1046         if (!isValid) {
1047             LogSyntaxError({ir::PREDEFINED_METHOD, name.Utf8(), "' should have exactly one required parameter."},
1048                            position);
1049         }
1050     } else if (name.Is(compiler::Signatures::SET_INDEX_METHOD)) {
1051         checkAsynchronous();
1052 
1053         bool isValid = function->Params().size() == 2U;
1054         if (isValid) {
1055             auto const *const param1 = function->Params()[0]->AsETSParameterExpression();
1056             auto const *const param2 = function->Params()[1]->AsETSParameterExpression();
1057             isValid = !param1->IsDefault() && !param1->IsRestParameter() && !param2->IsDefault() &&
1058                       !param2->IsRestParameter();
1059         }
1060 
1061         if (!isValid) {
1062             LogSyntaxError({ir::PREDEFINED_METHOD, name.Utf8(), "' should have exactly two required parameters."},
1063                            position);
1064         }
1065     } else if (name.Is(compiler::Signatures::ITERATOR_METHOD)) {
1066         checkAsynchronous();
1067 
1068         if (!function->Params().empty()) {
1069             LogSyntaxError({ir::PREDEFINED_METHOD, name.Utf8(), "' should not have parameters."}, position);
1070         }
1071     }
1072 }
1073 
CreateImplicitConstructor(ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags,const lexer::SourcePosition & startLoc)1074 void ETSParser::CreateImplicitConstructor([[maybe_unused]] ir::MethodDefinition *&ctor,
1075                                           ArenaVector<ir::AstNode *> &properties,
1076                                           [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
1077                                           ir::ModifierFlags flags, const lexer::SourcePosition &startLoc)
1078 {
1079     if (std::any_of(properties.cbegin(), properties.cend(), [](ir::AstNode *prop) {
1080             return prop->IsMethodDefinition() && prop->AsMethodDefinition()->IsConstructor();
1081         })) {
1082         return;
1083     }
1084 
1085     if ((modifiers & ir::ClassDefinitionModifiers::ANONYMOUS) != 0) {
1086         return;
1087     }
1088 
1089     auto *methodDef = BuildImplicitConstructor(ir::ClassDefinitionModifiers::SET_CTOR_ID, startLoc);
1090     if ((flags & ir::ModifierFlags::DECLARE) != 0) {
1091         methodDef->Function()->AddFlag(ir::ScriptFunctionFlags::EXTERNAL);
1092     }
1093     properties.push_back(methodDef);
1094 }
1095 
ParseMemberModifiers()1096 std::pair<ir::ModifierFlags, lexer::SourcePosition> ETSParser::ParseMemberModifiers()
1097 {
1098     auto memberModifiers = ir::ModifierFlags::STATIC | ir::ModifierFlags::PUBLIC;
1099 
1100     if (Lexer()->TryEatTokenType(lexer::TokenType::KEYW_EXPORT)) {
1101         const auto savedPos = Lexer()->Save();
1102         if (Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_DEFAULT)) {
1103             memberModifiers |= ir::ModifierFlags::DEFAULT_EXPORT;
1104         } else if (Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_TYPE)) {
1105             if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1106                 Lexer()->Rewind(savedPos);
1107             }
1108             memberModifiers |= ir::ModifierFlags::EXPORT_TYPE;
1109         } else {
1110             memberModifiers |= ir::ModifierFlags::EXPORT;
1111         }
1112     }
1113 
1114     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1115 
1116     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
1117         CheckDeclare();
1118         memberModifiers |= ir::ModifierFlags::DECLARE;
1119     }
1120     const auto tokenType = Lexer()->GetToken().KeywordType();
1121     if (tokenType == lexer::TokenType::KEYW_ASYNC || tokenType == lexer::TokenType::KEYW_NATIVE) {
1122         bool isAsync = tokenType == lexer::TokenType::KEYW_ASYNC;
1123 
1124         if (isAsync) {
1125             memberModifiers |= ir::ModifierFlags::ASYNC;
1126         } else {
1127             memberModifiers |= ir::ModifierFlags::NATIVE;
1128         }
1129         Lexer()->NextToken();
1130 
1131         if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION) {
1132             // async_function_bas.sts
1133             LogSyntaxError({isAsync ? "'async'" : "'native'", " flags must be used for functions only at top-level."});
1134 
1135             Lexer()->GetToken().SetTokenType(lexer::TokenType::KEYW_FUNCTION);
1136         }
1137     }
1138     return std::make_pair(memberModifiers, startLoc);
1139 }
1140 
1141 }  // namespace ark::es2panda::parser
1142