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
102namespace ark::es2panda::parser {
103class FunctionContext;
104
105using namespace std::literals::string_literals;
106
107static 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
113ir::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            ThrowSyntaxError("Keyword must not contain escaped characters");
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            ThrowSyntaxError("Duplicated modifier is not allowed");
145        }
146
147        Lexer()->NextToken();
148        flags |= currentFlag;
149    }
150
151    return flags;
152}
153
154std::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
162ir::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
176ir::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
184static 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
190std::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        ThrowSyntaxError("Keyword must not contain escaped characters");
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        ThrowSyntaxError("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
245static bool IsClassFieldModifier(lexer::TokenType type)
246{
247    return type == lexer::TokenType::KEYW_STATIC || type == lexer::TokenType::KEYW_READONLY;
248}
249
250ir::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            ThrowSyntaxError("Keyword must not contain escaped characters");
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            ThrowSyntaxError("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
292bool 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)
312ir::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
353ir::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            ThrowSyntaxError("Keyword must not contain escaped characters");
368        }
369
370        currentFlag = ParseClassMethodModifierFlag();
371        if ((flags & currentFlag) != 0) {
372            ThrowSyntaxError("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                ThrowSyntaxError("Native method cannot be async");
380            } else if ((flags & ir::ModifierFlags::ABSTRACT) != 0) {
381                ThrowSyntaxError("Abstract method cannot be async");
382            }
383        }
384    }
385
386    return flags;
387}
388
389// NOLINTNEXTLINE(google-default-arguments)
390void 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        ThrowSyntaxError("Field type annotation expected");
414    }
415
416    bool isDeclare = (modifiers & ir::ModifierFlags::DECLARE) != 0;
417
418    if (isDeclare && initializer != nullptr) {
419        ThrowSyntaxError("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
437ir::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::ScriptFunction *func = ParseFunction(newStatus, className);
462    func->SetIdent(methodName);
463    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
464    funcExpr->SetRange(func->Range());
465    func->AddModifier(modifiers);
466
467    if (className != nullptr) {
468        func->AddFlag(ir::ScriptFunctionFlags::INSTANCE_EXTENSION_METHOD);
469    }
470    auto *method = AllocNode<ir::MethodDefinition>(methodKind, methodName->Clone(Allocator(), nullptr)->AsExpression(),
471                                                   funcExpr, modifiers, Allocator(), false);
472    method->SetRange(funcExpr->Range());
473    func->Id()->SetReference();
474    return method;
475}
476
477ir::MethodDefinition *ETSParser::ParseClassMethod(ClassElementDescriptor *desc,
478                                                  const ArenaVector<ir::AstNode *> &properties,
479                                                  ir::Expression *propName, lexer::SourcePosition *propEnd)
480{
481    if (desc->methodKind != ir::MethodDefinitionKind::SET &&
482        (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) {
483        desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
484    }
485
486    ir::ScriptFunction *func = ParseFunction(desc->newStatus);
487    if (propName->IsIdentifier()) {
488        func->SetIdent(propName->AsIdentifier()->Clone(Allocator(), nullptr));
489        func->Id()->SetReference();
490    }
491
492    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
493    funcExpr->SetRange(func->Range());
494
495    if (desc->methodKind == ir::MethodDefinitionKind::SET) {
496        ValidateClassSetter(desc, properties, propName, func);
497    } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
498        ValidateClassGetter(desc, properties, propName, func);
499    }
500
501    *propEnd = func->End();
502    func->AddFlag(ir::ScriptFunctionFlags::METHOD);
503    auto *method =
504        AllocNode<ir::MethodDefinition>(desc->methodKind, propName->Clone(Allocator(), nullptr)->AsExpression(),
505                                        funcExpr, desc->modifiers, Allocator(), desc->isComputed);
506    method->SetRange(funcExpr->Range());
507
508    return method;
509}
510
511bool IsParseClassElementSeenStatic(lexer::Lexer *lexer)
512{
513    char32_t nextCp = lexer->Lookahead();
514    if (lexer->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC && nextCp != lexer::LEX_CHAR_EQUALS &&
515        nextCp != lexer::LEX_CHAR_COLON && nextCp != lexer::LEX_CHAR_LEFT_PAREN &&
516        nextCp != lexer::LEX_CHAR_LESS_THAN) {
517        lexer->NextToken();
518        return true;
519    }
520    return false;
521}
522
523ir::AstNode *ETSParser::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
524                                          ir::ClassDefinitionModifiers modifiers,
525                                          [[maybe_unused]] ir::ModifierFlags flags)
526{
527    auto startLoc = Lexer()->GetToken().Start();
528    ir::ModifierFlags memberModifiers = ir::ModifierFlags::NONE;
529    if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0 &&
530        Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXPORT) {
531        Lexer()->NextToken();  // eat exported
532        memberModifiers |= ir::ModifierFlags::EXPORTED;
533    }
534    auto savedPos = Lexer()->Save();  // NOLINT(clang-analyzer-deadcode.DeadStores)
535
536    if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
537        Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
538        return ParseClassStaticBlock();
539    }
540
541    auto [modifierFlags, isStepToken] = ParseClassMemberAccessModifiers();
542    memberModifiers |= modifierFlags;
543
544    if (InAmbientContext()) {
545        memberModifiers |= ir::ModifierFlags::DECLARE;
546    }
547
548    bool seenStatic = IsParseClassElementSeenStatic(Lexer());
549    if (seenStatic) {
550        memberModifiers |= ir::ModifierFlags::STATIC;
551    }
552
553    if (IsClassFieldModifier(Lexer()->GetToken().KeywordType())) {
554        memberModifiers |= ParseClassFieldModifiers(seenStatic);
555    } else if (IsClassMethodModifier(Lexer()->GetToken().Type())) {
556        memberModifiers |= ParseClassMethodModifiers(seenStatic);
557    }
558
559    switch (Lexer()->GetToken().Type()) {
560        case lexer::TokenType::KEYW_INTERFACE:
561        case lexer::TokenType::KEYW_CLASS:
562        case lexer::TokenType::KEYW_ENUM: {
563            return ParseInnerTypeDeclaration(memberModifiers, savedPos, isStepToken, seenStatic);
564        }
565        case lexer::TokenType::KEYW_CONSTRUCTOR: {
566            return ParseInnerConstructorDeclaration(memberModifiers, startLoc);
567        }
568        case lexer::TokenType::KEYW_NAMESPACE: {
569            return ParseNamespaceDeclaration(memberModifiers);
570        }
571        case lexer::TokenType::KEYW_PUBLIC:
572        case lexer::TokenType::KEYW_PRIVATE:
573        case lexer::TokenType::KEYW_PROTECTED: {
574            ThrowSyntaxError("Access modifier must precede field and method modifiers.");
575        }
576        default: {
577            return ParseInnerRest(properties, modifiers, memberModifiers, startLoc);
578        }
579    }
580}
581
582ir::MethodDefinition *ETSParser::ParseClassGetterSetterMethod(const ArenaVector<ir::AstNode *> &properties,
583                                                              const ir::ClassDefinitionModifiers modifiers,
584                                                              const ir::ModifierFlags memberModifiers)
585{
586    ClassElementDescriptor desc(Allocator());
587    desc.methodKind = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET
588                                                                                      : ir::MethodDefinitionKind::SET;
589    Lexer()->NextToken();  // eat get/set
590    auto *methodName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
591    if (desc.methodKind == ir::MethodDefinitionKind::GET) {
592        methodName->SetAccessor();
593    } else {
594        methodName->SetMutator();
595    }
596
597    Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
598
599    desc.newStatus = ParserStatus::ALLOW_SUPER;
600    desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U;
601    desc.propStart = Lexer()->GetToken().Start();
602    desc.modifiers = memberModifiers;
603
604    lexer::SourcePosition propEnd = methodName->End();
605    ir::MethodDefinition *method = ParseClassMethod(&desc, properties, methodName, &propEnd);
606    method->Function()->AddModifier(desc.modifiers);
607    method->SetRange({desc.propStart, propEnd});
608    if (desc.methodKind == ir::MethodDefinitionKind::GET) {
609        method->Function()->AddFlag(ir::ScriptFunctionFlags::GETTER);
610    } else {
611        method->Function()->AddFlag(ir::ScriptFunctionFlags::SETTER);
612    }
613
614    return method;
615}
616
617ir::MethodDefinition *ETSParser::ParseInterfaceGetterSetterMethod(const ir::ModifierFlags modifiers)
618{
619    auto methodKind = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET
620                                                                                      : ir::MethodDefinitionKind::SET;
621    Lexer()->NextToken();  // eat get/set
622    ExpectToken(lexer::TokenType::LITERAL_IDENT, false);
623    ir::MethodDefinition *method = ParseInterfaceMethod(modifiers, methodKind);
624    method->AddModifier(ir::ModifierFlags::PUBLIC);
625    method->SetRange({Lexer()->GetToken().Start(), method->Id()->End()});
626    if (methodKind == ir::MethodDefinitionKind::GET) {
627        method->Id()->SetAccessor();
628        method->Function()->AddFlag(ir::ScriptFunctionFlags::GETTER);
629    } else {
630        method->Id()->SetMutator();
631        method->Function()->AddFlag(ir::ScriptFunctionFlags::SETTER);
632    }
633    method->AddModifier(ir::ModifierFlags::PUBLIC);
634
635    method->Function()->SetIdent(method->Id()->Clone(Allocator(), nullptr));
636    method->Function()->AddModifier(method->Modifiers());
637
638    return method;
639}
640
641ir::TSInterfaceDeclaration *ETSParser::ParseInterfaceBody(ir::Identifier *name, bool isStatic)
642{
643    GetContext().Status() |= ParserStatus::ALLOW_THIS_TYPE;
644
645    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
646    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
647        auto options =
648            TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE;
649        typeParamDecl = ParseTypeParameterDeclaration(&options);
650    }
651
652    ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
653    if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
654        extends = ParseInterfaceExtendsClause();
655    }
656
657    lexer::SourcePosition bodyStart = Lexer()->GetToken().Start();
658    auto members = ParseTypeLiteralOrInterface();
659
660    for (auto &member : members) {
661        if (member->Type() == ir::AstNodeType::CLASS_DECLARATION ||
662            member->Type() == ir::AstNodeType::STRUCT_DECLARATION ||
663            member->Type() == ir::AstNodeType::TS_ENUM_DECLARATION ||
664            member->Type() == ir::AstNodeType::TS_INTERFACE_DECLARATION) {
665            ThrowSyntaxError(
666                "Local type declaration (class, struct, interface and enum) support is not yet implemented.");
667        }
668    }
669
670    auto *body = AllocNode<ir::TSInterfaceBody>(std::move(members));
671    body->SetRange({bodyStart, Lexer()->GetToken().End()});
672
673    const auto isExternal = IsExternal();
674    auto *interfaceDecl = AllocNode<ir::TSInterfaceDeclaration>(
675        Allocator(), std::move(extends),
676        ir::TSInterfaceDeclaration::ConstructorData {name, typeParamDecl, body, isStatic, isExternal,
677                                                     GetContext().GetLanguage()});
678
679    Lexer()->NextToken();
680    GetContext().Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
681
682    return interfaceDecl;
683}
684
685ir::Statement *ETSParser::ParseInterfaceDeclaration(bool isStatic)
686{
687    lexer::SourcePosition interfaceStart = Lexer()->GetToken().Start();
688    Lexer()->NextToken();  // eat interface keyword
689
690    auto *id = ExpectIdentifier(false, true);
691
692    auto *declNode = ParseInterfaceBody(id, isStatic);
693
694    declNode->SetRange({interfaceStart, Lexer()->GetToken().End()});
695    return declNode;
696}
697
698// NOLINTNEXTLINE(google-default-arguments)
699ir::ClassDefinition *ETSParser::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
700{
701    Lexer()->NextToken();
702
703    ir::Identifier *identNode = ParseClassIdent(modifiers);
704    if (identNode == nullptr && Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
705        Lexer()->NextToken();  // Error processing.
706    }
707
708    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
709    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
710        auto options =
711            TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE;
712        typeParamDecl = ParseTypeParameterDeclaration(&options);
713    }
714
715    // Parse SuperClass
716    auto [superClass, superTypeParams] = ParseSuperClass();
717
718    if (superClass != nullptr) {
719        modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
720        GetContext().Status() |= ParserStatus::ALLOW_SUPER;
721    }
722
723    if (InAmbientContext()) {
724        flags |= ir::ModifierFlags::DECLARE;
725    }
726
727    // Parse implements clause
728    ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
729    if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
730        Lexer()->NextToken();
731        implements = ParseClassImplementClause();
732    }
733
734    ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
735    ir::MethodDefinition *ctor = nullptr;
736    lexer::SourceRange bodyRange;
737
738    if ((flags & ir::ModifierFlags::DECLARE) != 0U &&
739        Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
740        // without ClassBody
741        bodyRange = lexer::SourceRange {Lexer()->GetToken().Start(), Lexer()->GetToken().Start()};
742    } else {
743        ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
744
745        // Parse ClassBody
746        std::tie(ctor, properties, bodyRange) = ParseClassBody(modifiers, flags);
747    }
748
749    auto *classDefinition = AllocNode<ir::ClassDefinition>(
750        util::StringView(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass,
751        std::move(properties), modifiers, flags, GetContext().GetLanguage());
752
753    classDefinition->SetRange(bodyRange);
754
755    GetContext().Status() &= ~ParserStatus::ALLOW_SUPER;
756
757    return classDefinition;
758}
759
760static bool IsInterfaceMethodModifier(lexer::TokenType type)
761{
762    // NOTE (psiket) Rewrite this
763    return type == lexer::TokenType::KEYW_STATIC || type == lexer::TokenType::KEYW_PRIVATE ||
764           type == lexer::TokenType::KEYW_PROTECTED || type == lexer::TokenType::KEYW_PUBLIC;
765}
766
767ir::ModifierFlags ETSParser::ParseInterfaceMethodModifiers()
768{
769    ir::ModifierFlags flags = ir::ModifierFlags::NONE;
770
771    while (IsInterfaceMethodModifier(Lexer()->GetToken().Type())) {
772        ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE;
773
774        if ((GetContext().Status() & ParserStatus::FUNCTION) != 0) {
775            if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_PUBLIC ||
776                Lexer()->GetToken().Type() == lexer::TokenType::KEYW_PROTECTED ||
777                Lexer()->GetToken().Type() == lexer::TokenType::KEYW_PRIVATE) {
778                ThrowSyntaxError("Local interface declaration members can not have access modifies",
779                                 Lexer()->GetToken().Start());
780            }
781        } else if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_PUBLIC ||
782                   Lexer()->GetToken().Type() == lexer::TokenType::KEYW_PROTECTED) {
783            break;
784        }
785        switch (Lexer()->GetToken().Type()) {
786            case lexer::TokenType::KEYW_STATIC: {
787                currentFlag = ir::ModifierFlags::STATIC;
788                break;
789            }
790            case lexer::TokenType::KEYW_PRIVATE: {
791                currentFlag = ir::ModifierFlags::PRIVATE;
792                break;
793            }
794            default: {
795                UNREACHABLE();
796            }
797        }
798
799        char32_t nextCp = Lexer()->Lookahead();
800        if (nextCp == lexer::LEX_CHAR_COLON || nextCp == lexer::LEX_CHAR_LEFT_PAREN ||
801            nextCp == lexer::LEX_CHAR_EQUALS) {
802            break;
803        }
804
805        if ((flags & currentFlag) != 0) {
806            ThrowSyntaxError("Duplicated modifier is not allowed");
807        }
808
809        Lexer()->NextToken();
810        flags |= currentFlag;
811    }
812
813    return flags;
814}
815
816ir::ClassProperty *ETSParser::ParseInterfaceField()
817{
818    ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
819    auto *name = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
820    name->SetRange(Lexer()->GetToken().Loc());
821    Lexer()->NextToken();
822    bool optionalField = false;
823
824    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
825        Lexer()->NextToken();  // eat '?'
826        optionalField = true;
827    }
828
829    ir::TypeNode *typeAnnotation = nullptr;
830    if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_COLON)) {
831        ThrowSyntaxError("Interface fields must have type annotation.");
832    }
833    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
834    typeAnnotation = ParseTypeAnnotation(&options);
835    if (typeAnnotation == nullptr) {  // Error processing.
836        return nullptr;
837    }
838
839    name->SetTsTypeAnnotation(typeAnnotation);
840    typeAnnotation->SetParent(name);
841
842    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) {
843        ThrowSyntaxError("Initializers are not allowed on interface properties.");
844    }
845
846    ir::ModifierFlags fieldModifiers = ir::ModifierFlags::PUBLIC;
847
848    if (InAmbientContext()) {
849        fieldModifiers |= ir::ModifierFlags::DECLARE;
850    }
851
852    auto *field = AllocNode<ir::ClassProperty>(name, nullptr, typeAnnotation->Clone(Allocator(), nullptr),
853                                               fieldModifiers, Allocator(), false);
854    if (optionalField) {
855        field->AddModifier(ir::ModifierFlags::OPTIONAL);
856    }
857    field->SetEnd(Lexer()->GetToken().End());
858
859    return field;
860}
861
862ir::MethodDefinition *ETSParser::ParseInterfaceMethod(ir::ModifierFlags flags, ir::MethodDefinitionKind methodKind)
863{
864    ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
865    auto *name = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
866    name->SetRange(Lexer()->GetToken().Loc());
867    Lexer()->NextToken();
868
869    FunctionContext functionContext(this, ParserStatus::FUNCTION);
870
871    lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
872
873    auto [signature, throwMarker] = ParseFunctionSignature(ParserStatus::NEED_RETURN_TYPE);
874
875    ir::BlockStatement *body = nullptr;
876
877    bool isDeclare = InAmbientContext();
878    if (isDeclare) {
879        flags |= ir::ModifierFlags::DECLARE;
880    }
881
882    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
883        if (methodKind == ir::MethodDefinitionKind::SET || methodKind == ir::MethodDefinitionKind::GET) {
884            ThrowSyntaxError("Getter and setter methods must be abstracts in the interface body", startLoc);
885        }
886        body = ParseBlockStatement();
887    } else if ((flags & (ir::ModifierFlags::PRIVATE | ir::ModifierFlags::STATIC)) != 0 && !isDeclare) {
888        ThrowSyntaxError("Private or static interface methods must have body", startLoc);
889    }
890
891    functionContext.AddFlag(throwMarker);
892
893    if ((GetContext().Status() & ParserStatus::FUNCTION_HAS_RETURN_STATEMENT) != 0) {
894        functionContext.AddFlag(ir::ScriptFunctionFlags::HAS_RETURN);
895        GetContext().Status() ^= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT;
896    }
897
898    auto *func = AllocNode<ir::ScriptFunction>(
899        Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(signature), functionContext.Flags(), flags,
900                                                             true, GetContext().GetLanguage()});
901
902    if ((flags & ir::ModifierFlags::STATIC) == 0 && body == nullptr) {
903        func->AddModifier(ir::ModifierFlags::ABSTRACT);
904    }
905    func->SetRange({startLoc, body != nullptr                           ? body->End()
906                              : func->ReturnTypeAnnotation() != nullptr ? func->ReturnTypeAnnotation()->End()
907                              : func->Params().empty()                  ? Lexer()->GetToken().End()
908                                                                        : (*func->Params().end())->End()});
909
910    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
911    funcExpr->SetRange(func->Range());
912    func->AddFlag(ir::ScriptFunctionFlags::METHOD);
913
914    func->SetIdent(name);
915    auto *method = AllocNode<ir::MethodDefinition>(methodKind, name->Clone(Allocator(), nullptr)->AsExpression(),
916                                                   funcExpr, flags, Allocator(), false);
917    method->SetRange(funcExpr->Range());
918
919    func->Id()->SetReference();
920
921    ConsumeSemicolon(method);
922
923    return method;
924}
925
926ir::AstNode *ETSParser::ParseTypeLiteralOrInterfaceMember()
927{
928    auto startLoc = Lexer()->GetToken().Start();
929    ir::ModifierFlags methodFlags = ParseInterfaceMethodModifiers();
930    if (methodFlags != ir::ModifierFlags::NONE) {
931        if ((methodFlags & ir::ModifierFlags::PRIVATE) == 0) {
932            methodFlags |= ir::ModifierFlags::PUBLIC;
933        }
934
935        auto *method = ParseInterfaceMethod(methodFlags, ir::MethodDefinitionKind::METHOD);
936        method->SetStart(startLoc);
937        return method;
938    }
939
940    if (Lexer()->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN && Lexer()->Lookahead() != lexer::LEX_CHAR_LESS_THAN &&
941        (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ||
942         Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_SET)) {
943        return ParseInterfaceGetterSetterMethod(methodFlags);
944    }
945
946    if (Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_READONLY)) {
947        auto *field = ParseInterfaceField();
948        field->SetStart(startLoc);
949        field->AddModifier(ir::ModifierFlags::READONLY);
950        return field;
951    }
952
953    if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
954        char32_t nextCp = Lexer()->Lookahead();
955        if (nextCp == lexer::LEX_CHAR_LEFT_PAREN || nextCp == lexer::LEX_CHAR_LESS_THAN) {
956            auto *method = ParseInterfaceMethod(ir::ModifierFlags::PUBLIC, ir::MethodDefinitionKind::METHOD);
957            method->SetStart(startLoc);
958            return method;
959        }
960
961        auto *field = ParseInterfaceField();
962        if (field != nullptr) {  // Error processing.
963            field->SetStart(startLoc);
964        }
965
966        return field;
967    }
968
969    return ParseTypeDeclaration(true);
970}
971
972bool ETSParser::CheckClassElement(ir::AstNode *property, [[maybe_unused]] ir::MethodDefinition *&ctor,
973                                  [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
974{
975    if (property->IsClassStaticBlock()) {
976        if (std::any_of(properties.cbegin(), properties.cend(),
977                        [](const auto *prop) { return prop->IsClassStaticBlock(); })) {
978            ThrowSyntaxError("Only one static block is allowed", property->Start());
979        }
980
981        auto *id = AllocNode<ir::Identifier>(compiler::Signatures::CCTOR, Allocator());
982        property->AsClassStaticBlock()->Function()->SetIdent(id);
983    }
984
985    if (property->IsTSInterfaceBody()) {
986        return CheckClassElementInterfaceBody(property, properties);
987    }
988
989    if (!property->IsMethodDefinition()) {
990        return false;
991    }
992
993    auto const *const method = property->AsMethodDefinition();
994    auto const *const function = method->Function();
995
996    //  Check the special '$_get' and '$_set' methods using for object's index access
997    if (method->Kind() == ir::MethodDefinitionKind::METHOD) {
998        CheckPredefinedMethods(function, property->Start());
999    }
1000
1001    return false;  // resolve overloads later on scopes stage
1002}
1003
1004void ETSParser::CheckPredefinedMethods(ir::ScriptFunction const *function, const lexer::SourcePosition &position) const
1005{
1006    auto const name = function->Id()->Name();
1007
1008    auto const checkAsynchronous = [this, function, &name, &position]() -> void {
1009        if (function->IsAsyncFunc()) {
1010            ThrowSyntaxError(std::string {ir::PREDEFINED_METHOD} + std::string {name.Utf8()} +
1011                                 std::string {"' cannot be asynchronous."},
1012                             position);
1013        }
1014    };
1015
1016    if (name.Is(compiler::Signatures::GET_INDEX_METHOD)) {
1017        checkAsynchronous();
1018
1019        bool isValid = function->Params().size() == 1U;
1020        if (isValid) {
1021            auto const *const param = function->Params()[0]->AsETSParameterExpression();
1022            isValid = !param->IsDefault() && !param->IsRestParameter();
1023        }
1024
1025        if (!isValid) {
1026            ThrowSyntaxError(std::string {ir::PREDEFINED_METHOD} + std::string {name.Utf8()} +
1027                                 std::string {"' should have exactly one required parameter."},
1028                             position);
1029        }
1030    } else if (name.Is(compiler::Signatures::SET_INDEX_METHOD)) {
1031        checkAsynchronous();
1032
1033        bool isValid = function->Params().size() == 2U;
1034        if (isValid) {
1035            auto const *const param1 = function->Params()[0]->AsETSParameterExpression();
1036            auto const *const param2 = function->Params()[1]->AsETSParameterExpression();
1037            isValid = !param1->IsDefault() && !param1->IsRestParameter() && !param2->IsDefault() &&
1038                      !param2->IsRestParameter();
1039        }
1040
1041        if (!isValid) {
1042            ThrowSyntaxError(std::string {ir::PREDEFINED_METHOD} + std::string {name.Utf8()} +
1043                                 std::string {"' should have exactly two required parameters."},
1044                             position);
1045        }
1046    } else if (name.Is(compiler::Signatures::ITERATOR_METHOD)) {
1047        checkAsynchronous();
1048
1049        if (!function->Params().empty()) {
1050            ThrowSyntaxError(std::string {ir::PREDEFINED_METHOD} + std::string {name.Utf8()} +
1051                                 std::string {"' should not have parameters."},
1052                             position);
1053        }
1054    }
1055}
1056
1057void ETSParser::CreateImplicitConstructor([[maybe_unused]] ir::MethodDefinition *&ctor,
1058                                          ArenaVector<ir::AstNode *> &properties,
1059                                          [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
1060                                          const lexer::SourcePosition &startLoc)
1061{
1062    if (std::any_of(properties.cbegin(), properties.cend(), [](ir::AstNode *prop) {
1063            return prop->IsMethodDefinition() && prop->AsMethodDefinition()->IsConstructor();
1064        })) {
1065        return;
1066    }
1067
1068    if ((modifiers & ir::ClassDefinitionModifiers::ANONYMOUS) != 0) {
1069        return;
1070    }
1071
1072    auto *methodDef = BuildImplicitConstructor(ir::ClassDefinitionModifiers::SET_CTOR_ID, startLoc);
1073    properties.push_back(methodDef);
1074}
1075
1076std::pair<ir::ModifierFlags, lexer::SourcePosition> ETSParser::ParseMemberModifiers()
1077{
1078    auto memberModifiers = ir::ModifierFlags::STATIC | ir::ModifierFlags::PUBLIC;
1079
1080    if (Lexer()->TryEatTokenType(lexer::TokenType::KEYW_EXPORT)) {
1081        const auto savedPos = Lexer()->Save();
1082        if (Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_DEFAULT)) {
1083            memberModifiers |= ir::ModifierFlags::DEFAULT_EXPORT;
1084        } else if (Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_TYPE)) {
1085            if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1086                Lexer()->Rewind(savedPos);
1087            }
1088            memberModifiers |= ir::ModifierFlags::EXPORT_TYPE;
1089        } else {
1090            memberModifiers |= ir::ModifierFlags::EXPORT;
1091        }
1092    }
1093
1094    lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1095
1096    if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
1097        CheckDeclare();
1098        memberModifiers |= ir::ModifierFlags::DECLARE;
1099    }
1100    const auto tokenType = Lexer()->GetToken().KeywordType();
1101    if (tokenType == lexer::TokenType::KEYW_ASYNC || tokenType == lexer::TokenType::KEYW_NATIVE) {
1102        bool isAsync = tokenType == lexer::TokenType::KEYW_ASYNC;
1103
1104        if (isAsync) {
1105            memberModifiers |= ir::ModifierFlags::ASYNC;
1106        } else {
1107            memberModifiers |= ir::ModifierFlags::NATIVE;
1108        }
1109        Lexer()->NextToken();
1110
1111        if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION) {
1112            ThrowSyntaxError(
1113                {isAsync ? "'async'" : "'native'", " flags must be used for functions only at top-level."});
1114        }
1115    }
1116    return std::make_pair(memberModifiers, startLoc);
1117}
1118
1119}  // namespace ark::es2panda::parser
1120