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