• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ir/astNode.h"
31 #include "ir/base/decorator.h"
32 #include "ir/base/catchClause.h"
33 #include "ir/base/scriptFunction.h"
34 #include "ir/base/methodDefinition.h"
35 #include "ir/base/spreadElement.h"
36 #include "ir/expressions/identifier.h"
37 #include "ir/expressions/functionExpression.h"
38 #include "ir/expressions/dummyNode.h"
39 #include "ir/module/importDeclaration.h"
40 #include "ir/module/importDefaultSpecifier.h"
41 #include "ir/module/importSpecifier.h"
42 #include "ir/module/exportSpecifier.h"
43 #include "ir/module/exportNamedDeclaration.h"
44 #include "ir/ets/etsPrimitiveType.h"
45 #include "ir/ets/etsPackageDeclaration.h"
46 #include "ir/ets/etsReExportDeclaration.h"
47 #include "ir/ets/etsWildcardType.h"
48 #include "ir/ets/etsTuple.h"
49 #include "ir/ets/etsFunctionType.h"
50 #include "ir/ets/etsScript.h"
51 #include "ir/ets/etsStringLiteralType.h"
52 #include "ir/ets/etsTypeReference.h"
53 #include "ir/ets/etsTypeReferencePart.h"
54 #include "ir/ets/etsNullishTypes.h"
55 #include "ir/ets/etsUnionType.h"
56 #include "ir/ets/etsImportSource.h"
57 #include "ir/ets/etsImportDeclaration.h"
58 #include "ir/ets/etsStructDeclaration.h"
59 #include "ir/module/importNamespaceSpecifier.h"
60 #include "ir/ts/tsInterfaceDeclaration.h"
61 #include "ir/ts/tsTypeParameterInstantiation.h"
62 #include "ir/ts/tsInterfaceBody.h"
63 #include "ir/ts/tsImportEqualsDeclaration.h"
64 #include "ir/ts/tsArrayType.h"
65 #include "ir/ts/tsQualifiedName.h"
66 #include "ir/ts/tsTypeReference.h"
67 #include "ir/ts/tsTypeParameter.h"
68 #include "ir/ts/tsInterfaceHeritage.h"
69 #include "ir/ts/tsFunctionType.h"
70 #include "ir/ts/tsTypeAliasDeclaration.h"
71 #include "ir/ts/tsTypeParameterDeclaration.h"
72 #include "ir/ts/tsThisType.h"
73 #include "generated/signatures.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         if ((status & ParserStatus::CONSTRUCTOR_FUNCTION) != 0U) {
84             ThrowSyntaxError("Type annotation isn't allowed for constructor.");
85         }
86         Lexer()->NextToken();  // eat ':'
87         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR |
88                                                TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE |
89                                                TypeAnnotationParsingOptions::RETURN_TYPE;
90         return ParseTypeAnnotation(&options);
91     }
92 
93     return nullptr;
94 }
95 
ParsePrimitiveType(TypeAnnotationParsingOptions * options,ir::PrimitiveType type)96 ir::TypeNode *ETSParser::ParsePrimitiveType(TypeAnnotationParsingOptions *options, ir::PrimitiveType type)
97 {
98     if (((*options) & TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE) != 0) {
99         ThrowSyntaxError("Primitive type is not allowed here.");
100     }
101 
102     auto *typeAnnotation = AllocNode<ir::ETSPrimitiveType>(type);
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         if (auto typeAnnotation = ParseTypeAnnotation(&options); typeAnnotation != nullptr) {  // Error processing.
118             types.push_back(typeAnnotation);
119         }
120     }
121 
122     auto const endLoc = types.back()->End();
123     auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(types));
124     unionType->SetRange({firstType->Start(), endLoc});
125     return unionType;
126 }
127 
GetTypeAnnotationOfPrimitiveType(lexer::TokenType tokenType,TypeAnnotationParsingOptions * options)128 ir::TypeNode *ETSParser::GetTypeAnnotationOfPrimitiveType([[maybe_unused]] lexer::TokenType tokenType,
129                                                           TypeAnnotationParsingOptions *options)
130 {
131     ir::TypeNode *typeAnnotation = nullptr;
132     switch (tokenType) {
133         case lexer::TokenType::KEYW_BOOLEAN:
134             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN);
135             break;
136         case lexer::TokenType::KEYW_DOUBLE:
137             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE);
138             break;
139         case lexer::TokenType::KEYW_BYTE:
140             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE);
141             break;
142         case lexer::TokenType::KEYW_FLOAT:
143             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT);
144             break;
145         case lexer::TokenType::KEYW_SHORT:
146             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT);
147             break;
148         case lexer::TokenType::KEYW_INT:
149             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT);
150             break;
151         case lexer::TokenType::KEYW_CHAR:
152             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR);
153             break;
154         case lexer::TokenType::KEYW_LONG:
155             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG);
156             break;
157         case lexer::TokenType::KEYW_VOID:
158             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::VOID);
159             break;
160         default:
161             typeAnnotation = ParseTypeReference(options);
162             break;
163     }
164     return typeAnnotation;
165 }
166 
ParseWildcardType(TypeAnnotationParsingOptions * options)167 ir::TypeNode *ETSParser::ParseWildcardType(TypeAnnotationParsingOptions *options)
168 {
169     const auto varianceStartLoc = Lexer()->GetToken().Start();
170     const auto varianceEndLoc = Lexer()->GetToken().End();
171     const auto varianceModifier = ParseTypeVarianceModifier(options);
172 
173     bool isUnboundOut = varianceModifier == ir::ModifierFlags::OUT &&
174                         (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_GREATER_THAN ||
175                          Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA);
176     ir::ETSTypeReference *typeReference = nullptr;
177     if (!isUnboundOut) {
178         auto reference = ParseTypeReference(options);
179         if (reference == nullptr) {  // Error processing.
180             return nullptr;
181         }
182 
183         typeReference = reference->AsETSTypeReference();
184     }
185 
186     auto *wildcardType = AllocNode<ir::ETSWildcardType>(typeReference, varianceModifier);
187     wildcardType->SetRange({varianceStartLoc, typeReference == nullptr ? varianceEndLoc : typeReference->End()});
188 
189     return wildcardType;
190 }
191 
ParseFunctionType()192 ir::TypeNode *ETSParser::ParseFunctionType()
193 {
194     auto startLoc = Lexer()->GetToken().Start();
195     auto fullParams = ParseFunctionParams();
196     // CC-OFFNXT(G.FMT.14-CPP) project code style
197     auto *const returnTypeAnnotation = [this]() -> ir::TypeNode * {
198         ExpectToken(lexer::TokenType::PUNCTUATOR_ARROW);
199         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
200         return ParseTypeAnnotation(&options);
201     }();
202     if (returnTypeAnnotation == nullptr) {  // Error processing.
203         return nullptr;
204     }
205 
206     ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(false);
207 
208     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
209     ArenaVector<ir::TypeNode *> constituentTypes(Allocator()->Adapter());
210     for (auto it : fullParams) {
211         if (!it->AsETSParameterExpression()->IsDefault()) {
212             params.push_back(it);
213         } else {
214             ArenaVector<ir::Expression *> tmpParams(Allocator()->Adapter());
215 
216             for (auto param : params) {
217                 tmpParams.push_back(param->Clone(Allocator(), nullptr)->AsExpression());
218             }
219 
220             auto *funcType = AllocNode<ir::ETSFunctionType>(
221                 ir::FunctionSignature(nullptr, std::move(tmpParams), returnTypeAnnotation->Clone(Allocator(), nullptr)),
222                 throwMarker);
223 
224             funcType->ReturnType()->SetParent(funcType);
225 
226             constituentTypes.push_back(funcType);
227             params.push_back(it);
228         }
229     }
230 
231     if (constituentTypes.empty()) {
232         auto *funcType = AllocNode<ir::ETSFunctionType>(
233             ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), throwMarker);
234         const auto endLoc = returnTypeAnnotation->End();
235         funcType->SetRange({startLoc, endLoc});
236         return funcType;
237     }
238 
239     auto *funcType = AllocNode<ir::ETSFunctionType>(
240         ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), throwMarker);
241     constituentTypes.push_back(funcType);
242 
243     auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(constituentTypes));
244     const auto endLoc = returnTypeAnnotation->End();
245     unionType->SetRange({startLoc, endLoc});
246 
247     return unionType;
248 }
249 
ParseTriplePeriod(bool spreadTypePresent)250 bool ETSParser::ParseTriplePeriod(bool spreadTypePresent)
251 {
252     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
253         if (spreadTypePresent) {
254             ThrowSyntaxError("Only one spread type declaration allowed, at the last index");
255         }
256 
257         spreadTypePresent = true;
258         Lexer()->NextToken();  // eat '...'
259     } else if (spreadTypePresent) {
260         // This can't be implemented to any index, with type consistency. If a spread type is in the middle of
261         // the tuple, then bounds check can't be made for element access, so the type of elements after the
262         // spread can't be determined in compile time.
263         ThrowSyntaxError("Spread type must be at the last index in the tuple type");
264     }
265 
266     return spreadTypePresent;
267 }
268 
ParseETSTupleType(TypeAnnotationParsingOptions * const options)269 ir::TypeNode *ETSParser::ParseETSTupleType(TypeAnnotationParsingOptions *const options)
270 {
271     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
272 
273     const auto startLoc = Lexer()->GetToken().Start();
274     Lexer()->NextToken();  // eat '['
275 
276     ArenaVector<ir::TypeNode *> tupleTypeList(Allocator()->Adapter());
277     auto *const tupleType = AllocNode<ir::ETSTuple>(Allocator());
278 
279     bool spreadTypePresent = false;
280 
281     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
282         // Parse named parameter if name presents
283         if ((Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) &&
284             (Lexer()->Lookahead() == lexer::LEX_CHAR_COLON)) {
285             ExpectIdentifier();
286             Lexer()->NextToken();  // eat ':'
287         }
288 
289         spreadTypePresent = ParseTriplePeriod(spreadTypePresent);
290 
291         auto *const currentTypeAnnotation = ParseTypeAnnotation(options);
292         if (currentTypeAnnotation == nullptr) {  // Error processing.
293             Lexer()->NextToken();
294             continue;
295         }
296 
297         currentTypeAnnotation->SetParent(tupleType);
298 
299         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
300             // NOTE(mmartin): implement optional types for tuples
301             ThrowSyntaxError("Optional types in tuples are not yet implemented.");
302         }
303 
304         if (spreadTypePresent) {
305             if (!currentTypeAnnotation->IsTSArrayType()) {
306                 ThrowSyntaxError("Spread type must be an array type");
307             }
308 
309             tupleType->SetSpreadType(currentTypeAnnotation);
310         } else {
311             tupleTypeList.push_back(currentTypeAnnotation);
312         }
313 
314         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
315             Lexer()->NextToken();  // eat comma
316             continue;
317         }
318 
319         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
320             // tuple_type_3_neg.sts
321             LogSyntaxError("Comma is mandatory between elements in a tuple type declaration");
322             Lexer()->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
323         }
324     }
325 
326     Lexer()->NextToken();  // eat ']'
327 
328     tupleType->SetTypeAnnotationsList(std::move(tupleTypeList));
329     const auto endLoc = Lexer()->GetToken().End();
330     tupleType->SetRange({startLoc, endLoc});
331 
332     return tupleType;
333 }
334 
335 // Helper function for  ETSParser::GetTypeAnnotationFromToken(...) method
ParsePotentialFunctionalType(TypeAnnotationParsingOptions * options,lexer::SourcePosition startLoc)336 ir::TypeNode *ETSParser::ParsePotentialFunctionalType(TypeAnnotationParsingOptions *options,
337                                                       lexer::SourcePosition startLoc)
338 {
339     if (((*options) & TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE) == 0 &&
340         (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
341          Lexer()->Lookahead() == lexer::LEX_CHAR_COLON || Lexer()->Lookahead() == lexer::LEX_CHAR_QUESTION)) {
342         GetContext().Status() |= ParserStatus::ALLOW_DEFAULT_VALUE;
343         auto typeAnnotation = ParseFunctionType();
344         GetContext().Status() ^= ParserStatus::ALLOW_DEFAULT_VALUE;
345         if (typeAnnotation == nullptr) {  // Error processing.
346             return nullptr;
347         }
348 
349         typeAnnotation->SetStart(startLoc);
350         return typeAnnotation;
351     }
352 
353     auto savePos = Lexer()->Save();
354     ParseTypeAnnotation(options);
355 
356     Lexer()->Rewind(savePos);
357     return nullptr;
358 }
359 
360 // Just to reduce the size of ParseTypeAnnotation(...) method
GetTypeAnnotationFromToken(TypeAnnotationParsingOptions * options)361 std::pair<ir::TypeNode *, bool> ETSParser::GetTypeAnnotationFromToken(TypeAnnotationParsingOptions *options)
362 {
363     ir::TypeNode *typeAnnotation = nullptr;
364 
365     switch (Lexer()->GetToken().Type()) {
366         case lexer::TokenType::LITERAL_IDENT: {
367             typeAnnotation = ParseLiteralIdent(options);
368             if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 &&
369                 (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) {
370                 return std::make_pair(typeAnnotation, false);
371             }
372             return std::make_pair(typeAnnotation, true);
373         }
374         case lexer::TokenType::LITERAL_NULL: {
375             typeAnnotation = AllocNode<ir::ETSNullType>();
376             typeAnnotation->SetRange(Lexer()->GetToken().Loc());
377             Lexer()->NextToken();
378             return std::make_pair(typeAnnotation, true);
379         }
380         case lexer::TokenType::KEYW_UNDEFINED: {
381             typeAnnotation = AllocNode<ir::ETSUndefinedType>();
382             typeAnnotation->SetRange(Lexer()->GetToken().Loc());
383             Lexer()->NextToken();
384             return std::make_pair(typeAnnotation, true);
385         }
386         case lexer::TokenType::LITERAL_STRING: {
387             typeAnnotation = AllocNode<ir::ETSStringLiteralType>(Lexer()->GetToken().String());
388             typeAnnotation->SetRange(Lexer()->GetToken().Loc());
389             Lexer()->NextToken();
390             return std::make_pair(typeAnnotation, true);
391         }
392         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
393             return GetTypeAnnotationFromParentheses(options);
394         }
395         case lexer::TokenType::PUNCTUATOR_FORMAT:
396             return std::make_pair(ParseTypeFormatPlaceholder(), true);
397         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
398             return std::make_pair(ParseETSTupleType(options), true);
399         case lexer::TokenType::KEYW_THIS:
400             return std::make_pair(ParseThisType(options), true);
401         default:
402             return std::make_pair(typeAnnotation, true);
403     }
404 }
405 
GetTypeAnnotationFromParentheses(TypeAnnotationParsingOptions * options)406 std::pair<ir::TypeNode *, bool> ETSParser::GetTypeAnnotationFromParentheses(TypeAnnotationParsingOptions *options)
407 {
408     ir::TypeNode *typeAnnotation = nullptr;
409     auto startLoc = Lexer()->GetToken().Start();
410     lexer::LexerPosition savedPos = Lexer()->Save();
411     Lexer()->NextToken();  // eat '('
412 
413     typeAnnotation = ParsePotentialFunctionalType(options, startLoc);
414     if (typeAnnotation != nullptr) {
415         return std::make_pair(typeAnnotation, true);
416     }
417 
418     typeAnnotation = ParseTypeAnnotation(options);
419     if (typeAnnotation == nullptr) {
420         return std::make_pair(typeAnnotation, true);
421     }
422     typeAnnotation->SetStart(startLoc);
423 
424     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
425         typeAnnotation = ParseUnionType(typeAnnotation);
426     }
427 
428     ParseRightParenthesis(options, typeAnnotation, savedPos);
429 
430     return std::make_pair(typeAnnotation, true);
431 }
432 
ParseThisType(TypeAnnotationParsingOptions * options)433 ir::TypeNode *ETSParser::ParseThisType(TypeAnnotationParsingOptions *options)
434 {
435     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS);
436 
437     // A syntax error should be thrown if
438     // - the usage of 'this' as a type is not allowed in the current context, or
439     // - 'this' is not used as a return type, or
440     // - the current context is an arrow function (might be inside a method of a class where 'this' is allowed).
441     if (((*options & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) &&
442         (((GetContext().Status() & ParserStatus::ALLOW_THIS_TYPE) == 0) ||
443          ((*options & TypeAnnotationParsingOptions::RETURN_TYPE) == 0) ||
444          ((GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0))) {
445         ThrowSyntaxError("A 'this' type is available only as return type in a non-static method of a class or struct.");
446     }
447 
448     auto *thisType = AllocNode<ir::TSThisType>();
449     thisType->SetRange(Lexer()->GetToken().Loc());
450 
451     Lexer()->NextToken();  // eat 'this'
452 
453     return thisType;
454 }
455 
ParseTsArrayType(ir::TypeNode * typeNode,TypeAnnotationParsingOptions * options)456 ir::TypeNode *ETSParser::ParseTsArrayType(ir::TypeNode *typeNode, TypeAnnotationParsingOptions *options)
457 {
458     while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
459         if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY) != 0) {
460             return typeNode;
461         }
462 
463         lexer::SourcePosition startPos = Lexer()->GetToken().Start();
464 
465         Lexer()->NextToken();  // eat '['
466 
467         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
468             if ((*options & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) {
469                 LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
470             }
471             return nullptr;
472         }
473 
474         typeNode = AllocNode<ir::TSArrayType>(typeNode);
475         typeNode->SetRange({startPos, Lexer()->GetToken().End()});
476 
477         Lexer()->NextToken();  // eat ']'
478     }
479 
480     return typeNode;
481 }
482 
ParseTypeAnnotationNoPreferParam(TypeAnnotationParsingOptions * options)483 ir::TypeNode *ETSParser::ParseTypeAnnotationNoPreferParam(TypeAnnotationParsingOptions *options)
484 {
485     bool const reportError = ((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0;
486 
487     auto [typeAnnotation, needFurtherProcessing] = GetTypeAnnotationFromToken(options);
488 
489     if (typeAnnotation == nullptr) {
490         if (reportError) {
491             LogSyntaxError("Invalid Type");
492         }
493         return nullptr;
494     }
495 
496     if (!needFurtherProcessing) {
497         return typeAnnotation;
498     }
499 
500     typeAnnotation = ParseTsArrayType(typeAnnotation, options);
501 
502     if (((*options) & TypeAnnotationParsingOptions::DISALLOW_UNION) == 0 &&
503         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
504         return ParseUnionType(typeAnnotation);
505     }
506 
507     return typeAnnotation;
508 }
509 
ParseTypeAnnotation(TypeAnnotationParsingOptions * options)510 ir::TypeNode *ETSParser::ParseTypeAnnotation(TypeAnnotationParsingOptions *options)
511 {
512     // if there is prefix readonly parameter type, change the return result to ETSTypeReference, like Readonly<>
513     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
514         auto startPos = Lexer()->GetToken().Start();
515         Lexer()->NextToken();  // eat 'readonly'
516         ir::TypeNode *typeAnnotation = ParseTypeAnnotationNoPreferParam(options);
517         if (!typeAnnotation->IsTSArrayType() && !typeAnnotation->IsETSTuple()) {
518             ThrowSyntaxError("'readonly' type modifier is only permitted on array and tuple types.");
519         }
520         typeAnnotation->SetStart(startPos);
521         typeAnnotation->AddModifier(ir::ModifierFlags::READONLY_PARAMETER);
522         return typeAnnotation;
523     }
524 
525     return ParseTypeAnnotationNoPreferParam(options);
526 }
527 
528 }  // namespace ark::es2panda::parser
529