• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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