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