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