1 /**
2 * Copyright (c) 2021-2025 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 #include "util/es2pandaMacros.h"
20 #include "parser/parserFlags.h"
21 #include "parser/parserStatusContext.h"
22 #include "util/helpers.h"
23 #include "util/language.h"
24 #include "utils/arena_containers.h"
25 #include "varbinder/varbinder.h"
26 #include "varbinder/ETSBinder.h"
27 #include "lexer/lexer.h"
28 #include "lexer/ETSLexer.h"
29 #include "ir/astNode.h"
30 #include "ir/base/decorator.h"
31 #include "ir/base/catchClause.h"
32 #include "ir/base/scriptFunction.h"
33 #include "ir/base/methodDefinition.h"
34 #include "ir/base/spreadElement.h"
35 #include "ir/expressions/identifier.h"
36 #include "ir/expressions/functionExpression.h"
37 #include "ir/expressions/dummyNode.h"
38 #include "ir/module/importDeclaration.h"
39 #include "ir/module/importDefaultSpecifier.h"
40 #include "ir/module/importSpecifier.h"
41 #include "ir/module/exportSpecifier.h"
42 #include "ir/module/exportNamedDeclaration.h"
43 #include "ir/ets/etsPrimitiveType.h"
44 #include "ir/ets/etsPackageDeclaration.h"
45 #include "ir/ets/etsReExportDeclaration.h"
46 #include "ir/ets/etsWildcardType.h"
47 #include "ir/ets/etsTuple.h"
48 #include "ir/ets/etsFunctionType.h"
49 #include "ir/ets/etsModule.h"
50 #include "ir/ets/etsStringLiteralType.h"
51 #include "ir/ets/etsTypeReference.h"
52 #include "ir/ets/etsTypeReferencePart.h"
53 #include "ir/ets/etsNullishTypes.h"
54 #include "ir/ets/etsUnionType.h"
55 #include "ir/ets/etsImportDeclaration.h"
56 #include "ir/ets/etsStructDeclaration.h"
57 #include "ir/module/importNamespaceSpecifier.h"
58 #include "ir/ts/tsInterfaceDeclaration.h"
59 #include "ir/ts/tsTypeParameterInstantiation.h"
60 #include "ir/ts/tsInterfaceBody.h"
61 #include "ir/ts/tsImportEqualsDeclaration.h"
62 #include "ir/ts/tsArrayType.h"
63 #include "ir/ts/tsQualifiedName.h"
64 #include "ir/ts/tsTypeReference.h"
65 #include "ir/ts/tsTypeParameter.h"
66 #include "ir/ts/tsInterfaceHeritage.h"
67 #include "ir/ts/tsFunctionType.h"
68 #include "ir/ts/tsTypeAliasDeclaration.h"
69 #include "ir/ts/tsTypeParameterDeclaration.h"
70 #include "ir/ts/tsThisType.h"
71 #include "generated/signatures.h"
72 #include "util/errorRecovery.h"
73 #include "generated/diagnostic.h"
74
75 namespace ark::es2panda::parser {
76 class FunctionContext;
77
78 using namespace std::literals::string_literals;
79
ParseFunctionReturnType(ParserStatus status)80 ir::TypeNode *ETSParser::ParseFunctionReturnType([[maybe_unused]] ParserStatus status)
81 {
82 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
83 return nullptr;
84 }
85 if ((status & ParserStatus::CONSTRUCTOR_FUNCTION) != 0U) {
86 LogError(diagnostic::TYPE_ANNOTATION_FOR_CONSTRUCTOR);
87 }
88 Lexer()->NextToken(); // eat ':'
89 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR |
90 TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE |
91 TypeAnnotationParsingOptions::RETURN_TYPE;
92 return ParseTypeAnnotation(&options);
93 }
94
ParsePrimitiveType(TypeAnnotationParsingOptions * options,ir::PrimitiveType type)95 ir::TypeNode *ETSParser::ParsePrimitiveType(TypeAnnotationParsingOptions *options, ir::PrimitiveType type)
96 {
97 if (((*options) & TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE) != 0) {
98 LogError(diagnostic::PRIMITIVE_NOT_ALLOWED);
99 }
100
101 auto *const typeAnnotation = AllocNode<ir::ETSPrimitiveType>(type, Allocator());
102 ES2PANDA_ASSERT(typeAnnotation != nullptr);
103 typeAnnotation->SetRange(Lexer()->GetToken().Loc());
104 Lexer()->NextToken();
105 return typeAnnotation;
106 }
107
ParseUnionType(ir::TypeNode * const firstType)108 ir::TypeNode *ETSParser::ParseUnionType(ir::TypeNode *const firstType)
109 {
110 ArenaVector<ir::TypeNode *> types(Allocator()->Adapter());
111 types.push_back(firstType->AsTypeNode());
112
113 while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
114 Lexer()->NextToken(); // eat '|'
115
116 auto options = TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::DISALLOW_UNION;
117 auto typeAnnotation = ParseTypeAnnotation(&options);
118 if (!typeAnnotation->IsBrokenTypeNode()) {
119 types.push_back(typeAnnotation);
120 }
121 }
122
123 auto const endLoc = types.back()->End();
124 auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(types), Allocator());
125 ES2PANDA_ASSERT(unionType != nullptr);
126 unionType->SetRange({firstType->Start(), endLoc});
127 return unionType;
128 }
129
GetTypeAnnotationOfPrimitiveType(lexer::TokenType tokenType,TypeAnnotationParsingOptions * options)130 ir::TypeNode *ETSParser::GetTypeAnnotationOfPrimitiveType([[maybe_unused]] lexer::TokenType tokenType,
131 TypeAnnotationParsingOptions *options)
132 {
133 ir::TypeNode *typeAnnotation = nullptr;
134 switch (tokenType) {
135 case lexer::TokenType::KEYW_BOOLEAN:
136 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN);
137 break;
138 case lexer::TokenType::KEYW_DOUBLE:
139 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE);
140 break;
141 case lexer::TokenType::KEYW_BYTE:
142 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE);
143 break;
144 case lexer::TokenType::KEYW_FLOAT:
145 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT);
146 break;
147 case lexer::TokenType::KEYW_SHORT:
148 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT);
149 break;
150 case lexer::TokenType::KEYW_INT:
151 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT);
152 break;
153 case lexer::TokenType::KEYW_CHAR:
154 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR);
155 break;
156 case lexer::TokenType::KEYW_LONG:
157 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG);
158 break;
159 case lexer::TokenType::KEYW_VOID:
160 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::VOID);
161 break;
162 default:
163 typeAnnotation = ParseTypeReference(options);
164 break;
165 }
166 return typeAnnotation;
167 }
168
ParseWildcardType(TypeAnnotationParsingOptions * options)169 ir::TypeNode *ETSParser::ParseWildcardType(TypeAnnotationParsingOptions *options)
170 {
171 const auto varianceStartLoc = Lexer()->GetToken().Start();
172 const auto varianceEndLoc = Lexer()->GetToken().End();
173 const auto varianceModifier = ParseTypeVarianceModifier(options);
174
175 bool isUnboundOut = varianceModifier == ir::ModifierFlags::OUT &&
176 (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_GREATER_THAN ||
177 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA);
178 ir::ETSTypeReference *typeReference = nullptr;
179 if (!isUnboundOut) {
180 auto reference = ParseTypeReference(options);
181 ES2PANDA_ASSERT(reference != nullptr);
182 typeReference = reference->AsETSTypeReference();
183 }
184
185 auto *wildcardType = AllocNode<ir::ETSWildcardType>(typeReference, varianceModifier, Allocator());
186 ES2PANDA_ASSERT(wildcardType != nullptr);
187 wildcardType->SetRange({varianceStartLoc, typeReference == nullptr ? varianceEndLoc : typeReference->End()});
188
189 return wildcardType;
190 }
191
ParseFunctionType(TypeAnnotationParsingOptions * options)192 ir::TypeNode *ETSParser::ParseFunctionType(TypeAnnotationParsingOptions *options)
193 {
194 auto startLoc = Lexer()->GetToken().Start();
195 auto params = ParseFunctionParams();
196 bool hasReceiver = !params.empty() && params[0]->IsETSParameterExpression() &&
197 params[0]->AsETSParameterExpression()->Ident()->IsReceiver();
198 if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_ARROW)) {
199 if (((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) {
200 LogExpectedToken(lexer::TokenType::PUNCTUATOR_ARROW);
201 }
202 return nullptr;
203 }
204 ir::TypeNode *returnTypeAnnotation = nullptr;
205 if (hasReceiver) {
206 SavedParserContext contextAfterParseParams(this, GetContext().Status() | ParserStatus::HAS_RECEIVER);
207 returnTypeAnnotation = ParseTypeAnnotation(options);
208 } else {
209 returnTypeAnnotation = ParseTypeAnnotation(options);
210 }
211 if (returnTypeAnnotation == nullptr) {
212 return nullptr;
213 }
214
215 ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(false);
216 auto *funcType = AllocNode<ir::ETSFunctionType>(
217 ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation, hasReceiver), throwMarker, Allocator());
218 funcType->SetRange({startLoc, returnTypeAnnotation->End()});
219
220 return funcType;
221 }
222
ParseTriplePeriod(bool spreadTypePresent)223 bool ETSParser::ParseTriplePeriod(bool spreadTypePresent)
224 {
225 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
226 if (spreadTypePresent) {
227 LogError(diagnostic::ONLY_SPREAD_AT_LAST_INDEX);
228 }
229
230 spreadTypePresent = true;
231 Lexer()->NextToken(); // eat '...'
232 } else if (spreadTypePresent) {
233 // This can't be implemented to any index, with type consistency. If a spread type is in the middle of
234 // the tuple, then bounds check can't be made for element access, so the type of elements after the
235 // spread can't be determined in compile time.
236 LogError(diagnostic::SPREAD_MUST_BE_LAST_IN_TUPLE);
237 }
238
239 return spreadTypePresent;
240 }
241
ParseETSTupleType(TypeAnnotationParsingOptions * const options)242 ir::TypeNode *ETSParser::ParseETSTupleType(TypeAnnotationParsingOptions *const options)
243 {
244 ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
245
246 const auto startLoc = Lexer()->GetToken().Start();
247 ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
248
249 ArenaVector<ir::TypeNode *> tupleTypeList(Allocator()->Adapter());
250 auto *const tupleType = AllocNode<ir::ETSTuple>(Allocator());
251
252 auto parseElem = [this, options, &tupleTypeList, &tupleType]() {
253 auto *const currentTypeAnnotation = ParseTypeAnnotation(options);
254 if (currentTypeAnnotation == nullptr) { // Error processing.
255 Lexer()->NextToken();
256 return false;
257 }
258
259 currentTypeAnnotation->SetParent(tupleType);
260 tupleTypeList.push_back(currentTypeAnnotation);
261
262 return true;
263 };
264
265 lexer::SourcePosition endLoc;
266 ParseList(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET, lexer::NextTokenFlags::NONE, parseElem, &endLoc, true);
267
268 ES2PANDA_ASSERT(tupleType != nullptr);
269 tupleType->SetTypeAnnotationsList(std::move(tupleTypeList));
270 tupleType->SetRange({startLoc, endLoc});
271
272 return tupleType;
273 }
274
275 // Helper function for ETSParser::GetTypeAnnotationFromToken(...) method
ParsePotentialFunctionalType(TypeAnnotationParsingOptions * options)276 ir::TypeNode *ETSParser::ParsePotentialFunctionalType(TypeAnnotationParsingOptions *options)
277 {
278 auto savePos = Lexer()->Save();
279 ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
280
281 auto isPotentiallyOptionalWithTypeAnnotation = [this]() {
282 bool res = false;
283
284 if (Lexer()->Lookahead() != lexer::LEX_CHAR_QUESTION) {
285 return res;
286 }
287
288 auto currentPos = Lexer()->Save();
289 // jump to '?' token
290 Lexer()->NextToken();
291
292 if (Lexer()->Lookahead() == lexer::LEX_CHAR_COLON) {
293 res = true;
294 }
295
296 Lexer()->Rewind(currentPos);
297 return res;
298 };
299 if (((*options) & TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE) == 0 &&
300 (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
301 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD ||
302 Lexer()->Lookahead() == lexer::LEX_CHAR_COLON || isPotentiallyOptionalWithTypeAnnotation())) {
303 GetContext().Status() |= (ParserStatus::ALLOW_DEFAULT_VALUE | ParserStatus::ALLOW_RECEIVER);
304 // '(' is consumed in `ParseFunctionType`
305 Lexer()->Rewind(savePos);
306 auto typeAnnotation = ParseFunctionType(options);
307 GetContext().Status() ^= (ParserStatus::ALLOW_DEFAULT_VALUE | ParserStatus::ALLOW_RECEIVER);
308 return typeAnnotation;
309 }
310 Lexer()->Rewind(savePos);
311 return nullptr;
312 }
313
314 // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP) solid logic
315 // Just to reduce the size of ParseTypeAnnotation(...) method
GetTypeAnnotationFromToken(TypeAnnotationParsingOptions * options)316 std::pair<ir::TypeNode *, bool> ETSParser::GetTypeAnnotationFromToken(TypeAnnotationParsingOptions *options)
317 {
318 auto tokenType = Lexer()->GetToken().Type();
319 if (IsPrimitiveType(Lexer()->GetToken().KeywordType()) || tokenType == lexer::TokenType::LITERAL_IDENT) {
320 auto typeAnnotation = ParseLiteralIdent(options);
321 if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 &&
322 (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) {
323 return std::make_pair(typeAnnotation, false);
324 }
325 return std::make_pair(typeAnnotation, true);
326 }
327
328 switch (tokenType) {
329 case lexer::TokenType::LITERAL_NULL: {
330 auto typeAnnotation = AllocNode<ir::ETSNullType>(Allocator());
331 ES2PANDA_ASSERT(typeAnnotation != nullptr);
332 typeAnnotation->SetRange(Lexer()->GetToken().Loc());
333 Lexer()->NextToken();
334 return std::make_pair(typeAnnotation, true);
335 }
336 case lexer::TokenType::KEYW_UNDEFINED: {
337 auto typeAnnotation = AllocNode<ir::ETSUndefinedType>(Allocator());
338 ES2PANDA_ASSERT(typeAnnotation != nullptr);
339 typeAnnotation->SetRange(Lexer()->GetToken().Loc());
340 Lexer()->NextToken();
341 return std::make_pair(typeAnnotation, true);
342 }
343 case lexer::TokenType::LITERAL_STRING: {
344 auto typeAnnotation = AllocNode<ir::ETSStringLiteralType>(Lexer()->GetToken().String(), Allocator());
345 ES2PANDA_ASSERT(typeAnnotation != nullptr);
346 typeAnnotation->SetRange(Lexer()->GetToken().Loc());
347 Lexer()->NextToken();
348 return std::make_pair(typeAnnotation, true);
349 }
350 case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
351 return std::make_pair(ParseMultilineString(), true);
352 }
353 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
354 return GetTypeAnnotationFromParentheses(options);
355 }
356 case lexer::TokenType::PUNCTUATOR_FORMAT:
357 return std::make_pair(ParseTypeFormatPlaceholder(), true);
358 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
359 return std::make_pair(ParseETSTupleType(options), true);
360 case lexer::TokenType::KEYW_THIS:
361 return std::make_pair(ParseThisType(options), true);
362 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE:
363 if (((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) {
364 auto startPos = Lexer()->GetToken().Start();
365 auto modifiers = ir::ClassDefinitionModifiers::ID_REQUIRED | ir::ClassDefinitionModifiers::CLASS_DECL |
366 ir::ClassDefinitionModifiers::DECLARATION;
367 auto flags = ir::ModifierFlags::NONE;
368 ParseClassBody(modifiers, flags);
369 LogError(diagnostic::ERROR_ARKTS_NO_OBJ_LITERAL_TO_DECL_TYPE, {}, startPos);
370 return {AllocBrokenType({startPos, Lexer()->GetToken().End()}), false};
371 }
372 [[fallthrough]];
373 default: {
374 return {nullptr, true};
375 }
376 }
377 }
378
GetTypeAnnotationFromParentheses(TypeAnnotationParsingOptions * options)379 std::pair<ir::TypeNode *, bool> ETSParser::GetTypeAnnotationFromParentheses(TypeAnnotationParsingOptions *options)
380 {
381 auto startLoc = Lexer()->GetToken().Start();
382
383 ir::TypeNode *typeAnnotation = ParsePotentialFunctionalType(options);
384 if (typeAnnotation != nullptr) {
385 typeAnnotation->SetStart(startLoc);
386 return std::make_pair(typeAnnotation, true);
387 }
388
389 lexer::LexerPosition savedPos = Lexer()->Save();
390 if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) {
391 if (((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) {
392 LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
393 }
394 return {nullptr, false};
395 }
396
397 typeAnnotation = ParseTypeAnnotation(options);
398 if (typeAnnotation == nullptr) {
399 return std::make_pair(typeAnnotation, true);
400 }
401
402 typeAnnotation->SetStart(startLoc);
403
404 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
405 typeAnnotation = ParseUnionType(typeAnnotation);
406 }
407
408 ParseRightParenthesis(options, typeAnnotation, savedPos);
409
410 return std::make_pair(typeAnnotation, true);
411 }
412
IsSimpleReturnThis(lexer::Token const & tokenAfterThis)413 static bool IsSimpleReturnThis(lexer::Token const &tokenAfterThis)
414 {
415 return (tokenAfterThis.Type() == lexer::TokenType::PUNCTUATOR_ARROW) ||
416 (tokenAfterThis.Type() == lexer::TokenType::PUNCTUATOR_COMMA) ||
417 (tokenAfterThis.Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) ||
418 (tokenAfterThis.Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) ||
419 (tokenAfterThis.Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) ||
420 ((tokenAfterThis.Flags() & lexer::TokenFlags::NEW_LINE) != 0);
421 }
422
ParseThisType(TypeAnnotationParsingOptions * options)423 ir::TypeNode *ETSParser::ParseThisType(TypeAnnotationParsingOptions *options)
424 {
425 ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS);
426
427 auto startPos = Lexer()->GetToken().Start();
428 auto const tokenLoc = Lexer()->GetToken().Loc();
429 Lexer()->NextToken(); // eat 'this'
430
431 // A syntax error should be thrown if
432 // - the usage of 'this' as a type is not allowed in the current context, or
433 // - 'this' is not used as a return type, or
434 // - the current context is an arrow function (might be inside a method of a class where 'this' is allowed).
435 // - Specially, Function with Receiver, Lambda with Receiver and Function type with Receiver can return 'this'.
436 bool reportErr = (*options & TypeAnnotationParsingOptions::REPORT_ERROR) != 0;
437 bool allowThisType = ((GetContext().Status() & ParserStatus::ALLOW_THIS_TYPE) != 0);
438 bool isArrowFunc = (GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0;
439 bool parseReturnType = (*options & TypeAnnotationParsingOptions::RETURN_TYPE) != 0;
440 bool isExtensionFunction = (GetContext().Status() & ParserStatus::HAS_RECEIVER) != 0;
441 bool isInUnion = (*options & TypeAnnotationParsingOptions::DISALLOW_UNION) != 0;
442 if (isExtensionFunction) {
443 if (reportErr && (!IsSimpleReturnThis(Lexer()->GetToken()) || isInUnion)) {
444 LogError(diagnostic::THIS_IN_NON_STATIC_METHOD, {}, startPos);
445 }
446 } else if (reportErr && (!allowThisType || !parseReturnType || isArrowFunc)) {
447 LogError(diagnostic::THIS_IN_NON_STATIC_METHOD, {}, startPos);
448 }
449
450 auto *const thisType = AllocNode<ir::TSThisType>(Allocator());
451 ES2PANDA_ASSERT(thisType != nullptr);
452 thisType->SetRange(tokenLoc);
453
454 return thisType;
455 }
456
ParseTsArrayType(ir::TypeNode * typeNode,TypeAnnotationParsingOptions * options)457 ir::TypeNode *ETSParser::ParseTsArrayType(ir::TypeNode *typeNode, TypeAnnotationParsingOptions *options)
458 {
459 while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
460 if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY) != 0) {
461 return typeNode;
462 }
463
464 lexer::SourcePosition startPos = Lexer()->GetToken().Start();
465
466 Lexer()->NextToken(); // eat '['
467
468 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
469 if ((*options & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) {
470 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
471 }
472 return AllocBrokenType({Lexer()->GetToken().Start(), Lexer()->GetToken().End()});
473 }
474
475 typeNode = AllocNode<ir::TSArrayType>(typeNode, Allocator());
476 typeNode->SetRange({startPos, Lexer()->GetToken().End()});
477 Lexer()->NextToken(); // eat ']'
478 }
479 return typeNode;
480 }
481
ParseTypeAnnotationNoPreferParam(TypeAnnotationParsingOptions * options)482 ir::TypeNode *ETSParser::ParseTypeAnnotationNoPreferParam(TypeAnnotationParsingOptions *options)
483 {
484 bool const reportError = ((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0;
485 ArenaVector<ir::AnnotationUsage *> annotations {Allocator()->Adapter()};
486 if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_AT)) {
487 annotations = ParseAnnotations(false);
488 }
489 auto startPos = Lexer()->GetToken().Start();
490 auto [typeAnnotation, needFurtherProcessing] = GetTypeAnnotationFromToken(options);
491
492 if (typeAnnotation == nullptr) {
493 if (reportError) {
494 LogError(diagnostic::INVALID_TYPE);
495 return AllocBrokenType({Lexer()->GetToken().Start(), Lexer()->GetToken().End()});
496 }
497 return nullptr;
498 }
499
500 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
501 typeAnnotation = AllocNode<ir::ETSNonNullishTypeNode>(typeAnnotation, Allocator());
502 Lexer()->NextToken();
503 }
504
505 if (!needFurtherProcessing) {
506 return typeAnnotation;
507 }
508
509 typeAnnotation = ParseTsArrayType(typeAnnotation, options);
510
511 ApplyAnnotationsToNode(typeAnnotation, std::move(annotations), startPos, *options);
512 return typeAnnotation;
513 }
514
ParseReadonlyInTypeAnnotation()515 bool ETSParser::ParseReadonlyInTypeAnnotation()
516 {
517 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
518 Lexer()->NextToken(); // eat '<'
519 Lexer()->NextToken(); // eat 'identifier'
520 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
521 Lexer()->NextToken(); // eat '>'
522 return true;
523 }
524 }
525
526 return false;
527 }
528
IsReadonlyApplicableType(ir::TypeNode * typeNode)529 static bool IsReadonlyApplicableType(ir::TypeNode *typeNode)
530 {
531 return typeNode->IsTSArrayType() || typeNode->IsETSTuple() ||
532 (typeNode->IsETSTypeReference() &&
533 typeNode->AsETSTypeReference()->BaseName()->Name() == compiler::Signatures::ARRAY);
534 }
535
ParseTypeAnnotation(TypeAnnotationParsingOptions * options)536 ir::TypeNode *ETSParser::ParseTypeAnnotation(TypeAnnotationParsingOptions *options)
537 {
538 const auto startPos = Lexer()->GetToken().Start();
539 bool hasReadonly = Lexer()->TryEatTokenFromKeywordType(lexer::TokenType::KEYW_READONLY);
540 const auto beforeTypeAnnotation = Lexer()->GetToken().Loc();
541 auto typeAnnotation = ParseTypeAnnotationNoPreferParam(options);
542 if (typeAnnotation == nullptr) {
543 if ((*options & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) {
544 LogError(diagnostic::INVALID_TYPE);
545 }
546 return AllocBrokenType(beforeTypeAnnotation);
547 }
548
549 if (hasReadonly) {
550 if (!IsReadonlyApplicableType(typeAnnotation)) {
551 if (!ParseReadonlyInTypeAnnotation()) {
552 LogError(diagnostic::READONLY_ONLY_ON_ARRAY_OR_TUPLE);
553 } else {
554 LogError(diagnostic::READONLY_TYPE_EXPECTED);
555 }
556 }
557 typeAnnotation->SetStart(startPos);
558 typeAnnotation->AddModifier(ir::ModifierFlags::READONLY_PARAMETER);
559 }
560
561 if (((*options) & TypeAnnotationParsingOptions::DISALLOW_UNION) == 0 &&
562 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
563 return ParseUnionType(typeAnnotation);
564 }
565
566 return typeAnnotation;
567 }
568
ParseMultilineString()569 ir::TypeNode *ETSParser::ParseMultilineString()
570 {
571 const auto startPos = Lexer()->GetToken().Start();
572 const auto multilineStr = Lexer()->ScanMultilineString();
573 Lexer()->ScanTemplateStringEnd();
574
575 auto typeAnnotation = AllocNode<ir::ETSStringLiteralType>(multilineStr, Allocator());
576 ES2PANDA_ASSERT(typeAnnotation != nullptr);
577 typeAnnotation->SetRange({startPos, Lexer()->GetToken().End()});
578 Lexer()->NextToken();
579
580 return typeAnnotation;
581 }
582
583 } // namespace ark::es2panda::parser
584