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/etsTypeReference.h"
52 #include "ir/ets/etsTypeReferencePart.h"
53 #include "ir/ets/etsNullishTypes.h"
54 #include "ir/ets/etsUnionType.h"
55 #include "ir/ets/etsImportSource.h"
56 #include "ir/ets/etsImportDeclaration.h"
57 #include "ir/ets/etsStructDeclaration.h"
58 #include "ir/module/importNamespaceSpecifier.h"
59 #include "ir/ts/tsInterfaceDeclaration.h"
60 #include "ir/ts/tsTypeParameterInstantiation.h"
61 #include "ir/ts/tsInterfaceBody.h"
62 #include "ir/ts/tsImportEqualsDeclaration.h"
63 #include "ir/ts/tsArrayType.h"
64 #include "ir/ts/tsQualifiedName.h"
65 #include "ir/ts/tsTypeReference.h"
66 #include "ir/ts/tsTypeParameter.h"
67 #include "ir/ts/tsInterfaceHeritage.h"
68 #include "ir/ts/tsFunctionType.h"
69 #include "ir/ts/tsTypeAliasDeclaration.h"
70 #include "ir/ts/tsTypeParameterDeclaration.h"
71 #include "ir/ts/tsThisType.h"
72 #include "generated/signatures.h"
73
74 namespace ark::es2panda::parser {
75 class FunctionContext;
76
77 using namespace std::literals::string_literals;
78
ParseFunctionReturnType(ParserStatus status)79 ir::TypeNode *ETSParser::ParseFunctionReturnType([[maybe_unused]] ParserStatus status)
80 {
81 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
82 if ((status & ParserStatus::CONSTRUCTOR_FUNCTION) != 0U) {
83 ThrowSyntaxError("Type annotation isn't allowed for constructor.");
84 }
85 Lexer()->NextToken(); // eat ':'
86 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR |
87 TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE |
88 TypeAnnotationParsingOptions::RETURN_TYPE;
89 return ParseTypeAnnotation(&options);
90 }
91
92 return nullptr;
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 ThrowSyntaxError("Primitive type is not allowed here.");
99 }
100
101 auto *typeAnnotation = AllocNode<ir::ETSPrimitiveType>(type);
102 typeAnnotation->SetRange(Lexer()->GetToken().Loc());
103 Lexer()->NextToken();
104 return typeAnnotation;
105 }
106
ParseUnionType(ir::TypeNode * const firstType)107 ir::TypeNode *ETSParser::ParseUnionType(ir::TypeNode *const firstType)
108 {
109 ArenaVector<ir::TypeNode *> types(Allocator()->Adapter());
110 types.push_back(firstType->AsTypeNode());
111
112 while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
113 Lexer()->NextToken(); // eat '|'
114
115 auto options = TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::DISALLOW_UNION;
116 types.push_back(ParseTypeAnnotation(&options));
117 }
118
119 auto const endLoc = types.back()->End();
120 auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(types));
121 unionType->SetRange({firstType->Start(), endLoc});
122 return unionType;
123 }
124
GetTypeAnnotationOfPrimitiveType(lexer::TokenType tokenType,TypeAnnotationParsingOptions * options)125 ir::TypeNode *ETSParser::GetTypeAnnotationOfPrimitiveType([[maybe_unused]] lexer::TokenType tokenType,
126 TypeAnnotationParsingOptions *options)
127 {
128 ir::TypeNode *typeAnnotation = nullptr;
129 switch (tokenType) {
130 case lexer::TokenType::KEYW_BOOLEAN:
131 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN);
132 break;
133 case lexer::TokenType::KEYW_DOUBLE:
134 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE);
135 break;
136 case lexer::TokenType::KEYW_BYTE:
137 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE);
138 break;
139 case lexer::TokenType::KEYW_FLOAT:
140 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT);
141 break;
142 case lexer::TokenType::KEYW_SHORT:
143 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT);
144 break;
145 case lexer::TokenType::KEYW_INT:
146 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT);
147 break;
148 case lexer::TokenType::KEYW_CHAR:
149 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR);
150 break;
151 case lexer::TokenType::KEYW_LONG:
152 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG);
153 break;
154 case lexer::TokenType::KEYW_VOID:
155 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::VOID);
156 break;
157 default:
158 typeAnnotation = ParseTypeReference(options);
159 break;
160 }
161 return typeAnnotation;
162 }
163
ParseWildcardType(TypeAnnotationParsingOptions * options)164 ir::TypeNode *ETSParser::ParseWildcardType(TypeAnnotationParsingOptions *options)
165 {
166 const auto varianceStartLoc = Lexer()->GetToken().Start();
167 const auto varianceEndLoc = Lexer()->GetToken().End();
168 const auto varianceModifier = ParseTypeVarianceModifier(options);
169
170 auto *typeReference = [this, &varianceModifier, options]() -> ir::ETSTypeReference * {
171 if (varianceModifier == ir::ModifierFlags::OUT &&
172 (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_GREATER_THAN ||
173 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA)) {
174 // unbounded 'out'
175 return nullptr;
176 }
177 return ParseTypeReference(options)->AsETSTypeReference();
178 }();
179
180 auto *wildcardType = AllocNode<ir::ETSWildcardType>(typeReference, varianceModifier);
181 wildcardType->SetRange({varianceStartLoc, typeReference == nullptr ? varianceEndLoc : typeReference->End()});
182
183 return wildcardType;
184 }
185
ParseFunctionType()186 ir::TypeNode *ETSParser::ParseFunctionType()
187 {
188 auto startLoc = Lexer()->GetToken().Start();
189 auto fullParams = ParseFunctionParams();
190
191 auto *const returnTypeAnnotation = [this]() -> ir::TypeNode * {
192 ExpectToken(lexer::TokenType::PUNCTUATOR_ARROW);
193 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
194 return ParseTypeAnnotation(&options);
195 }();
196
197 ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(false);
198
199 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
200 ArenaVector<ir::TypeNode *> constituentTypes(Allocator()->Adapter());
201 for (auto it : fullParams) {
202 if (!it->AsETSParameterExpression()->IsDefault()) {
203 params.push_back(it);
204 } else {
205 ArenaVector<ir::Expression *> tmpParams(Allocator()->Adapter());
206
207 for (auto param : params) {
208 tmpParams.push_back(param->Clone(Allocator(), nullptr)->AsExpression());
209 }
210
211 auto *funcType = AllocNode<ir::ETSFunctionType>(
212 ir::FunctionSignature(nullptr, std::move(tmpParams), returnTypeAnnotation->Clone(Allocator(), nullptr)),
213 throwMarker);
214
215 funcType->ReturnType()->SetParent(funcType);
216
217 constituentTypes.push_back(funcType);
218 params.push_back(it);
219 }
220 }
221
222 if (constituentTypes.empty()) {
223 auto *funcType = AllocNode<ir::ETSFunctionType>(
224 ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), throwMarker);
225 const auto endLoc = returnTypeAnnotation->End();
226 funcType->SetRange({startLoc, endLoc});
227 return funcType;
228 }
229
230 auto *funcType = AllocNode<ir::ETSFunctionType>(
231 ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), throwMarker);
232 constituentTypes.push_back(funcType);
233
234 auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(constituentTypes));
235 const auto endLoc = returnTypeAnnotation->End();
236 unionType->SetRange({startLoc, endLoc});
237
238 return unionType;
239 }
240
ParseETSTupleType(TypeAnnotationParsingOptions * const options)241 ir::TypeNode *ETSParser::ParseETSTupleType(TypeAnnotationParsingOptions *const options)
242 {
243 ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
244
245 const auto startLoc = Lexer()->GetToken().Start();
246 Lexer()->NextToken(); // eat '['
247
248 ArenaVector<ir::TypeNode *> tupleTypeList(Allocator()->Adapter());
249 auto *const tupleType = AllocNode<ir::ETSTuple>(Allocator());
250
251 bool spreadTypePresent = false;
252
253 while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
254 // Parse named parameter if name presents
255 if ((Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) &&
256 (Lexer()->Lookahead() == lexer::LEX_CHAR_COLON)) {
257 ExpectIdentifier();
258 Lexer()->NextToken(); // eat ':'
259 }
260
261 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
262 if (spreadTypePresent) {
263 ThrowSyntaxError("Only one spread type declaration allowed, at the last index");
264 }
265
266 spreadTypePresent = true;
267 Lexer()->NextToken(); // eat '...'
268 } else if (spreadTypePresent) {
269 // This can't be implemented to any index, with type consistency. If a spread type is in the middle of
270 // the tuple, then bounds check can't be made for element access, so the type of elements after the
271 // spread can't be determined in compile time.
272 ThrowSyntaxError("Spread type must be at the last index in the tuple type");
273 }
274
275 auto *const currentTypeAnnotation = ParseTypeAnnotation(options);
276 currentTypeAnnotation->SetParent(tupleType);
277
278 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
279 // NOTE(mmartin): implement optional types for tuples
280 ThrowSyntaxError("Optional types in tuples are not yet implemented.");
281 }
282
283 if (spreadTypePresent) {
284 if (!currentTypeAnnotation->IsTSArrayType()) {
285 ThrowSyntaxError("Spread type must be an array type");
286 }
287
288 tupleType->SetSpreadType(currentTypeAnnotation);
289 } else {
290 tupleTypeList.push_back(currentTypeAnnotation);
291 }
292
293 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
294 Lexer()->NextToken(); // eat comma
295 continue;
296 }
297
298 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
299 ThrowSyntaxError("Comma is mandatory between elements in a tuple type declaration");
300 }
301 }
302
303 Lexer()->NextToken(); // eat ']'
304
305 tupleType->SetTypeAnnotationsList(tupleTypeList);
306 const auto endLoc = Lexer()->GetToken().End();
307 tupleType->SetRange({startLoc, endLoc});
308
309 return tupleType;
310 }
311
312 // Helper function for ETSParser::GetTypeAnnotationFromToken(...) method
ParsePotentialFunctionalType(TypeAnnotationParsingOptions * options,lexer::SourcePosition startLoc)313 ir::TypeNode *ETSParser::ParsePotentialFunctionalType(TypeAnnotationParsingOptions *options,
314 lexer::SourcePosition startLoc)
315 {
316 if (((*options) & TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE) == 0 &&
317 (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
318 Lexer()->Lookahead() == lexer::LEX_CHAR_COLON || Lexer()->Lookahead() == lexer::LEX_CHAR_QUESTION)) {
319 GetContext().Status() |= ParserStatus::ALLOW_DEFAULT_VALUE;
320 auto typeAnnotation = ParseFunctionType();
321 typeAnnotation->SetStart(startLoc);
322 GetContext().Status() ^= ParserStatus::ALLOW_DEFAULT_VALUE;
323 return typeAnnotation;
324 }
325
326 auto savePos = Lexer()->Save();
327 ParseTypeAnnotation(options);
328
329 Lexer()->Rewind(savePos);
330 return nullptr;
331 }
332
333 // Just to reduce the size of ParseTypeAnnotation(...) method
GetTypeAnnotationFromToken(TypeAnnotationParsingOptions * options)334 std::pair<ir::TypeNode *, bool> ETSParser::GetTypeAnnotationFromToken(TypeAnnotationParsingOptions *options)
335 {
336 ir::TypeNode *typeAnnotation = nullptr;
337
338 switch (Lexer()->GetToken().Type()) {
339 case lexer::TokenType::LITERAL_IDENT: {
340 typeAnnotation = ParseLiteralIdent(options);
341 if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 &&
342 (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) {
343 return std::make_pair(typeAnnotation, false);
344 }
345 return std::make_pair(typeAnnotation, true);
346 }
347 case lexer::TokenType::LITERAL_NULL: {
348 typeAnnotation = AllocNode<ir::ETSNullType>();
349 typeAnnotation->SetRange(Lexer()->GetToken().Loc());
350 Lexer()->NextToken();
351 return std::make_pair(typeAnnotation, true);
352 }
353 case lexer::TokenType::KEYW_UNDEFINED: {
354 typeAnnotation = AllocNode<ir::ETSUndefinedType>();
355 typeAnnotation->SetRange(Lexer()->GetToken().Loc());
356 Lexer()->NextToken();
357 return std::make_pair(typeAnnotation, true);
358 }
359 case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
360 return GetTypeAnnotationFromParentheses(options);
361 }
362 case lexer::TokenType::PUNCTUATOR_FORMAT:
363 return std::make_pair(ParseTypeFormatPlaceholder(), true);
364 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
365 return std::make_pair(ParseETSTupleType(options), true);
366 case lexer::TokenType::KEYW_THIS:
367 return std::make_pair(ParseThisType(options), true);
368 default:
369 return std::make_pair(typeAnnotation, true);
370 }
371 }
372
GetTypeAnnotationFromParentheses(TypeAnnotationParsingOptions * options)373 std::pair<ir::TypeNode *, bool> ETSParser::GetTypeAnnotationFromParentheses(TypeAnnotationParsingOptions *options)
374 {
375 ir::TypeNode *typeAnnotation = nullptr;
376 auto startLoc = Lexer()->GetToken().Start();
377 lexer::LexerPosition savedPos = Lexer()->Save();
378 Lexer()->NextToken(); // eat '('
379
380 typeAnnotation = ParsePotentialFunctionalType(options, startLoc);
381 if (typeAnnotation != nullptr) {
382 return std::make_pair(typeAnnotation, true);
383 }
384
385 typeAnnotation = ParseTypeAnnotation(options);
386 if (typeAnnotation == nullptr) {
387 return std::make_pair(typeAnnotation, true);
388 }
389 typeAnnotation->SetStart(startLoc);
390
391 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
392 typeAnnotation = ParseUnionType(typeAnnotation);
393 }
394
395 ParseRightParenthesis(options, typeAnnotation, savedPos);
396
397 return std::make_pair(typeAnnotation, true);
398 }
399
ParseThisType(TypeAnnotationParsingOptions * options)400 ir::TypeNode *ETSParser::ParseThisType(TypeAnnotationParsingOptions *options)
401 {
402 ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS);
403
404 // A syntax error should be thrown if
405 // - the usage of 'this' as a type is not allowed in the current context, or
406 // - 'this' is not used as a return type, or
407 // - the current context is an arrow function (might be inside a method of a class where 'this' is allowed).
408 if (((*options & TypeAnnotationParsingOptions::THROW_ERROR) != 0) &&
409 (((GetContext().Status() & ParserStatus::ALLOW_THIS_TYPE) == 0) ||
410 ((*options & TypeAnnotationParsingOptions::RETURN_TYPE) == 0) ||
411 ((GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0))) {
412 ThrowSyntaxError("A 'this' type is available only as return type in a non-static method of a class or struct.");
413 }
414
415 auto *thisType = AllocNode<ir::TSThisType>();
416 thisType->SetRange(Lexer()->GetToken().Loc());
417
418 Lexer()->NextToken(); // eat 'this'
419
420 return thisType;
421 }
422
ParseTypeAnnotation(TypeAnnotationParsingOptions * options)423 ir::TypeNode *ETSParser::ParseTypeAnnotation(TypeAnnotationParsingOptions *options)
424 {
425 bool const throwError = ((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0;
426
427 auto [typeAnnotation, needFurtherProcessing] = GetTypeAnnotationFromToken(options);
428
429 if (typeAnnotation == nullptr) {
430 if (throwError) {
431 ThrowSyntaxError("Invalid Type");
432 }
433 return nullptr;
434 }
435
436 if (!needFurtherProcessing) {
437 return typeAnnotation;
438 }
439
440 const lexer::SourcePosition &startPos = Lexer()->GetToken().Start();
441
442 while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
443 Lexer()->NextToken(); // eat '['
444
445 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
446 if (throwError) {
447 ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
448 }
449 return nullptr;
450 }
451
452 Lexer()->NextToken(); // eat ']'
453 typeAnnotation = AllocNode<ir::TSArrayType>(typeAnnotation);
454 typeAnnotation->SetRange({startPos, Lexer()->GetToken().End()});
455 }
456
457 if (((*options) & TypeAnnotationParsingOptions::DISALLOW_UNION) == 0 &&
458 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
459 return ParseUnionType(typeAnnotation);
460 }
461
462 return typeAnnotation;
463 }
464
465 } // namespace ark::es2panda::parser
466