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