• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 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 "parserImpl.h"
17 
18 #include <binder/scope.h>
19 #include <binder/tsBinding.h>
20 #include <util/helpers.h>
21 #include <ir/astDump.h>
22 #include <ir/astNode.h>
23 #include <ir/base/classDefinition.h>
24 #include <ir/base/classProperty.h>
25 #include <ir/base/decorator.h>
26 #include <ir/base/methodDefinition.h>
27 #include <ir/base/property.h>
28 #include <ir/base/scriptFunction.h>
29 #include <ir/base/spreadElement.h>
30 #include <ir/expression.h>
31 #include <ir/expressions/arrayExpression.h>
32 #include <ir/expressions/assignmentExpression.h>
33 #include <ir/expressions/callExpression.h>
34 #include <ir/expressions/functionExpression.h>
35 #include <ir/expressions/identifier.h>
36 #include <ir/expressions/literals/bigIntLiteral.h>
37 #include <ir/expressions/literals/booleanLiteral.h>
38 #include <ir/expressions/literals/nullLiteral.h>
39 #include <ir/expressions/literals/numberLiteral.h>
40 #include <ir/expressions/literals/stringLiteral.h>
41 #include <ir/expressions/memberExpression.h>
42 #include <ir/expressions/objectExpression.h>
43 #include <ir/expressions/superExpression.h>
44 #include <ir/module/exportDefaultDeclaration.h>
45 #include <ir/module/exportNamedDeclaration.h>
46 #include <ir/module/exportSpecifier.h>
47 #include <ir/statements/blockStatement.h>
48 #include <ir/statements/classDeclaration.h>
49 #include <ir/statements/emptyStatement.h>
50 #include <ir/statements/expressionStatement.h>
51 #include <ir/statements/functionDeclaration.h>
52 #include <ir/statements/variableDeclaration.h>
53 #include <ir/ts/tsAnyKeyword.h>
54 #include <ir/ts/tsArrayType.h>
55 #include <ir/ts/tsAsExpression.h>
56 #include <ir/ts/tsBigintKeyword.h>
57 #include <ir/ts/tsBooleanKeyword.h>
58 #include <ir/ts/tsClassImplements.h>
59 #include <ir/ts/tsConditionalType.h>
60 #include <ir/ts/tsConstructorType.h>
61 #include <ir/ts/tsEnumDeclaration.h>
62 #include <ir/ts/tsEnumMember.h>
63 #include <ir/ts/tsFunctionType.h>
64 #include <ir/ts/tsImportType.h>
65 #include <ir/ts/tsIndexSignature.h>
66 #include <ir/ts/tsIndexedAccessType.h>
67 #include <ir/ts/tsInferType.h>
68 #include <ir/ts/tsIntersectionType.h>
69 #include <ir/ts/tsLiteralType.h>
70 #include <ir/ts/tsMappedType.h>
71 #include <ir/ts/tsMethodSignature.h>
72 #include <ir/ts/tsModuleDeclaration.h>
73 #include <ir/ts/tsNamedTupleMember.h>
74 #include <ir/ts/tsNeverKeyword.h>
75 #include <ir/ts/tsNullKeyword.h>
76 #include <ir/ts/tsNumberKeyword.h>
77 #include <ir/ts/tsObjectKeyword.h>
78 #include <ir/ts/tsOptionalType.h>
79 #include <ir/ts/tsParameterProperty.h>
80 #include <ir/ts/tsParenthesizedType.h>
81 #include <ir/ts/tsPrivateIdentifier.h>
82 #include <ir/ts/tsPropertySignature.h>
83 #include <ir/ts/tsQualifiedName.h>
84 #include <ir/ts/tsRestType.h>
85 #include <ir/ts/tsSignatureDeclaration.h>
86 #include <ir/ts/tsStringKeyword.h>
87 #include <ir/ts/tsSymbolKeyword.h>
88 #include <ir/ts/tsTemplateLiteralType.h>
89 #include <ir/ts/tsThisType.h>
90 #include <ir/ts/tsTupleType.h>
91 #include <ir/ts/tsTypeAssertion.h>
92 #include <ir/ts/tsTypeLiteral.h>
93 #include <ir/ts/tsTypeOperator.h>
94 #include <ir/ts/tsTypeParameterDeclaration.h>
95 #include <ir/ts/tsTypeParameterInstantiation.h>
96 #include <ir/ts/tsTypePredicate.h>
97 #include <ir/ts/tsTypeQuery.h>
98 #include <ir/ts/tsTypeReference.h>
99 #include <ir/ts/tsUndefinedKeyword.h>
100 #include <ir/ts/tsUnionType.h>
101 #include <ir/ts/tsUnknownKeyword.h>
102 #include <ir/ts/tsVoidKeyword.h>
103 #include <lexer/lexer.h>
104 #include <lexer/token/letters.h>
105 #include <lexer/token/sourceLocation.h>
106 #include <mem/pool_manager.h>
107 
108 namespace panda::es2panda::parser {
109 
ParserImpl(ScriptExtension extension)110 ParserImpl::ParserImpl(ScriptExtension extension) : program_(extension), context_(&program_) {}
111 
InitLexer(const std::string & fileName,const std::string & source)112 std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const std::string &fileName, const std::string &source)
113 {
114     bool isDtsFile = false;
115     if (Extension() == ScriptExtension::TS) {
116         isDtsFile = util::Helpers::FileExtensionIs(fileName, ".d.ts");
117     }
118     program_.SetSource(source, fileName, isDtsFile);
119     auto lexer = std::make_unique<lexer::Lexer>(&context_);
120     lexer_ = lexer.get();
121 
122     return lexer;
123 }
124 
Parse(const std::string & fileName,const std::string & source,const std::string & recordName,ScriptKind kind)125 Program ParserImpl::Parse(const std::string &fileName, const std::string &source,
126                           const std::string &recordName, ScriptKind kind)
127 {
128     program_.SetKind(kind);
129     program_.SetRecordName(recordName);
130 
131     /*
132      * In order to make the lexer's memory alive, the return value 'lexer' can not be omitted.
133      */
134     auto lexer = InitLexer(fileName, source);
135     switch (kind) {
136         case ScriptKind::SCRIPT: {
137             ParseScript();
138             break;
139         }
140         case ScriptKind::MODULE: {
141             ParseModule();
142             break;
143         }
144         case ScriptKind::COMMONJS: {
145             ParseCommonjs();
146             break;
147         }
148         default: {
149             UNREACHABLE();
150         }
151     }
152     binder::ResolveBindingFlags bindFlags = binder::ResolveBindingFlags::ALL;
153     if (Extension() == ScriptExtension::TS) {
154         bindFlags = binder::ResolveBindingFlags::TS_BEFORE_TRANSFORM;
155     }
156     Binder()->IdentifierAnalysis(bindFlags);
157     return std::move(program_);
158 }
159 
ParseScript()160 void ParserImpl::ParseScript()
161 {
162     ParseProgram(ScriptKind::SCRIPT);
163 }
164 
ParseModule()165 void ParserImpl::ParseModule()
166 {
167     context_.Status() |= (ParserStatus::MODULE);
168     ParseProgram(ScriptKind::MODULE);
169 }
170 
ParseProgram(ScriptKind kind)171 void ParserImpl::ParseProgram(ScriptKind kind)
172 {
173     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
174     lexer_->NextToken();
175 
176     auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
177     if (IsDtsFile() && !CheckTopStatementsForRequiredDeclare(statements)) {
178         ThrowSyntaxError(
179             "Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier.");
180     }
181 
182     auto *blockStmt = AllocNode<ir::BlockStatement>(Binder()->GetScope(), std::move(statements));
183     Binder()->GetScope()->BindNode(blockStmt);
184     blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
185 
186     program_.SetAst(blockStmt);
187 }
188 
CheckTopStatementsForRequiredDeclare(const ArenaVector<ir::Statement * > & statements)189 bool ParserImpl::CheckTopStatementsForRequiredDeclare(const ArenaVector<ir::Statement *> &statements)
190 {
191     for (auto *statement : statements) {
192         switch (statement->Type()) {
193             case ir::AstNodeType::TS_INTERFACE_DECLARATION:
194             case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION:
195             case ir::AstNodeType::IMPORT_DECLARATION:
196             case ir::AstNodeType::TS_IMPORT_EQUALS_DECLARATION:
197             case ir::AstNodeType::EXPORT_ALL_DECLARATION:
198             case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION:
199             case ir::AstNodeType::EXPORT_NAMED_DECLARATION:
200             case ir::AstNodeType::TS_NAMESPACE_EXPORT_DECLARATION:
201                 continue;
202             case ir::AstNodeType::CLASS_DECLARATION: {
203                 if (!statement->AsClassDeclaration()->Definition()->Declare()) {
204                     return false;
205                 }
206                 break;
207             }
208             case ir::AstNodeType::FUNCTION_DECLARATION: {
209                 if (!statement->AsFunctionDeclaration()->Function()->Declare() &&
210                     !statement->AsFunctionDeclaration()->Function()->IsOverload()) {
211                     return false;
212                 }
213                 break;
214             }
215             case ir::AstNodeType::VARIABLE_DECLARATION: {
216                 if (!statement->AsVariableDeclaration()->Declare()) {
217                     return false;
218                 }
219                 break;
220             }
221             case ir::AstNodeType::TS_MODULE_DECLARATION: {
222                 if (!statement->AsTSModuleDeclaration()->Declare()) {
223                     return false;
224                 }
225                 break;
226             }
227             case ir::AstNodeType::TS_ENUM_DECLARATION: {
228                 if (!statement->AsTSEnumDeclaration()->IsDeclare()) {
229                     return false;
230                 }
231                 break;
232             }
233             default:
234                 ThrowSyntaxError("Statements are not allowed in ambient contexts.");
235                 UNREACHABLE();
236         }
237     }
238     return true;
239 }
240 
241 /*
242  * Definitions of private methods
243  */
CarryExpressionParserFlag(ExpressionParseFlags origin,ExpressionParseFlags carry)244 ExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry)
245 {
246     return static_cast<ExpressionParseFlags>(origin & carry);
247 }
248 
CarryPatternFlags(ExpressionParseFlags flags)249 ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags)
250 {
251     return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
252                                                 ExpressionParseFlags::OBJECT_PATTERN);
253 }
254 
CarryAllowTsParamAndPatternFlags(ExpressionParseFlags flags)255 ExpressionParseFlags ParserImpl::CarryAllowTsParamAndPatternFlags(ExpressionParseFlags flags)
256 {
257     return CarryExpressionParserFlag(flags, ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN |
258                                             ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
259                                             ExpressionParseFlags::OBJECT_PATTERN);
260 }
261 
CurrentLiteralIsBasicType()262 bool ParserImpl::CurrentLiteralIsBasicType()
263 {
264     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
265            lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
266 
267     switch (lexer_->GetToken().KeywordType()) {
268         case lexer::TokenType::KEYW_ANY:
269         case lexer::TokenType::KEYW_BOOLEAN:
270         case lexer::TokenType::KEYW_NUMBER:
271         case lexer::TokenType::KEYW_STRING:
272         case lexer::TokenType::KEYW_SYMBOL:
273         case lexer::TokenType::KEYW_UNKNOWN:
274         case lexer::TokenType::KEYW_UNDEFINED:
275         case lexer::TokenType::KEYW_NEVER:
276         case lexer::TokenType::KEYW_OBJECT:
277         case lexer::TokenType::KEYW_BIGINT: {
278             return true;
279         }
280         default: {
281             break;
282         }
283     }
284 
285     return false;
286 }
CurrentIsBasicType()287 bool ParserImpl::CurrentIsBasicType()
288 {
289     switch (lexer_->GetToken().Type()) {
290         case lexer::TokenType::PUNCTUATOR_MINUS:
291         case lexer::TokenType::LITERAL_NUMBER:
292         case lexer::TokenType::LITERAL_STRING:
293         case lexer::TokenType::LITERAL_FALSE:
294         case lexer::TokenType::LITERAL_TRUE:
295         case lexer::TokenType::LITERAL_NULL:
296         case lexer::TokenType::KEYW_VOID: {
297             return true;
298         }
299         case lexer::TokenType::LITERAL_IDENT: {
300             return CurrentLiteralIsBasicType();
301         }
302         default: {
303             break;
304         }
305     }
306 
307     return false;
308 }
309 
ParseTsConstExpression()310 ir::TSTypeReference *ParserImpl::ParseTsConstExpression()
311 {
312     auto *identRef = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
313     identRef->SetReference();
314     identRef->SetRange(lexer_->GetToken().Loc());
315 
316     auto *typeReference = AllocNode<ir::TSTypeReference>(identRef, nullptr);
317     typeReference->SetRange(lexer_->GetToken().Loc());
318 
319     lexer_->NextToken();
320 
321     return typeReference;
322 }
323 
ParseTsIdentifierReference(TypeAnnotationParsingOptions options)324 ir::Expression *ParserImpl::ParseTsIdentifierReference(TypeAnnotationParsingOptions options)
325 {
326     if (CurrentLiteralIsBasicType() && lexer_->Lookahead() != LEX_CHAR_DOT) {
327         return ParseTsBasicType(options);
328     }
329 
330     return ParseTsTypeReferenceOrQuery(options, false);
331 }
332 
IsStartOfMappedType() const333 bool ParserImpl::IsStartOfMappedType() const
334 {
335     auto pos = lexer_->Save();
336     lexer_->NextToken();
337     bool result = false;
338 
339     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
340         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
341         lexer_->NextToken();
342         result = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY;
343         lexer_->Rewind(pos);
344         return result;
345     }
346 
347     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
348         lexer_->NextToken();
349     }
350 
351     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
352         lexer_->Rewind(pos);
353         return false;
354     }
355 
356     lexer_->NextToken();
357 
358     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
359         lexer_->Rewind(pos);
360         return false;
361     }
362 
363     lexer_->NextToken();
364 
365     result = lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN;
366 
367     lexer_->Rewind(pos);
368     return result;
369 }
370 
IsStartOfTsTypePredicate() const371 bool ParserImpl::IsStartOfTsTypePredicate() const
372 {
373     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
374            lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
375 
376     auto pos = lexer_->Save();
377     bool isAsserts = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
378     if (isAsserts) {
379         lexer_->NextToken();
380     }
381 
382     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
383         lexer_->GetToken().Type() != lexer::TokenType::KEYW_THIS) {
384         lexer_->Rewind(pos);
385         return false;
386     }
387 
388     if (isAsserts) {
389         lexer_->Rewind(pos);
390         return true;
391     }
392 
393     lexer_->NextToken();
394 
395     bool result = !lexer_->GetToken().NewLine() && (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IS);
396     lexer_->Rewind(pos);
397     return result;
398 }
399 
IsStartOfAbstractConstructorType() const400 bool ParserImpl::IsStartOfAbstractConstructorType() const
401 {
402     if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_ABSTRACT) {
403         return false;
404     }
405 
406     lexer::LexerPosition pos = lexer_->Save();
407     lexer_->NextToken();  // eat 'abstract'
408     bool result = lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW;
409 
410     lexer_->Rewind(pos);
411 
412     return result;
413 }
414 
ParseTsTypeLiteralOrTsMappedType(ir::Expression * typeAnnotation)415 ir::Expression *ParserImpl::ParseTsTypeLiteralOrTsMappedType(ir::Expression *typeAnnotation)
416 {
417     if (typeAnnotation) {
418         return nullptr;
419     }
420 
421     if (IsStartOfMappedType()) {
422         return ParseTsMappedType();
423     }
424 
425     lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
426     auto members = ParseTsTypeLiteralOrInterface();
427     lexer::SourcePosition bodyEnd = lexer_->GetToken().End();
428     lexer_->NextToken();
429 
430     auto *literalType = AllocNode<ir::TSTypeLiteral>(std::move(members));
431     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, literalType);
432     literalType->SetVariable(typeVar);
433     literalType->SetRange({bodyStart, bodyEnd});
434     return literalType;
435 }
436 
ParseTsTypeReferenceOrTsTypePredicate(ir::Expression * typeAnnotation,bool canBeTsTypePredicate,bool throwError)437 ir::Expression *ParserImpl::ParseTsTypeReferenceOrTsTypePredicate(ir::Expression *typeAnnotation,
438                                                                   bool canBeTsTypePredicate, bool throwError)
439 {
440     if (typeAnnotation) {
441         return nullptr;
442     }
443 
444     if (canBeTsTypePredicate && IsStartOfTsTypePredicate()) {
445         return ParseTsTypePredicate();
446     }
447 
448     return ParseTsTypeOperatorOrTypeReference(throwError);
449 }
450 
ParseTsThisTypeOrTsTypePredicate(ir::Expression * typeAnnotation,bool canBeTsTypePredicate,bool throwError)451 ir::Expression *ParserImpl::ParseTsThisTypeOrTsTypePredicate(ir::Expression *typeAnnotation, bool canBeTsTypePredicate,
452                                                              bool throwError)
453 {
454     if (typeAnnotation) {
455         return nullptr;
456     }
457 
458     if (canBeTsTypePredicate && IsStartOfTsTypePredicate()) {
459         return ParseTsTypePredicate();
460     }
461 
462     return ParseTsThisType(throwError);
463 }
464 
ParseTsTemplateLiteralType(bool throwError)465 ir::Expression *ParserImpl::ParseTsTemplateLiteralType(bool throwError)
466 {
467     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK);
468     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
469 
470     ArenaVector<ir::TemplateElement *> quasis(Allocator()->Adapter());
471     ArenaVector<ir::Expression *> references(Allocator()->Adapter());
472 
473     while (true) {
474         lexer_->ResetTokenEnd();
475         const auto startPos = lexer_->Save();
476 
477         lexer_->ScanString<LEX_CHAR_BACK_TICK>();
478         util::StringView cooked = lexer_->GetToken().String();
479 
480         lexer_->Rewind(startPos);
481         auto [raw, end, scanExpression] = lexer_->ScanTemplateString();
482 
483         auto *element = AllocNode<ir::TemplateElement>(raw.View(), cooked);
484         element->SetRange({lexer::SourcePosition{startPos.iterator.Index(), startPos.line},
485                            lexer::SourcePosition{end, lexer_->Line()}});
486         quasis.push_back(element);
487 
488         if (!scanExpression) {
489             lexer_->ScanTemplateStringEnd();
490             break;
491         }
492 
493         ir::Expression *reference = nullptr;
494 
495         {
496             lexer::TemplateLiteralParserContext ctx(lexer_);
497             lexer_->PushTemplateContext(&ctx);
498             lexer_->NextToken();
499             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
500             reference = ParseTsTypeAnnotation(&options);
501         }
502 
503         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
504             if (throwError) {
505                 ThrowSyntaxError("Unexpected token, expected '}'.");
506             }
507             return nullptr;
508         }
509 
510         references.push_back(reference);
511     }
512 
513     ir::Expression *typeAnnotation = AllocNode<ir::TSTemplateLiteralType>(std::move(quasis), std::move(references));
514     typeAnnotation->SetRange({startLoc, lexer_->GetToken().End()});
515 
516     lexer_->NextToken();
517 
518     return typeAnnotation;
519 }
520 
ParseTsTypeAnnotationElement(ir::Expression * typeAnnotation,TypeAnnotationParsingOptions * options)521 ir::Expression *ParserImpl::ParseTsTypeAnnotationElement(ir::Expression *typeAnnotation,
522                                                          TypeAnnotationParsingOptions *options)
523 {
524     switch (lexer_->GetToken().Type()) {
525         case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
526             if (*options & (TypeAnnotationParsingOptions::IN_MODIFIER | TypeAnnotationParsingOptions::IN_UNION |
527                 TypeAnnotationParsingOptions::IN_INTERSECTION)) {
528                 break;
529             }
530 
531             return ParseTsUnionType(typeAnnotation, *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
532         }
533         case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
534             if (*options & (TypeAnnotationParsingOptions::IN_MODIFIER |
535 	        TypeAnnotationParsingOptions::IN_INTERSECTION)) {
536                 break;
537             }
538 
539             return ParseTsIntersectionType(typeAnnotation, *options & TypeAnnotationParsingOptions::IN_UNION,
540                                            *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
541         }
542         case lexer::TokenType::PUNCTUATOR_LESS_THAN:
543         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
544         case lexer::TokenType::KEYW_NEW: {
545             return ParseTsParenthesizedOrFunctionType(typeAnnotation,
546                                                       *options & TypeAnnotationParsingOptions::THROW_ERROR);
547         }
548         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
549             if (typeAnnotation) {
550                 if (lexer_->GetToken().NewLine()) {
551                     break;
552                 }
553                 if (lexer_->Lookahead() == LEX_CHAR_RIGHT_SQUARE) {
554                     return ParseTsArrayType(typeAnnotation);
555                 }
556 
557                 return ParseTsIndexAccessType(typeAnnotation, *options & TypeAnnotationParsingOptions::THROW_ERROR);
558             }
559 
560             return ParseTsTupleType();
561         }
562         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
563             return ParseTsTypeLiteralOrTsMappedType(typeAnnotation);
564         }
565         case lexer::TokenType::PUNCTUATOR_MINUS:
566         case lexer::TokenType::LITERAL_NUMBER:
567         case lexer::TokenType::LITERAL_STRING:
568         case lexer::TokenType::LITERAL_FALSE:
569         case lexer::TokenType::LITERAL_TRUE:
570         case lexer::TokenType::LITERAL_NULL:
571         case lexer::TokenType::KEYW_VOID: {
572             if (typeAnnotation) {
573                 break;
574             }
575 
576             return ParseTsBasicType(*options);
577         }
578         case lexer::TokenType::KEYW_TYPEOF: {
579             if (typeAnnotation) {
580                 break;
581             }
582 
583             return ParseTsTypeReferenceOrQuery(*options, true);
584         }
585         case lexer::TokenType::KEYW_IMPORT: {
586             if (typeAnnotation) {
587                 break;
588             }
589 
590             lexer::SourcePosition startLoc = lexer_->GetToken().Start();
591             return ParseTsImportType(startLoc);
592         }
593         case lexer::TokenType::KEYW_CONST: {
594             if (!(*options & TypeAnnotationParsingOptions::ALLOW_CONST)) {
595                 break;
596             }
597 
598             *options &= ~TypeAnnotationParsingOptions::ALLOW_CONST;
599             return ParseTsConstExpression();
600         }
601         case lexer::TokenType::LITERAL_IDENT: {
602             if (IsStartOfAbstractConstructorType()) {
603                 return ParseTsParenthesizedOrFunctionType(typeAnnotation,
604                                                           *options & TypeAnnotationParsingOptions::THROW_ERROR);
605             }
606 
607             return ParseTsTypeReferenceOrTsTypePredicate(
608                 typeAnnotation, *options & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE,
609                 *options & TypeAnnotationParsingOptions::THROW_ERROR);
610         }
611         case lexer::TokenType::KEYW_EXTENDS: {
612             if (*options & (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) {
613                 break;
614             }
615 
616             if (!typeAnnotation) {
617                 return ParseTsIdentifierReference(*options);
618             }
619 
620             return ParseTsConditionalType(typeAnnotation, *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
621         }
622         case lexer::TokenType::KEYW_THIS: {
623             return ParseTsThisTypeOrTsTypePredicate(typeAnnotation,
624                                                     *options & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE,
625                                                     *options & TypeAnnotationParsingOptions::THROW_ERROR);
626         }
627         case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
628             return ParseTsTemplateLiteralType(*options & TypeAnnotationParsingOptions::THROW_ERROR);
629         }
630         default: {
631             break;
632         }
633     }
634 
635     if (!typeAnnotation && (*options & TypeAnnotationParsingOptions::THROW_ERROR)) {
636         ThrowSyntaxError("Type expected");
637     }
638 
639     return nullptr;
640 }
641 
ParseTsImportType(const lexer::SourcePosition & startLoc,bool isTypeof)642 ir::TSImportType *ParserImpl::ParseTsImportType(const lexer::SourcePosition &startLoc, bool isTypeof)
643 {
644     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_IMPORT);
645 
646     lexer_->NextToken();
647 
648     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
649         ThrowSyntaxError("'(' expected");
650     }
651 
652     lexer_->NextToken();
653 
654     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
655     ir::Expression *param = ParseTsTypeAnnotation(&options);
656 
657     if (!param->IsTSLiteralType() || !param->AsTSLiteralType()->Literal()->IsStringLiteral()) {
658         ThrowSyntaxError("String literal expected");
659     }
660 
661     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
662         ThrowSyntaxError("')' expected");
663     }
664 
665     lexer_->NextToken();
666 
667     ir::Expression *qualifier = nullptr;
668     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
669         lexer_->NextToken();
670 
671         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
672             ThrowSyntaxError("Identifier expected");
673         }
674 
675         qualifier = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
676         qualifier->SetRange(lexer_->GetToken().Loc());
677 
678         lexer_->NextToken();
679 
680         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
681             qualifier = ParseTsQualifiedReference(qualifier);
682         }
683     }
684 
685     ir::TSTypeParameterInstantiation *typeParams = nullptr;
686     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT ||
687         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
688         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
689             lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
690         }
691 
692         typeParams = ParseTsTypeParameterInstantiation();
693     }
694 
695     auto *importType = AllocNode<ir::TSImportType>(param, typeParams, qualifier, isTypeof);
696 
697     importType->SetRange({startLoc, lexer_->GetToken().End()});
698 
699     return importType;
700 }
701 
ParseTsThisType(bool throwError)702 ir::Expression *ParserImpl::ParseTsThisType(bool throwError)
703 {
704     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
705 
706     if (throwError && !(context_.Status() & ParserStatus::ALLOW_THIS_TYPE)) {
707         ThrowSyntaxError(
708             "A 'this' type is available only in a non-static member "
709             "of a class or interface.");
710     }
711 
712     auto *returnType = AllocNode<ir::TSThisType>();
713     returnType->SetRange(lexer_->GetToken().Loc());
714 
715     lexer_->NextToken();
716 
717     return returnType;
718 }
719 
ParseTsConditionalType(ir::Expression * checkType,bool restrictExtends)720 ir::Expression *ParserImpl::ParseTsConditionalType(ir::Expression *checkType, bool restrictExtends)
721 {
722     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
723     if (restrictExtends) {
724         ThrowSyntaxError("'?' expected.");
725     }
726 
727     lexer::SourcePosition startLoc = checkType->Start();
728 
729     lexer_->NextToken();  // eat 'extends'
730 
731     ParserStatus savedStatus = context_.Status();
732     context_.Status() |= ParserStatus::IN_EXTENDS;
733 
734     TypeAnnotationParsingOptions options =
735         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
736     auto *extendsType = ParseTsTypeAnnotation(&options);
737 
738     context_.Status() = savedStatus;
739 
740     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
741         ThrowSyntaxError("'?' expected.");
742     }
743 
744     lexer_->NextToken();  // eat '?'
745 
746     options &= ~TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
747     auto *trueType = ParseTsTypeAnnotation(&options);
748 
749     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
750         ThrowSyntaxError("':' expected.");
751     }
752 
753     lexer_->NextToken();  // eat ':'
754 
755     auto *falseType = ParseTsTypeAnnotation(&options);
756 
757     lexer::SourcePosition endLoc = falseType->End();
758 
759     auto *conditionalType = AllocNode<ir::TSConditionalType>(checkType, extendsType, trueType, falseType);
760 
761     conditionalType->SetRange({startLoc, endLoc});
762 
763     return conditionalType;
764 }
765 
ParseTsTypeAnnotation(TypeAnnotationParsingOptions * options)766 ir::Expression *ParserImpl::ParseTsTypeAnnotation(TypeAnnotationParsingOptions *options)
767 {
768     ir::Expression *typeAnnotation = nullptr;
769 
770     while (true) {
771         ir::Expression *element = ParseTsTypeAnnotationElement(typeAnnotation, options);
772 
773         *options &= ~TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
774 
775         if (!element) {
776             break;
777         }
778 
779         typeAnnotation = element;
780 
781         if ((*options & TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE) && lexer_->GetToken().NewLine()) {
782             break;
783         }
784     }
785 
786     return typeAnnotation;
787 }
788 
ParseTsTypeOperatorOrTypeReference(bool throwError)789 ir::Expression *ParserImpl::ParseTsTypeOperatorOrTypeReference(bool throwError)
790 {
791     TypeAnnotationParsingOptions options = throwError ?
792         TypeAnnotationParsingOptions::THROW_ERROR : TypeAnnotationParsingOptions::NO_OPTS;
793 
794     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
795         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
796         lexer_->NextToken();
797 
798         options |= TypeAnnotationParsingOptions::IN_MODIFIER;
799         ir::Expression *type = ParseTsTypeAnnotation(&options);
800         ASSERT(type != nullptr);
801 
802         if (!type->IsTSArrayType() && !type->IsTSTupleType()) {
803             ThrowSyntaxError(
804                 "'readonly' type modifier is only permitted on array "
805                 "and tuple literal types.");
806         }
807 
808         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::READONLY);
809 
810         typeOperator->SetRange({typeOperatorStart, type->End()});
811 
812         return typeOperator;
813     }
814 
815     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_KEYOF) {
816         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
817         lexer_->NextToken();
818 
819         options |= TypeAnnotationParsingOptions::IN_MODIFIER;
820         ir::Expression *type = ParseTsTypeAnnotation(&options);
821         ASSERT(type != nullptr);
822 
823         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::KEYOF);
824 
825         typeOperator->SetRange({typeOperatorStart, type->End()});
826 
827         return typeOperator;
828     }
829 
830     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNIQUE) {
831         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
832         lexer_->NextToken();
833 
834         ir::Expression *type = ParseTsTypeAnnotation(&options);
835         ASSERT(type != nullptr);
836 
837         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::UNIQUE);
838 
839         typeOperator->SetRange({typeOperatorStart, type->End()});
840 
841         return typeOperator;
842     }
843 
844     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INFER) {
845         if (!(context_.Status() & ParserStatus::IN_EXTENDS)) {
846             ThrowSyntaxError(
847                 "'infer' declarations are only permitted in the "
848                 "'extends' clause of a conditional type.");
849         }
850 
851         lexer::SourcePosition inferStart = lexer_->GetToken().Start();
852         lexer_->NextToken();
853 
854         ir::TSTypeParameter *typeParam = ParseTsTypeParameter(true);
855 
856         auto *inferType = AllocNode<ir::TSInferType>(typeParam);
857 
858         inferType->SetRange({inferStart, lexer_->GetToken().End()});
859 
860         return inferType;
861     }
862 
863     return ParseTsIdentifierReference(options);
864 }
865 
IsTSNamedTupleMember()866 bool ParserImpl::IsTSNamedTupleMember()
867 {
868     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
869         return false;
870     }
871     const auto savePos = lexer_->Save();
872     bool isNamedMember = false;
873     lexer_->NextToken();
874     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON ||
875         (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK &&
876          lexer_->Lookahead() == LEX_CHAR_COLON)) {
877             isNamedMember = true;
878     }
879     lexer_->Rewind(savePos);
880     return isNamedMember;
881 }
882 
HandleRestType(ir::AstNodeType elementType,bool * hasRestType) const883 void ParserImpl::HandleRestType(ir::AstNodeType elementType, bool *hasRestType) const
884 {
885     if (elementType ==  ir::AstNodeType::TS_ARRAY_TYPE && *hasRestType) {
886         ThrowSyntaxError("A rest element cannot follow another rest element");
887     }
888     *hasRestType = true;
889 }
890 
ParseTsTupleElement(ir::TSTupleKind * kind,bool * seenOptional,bool * hasRestType)891 ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *seenOptional, bool *hasRestType)
892 {
893     lexer::SourcePosition startPos = lexer_->GetToken().Start();
894     ir::Expression *element = nullptr;
895     bool isRestType = false;
896     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
897 
898     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
899         isRestType = true;
900         lexer_->NextToken();  // eat '...'
901     }
902 
903     if (IsTSNamedTupleMember()) {
904         if (*kind == ir::TSTupleKind::DEFAULT) {
905             ThrowSyntaxError("Tuple members must all have or haven't names");
906         }
907         *kind = ir::TSTupleKind::NAMED;
908 
909         auto *elementIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
910         elementIdent->SetRange(lexer_->GetToken().Loc());
911         lexer_->NextToken();  // eat identifier
912 
913         bool isOptional = false;
914         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
915             lexer_->NextToken();  // eat '?'
916             isOptional = true;
917             *seenOptional = true;
918         } else if (*seenOptional && !isRestType) {
919             ThrowSyntaxError("A required element cannot follow an optional element");
920         }
921 
922         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
923             ThrowSyntaxError("':' expected");
924         }
925 
926         lexer_->NextToken();  // eat ':'
927         auto *elementType = ParseTsTypeAnnotation(&options);
928         ASSERT(elementType != nullptr);
929 
930         if (elementType && isRestType) {
931             HandleRestType(elementType->Type(), hasRestType);
932         }
933 
934         element = AllocNode<ir::TSNamedTupleMember>(elementIdent, elementType, isOptional, isRestType);
935         element->SetRange({startPos, elementType->End()});
936     } else {
937         if (*kind == ir::TSTupleKind::NAMED) {
938             ThrowSyntaxError("Tuple members must all have or haven't names");
939         }
940         *kind = ir::TSTupleKind::DEFAULT;
941 
942         element = ParseTsTypeAnnotation(&options);
943         ASSERT(element != nullptr);
944         if (element && isRestType) {
945             HandleRestType(element->Type(), hasRestType);
946             lexer::SourcePosition endPos = element->End();
947             element = AllocNode<ir::TSRestType>(std::move(element));
948             element->SetRange({startPos, endPos});
949         }
950 
951         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
952             lexer::SourcePosition elementStartPos = element->Start();
953             element = AllocNode<ir::TSOptionalType>(std::move(element));
954             element->SetRange({elementStartPos, lexer_->GetToken().End()});
955             lexer_->NextToken();  // eat '?'
956             *seenOptional = true;
957         } else if (*seenOptional && !isRestType) {
958             ThrowSyntaxError("A required element cannot follow an optional element");
959         }
960     }
961     return element;
962 }
963 
ParseTsTupleType()964 ir::TSTupleType *ParserImpl::ParseTsTupleType()
965 {
966     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
967     lexer::SourcePosition tupleStart = lexer_->GetToken().Start();
968     ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
969     ir::TSTupleKind kind = ir::TSTupleKind::NONE;
970     bool seenOptional = false;
971     bool hasRestType = false;
972 
973     lexer_->NextToken();  // eat '['
974 
975     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
976         ir::Expression *element = ParseTsTupleElement(&kind, &seenOptional, &hasRestType);
977 
978         elements.push_back(element);
979 
980         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
981             break;
982         }
983 
984         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
985             ThrowSyntaxError("',' expected.");
986         }
987 
988         lexer_->NextToken();  // eat ','
989     }
990 
991     lexer::SourcePosition tupleEnd = lexer_->GetToken().End();
992     lexer_->NextToken();  // eat ']'
993 
994     auto *tupleType = AllocNode<ir::TSTupleType>(std::move(elements));
995     tupleType->SetRange({tupleStart, tupleEnd});
996     return tupleType;
997 }
998 
ParseTsQualifiedReference(ir::Expression * typeName)999 ir::Expression *ParserImpl::ParseTsQualifiedReference(ir::Expression *typeName)
1000 {
1001     lexer::SourcePosition startLoc = typeName->Start();
1002 
1003     do {
1004         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '.'
1005 
1006         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1007             ThrowSyntaxError("Identifier expected");
1008         }
1009 
1010         auto *propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1011         propName->SetRange(lexer_->GetToken().Loc());
1012 
1013         typeName = AllocNode<ir::TSQualifiedName>(typeName, propName);
1014         typeName->SetRange({typeName->AsTSQualifiedName()->Left()->Start(), lexer_->GetToken().End()});
1015 
1016         lexer_->NextToken();
1017     } while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD);
1018 
1019     typeName->SetRange({startLoc, lexer_->GetToken().End()});
1020 
1021     return typeName;
1022 }
1023 
ParseTsIndexAccessType(ir::Expression * typeName,bool throwError)1024 ir::Expression *ParserImpl::ParseTsIndexAccessType(ir::Expression *typeName, bool throwError)
1025 {
1026     TypeAnnotationParsingOptions options = throwError ?
1027         TypeAnnotationParsingOptions::THROW_ERROR : TypeAnnotationParsingOptions::NO_OPTS;
1028 
1029     do {
1030         lexer_->NextToken();  // eat '['
1031 
1032         ir::Expression *indexType = ParseTsTypeAnnotation(&options);
1033 
1034         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1035             if (!throwError) {
1036                 return nullptr;
1037             }
1038             ThrowSyntaxError("']' expected");
1039         }
1040 
1041         lexer_->NextToken();  // eat ']'
1042 
1043         typeName = AllocNode<ir::TSIndexedAccessType>(typeName, indexType);
1044         typeName->SetRange({typeName->AsTSIndexedAccessType()->ObjectType()->Start(), lexer_->GetToken().End()});
1045     } while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
1046              lexer_->Lookahead() != LEX_CHAR_RIGHT_SQUARE);
1047 
1048     return typeName;
1049 }
1050 
ParseTsTypeReferenceOrQuery(TypeAnnotationParsingOptions options,bool parseQuery)1051 ir::Expression *ParserImpl::ParseTsTypeReferenceOrQuery(TypeAnnotationParsingOptions options, bool parseQuery)
1052 {
1053     lexer::SourcePosition referenceStartLoc = lexer_->GetToken().Start();
1054 
1055     if (parseQuery) {
1056         ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_TYPEOF);
1057         lexer_->NextToken();  // eat 'typeof'
1058 
1059         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) {
1060             lexer::SourcePosition &startLoc = referenceStartLoc;
1061             return ParseTsImportType(startLoc, true);
1062         }
1063 
1064         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1065             ThrowSyntaxError("Identifier expected.");
1066         }
1067     }
1068 
1069     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
1070            lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
1071 
1072     ir::Expression *typeName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1073     typeName->SetRange(lexer_->GetToken().Loc());
1074     typeName->AsIdentifier()->SetReference();
1075 
1076     if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
1077         lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
1078     } else {
1079         lexer_->NextToken();
1080     }
1081 
1082     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
1083         typeName = ParseTsQualifiedReference(typeName);
1084     }
1085 
1086     ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
1087     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1088         if (parseQuery) {
1089             ThrowSyntaxError("Unexpected token.");
1090         }
1091 
1092         typeParamInst = ParseTsTypeParameterInstantiation(options & TypeAnnotationParsingOptions::THROW_ERROR);
1093     }
1094 
1095     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
1096         lexer_->Lookahead() != LEX_CHAR_RIGHT_SQUARE) {
1097         if (parseQuery) {
1098             typeName = AllocNode<ir::TSTypeQuery>(typeName);
1099         } else {
1100             typeName = AllocNode<ir::TSTypeReference>(typeName, typeParamInst);
1101         }
1102 
1103         typeName->SetRange({referenceStartLoc, lexer_->GetToken().End()});
1104 
1105         return ParseTsIndexAccessType(typeName, options & TypeAnnotationParsingOptions::THROW_ERROR);
1106     }
1107 
1108     ir::Expression *returnNode = nullptr;
1109 
1110     lexer::SourcePosition referenceEndLoc = typeName->End();
1111 
1112     if (parseQuery) {
1113         returnNode = AllocNode<ir::TSTypeQuery>(typeName);
1114     } else {
1115         returnNode = AllocNode<ir::TSTypeReference>(typeName, typeParamInst);
1116     }
1117 
1118     returnNode->SetRange({referenceStartLoc, referenceEndLoc});
1119 
1120     return returnNode;
1121 }
1122 
ParseTsMappedTypeParameter()1123 ir::TSTypeParameter *ParserImpl::ParseTsMappedTypeParameter()
1124 {
1125     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1126 
1127     auto *paramName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1128     paramName->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
1129 
1130     lexer_->NextToken();
1131 
1132     lexer_->NextToken();  // eat 'in'
1133 
1134     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1135     ir::Expression *constraint = ParseTsTypeAnnotation(&options);
1136 
1137     lexer::SourcePosition endLoc = constraint->End();
1138 
1139     auto *typeParameter = AllocNode<ir::TSTypeParameter>(paramName, constraint, nullptr);
1140 
1141     typeParameter->SetRange({startLoc, endLoc});
1142 
1143     return typeParameter;
1144 }
1145 
ParseMappedOption(lexer::TokenType tokenType)1146 ir::MappedOption ParserImpl::ParseMappedOption(lexer::TokenType tokenType)
1147 {
1148     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MINUS &&
1149         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PLUS &&
1150         lexer_->GetToken().KeywordType() != tokenType && lexer_->GetToken().Type() != tokenType) {
1151         return ir::MappedOption::NO_OPTS;
1152     }
1153 
1154     auto result = lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ? ir::MappedOption::MINUS
1155                                                                                   : ir::MappedOption::PLUS;
1156 
1157     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
1158         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
1159         lexer_->NextToken();
1160     }
1161 
1162     if (lexer_->GetToken().KeywordType() != tokenType && lexer_->GetToken().Type() != tokenType) {
1163         ThrowSyntaxError({"'", TokenToString(tokenType), "' expected."});
1164     }
1165 
1166     lexer_->NextToken();
1167 
1168     return result;
1169 }
1170 
ParseTsMappedType()1171 ir::TSMappedType *ParserImpl::ParseTsMappedType()
1172 {
1173     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1174 
1175     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1176     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
1177 
1178     ir::MappedOption readonly = ParseMappedOption(lexer::TokenType::KEYW_READONLY);
1179 
1180     lexer_->NextToken();  // eat '['
1181 
1182     ir::TSTypeParameter *typeParameter = ParseTsMappedTypeParameter();
1183 
1184     ir::Expression *nameKeyType = nullptr;
1185     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
1186         lexer_->NextToken();  // eat 'as'
1187         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1188         nameKeyType = ParseTsTypeAnnotation(&options);
1189         ASSERT(nameKeyType != nullptr);
1190     }
1191 
1192     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1193         ThrowSyntaxError("']' expected");
1194     }
1195 
1196     lexer_->NextToken();  // eat ']'
1197 
1198     ir::MappedOption optional = ParseMappedOption(lexer::TokenType::PUNCTUATOR_QUESTION_MARK);
1199 
1200     ir::Expression *typeAnnotation = nullptr;
1201     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1202         lexer_->NextToken();  // eat ':'
1203         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1204         typeAnnotation = ParseTsTypeAnnotation(&options);
1205     }
1206 
1207     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1208         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1209         ThrowSyntaxError("';' expected");
1210     }
1211 
1212     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1213         lexer_->NextToken();  // eat ';'
1214     }
1215 
1216     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1217         ThrowSyntaxError("'}' expected");
1218     }
1219 
1220     auto *mappedType = AllocNode<ir::TSMappedType>(typeParameter, nameKeyType, typeAnnotation, readonly, optional);
1221 
1222     mappedType->SetRange({startLoc, lexer_->GetToken().End()});
1223 
1224     lexer_->NextToken();  // eat '}'
1225 
1226     return mappedType;
1227 }
1228 
ParseTsTypePredicate()1229 ir::TSTypePredicate *ParserImpl::ParseTsTypePredicate()
1230 {
1231     auto pos = lexer_->Save();
1232     lexer::SourcePosition startPos = lexer_->GetToken().Start();
1233     bool isAsserts = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
1234     if (isAsserts) {
1235         lexer_->NextToken();  // eat 'asserts'
1236         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IS) {
1237             isAsserts = false;
1238             lexer_->Rewind(pos);
1239         }
1240     }
1241 
1242     ir::Expression *parameterName = nullptr;
1243     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1244         parameterName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1245     } else {
1246         parameterName = AllocNode<ir::TSThisType>();
1247     }
1248 
1249     parameterName->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
1250 
1251     lexer_->NextToken();
1252 
1253     ir::Expression *typeAnnotation = nullptr;
1254     lexer::SourcePosition endPos;
1255     ir::TSTypePredicate *result = nullptr;
1256 
1257     if (isAsserts && lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IS) {
1258         endPos = parameterName->End();
1259         result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts);
1260         result->SetRange({startPos, endPos});
1261         return result;
1262     }
1263 
1264     lexer_->NextToken();  // eat 'is'
1265 
1266     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1267     typeAnnotation = ParseTsTypeAnnotation(&options);
1268     endPos = typeAnnotation->End();
1269 
1270     result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts);
1271 
1272     result->SetRange({startPos, endPos});
1273 
1274     return result;
1275 }
1276 
ParseTsTypeLiteralOrInterfaceKey(bool * computed,bool * signature,bool * isIndexSignature)1277 ir::Expression *ParserImpl::ParseTsTypeLiteralOrInterfaceKey(bool *computed, bool *signature, bool *isIndexSignature)
1278 {
1279     ir::Expression *key = nullptr;
1280 
1281     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
1282         (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NEW ||
1283          (lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN && lexer_->Lookahead() != LEX_CHAR_LESS_THAN))) {
1284         key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1285         key->SetRange(lexer_->GetToken().Loc());
1286         lexer_->NextToken();
1287     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1288         if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1289             key = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1290         } else {
1291             key = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1292         }
1293 
1294         key->SetRange(lexer_->GetToken().Loc());
1295         lexer_->NextToken();
1296     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
1297         key = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1298         key->SetRange(lexer_->GetToken().Loc());
1299         lexer_->NextToken();
1300     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1301         *computed = true;
1302         lexer_->NextToken();  // eat '['
1303 
1304         if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && lexer_->Lookahead() == LEX_CHAR_COLON) {
1305             *isIndexSignature = true;
1306             key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1307             key->SetRange(lexer_->GetToken().Loc());
1308 
1309             lexer_->NextToken();  // eat param
1310 
1311             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1312                 ThrowSyntaxError("':' expected");
1313             }
1314 
1315             lexer_->NextToken();  // eat ':'
1316 
1317             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1318             ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
1319 
1320             if (!typeAnnotation->IsTSNumberKeyword() && !typeAnnotation->IsTSStringKeyword()) {
1321                 ThrowSyntaxError(
1322                     "An index signature parameter type must be either "
1323                     "'string' or 'number'");
1324             }
1325 
1326             key->SetTsTypeAnnotation(typeAnnotation);
1327         } else {
1328             key = ParseExpression();
1329         }
1330 
1331         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1332             ThrowSyntaxError("']' expected");
1333         }
1334 
1335         lexer_->NextToken();  // eat ']'
1336     } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1337                lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN &&
1338                lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NEW) {
1339         ThrowSyntaxError("Unexpected token");
1340     } else {
1341         *signature = true;
1342     }
1343 
1344     return key;
1345 }
1346 
CreateTSVariableForProperty(ir::AstNode * node,const ir::Expression * key,binder::VariableFlags flags)1347 void ParserImpl::CreateTSVariableForProperty(ir::AstNode *node, const ir::Expression *key, binder::VariableFlags flags)
1348 {
1349     binder::Variable *propVar = nullptr;
1350     bool isMethod = flags & binder::VariableFlags::METHOD;
1351     util::StringView propName = "__computed";
1352 
1353     switch (key->Type()) {
1354         case ir::AstNodeType::IDENTIFIER: {
1355             propName = key->AsIdentifier()->Name();
1356             break;
1357         }
1358         case ir::AstNodeType::NUMBER_LITERAL: {
1359             propName = key->AsNumberLiteral()->Str();
1360             flags |= binder::VariableFlags::NUMERIC_NAME;
1361             break;
1362         }
1363         case ir::AstNodeType::STRING_LITERAL: {
1364             propName = key->AsStringLiteral()->Str();
1365             break;
1366         }
1367         default: {
1368             flags |= binder::VariableFlags::COMPUTED;
1369             break;
1370         }
1371     }
1372 
1373     propVar = isMethod ? binder::Scope::CreateVar<binder::MethodDecl>(Allocator(), propName, flags, node)
1374                        : binder::Scope::CreateVar<binder::PropertyDecl>(Allocator(), propName, flags, node);
1375 
1376     node->SetVariable(propVar);
1377 }
1378 
ParseTsTypeLiteralOrInterfaceMember()1379 ir::Expression *ParserImpl::ParseTsTypeLiteralOrInterfaceMember()
1380 {
1381     bool computed = false;
1382     bool optional = false;
1383     bool signature = false;
1384     bool readonly = false;
1385     bool isConstructSignature = false;
1386     bool isIndexSignature = false;
1387     lexer::SourcePosition memberStartLoc = lexer_->GetToken().Start();
1388     char32_t nextToken = lexer_->Lookahead();
1389     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY && nextToken != LEX_CHAR_LEFT_PAREN &&
1390         nextToken != LEX_CHAR_COLON && nextToken != LEX_CHAR_COMMA && nextToken != LEX_CHAR_LESS_THAN &&
1391         nextToken != LEX_CHAR_SEMICOLON) {
1392         readonly = true;
1393         lexer_->NextToken();
1394     }
1395 
1396     ir::Expression *key = ParseTsTypeLiteralOrInterfaceKey(&computed, &signature, &isIndexSignature);
1397 
1398     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1399         if (isIndexSignature) {
1400             ThrowSyntaxError("';' expected");
1401         }
1402 
1403         optional = true;
1404         lexer_->NextToken();  // eat '?'
1405     }
1406 
1407     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEW && signature) {
1408         lexer_->NextToken();  // eat 'new'
1409 
1410         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1411             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1412             ThrowSyntaxError("'(' expected");
1413         }
1414 
1415         isConstructSignature = true;
1416     }
1417 
1418     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1419     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1420         if (isIndexSignature) {
1421             ThrowSyntaxError("';' expected");
1422         }
1423 
1424         typeParamDecl = ParseTsTypeParameterDeclaration();
1425 
1426         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1427             ThrowSyntaxError("'(' expected");
1428         }
1429     }
1430 
1431     ir::Expression *member = nullptr;
1432     ir::Expression *typeAnnotation = nullptr;
1433     binder::VariableFlags flags = binder::VariableFlags::NONE;
1434 
1435     if (optional) {
1436         flags |= binder::VariableFlags::OPTIONAL;
1437     }
1438 
1439     if (readonly) {
1440         flags |= binder::VariableFlags::READONLY;
1441     }
1442 
1443     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && !isIndexSignature) {
1444         FunctionParameterContext funcParamContext(&context_, Binder());
1445         auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1446         ArenaVector<ir::Expression *> params = ParseFunctionParams(true);
1447 
1448         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1449             lexer_->NextToken();  // eat ':'
1450             TypeAnnotationParsingOptions options =
1451                 TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1452             typeAnnotation = ParseTsTypeAnnotation(&options);
1453         }
1454 
1455         if (signature) {
1456             auto kind = isConstructSignature
1457                             ? ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CONSTRUCT_SIGNATURE
1458                             : ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE;
1459             member = AllocNode<ir::TSSignatureDeclaration>(funcParamScope, kind, typeParamDecl, std::move(params),
1460                                                            typeAnnotation);
1461             funcParamScope->BindNode(member);
1462         } else {
1463             member = AllocNode<ir::TSMethodSignature>(funcParamScope, key, typeParamDecl, std::move(params),
1464                                                       typeAnnotation, computed, optional);
1465             funcParamScope->BindNode(member);
1466             CreateTSVariableForProperty(member, key, flags | binder::VariableFlags::METHOD);
1467         }
1468     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1469         lexer_->NextToken();  // eat ':'
1470         TypeAnnotationParsingOptions options =
1471             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
1472         typeAnnotation = ParseTsTypeAnnotation(&options);
1473     } else if (isIndexSignature) {
1474         ThrowSyntaxError("An index signature must have a type annotation.", memberStartLoc);
1475     }
1476 
1477     if (!member && isIndexSignature) {
1478         member = AllocNode<ir::TSIndexSignature>(key, typeAnnotation, readonly);
1479     } else if (!member) {
1480         member = AllocNode<ir::TSPropertySignature>(key, typeAnnotation, computed, optional, readonly);
1481         CreateTSVariableForProperty(member, key, flags | binder::VariableFlags::PROPERTY);
1482     } else if (readonly) {
1483         ThrowSyntaxError(
1484             "'readonly' modifier can only appear on a property "
1485             "declaration or index signature.",
1486             memberStartLoc);
1487     }
1488 
1489     member->SetRange({memberStartLoc, lexer_->GetToken().End()});
1490 
1491     return member;
1492 }
1493 
GetTSPropertyName(ir::Expression * key)1494 util::StringView GetTSPropertyName(ir::Expression *key)
1495 {
1496     switch (key->Type()) {
1497         case ir::AstNodeType::IDENTIFIER: {
1498             return key->AsIdentifier()->Name();
1499         }
1500         case ir::AstNodeType::NUMBER_LITERAL: {
1501             return key->AsNumberLiteral()->Str();
1502         }
1503         case ir::AstNodeType::STRING_LITERAL: {
1504             return key->AsStringLiteral()->Str();
1505         }
1506         default: {
1507             UNREACHABLE();
1508         }
1509     }
1510 }
1511 
CheckObjectTypeForDuplicatedProperties(ir::Expression * member,ArenaVector<ir::Expression * > const & members)1512 void ParserImpl::CheckObjectTypeForDuplicatedProperties(ir::Expression *member, ArenaVector<ir::Expression *> const &members)
1513 {
1514     ir::Expression *key = nullptr;
1515 
1516     if (member->IsTSPropertySignature()) {
1517         key = member->AsTSPropertySignature()->Key();
1518     } else if (member->IsTSMethodSignature()) {
1519         key = member->AsTSMethodSignature()->Key();
1520     } else {
1521         return;
1522     }
1523 
1524     if (!key->IsIdentifier() && !key->IsNumberLiteral() && !key->IsStringLiteral()) {
1525         return;
1526     }
1527 
1528     for (auto *it : members) {
1529         ir::Expression *compare = nullptr;
1530 
1531         switch (it->Type()) {
1532             case ir::AstNodeType::TS_PROPERTY_SIGNATURE: {
1533                 compare = it->AsTSPropertySignature()->Key();
1534                 break;
1535             }
1536             case ir::AstNodeType::TS_METHOD_SIGNATURE: {
1537                 compare = it->AsTSMethodSignature()->Key();
1538                 break;
1539             }
1540             default: {
1541                 continue;
1542             }
1543         }
1544 
1545         if (!compare->IsIdentifier() && !compare->IsNumberLiteral() && !compare->IsStringLiteral()) {
1546             continue;
1547         }
1548 
1549         if (member->IsTSMethodSignature() && it->Type() == ir::AstNodeType::TS_METHOD_SIGNATURE) {
1550             continue;
1551         }
1552 
1553         if (GetTSPropertyName(key) == GetTSPropertyName(compare)) {
1554             ThrowSyntaxError("Duplicated identifier", key->Start());
1555         }
1556     }
1557 }
1558 
ParseTsTypeLiteralOrInterface()1559 ArenaVector<ir::Expression *> ParserImpl::ParseTsTypeLiteralOrInterface()
1560 {
1561     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1562 
1563     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
1564 
1565     ArenaVector<ir::Expression *> members(Allocator()->Adapter());
1566 
1567     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1568         ir::Expression *member = ParseTsTypeLiteralOrInterfaceMember();
1569 
1570         CheckObjectTypeForDuplicatedProperties(member, members);
1571 
1572         members.push_back(member);
1573 
1574         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1575             break;
1576         }
1577 
1578         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1579             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1580             if (!lexer_->GetToken().NewLine()) {
1581                 ThrowSyntaxError("',' expected");
1582             }
1583 
1584             if (lexer_->GetToken().IsKeyword()) {
1585                 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
1586             }
1587 
1588             continue;
1589         }
1590 
1591         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
1592     }
1593 
1594     return members;
1595 }
1596 
ParseTsArrayType(ir::Expression * elementType)1597 ir::TSArrayType *ParserImpl::ParseTsArrayType(ir::Expression *elementType)
1598 {
1599     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
1600     lexer_->NextToken();  // eat '['
1601 
1602     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1603         ThrowSyntaxError("']' expected");
1604     }
1605 
1606     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1607     lexer_->NextToken();  // eat ']'
1608 
1609     lexer::SourcePosition startLoc = elementType->Start();
1610     auto *arrayType = AllocNode<ir::TSArrayType>(elementType);
1611     arrayType->SetRange({startLoc, endLoc});
1612 
1613     return arrayType;
1614 }
1615 
ParseTsUnionType(ir::Expression * type,bool restrictExtends)1616 ir::TSUnionType *ParserImpl::ParseTsUnionType(ir::Expression *type, bool restrictExtends)
1617 {
1618     ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1619     lexer::SourcePosition startLoc;
1620 
1621     TypeAnnotationParsingOptions options =
1622         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::IN_UNION;
1623 
1624     if (restrictExtends) {
1625         options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1626     }
1627 
1628     if (type) {
1629         startLoc = type->Start();
1630         types.push_back(type);
1631     } else {
1632         startLoc = lexer_->GetToken().Start();
1633     }
1634 
1635     while (true) {
1636         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
1637             break;
1638         }
1639 
1640         lexer_->NextToken();  // eat '|'
1641 
1642         types.push_back(ParseTsTypeAnnotation(&options));
1643     }
1644 
1645     lexer::SourcePosition endLoc = types.back()->End();
1646 
1647     auto *unionType = AllocNode<ir::TSUnionType>(std::move(types));
1648     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, unionType);
1649     unionType->SetVariable(typeVar);
1650     unionType->SetRange({startLoc, endLoc});
1651 
1652     return unionType;
1653 }
1654 
ParseTsIntersectionType(ir::Expression * type,bool inUnion,bool restrictExtends)1655 ir::TSIntersectionType *ParserImpl::ParseTsIntersectionType(ir::Expression *type, bool inUnion, bool restrictExtends)
1656 {
1657     ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1658     lexer::SourcePosition startLoc;
1659 
1660     TypeAnnotationParsingOptions options =
1661         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::IN_INTERSECTION;
1662 
1663     if (restrictExtends) {
1664         options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1665     }
1666 
1667     if (inUnion) {
1668         options |= TypeAnnotationParsingOptions::IN_UNION;
1669     }
1670 
1671     if (type) {
1672         startLoc = type->Start();
1673         types.push_back(type);
1674     } else {
1675         startLoc = lexer_->GetToken().Start();
1676     }
1677 
1678     while (true) {
1679         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_AND) {
1680             break;
1681         }
1682 
1683         lexer_->NextToken();  // eat '&'
1684 
1685         types.push_back(ParseTsTypeAnnotation(&options));
1686     }
1687 
1688     lexer::SourcePosition endLoc = types.back()->End();
1689 
1690     auto *intersectionType = AllocNode<ir::TSIntersectionType>(std::move(types));
1691     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, intersectionType);
1692     intersectionType->SetVariable(typeVar);
1693     intersectionType->SetRange({startLoc, endLoc});
1694 
1695     return intersectionType;
1696 }
1697 
IsTsFunctionType()1698 bool ParserImpl::IsTsFunctionType()
1699 {
1700     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1701     const auto startPos = lexer_->Save();
1702     lexer_->NextToken();  // eat '('
1703     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
1704         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
1705         lexer_->Rewind(startPos);
1706         return true;
1707     }
1708 
1709     try {
1710         ParseModifiers();
1711         if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
1712             (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS)) {
1713             lexer_->NextToken();
1714         } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1715             ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1716         } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1717             ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
1718         } else {
1719             lexer_->Rewind(startPos);
1720             return false;
1721         }
1722     } catch ([[maybe_unused]] const class Error &e) {
1723         lexer_->Rewind(startPos);
1724         return false;
1725     }
1726 
1727     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ||
1728         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK ||
1729         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON ||
1730         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) {
1731         lexer_->Rewind(startPos);
1732         return true;
1733     }
1734 
1735     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1736         lexer_->NextToken();  // eat ')'
1737         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1738             lexer_->Rewind(startPos);
1739             return true;
1740         }
1741     }
1742     lexer_->Rewind(startPos);
1743     return false;
1744 }
1745 
ParseTsParenthesizedOrFunctionType(ir::Expression * typeAnnotation,bool throwError)1746 ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError)
1747 {
1748     if (typeAnnotation) {
1749         return nullptr;
1750     }
1751 
1752     lexer::SourcePosition typeStart = lexer_->GetToken().Start();
1753 
1754     bool abstractConstructor = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT;
1755     if (abstractConstructor) {
1756         lexer_->NextToken();  // eat 'abstract'
1757     }
1758 
1759     bool isConstructionType = false;
1760 
1761     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW) {
1762         lexer_->NextToken();  // eat 'new'
1763         isConstructionType = true;
1764 
1765         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1766             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1767             if (!throwError) {
1768                 return nullptr;
1769             }
1770             ThrowSyntaxError("'(' expected");
1771         }
1772     }
1773 
1774     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || isConstructionType) {
1775         return ParseTsFunctionType(typeStart, isConstructionType, throwError, abstractConstructor);
1776     }
1777 
1778     if (IsTsFunctionType()) {
1779         return ParseTsFunctionType(typeStart, false, throwError);
1780     }
1781 
1782     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1783     lexer_->NextToken();  // eat '('
1784 
1785     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
1786     ir::Expression *type = ParseTsTypeAnnotation(&options);
1787 
1788     if (throwError && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1789         ThrowSyntaxError("')' expected");
1790     }
1791 
1792     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1793     lexer_->NextToken();  // eat ')'
1794 
1795     auto *result = AllocNode<ir::TSParenthesizedType>(type);
1796     result->SetRange({typeStart, endLoc});
1797 
1798     return result;
1799 }
1800 
ParseTsFunctionType(lexer::SourcePosition startLoc,bool isConstructionType,bool throwError,bool abstractConstructor)1801 ir::Expression *ParserImpl::ParseTsFunctionType(lexer::SourcePosition startLoc, bool isConstructionType,
1802                                                 bool throwError, bool abstractConstructor)
1803 {
1804     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1805     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1806         typeParamDecl = ParseTsTypeParameterDeclaration(throwError);
1807 
1808         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1809             if (!throwError) {
1810                 return nullptr;
1811             }
1812 
1813             ThrowSyntaxError("'(' expected");
1814         }
1815     }
1816 
1817     FunctionParameterContext funcParamContext(&context_, Binder());
1818     auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1819 
1820     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1821     try {
1822         params = ParseFunctionParams(true);
1823     } catch (const Error &e) {
1824         if (!throwError) {
1825             return nullptr;
1826         }
1827         throw e;
1828     }
1829 
1830     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1831         ThrowSyntaxError("'=>' expected");
1832     }
1833 
1834     lexer_->NextToken();  // eat '=>'
1835 
1836     TypeAnnotationParsingOptions options =
1837         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1838     ir::Expression *returnTypeAnnotation = ParseTsTypeAnnotation(&options);
1839 
1840     ir::Expression *funcType = nullptr;
1841 
1842     if (isConstructionType) {
1843         funcType = AllocNode<ir::TSConstructorType>(funcParamScope, std::move(params), typeParamDecl,
1844                                                     returnTypeAnnotation, abstractConstructor);
1845     } else {
1846         funcType =
1847             AllocNode<ir::TSFunctionType>(funcParamScope, std::move(params), typeParamDecl, returnTypeAnnotation);
1848     }
1849 
1850     funcType->SetRange({startLoc, returnTypeAnnotation->End()});
1851     funcParamScope->BindNode(funcType);
1852 
1853     return funcType;
1854 }
1855 
ParseTsBasicType(TypeAnnotationParsingOptions options)1856 ir::Expression *ParserImpl::ParseTsBasicType(TypeAnnotationParsingOptions options)
1857 {
1858     ir::Expression *typeAnnotation = nullptr;
1859 
1860     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) {
1861         lexer_->NextToken();
1862 
1863         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) {
1864             if (options & TypeAnnotationParsingOptions::THROW_ERROR) {
1865                 ThrowSyntaxError("Type expected");
1866             } else {
1867                 return nullptr;
1868             }
1869         }
1870     }
1871     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1872         if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1873             auto *bigintNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1874             bigintNode->SetRange(lexer_->GetToken().Loc());
1875 
1876             typeAnnotation = AllocNode<ir::TSLiteralType>(bigintNode);
1877         } else {
1878             auto *numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1879             numberNode->SetRange(lexer_->GetToken().Loc());
1880 
1881             typeAnnotation = AllocNode<ir::TSLiteralType>(numberNode);
1882         }
1883     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
1884         auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1885         stringNode->SetRange(lexer_->GetToken().Loc());
1886 
1887         typeAnnotation = AllocNode<ir::TSLiteralType>(stringNode);
1888     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE) {
1889         auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(true);
1890         booleanLiteral->SetRange(lexer_->GetToken().Loc());
1891 
1892         typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
1893     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_FALSE) {
1894         auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(false);
1895         booleanLiteral->SetRange(lexer_->GetToken().Loc());
1896 
1897         typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
1898     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ANY) {
1899         typeAnnotation = AllocNode<ir::TSAnyKeyword>();
1900     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BOOLEAN) {
1901         typeAnnotation = AllocNode<ir::TSBooleanKeyword>();
1902     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NUMBER) {
1903         typeAnnotation = AllocNode<ir::TSNumberKeyword>();
1904     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STRING) {
1905         typeAnnotation = AllocNode<ir::TSStringKeyword>();
1906     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNKNOWN) {
1907         typeAnnotation = AllocNode<ir::TSUnknownKeyword>();
1908     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_VOID) {
1909         typeAnnotation = AllocNode<ir::TSVoidKeyword>();
1910     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::LITERAL_NULL) {
1911         typeAnnotation = AllocNode<ir::TSNullKeyword>();
1912     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNDEFINED) {
1913         typeAnnotation = AllocNode<ir::TSUndefinedKeyword>();
1914     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEVER) {
1915         typeAnnotation = AllocNode<ir::TSNeverKeyword>();
1916     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OBJECT) {
1917         typeAnnotation = AllocNode<ir::TSObjectKeyword>();
1918     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BIGINT) {
1919         typeAnnotation = AllocNode<ir::TSBigintKeyword>();
1920     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SYMBOL) {
1921         typeAnnotation = AllocNode<ir::TSSymbolKeyword>();
1922     } else {
1923         ThrowSyntaxError("Unexpected type");
1924     }
1925 
1926     typeAnnotation->SetRange(lexer_->GetToken().Loc());
1927 
1928     lexer_->NextToken();
1929     return typeAnnotation;
1930 }
1931 
GetAccessability(ir::ModifierFlags modifiers)1932 static ir::ModifierFlags GetAccessability(ir::ModifierFlags modifiers)
1933 {
1934     if (modifiers & ir::ModifierFlags::PUBLIC) {
1935         return ir::ModifierFlags::PUBLIC;
1936     }
1937 
1938     if (modifiers & ir::ModifierFlags::PRIVATE) {
1939         return ir::ModifierFlags::PRIVATE;
1940     }
1941 
1942     if (modifiers & ir::ModifierFlags::PROTECTED) {
1943         return ir::ModifierFlags::PROTECTED;
1944     }
1945 
1946     return ir::ModifierFlags::NONE;
1947 }
1948 
IsModifierKind(const lexer::Token & token)1949 static bool IsModifierKind(const lexer::Token &token)
1950 {
1951     if (token.Type() == lexer::TokenType::LITERAL_IDENT) {
1952         switch (token.KeywordType()) {
1953             case lexer::TokenType::KEYW_PUBLIC:
1954             case lexer::TokenType::KEYW_PRIVATE:
1955             case lexer::TokenType::KEYW_PROTECTED:
1956             case lexer::TokenType::KEYW_STATIC:
1957             case lexer::TokenType::KEYW_ASYNC:
1958             case lexer::TokenType::KEYW_ABSTRACT:
1959             case lexer::TokenType::KEYW_DECLARE:
1960             case lexer::TokenType::KEYW_READONLY:
1961                 return true;
1962             default:
1963                 return false;
1964         }
1965     }
1966 
1967     return false;
1968 }
1969 
ParseModifiers()1970 ir::ModifierFlags ParserImpl::ParseModifiers()
1971 {
1972     ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
1973     ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
1974 
1975     while (IsModifierKind(lexer_->GetToken())) {
1976         char32_t nextCp = lexer_->Lookahead();
1977         if (!((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
1978               (Extension() == ScriptExtension::TS && nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON &&
1979                nextCp != LEX_CHAR_COMMA && nextCp != LEX_CHAR_LEFT_PAREN))) {
1980             break;
1981         }
1982 
1983         lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
1984         if (tokenFlags & lexer::TokenFlags::HAS_ESCAPE) {
1985             ThrowSyntaxError("Keyword must not contain escaped characters");
1986         }
1987 
1988         ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
1989         ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
1990 
1991         switch (lexer_->GetToken().KeywordType()) {
1992             case lexer::TokenType::KEYW_PUBLIC: {
1993                 actualStatus = ir::ModifierFlags::PUBLIC;
1994                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
1995                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1996                 break;
1997             }
1998             case lexer::TokenType::KEYW_PRIVATE: {
1999                 actualStatus = ir::ModifierFlags::PRIVATE;
2000                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2001                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2002                 break;
2003             }
2004             case lexer::TokenType::KEYW_PROTECTED: {
2005                 actualStatus = ir::ModifierFlags::PROTECTED;
2006                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2007                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2008                 break;
2009             }
2010             case lexer::TokenType::KEYW_STATIC: {
2011                 actualStatus = ir::ModifierFlags::STATIC;
2012                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE |
2013                              ir::ModifierFlags::ABSTRACT;
2014                 break;
2015             }
2016             case lexer::TokenType::KEYW_ASYNC: {
2017                 actualStatus = ir::ModifierFlags::ASYNC;
2018                 nextStatus = ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2019                 break;
2020             }
2021             case lexer::TokenType::KEYW_ABSTRACT: {
2022                 actualStatus = ir::ModifierFlags::ABSTRACT;
2023                 nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
2024                              ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE;
2025                 break;
2026             }
2027             case lexer::TokenType::KEYW_DECLARE: {
2028                 actualStatus = ir::ModifierFlags::DECLARE;
2029                 nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
2030                              ir::ModifierFlags::READONLY;
2031                 break;
2032             }
2033             case lexer::TokenType::KEYW_READONLY: {
2034                 actualStatus = ir::ModifierFlags::READONLY;
2035                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2036                 break;
2037             }
2038             default: {
2039                 UNREACHABLE();
2040             }
2041         }
2042 
2043         if (lexer_->Lookahead() == LEX_CHAR_COLON || lexer_->Lookahead() == LEX_CHAR_COMMA ||
2044             lexer_->Lookahead() == LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == LEX_CHAR_QUESTION ||
2045             lexer_->Lookahead() == LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
2046             break;
2047         }
2048 
2049         auto pos = lexer_->Save();
2050         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2051 
2052         if ((prevStatus & actualStatus) == 0) {
2053             lexer_->Rewind(pos);
2054             ThrowSyntaxError("Unexpected modifier");
2055         }
2056 
2057         if ((resultStatus & actualStatus) != 0) {
2058             lexer_->Rewind(pos);
2059             ThrowSyntaxError("Duplicated modifier is not allowed");
2060         }
2061 
2062         if ((context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) &&
2063             (actualStatus & ~ir::ModifierFlags::ALLOWED_IN_CTOR_PARAMETER)) {
2064             lexer_->Rewind(pos);
2065             ThrowParameterModifierError(actualStatus);
2066         }
2067 
2068         resultStatus |= actualStatus;
2069         prevStatus = nextStatus;
2070     }
2071 
2072     return resultStatus;
2073 }
2074 
CheckAccessorPair(const ArenaVector<ir::Statement * > & properties,const ir::Expression * propName,ir::MethodDefinitionKind methodKind,ir::ModifierFlags access,bool hasDecorator,lexer::SourcePosition errorInfo)2075 void ParserImpl::CheckAccessorPair(const ArenaVector<ir::Statement *> &properties, const ir::Expression *propName,
2076                                    ir::MethodDefinitionKind methodKind, ir::ModifierFlags access, bool hasDecorator,
2077                                    lexer::SourcePosition errorInfo)
2078 {
2079     for (const auto &it : properties) {
2080         if (!it->IsMethodDefinition() || (!hasDecorator && it->AsMethodDefinition()->Kind() != methodKind)) {
2081             continue;
2082         }
2083 
2084         const ir::Expression *key = it->AsMethodDefinition()->Key();
2085 
2086         if (key->Type() != propName->Type()) {
2087             continue;
2088         }
2089 
2090         bool keyIsSame = false;
2091 
2092         if (key->IsIdentifier()) {
2093             const util::StringView &strName = propName->AsIdentifier()->Name();
2094             const util::StringView &compareName = (key->AsIdentifier()->Name());
2095 
2096             keyIsSame = strName == compareName;
2097         } else if (key->IsNumberLiteral()) {
2098             keyIsSame = *key->AsNumberLiteral() == *propName->AsNumberLiteral();
2099         } else if (key->IsStringLiteral()) {
2100             keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral();
2101         }
2102 
2103         if (!keyIsSame) {
2104             continue;
2105         }
2106 
2107         if (hasDecorator &&
2108             (it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::GET ||
2109              it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::SET) &&
2110             !it->AsMethodDefinition()->Decorators().empty()) {
2111             ThrowSyntaxError("Decorators cannot be applied to multiple get/set accessors of the same name.", errorInfo);
2112         }
2113 
2114         if (it->AsMethodDefinition()->Kind() != methodKind) {
2115             continue;
2116         }
2117 
2118         ir::ModifierFlags getAccess = ir::ModifierFlags::NONE;
2119         ir::ModifierFlags setAccess = ir::ModifierFlags::NONE;
2120 
2121         if (methodKind == ir::MethodDefinitionKind::GET) {
2122             setAccess = access;
2123             getAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
2124         } else {
2125             getAccess = access;
2126             setAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
2127         }
2128 
2129         if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) ||
2130             (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) {
2131             ThrowSyntaxError("A get accessor must be at least as accessible as the setter", key->Start());
2132         }
2133     }
2134 }
2135 
ParseClassKeyModifiers(ClassElmentDescriptor * desc)2136 void ParserImpl::ParseClassKeyModifiers(ClassElmentDescriptor *desc)
2137 {
2138     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2139         return;
2140     }
2141 
2142     char32_t nextCp = lexer_->Lookahead();
2143 
2144     if ((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
2145         (Extension() == ScriptExtension::TS &&
2146         nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON && nextCp != LEX_CHAR_LEFT_PAREN &&
2147         nextCp != LEX_CHAR_LESS_THAN && nextCp != LEX_CHAR_QUESTION && nextCp != LEX_CHAR_COLON)) {
2148         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GET) {
2149             if (desc->isPrivateIdent) {
2150                 ThrowSyntaxError("Private identifier can not be getter");
2151             }
2152 
2153             if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2154                 ThrowSyntaxError("Keyword must not contain escaped characters");
2155             }
2156 
2157             desc->methodKind = ir::MethodDefinitionKind::GET;
2158             desc->methodStart = lexer_->GetToken().Start();
2159 
2160             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2161         } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SET) {
2162             if (desc->isPrivateIdent) {
2163                 ThrowSyntaxError("Private identifier can not be setter");
2164             }
2165 
2166             if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2167                 ThrowSyntaxError("Keyword must not contain escaped characters");
2168             }
2169 
2170             desc->methodKind = ir::MethodDefinitionKind::SET;
2171             desc->methodStart = lexer_->GetToken().Start();
2172 
2173             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2174         }
2175     }
2176 }
2177 
ThrowIfPrivateIdent(ClassElmentDescriptor * desc,const char * msg)2178 void ParserImpl::ThrowIfPrivateIdent(ClassElmentDescriptor *desc, const char *msg)
2179 {
2180     if (desc->isPrivateIdent) {
2181         ThrowSyntaxError(msg);
2182     }
2183 }
2184 
ValidateClassKey(ClassElmentDescriptor * desc,bool isDeclare)2185 void ParserImpl::ValidateClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2186 {
2187     if ((desc->modifiers & ir::ModifierFlags::ASYNC) &&
2188         (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) {
2189         ThrowSyntaxError("Async method can not be getter nor setter");
2190     }
2191 
2192     const util::StringView &propNameStr = lexer_->GetToken().Ident();
2193 
2194     if (propNameStr.Is("constructor")) {
2195         ThrowIfPrivateIdent(desc, "Private identifier can not be constructor");
2196 
2197         if (!(desc->modifiers & ir::ModifierFlags::STATIC)) {
2198             if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->methodKind == ir::MethodDefinitionKind::GET ||
2199                 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
2200                 ThrowSyntaxError("Constructor can not be special method");
2201             }
2202 
2203             desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
2204             desc->methodStart = lexer_->GetToken().Start();
2205             desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
2206 
2207             if (desc->hasSuperClass) {
2208                 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
2209             }
2210         } else if (Extension() == ScriptExtension::TS) {
2211             ThrowSyntaxError("Static modifier can not appear on a constructor");
2212         }
2213     } else if (!isDeclare && propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC)) {
2214         ThrowSyntaxError("Classes may not have static property named prototype");
2215     }
2216 }
2217 
ParseClassKey(ClassElmentDescriptor * desc,bool isDeclare)2218 ir::Expression *ParserImpl::ParseClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2219 {
2220     ir::Expression *propName = nullptr;
2221     if (lexer_->GetToken().IsKeyword()) {
2222         lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
2223     }
2224 
2225     switch (lexer_->GetToken().Type()) {
2226         case lexer::TokenType::LITERAL_IDENT: {
2227             ValidateClassKey(desc, isDeclare);
2228 
2229             propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2230             propName->SetRange(lexer_->GetToken().Loc());
2231             break;
2232         }
2233         case lexer::TokenType::LITERAL_STRING: {
2234             ThrowIfPrivateIdent(desc, "Private identifier name can not be string");
2235 
2236             propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2237             propName->SetRange(lexer_->GetToken().Loc());
2238             break;
2239         }
2240         case lexer::TokenType::LITERAL_NUMBER: {
2241             ThrowIfPrivateIdent(desc, "Private identifier name can not be number");
2242 
2243             if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
2244                 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
2245             } else {
2246                 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
2247             }
2248 
2249             propName->SetRange(lexer_->GetToken().Loc());
2250             break;
2251         }
2252         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2253             ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2254 
2255             lexer_->NextToken();  // eat left square bracket
2256 
2257             if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2258                 lexer_->Lookahead() == LEX_CHAR_COLON) {
2259                 desc->isIndexSignature = true;
2260 
2261                 propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2262                 propName->SetRange(lexer_->GetToken().Loc());
2263 
2264                 lexer_->NextToken();  // eat param
2265 
2266                 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2267                     ThrowSyntaxError("':' expected");
2268                 }
2269 
2270                 lexer_->NextToken();  // eat ':'
2271                 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2272                 ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
2273 
2274                 if (!typeAnnotation->IsTSNumberKeyword() && !typeAnnotation->IsTSStringKeyword()) {
2275                     ThrowSyntaxError(
2276                         "An index signature parameter type must be either "
2277                         "'string' or 'number'");
2278                 }
2279 
2280                 propName->SetTsTypeAnnotation(typeAnnotation);
2281 
2282                 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2283                     ThrowSyntaxError("']' expected");
2284                 }
2285 
2286                 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2287 
2288                 return propName;
2289             }
2290 
2291             desc->isComputed = true;
2292 
2293             propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2294 
2295             if (Extension() == ScriptExtension::TS) {
2296                 // TODO(songqi): Determine whether MemberExpression is a symbol during type check.
2297                 desc->invalidComputedProperty = !propName->IsNumberLiteral() &&
2298                     util::Helpers::GetSignedNumberLiteral(propName) == util::SignedNumberLiteral::UNRECOGNIZED &&
2299                     !propName->IsStringLiteral() && !propName->IsMemberExpression() && !propName->IsIdentifier();
2300             }
2301 
2302             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2303                 ThrowSyntaxError("Unexpected token, expected ']'");
2304             }
2305             break;
2306         }
2307         default: {
2308             ThrowSyntaxError("Unexpected token in class property");
2309         }
2310     }
2311 
2312     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2313 
2314     return propName;
2315 }
2316 
ValidateClassMethodStart(ClassElmentDescriptor * desc,ir::Expression * typeAnnotation)2317 void ParserImpl::ValidateClassMethodStart(ClassElmentDescriptor *desc, ir::Expression *typeAnnotation)
2318 {
2319     if (Extension() == ScriptExtension::JS) {
2320         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2321             return;
2322         }
2323         desc->classMethod = true;
2324     }
2325 
2326     if (Extension() == ScriptExtension::TS &&
2327         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && desc->isPrivateIdent) {
2328         ThrowSyntaxError("A method cannot be named with a private identifier");
2329     }
2330 
2331     if (Extension() == ScriptExtension::TS) {
2332         if (!typeAnnotation && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
2333                                 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN)) {
2334             if ((desc->modifiers & (ir::ModifierFlags::DECLARE | ir::ModifierFlags::READONLY))) {
2335                 ThrowSyntaxError("Class method can not be declare nor readonly");
2336             }
2337             desc->classMethod = true;
2338         } else {
2339             if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->isGenerator) {
2340                 ThrowSyntaxError("Expected '('");
2341             }
2342             desc->classField = true;
2343 
2344             if (desc->invalidComputedProperty) {
2345                 ThrowSyntaxError(
2346                     "Computed property name must refer to a symbol or "
2347                     "literal expression whos value is "
2348                     "number or string");
2349             }
2350         }
2351     }
2352 
2353     if (desc->modifiers & ir::ModifierFlags::ASYNC) {
2354         desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
2355     }
2356 
2357     if (desc->isGenerator) {
2358         desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
2359     }
2360 }
2361 
ValidateClassSetter(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::ScriptFunction * func,bool hasDecorator,lexer::SourcePosition errorInfo)2362 void ParserImpl::ValidateClassSetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2363                                      ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2364                                      lexer::SourcePosition errorInfo)
2365 {
2366     if (func->Params().size() != 1) {
2367         ThrowSyntaxError("Setter must have exactly one formal parameter");
2368     }
2369 
2370     if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2371         ir::ModifierFlags access = GetAccessability(desc->modifiers);
2372         CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::GET, access, hasDecorator, errorInfo);
2373     }
2374 }
2375 
ValidateClassGetter(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::ScriptFunction * func,bool hasDecorator,lexer::SourcePosition errorInfo)2376 void ParserImpl::ValidateClassGetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2377                                      ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2378                                      lexer::SourcePosition errorInfo)
2379 {
2380     if (!func->Params().empty()) {
2381         ThrowSyntaxError("Getter must not have formal parameters");
2382     }
2383 
2384     if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2385         ir::ModifierFlags access = GetAccessability(desc->modifiers);
2386 
2387         CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::SET, access, hasDecorator, errorInfo);
2388     }
2389 }
2390 
ParseClassMethod(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd,ArenaVector<ir::Decorator * > && decorators,bool isDeclare)2391 ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc,
2392                                                    const ArenaVector<ir::Statement *> &properties,
2393                                                    ir::Expression *propName, lexer::SourcePosition *propEnd,
2394                                                    ArenaVector<ir::Decorator *> &&decorators, bool isDeclare)
2395 {
2396     if (Extension() == ScriptExtension::TS) {
2397         if (desc->methodKind == ir::MethodDefinitionKind::SET || desc->methodKind == ir::MethodDefinitionKind::GET) {
2398             desc->newStatus |= ParserStatus::ACCESSOR_FUNCTION;
2399         }
2400 
2401         desc->newStatus |= ParserStatus::IN_METHOD_DEFINITION;
2402     }
2403 
2404     if (isDeclare && (desc->newStatus & ParserStatus::ASYNC_FUNCTION)) {
2405         ThrowSyntaxError("'async' modifier cannot be used in an ambient context.");
2406     }
2407 
2408     if (isDeclare && desc->isGenerator) {
2409         ThrowSyntaxError("Generators are not allowed in an ambient context.");
2410     }
2411 
2412     ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
2413     ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare, &paramDecorators);
2414     if (func->Body() != nullptr) {
2415         lexer_->NextToken();
2416     }
2417 
2418     if (func->IsOverload() && !decorators.empty()) {
2419         ThrowSyntaxError("A decorator can only decorate a method implementation, not an overload.",
2420                          decorators.front()->Start());
2421     }
2422 
2423     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2424     funcExpr->SetRange(func->Range());
2425 
2426     lexer::SourcePosition errorInfo = decorators.empty() ? func->Start() : decorators[0]->Start();
2427 
2428     if (desc->methodKind == ir::MethodDefinitionKind::SET) {
2429         ValidateClassSetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2430     } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
2431         ValidateClassGetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2432     }
2433 
2434     *propEnd = func->End();
2435     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
2436     auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(),
2437                                                    std::move(decorators), std::move(paramDecorators),
2438                                                    desc->isComputed);
2439     method->SetRange(funcExpr->Range());
2440     return method;
2441 }
2442 
ParseClassProperty(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::Expression * typeAnnotation,ArenaVector<ir::Decorator * > && decorators,bool isDeclare)2443 ir::Statement *ParserImpl::ParseClassProperty(ClassElmentDescriptor *desc,
2444                                               const ArenaVector<ir::Statement *> &properties, ir::Expression *propName,
2445                                               ir::Expression *typeAnnotation, ArenaVector<ir::Decorator *> &&decorators,
2446                                               bool isDeclare)
2447 {
2448     lexer::SourcePosition propEnd = propName->End();
2449     ir::Statement *property = nullptr;
2450 
2451     if (desc->classMethod) {
2452         property = ParseClassMethod(desc, properties, propName, &propEnd, std::move(decorators), isDeclare);
2453         property->SetRange({desc->propStart, propEnd});
2454         return property;
2455     }
2456 
2457     ir::Expression *value = nullptr;
2458 
2459     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2460         lexer_->NextToken();  // eat equals
2461 
2462         if (isDeclare) {
2463             ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
2464         }
2465         // TODO(songqi):static classProperty's value can use super keyword in TypeScript4.4.
2466         // Currently only Parser is supported, Compiler support requires Transformer.
2467         context_.Status() |= ParserStatus::ALLOW_SUPER;
2468         value = ParseExpression();
2469         context_.Status() &= ~ParserStatus::ALLOW_SUPER;
2470         propEnd = value->End();
2471     }
2472 
2473     ir::Expression *privateId = nullptr;
2474 
2475     if (Extension() == ScriptExtension::JS) {
2476         if (desc->isPrivateIdent) {
2477             ThrowSyntaxError("Private js fields are not supported");
2478         }
2479     } else {
2480         if (desc->isPrivateIdent) {
2481             privateId = AllocNode<ir::TSPrivateIdentifier>(propName, value, typeAnnotation);
2482             privateId->SetRange({desc->propStart, propName->End()});
2483         }
2484     }
2485 
2486     property = AllocNode<ir::ClassProperty>(desc->isPrivateIdent ? privateId : propName, value, typeAnnotation,
2487                                             desc->modifiers, std::move(decorators), desc->isComputed,
2488                                             desc->modifiers & ir::ModifierFlags::DEFINITE);
2489 
2490     property->SetRange({desc->propStart, propEnd});
2491     return property;
2492 }
2493 
CheckClassGeneratorMethod(ClassElmentDescriptor * desc)2494 void ParserImpl::CheckClassGeneratorMethod(ClassElmentDescriptor *desc)
2495 {
2496     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2497         return;
2498     }
2499 
2500     ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2501 
2502     desc->isGenerator = true;
2503     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2504 }
2505 
CheckClassPrivateIdentifier(ClassElmentDescriptor * desc)2506 void ParserImpl::CheckClassPrivateIdentifier(ClassElmentDescriptor *desc)
2507 {
2508     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
2509         return;
2510     }
2511 
2512     if (Extension() == ScriptExtension::JS) {
2513         ThrowSyntaxError("JS private class fields are not supported.");
2514     }
2515 
2516     if (Extension() == ScriptExtension::AS) {
2517         return;
2518     }
2519 
2520     if (desc->modifiers & ~ir::ModifierFlags::READONLY) {
2521         ThrowSyntaxError("Unexpected modifier on private identifier");
2522     }
2523 
2524     desc->isPrivateIdent = true;
2525     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2526 }
2527 
ParseClassKeyAnnotation()2528 ir::Expression *ParserImpl::ParseClassKeyAnnotation()
2529 {
2530     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2531         lexer_->NextToken();  // eat ':'
2532         TypeAnnotationParsingOptions options =
2533             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
2534         return ParseTsTypeAnnotation(&options);
2535     }
2536 
2537     return nullptr;
2538 }
2539 
ParseDecorator()2540 ir::Decorator *ParserImpl::ParseDecorator()
2541 {
2542     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT);
2543 
2544     lexer::SourcePosition start = lexer_->GetToken().Start();
2545     lexer_->NextToken();  // eat '@'
2546 
2547     ir::Expression *expr = ParseLeftHandSideExpression();
2548     auto *result = AllocNode<ir::Decorator>(expr);
2549     result->SetRange({start, expr->End()});
2550 
2551     return result;
2552 }
2553 
ParseDecorators()2554 ArenaVector<ir::Decorator *> ParserImpl::ParseDecorators()
2555 {
2556     ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2557     auto savedStatus = context_.Status();
2558     context_.Status() |= ParserStatus::IN_DECORATOR;
2559 
2560     while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
2561         decorators.push_back(ParseDecorator());
2562     }
2563 
2564     if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2565         (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2566         lexer_->GetToken().Type() != lexer::TokenType::KEYW_EXPORT &&
2567         !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2568           (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE ||
2569            lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) {
2570         ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2571     }
2572 
2573     context_.Status() = savedStatus;
2574     return decorators;
2575 }
2576 
ParseClassElement(const ArenaVector<ir::Statement * > & properties,ArenaVector<ir::TSIndexSignature * > * indexSignatures,bool hasSuperClass,bool isDeclare,bool isAbstractClass)2577 ir::Statement *ParserImpl::ParseClassElement(const ArenaVector<ir::Statement *> &properties,
2578                                              ArenaVector<ir::TSIndexSignature *> *indexSignatures, bool hasSuperClass,
2579                                              bool isDeclare, bool isAbstractClass)
2580 {
2581     ClassElmentDescriptor desc;
2582 
2583     desc.methodKind = ir::MethodDefinitionKind::METHOD;
2584     desc.newStatus = ParserStatus::ALLOW_SUPER;
2585     desc.hasSuperClass = hasSuperClass;
2586     desc.propStart = lexer_->GetToken().Start();
2587 
2588     auto decorators = ParseDecorators();
2589 
2590     desc.modifiers = ParseModifiers();
2591 
2592     if ((desc.modifiers & ir::ModifierFlags::ABSTRACT) && !isAbstractClass) {
2593         ThrowSyntaxError("Abstract methods can only appear within an abstract class.");
2594     }
2595 
2596     CheckClassPrivateIdentifier(&desc);
2597     CheckClassGeneratorMethod(&desc);
2598     ParseClassKeyModifiers(&desc);
2599 
2600     if (!(desc.modifiers & ir::ModifierFlags::STATIC)) {
2601         context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
2602     }
2603 
2604     ir::Expression *propName = ParseClassKey(&desc, isDeclare);
2605 
2606     if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR && !decorators.empty()) {
2607         ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2608     }
2609 
2610     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
2611         if (desc.isIndexSignature) {
2612             ThrowSyntaxError("';' expected");
2613         }
2614 
2615         if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR) {
2616             ThrowSyntaxError("'(' expected");
2617         }
2618 
2619         desc.modifiers |= ir::ModifierFlags::OPTIONAL;
2620         lexer_->NextToken();
2621     } else if (Extension() == ScriptExtension::TS &&
2622                lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2623         if (desc.isIndexSignature || lexer_->Lookahead() != LEX_CHAR_COLON) {
2624             ThrowSyntaxError("';' expected");
2625         }
2626 
2627         desc.modifiers |= ir::ModifierFlags::DEFINITE;
2628         lexer_->NextToken();
2629     }
2630 
2631     ir::Expression *typeAnnotation = ParseClassKeyAnnotation();
2632 
2633     ir::Statement *property = nullptr;
2634     if (desc.isIndexSignature) {
2635         if (!decorators.empty()) {
2636             ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2637         }
2638 
2639         if (!typeAnnotation) {
2640             ThrowSyntaxError("An index signature must have a type annotation");
2641         }
2642 
2643         auto *indexSignature =
2644             AllocNode<ir::TSIndexSignature>(propName, typeAnnotation, desc.modifiers & ir::ModifierFlags::READONLY);
2645 
2646         indexSignature->SetRange({indexSignature->Param()->Start(), indexSignature->TypeAnnotation()->End()});
2647 
2648         indexSignatures->push_back(indexSignature);
2649 
2650         property = AllocNode<ir::EmptyStatement>();
2651     } else {
2652         ValidateClassMethodStart(&desc, typeAnnotation);
2653         property = ParseClassProperty(&desc, properties, propName, typeAnnotation, std::move(decorators),
2654                                       isDeclare || (desc.modifiers & ir::ModifierFlags::DECLARE));
2655     }
2656 
2657     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
2658         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
2659         !(lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) &&
2660         !(property->IsMethodDefinition() && property->AsMethodDefinition()->Value()->Function()->Body())) {
2661         ThrowSyntaxError("';' expected.");
2662     }
2663 
2664     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2665         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2666     }
2667 
2668     context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
2669 
2670     return property;
2671 }
2672 
IsConstructor(ir::Statement * stmt)2673 static bool IsConstructor(ir::Statement *stmt)
2674 {
2675     if (!stmt->IsMethodDefinition()) {
2676         return false;
2677     }
2678 
2679     ir::MethodDefinition *def = stmt->AsMethodDefinition();
2680     return def->Kind() == ir::MethodDefinitionKind::CONSTRUCTOR;
2681 }
2682 
CreateImplicitConstructor(ir::Expression * superClass,bool hasSuperClass,bool isDeclare)2683 ir::MethodDefinition *ParserImpl::CreateImplicitConstructor(ir::Expression *superClass,
2684                                                             bool hasSuperClass, bool isDeclare)
2685 {
2686     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2687     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
2688 
2689     auto *paramScope = Binder()->Allocator()->New<binder::FunctionParamScope>(Allocator(), Binder()->GetScope());
2690     auto *scope = Binder()->Allocator()->New<binder::FunctionScope>(Allocator(), paramScope);
2691 
2692     if (hasSuperClass) {
2693         if (Extension() != ScriptExtension::TS || !superClass->IsNullLiteral()) {
2694             util::StringView argsStr = "args";
2695             params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT,
2696                                                           AllocNode<ir::Identifier>(argsStr)));
2697             paramScope->AddParamDecl(Allocator(), params.back());
2698 
2699             ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
2700             auto *superExpr = AllocNode<ir::SuperExpression>();
2701             callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT,
2702                                                             AllocNode<ir::Identifier>(argsStr)));
2703 
2704             auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
2705             statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
2706         }
2707     }
2708 
2709     auto *body = AllocNode<ir::BlockStatement>(scope, std::move(statements));
2710     auto *func = AllocNode<ir::ScriptFunction>(scope, std::move(params), nullptr, isDeclare ? nullptr : body, nullptr,
2711                                                ir::ScriptFunctionFlags::CONSTRUCTOR, isDeclare,
2712                                                Extension() == ScriptExtension::TS);
2713     scope->BindNode(func);
2714     paramScope->BindNode(func);
2715     scope->BindParamScope(paramScope);
2716     paramScope->BindFunctionScope(scope);
2717 
2718     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2719     auto *key = AllocNode<ir::Identifier>("constructor");
2720 
2721     ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2722     ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
2723     auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
2724                                                  ir::ModifierFlags::NONE, Allocator(), std::move(decorators),
2725                                                  std::move(paramDecorators), false);
2726 
2727     return ctor;
2728 }
2729 
IsPropertyKeysAreSame(const ir::Expression * exp1,const ir::Expression * exp2)2730 bool ParserImpl::IsPropertyKeysAreSame(const ir::Expression *exp1, const ir::Expression *exp2)
2731 {
2732     if (exp1->IsIdentifier() && exp2->IsIdentifier()) {
2733         return exp1->AsIdentifier()->Name() == exp2->AsIdentifier()->Name();
2734     }
2735 
2736     if (exp1->IsIdentifier() && exp2->IsStringLiteral()) {
2737         return exp1->AsIdentifier()->Name() == exp2->AsStringLiteral()->Str();
2738     }
2739 
2740     if (exp1->IsStringLiteral() && exp2->IsStringLiteral()) {
2741         return *exp1->AsStringLiteral() == *exp2->AsStringLiteral();
2742     }
2743 
2744     if (exp1->IsStringLiteral() && exp2->IsIdentifier()) {
2745         return exp1->AsStringLiteral()->Str() == exp2->AsIdentifier()->Name();
2746     }
2747 
2748     if (exp1->IsStringLiteral() && exp2->IsNumberLiteral()) {
2749         std::string exp2String = std::to_string(exp2->AsNumberLiteral()->Number<double>());
2750         exp2String.erase(exp2String.find_last_not_of('0'), std::string::npos);
2751         return exp1->AsStringLiteral()->Str().Utf8() == exp2String;
2752     }
2753 
2754     if (exp1->IsNumberLiteral() && exp2->IsNumberLiteral()) {
2755         return exp1->AsNumberLiteral()->Number<double>() == exp2->AsNumberLiteral()->Number<double>();
2756     }
2757 
2758     if (exp1->IsNumberLiteral() && exp2->IsStringLiteral()) {
2759         std::string exp1String = std::to_string(exp1->AsNumberLiteral()->Number<double>());
2760         exp1String.erase(exp1String.find_last_not_of('0'), std::string::npos);
2761         return exp1String == exp2->AsStringLiteral()->Str().Utf8();
2762     }
2763 
2764     return false;
2765 }
2766 
IsMemberExpressionsAreSame(const ir::MemberExpression * mExp1,const ir::MemberExpression * mExp2)2767 bool ParserImpl::IsMemberExpressionsAreSame(const ir::MemberExpression *mExp1, const ir::MemberExpression *mExp2)
2768 {
2769     if (!IsPropertyKeysAreSame(mExp1->Property(), mExp2->Property())) {
2770         return false;
2771     }
2772 
2773     if (mExp1->Object()->IsMemberExpression() && mExp2->Object()->IsMemberExpression()) {
2774         return IsMemberExpressionsAreSame(mExp1->Object()->AsMemberExpression(), mExp2->Object()->AsMemberExpression());
2775     }
2776 
2777     return IsPropertyKeysAreSame(mExp1->Object(), mExp2->Object());
2778 }
2779 
IsMethodDefinitionsAreSame(const ir::MethodDefinition * property,ir::MethodDefinition * overload)2780 bool ParserImpl::IsMethodDefinitionsAreSame(const ir::MethodDefinition *property, ir::MethodDefinition *overload)
2781 {
2782     if (property->Kind() != overload->Kind() || property->IsStatic() != overload->IsStatic()) {
2783         return false;
2784     }
2785 
2786     if (property->Key()->IsMemberExpression() && overload->Key()->IsMemberExpression()) {
2787         return IsMemberExpressionsAreSame(property->Key()->AsMemberExpression(), overload->Key()->AsMemberExpression());
2788     }
2789 
2790     return IsPropertyKeysAreSame(property->Key(), overload->Key());
2791 }
2792 
SetIdentNodeInClassDefinition(bool isDeclare,binder::ConstDecl ** decl)2793 ir::Identifier *ParserImpl::SetIdentNodeInClassDefinition(bool isDeclare, binder::ConstDecl **decl)
2794 {
2795     lexer::TokenType keywType = lexer_->GetToken().KeywordType();
2796     CheckStrictReservedWord();
2797 
2798     if (keywType == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
2799         ThrowSyntaxError("Unexpected reserved word");
2800     }
2801 
2802     const util::StringView &identStr = lexer_->GetToken().Ident();
2803 
2804     *decl = Binder()->AddDecl<binder::ConstDecl>(lexer_->GetToken().Start(), isDeclare, identStr);
2805 
2806     auto *identNode = AllocNode<ir::Identifier>(identStr);
2807     identNode->SetRange(lexer_->GetToken().Loc());
2808 
2809     lexer_->NextToken();
2810 
2811     return identNode;
2812 }
2813 
ParseClassDefinition(bool isDeclaration,bool idRequired,bool isDeclare,bool isAbstract)2814 ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool idRequired, bool isDeclare,
2815                                                       bool isAbstract)
2816 {
2817     isDeclare = isDeclare | (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT);
2818     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2819     lexer_->NextToken();
2820 
2821     binder::ConstDecl *decl = nullptr;
2822     ir::Identifier *identNode = nullptr;
2823 
2824     auto classCtx = binder::LexicalScope<binder::LocalScope>(Binder());
2825 
2826     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && (Extension() != ScriptExtension::TS ||
2827         lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IMPLEMENTS)) {
2828         identNode = SetIdentNodeInClassDefinition(isDeclare, &decl);
2829     } else if (isDeclaration && idRequired) {
2830         ThrowSyntaxError("Unexpected token, expected an identifier.");
2831     }
2832 
2833     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
2834     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
2835         typeParamDecl = ParseTsTypeParameterDeclaration();
2836     }
2837 
2838     // Parse SuperClass
2839     ir::Expression *superClass = nullptr;
2840     bool hasSuperClass = false;
2841 
2842     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
2843         lexer_->NextToken();
2844         hasSuperClass = true;
2845         superClass = ParseLeftHandSideExpression();
2846     }
2847 
2848     ir::TSTypeParameterInstantiation *superTypeParams = nullptr;
2849     if (Extension() == ScriptExtension::TS && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
2850                                                lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT)) {
2851         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2852             lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2853         }
2854 
2855         superTypeParams = ParseTsTypeParameterInstantiation();
2856     }
2857 
2858     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
2859     if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
2860         lexer_->NextToken();
2861 
2862         while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2863             lexer::SourcePosition implStart = lexer_->GetToken().Start();
2864 
2865             if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2866                 ThrowSyntaxError("Identifier expected");
2867             }
2868 
2869             ir::Expression *expr = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2870             expr->SetRange(lexer_->GetToken().Loc());
2871             expr->AsIdentifier()->SetReference();
2872 
2873             lexer_->NextToken();
2874 
2875             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2876                 expr = ParseTsQualifiedReference(expr);
2877             }
2878 
2879             ir::TSTypeParameterInstantiation *implTypeParams = nullptr;
2880             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2881                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2882             }
2883 
2884             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
2885                 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2886                 implTypeParams = ParseTsTypeParameterInstantiation();
2887             }
2888 
2889             auto *impl = AllocNode<ir::TSClassImplements>(expr, implTypeParams);
2890             impl->SetRange({implStart, lexer_->GetToken().End()});
2891             implements.push_back(impl);
2892 
2893             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2894                 lexer_->NextToken();
2895                 continue;
2896             }
2897 
2898             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2899                 ThrowSyntaxError("',' expected");
2900             }
2901         }
2902 
2903         if (implements.empty()) {
2904             ThrowSyntaxError("Implements clause can not be empty");
2905         }
2906     }
2907 
2908     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2909         ThrowSyntaxError("Unexpected token, expected '{'");
2910     }
2911 
2912     // Parse ClassBody
2913     auto savedStatus = context_.Status();
2914     context_.Status() |= ParserStatus::IN_CLASS_BODY;
2915     context_.Status() &= ~(ParserStatus::CONSTRUCTOR_FUNCTION);
2916     lexer::SourcePosition classBodyStartLoc = lexer_->GetToken().Start();
2917     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2918 
2919     ir::MethodDefinition *ctor = nullptr;
2920     ArenaVector<ir::Statement *> properties(Allocator()->Adapter());
2921     ArenaVector<ir::TSIndexSignature *> indexSignatures(Allocator()->Adapter());
2922     bool hasConstructorFuncBody = false;
2923     bool isCtorContinuousDefined = true;
2924 
2925     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2926         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2927             lexer_->NextToken();
2928             continue;
2929         }
2930 
2931         ir::Statement *property = ParseClassElement(properties, &indexSignatures, hasSuperClass, isDeclare, isAbstract);
2932 
2933         if (property->IsEmptyStatement()) {
2934             continue;
2935         }
2936 
2937         if (IsConstructor(property)) {
2938             if (!isDeclare && !isCtorContinuousDefined) {
2939                 ThrowSyntaxError("Constructor implementation is missing.", property->Start());
2940             }
2941 
2942             if (hasConstructorFuncBody) {
2943                 ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
2944             }
2945             ctor = property->AsMethodDefinition();
2946             hasConstructorFuncBody = ctor->Value()->Function()->Body() != nullptr;
2947             continue;
2948         }
2949         isCtorContinuousDefined = ctor == nullptr;
2950         properties.push_back(property);
2951     }
2952 
2953     context_.Status() = savedStatus;
2954 
2955     lexer::SourcePosition classBodyEndLoc = lexer_->GetToken().End();
2956     if (ctor == nullptr) {
2957         ctor = CreateImplicitConstructor(superClass, hasSuperClass, isDeclare);
2958         ctor->SetRange({startLoc, classBodyEndLoc});
2959         hasConstructorFuncBody = !isDeclare;
2960     }
2961     lexer_->NextToken();
2962 
2963     ValidateClassConstructor(ctor, properties, superClass, isDeclare, hasConstructorFuncBody, hasSuperClass);
2964 
2965     auto *classDefinition = AllocNode<ir::ClassDefinition>(
2966         classCtx.GetScope(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass,
2967         std::move(properties), std::move(indexSignatures), isDeclare, isAbstract);
2968 
2969     classDefinition->SetRange({classBodyStartLoc, classBodyEndLoc});
2970     if (decl != nullptr) {
2971         decl->BindNode(classDefinition);
2972     }
2973 
2974     return classDefinition;
2975 }
2976 
ValidateClassConstructor(ir::MethodDefinition * ctor,ArenaVector<ir::Statement * > & properties,ir::Expression * superClass,bool isDeclare,bool hasConstructorFuncBody,bool hasSuperClass)2977 void ParserImpl::ValidateClassConstructor(ir::MethodDefinition *ctor,
2978                                           ArenaVector<ir::Statement *> &properties,
2979                                           ir::Expression *superClass,
2980                                           bool isDeclare, bool hasConstructorFuncBody, bool hasSuperClass)
2981 {
2982     if (!hasConstructorFuncBody) {
2983         if (isDeclare) {
2984             return;
2985         }
2986         ThrowSyntaxError("Constructor implementation is missing.", ctor->Start());
2987     }
2988 
2989     if (Extension() != ScriptExtension::TS || !hasSuperClass) {
2990         return;
2991     }
2992 
2993     bool hasSuperCall = false;
2994     FindSuperCallInConstructor(ctor, &hasSuperCall);
2995     if (hasSuperCall) {
2996         if (superClass->IsNullLiteral()) {
2997             ThrowSyntaxError("A constructor cannot contain a super call when its class extends null.", ctor->Start());
2998         }
2999 
3000         if (SuperCallShouldBeFirst(ctor, properties)) {
3001             ir::Statement *firstStat = nullptr;
3002             ASSERT(ctor->Function()->Body()->IsBlockStatement());
3003             ir::BlockStatement *blockStat = ctor->Function()->Body()->AsBlockStatement();
3004             for (auto iter = blockStat->Statements().begin(); iter != blockStat->Statements().end();) {
3005                 if ((*iter)->IsExpressionStatement() &&
3006                     (*iter)->AsExpressionStatement()->GetExpression()->IsStringLiteral()) {
3007                     iter++;
3008                 } else {
3009                     firstStat = *iter;
3010                     break;
3011                 }
3012             }
3013 
3014             if (firstStat == nullptr || !firstStat->IsExpressionStatement() ||
3015                 !firstStat->AsExpressionStatement()->GetExpression()->IsCallExpression() ||
3016                 !firstStat->AsExpressionStatement()->GetExpression()->AsCallExpression()
3017                 ->Callee()->IsSuperExpression()) {
3018                 ThrowSyntaxError("A super call must be the first statement in the constructor when a class contains "
3019                                  "initialized properties, parameter properties, or private identifiers.",
3020                                  ctor->Start());
3021             }
3022         }
3023     } else if (!superClass->IsNullLiteral()) {
3024         ThrowSyntaxError("Constructors for derived classes must contain a super call.", ctor->Start());
3025     }
3026 }
3027 
SuperCallShouldBeFirst(ir::MethodDefinition * ctor,ArenaVector<ir::Statement * > & properties)3028 bool ParserImpl::SuperCallShouldBeFirst(ir::MethodDefinition *ctor, ArenaVector<ir::Statement *> &properties)
3029 {
3030     for (const auto *property : properties) {
3031         if (property->IsClassProperty() && (property->AsClassProperty()->Value() != nullptr ||
3032             property->AsClassProperty()->Key()->IsTSPrivateIdentifier())) {
3033             return true;
3034         }
3035     }
3036 
3037     for (const auto &param : ctor->Function()->Params()) {
3038         if (param->IsTSParameterProperty() &&
3039             (param->AsTSParameterProperty()->Accessibility() != ir::AccessibilityOption::NO_OPTS ||
3040             param->AsTSParameterProperty()->Readonly())) {
3041             return true;
3042         }
3043     }
3044     return false;
3045 }
3046 
FindSuperCallInConstructor(const ir::AstNode * parent,bool * hasSuperCall)3047 void ParserImpl::FindSuperCallInConstructor(const ir::AstNode *parent, bool *hasSuperCall)
3048 {
3049     parent->Iterate([this, hasSuperCall](auto *childNode) {
3050         FindSuperCallInConstructorChildNode(childNode, hasSuperCall);
3051     });
3052 }
3053 
FindSuperCallInConstructorChildNode(const ir::AstNode * childNode,bool * hasSuperCall)3054 void ParserImpl::FindSuperCallInConstructorChildNode(const ir::AstNode *childNode, bool *hasSuperCall)
3055 {
3056     if (*hasSuperCall) {
3057         return;
3058     }
3059     switch (childNode->Type()) {
3060         case ir::AstNodeType::CALL_EXPRESSION: {
3061             if (childNode->AsCallExpression()->Callee()->IsSuperExpression()) {
3062                 *hasSuperCall = true;
3063             }
3064             break;
3065         }
3066         case ir::AstNodeType::CLASS_DEFINITION: {
3067             break;
3068         }
3069         default: {
3070             FindSuperCallInConstructor(childNode, hasSuperCall);
3071             break;
3072         }
3073     }
3074 }
3075 
ParseEnumMembers(ir::Identifier * key,const lexer::SourcePosition & enumStart,bool isExport,bool isDeclare,bool isConst)3076 ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart,
3077                                                     bool isExport, bool isDeclare, bool isConst)
3078 {
3079     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3080         ThrowSyntaxError("'{' expected");
3081     }
3082 
3083     ArenaVector<ir::TSEnumMember *> members(Allocator()->Adapter());
3084     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
3085 
3086     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3087         ir::Expression *memberKey = nullptr;
3088         const auto &keyStartLoc = lexer_->GetToken().Start();
3089         binder::EnumDecl *decl {};
3090 
3091         if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3092             memberKey = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
3093             decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().Ident());
3094             memberKey->SetRange(lexer_->GetToken().Loc());
3095             lexer_->NextToken();
3096         } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
3097             memberKey = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3098             decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().String());
3099             memberKey->SetRange(lexer_->GetToken().Loc());
3100             lexer_->NextToken();
3101         } else {
3102             ThrowSyntaxError("Unexpected token in enum member");
3103         }
3104 
3105         ir::Expression *memberInit = nullptr;
3106         lexer::SourcePosition initStart = lexer_->GetToken().Start();
3107 
3108         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3109             lexer_->NextToken();  // eat '='
3110             initStart = lexer_->GetToken().Start();
3111             memberInit = ParseExpression();
3112         }
3113 
3114         auto *member = AllocNode<ir::TSEnumMember>(memberKey, memberInit);
3115         decl->BindNode(member);
3116         member->SetRange({initStart, lexer_->GetToken().End()});
3117         members.push_back(member);
3118 
3119         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3120             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat ','
3121         }
3122     }
3123 
3124     auto *enumDeclaration = AllocNode<ir::TSEnumDeclaration>(
3125         Binder()->GetScope()->AsTSEnumScope(), key, std::move(members), isExport, isDeclare, isConst);
3126     enumDeclaration->SetRange({enumStart, lexer_->GetToken().End()});
3127     Binder()->GetScope()->BindNode(enumDeclaration);
3128     lexer_->NextToken();  // eat '}'
3129 
3130     return enumDeclaration;
3131 }
3132 
ParseEnumDeclaration(bool isExport,bool isDeclare,bool isConst)3133 ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isExport, bool isDeclare, bool isConst)
3134 {
3135     ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM);
3136     lexer::SourcePosition enumStart = lexer_->GetToken().Start();
3137     lexer_->NextToken();  // eat enum keyword
3138 
3139     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3140         ThrowSyntaxError("Identifier expected");
3141     }
3142 
3143     const util::StringView &ident = lexer_->GetToken().Ident();
3144     auto *currentScope = Binder()->GetScope();
3145     binder::Variable *res = currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3146     if (res == nullptr && isExport && currentScope->IsTSModuleScope()) {
3147         res = currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3148         if (res != nullptr) {
3149             currentScope->AddLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident, res);
3150         }
3151     }
3152     if (res == nullptr) {
3153         Binder()->AddTsDecl<binder::EnumLiteralDecl>(lexer_->GetToken().Start(), isDeclare,
3154                                                      Allocator(), ident, isExport, isConst);
3155         res = currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3156         if (isExport && currentScope->IsTSModuleScope()) {
3157             currentScope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::ENUMLITERAL>(ident, res);
3158         }
3159         res->AsEnumLiteralVariable()->SetEnumMembers(Allocator()->New<binder::VariableMap>(Allocator()->Adapter()));
3160     }
3161     binder::VariableMap *enumMemberBindings = res->AsEnumLiteralVariable()->GetEnumMembers();
3162 
3163     auto *key = AllocNode<ir::Identifier>(ident);
3164     key->SetRange(lexer_->GetToken().Loc());
3165     key->SetReference();
3166     lexer_->NextToken();
3167 
3168     if (!res->Declaration()->IsEnumLiteralDecl() ||
3169         (isConst ^ res->Declaration()->AsEnumLiteralDecl()->IsConst())) {
3170         Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident);
3171     }
3172 
3173     auto enumCtx = binder::LexicalScope<binder::TSEnumScope>(Binder(), enumMemberBindings);
3174     auto *enumDeclaration = ParseEnumMembers(key, enumStart, isExport, isDeclare, isConst);
3175     res->Declaration()->AsEnumLiteralDecl()->Add(enumDeclaration);
3176 
3177     return enumDeclaration;
3178 }
3179 
ValidateFunctionParam(const ArenaVector<ir::Expression * > & params,const ir::Expression * parameter,bool * seenOptional)3180 void ParserImpl::ValidateFunctionParam(const ArenaVector<ir::Expression *> &params, const ir::Expression *parameter,
3181                                        bool *seenOptional)
3182 {
3183     if (!parameter->IsIdentifier()) {
3184         context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
3185         if (!parameter->IsRestElement()) {
3186             return;
3187         }
3188 
3189         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3190             const char *msg = (Extension() == ScriptExtension::JS ? "Rest parameter must be last formal parameter"
3191                                                                   : "A rest parameter must be last in parameter list");
3192             ThrowSyntaxError(msg);
3193         }
3194         return;
3195     }
3196 
3197     if (Extension() != ScriptExtension::TS) {
3198         return;
3199     }
3200 
3201     bool currentIsOptinal = parameter->AsIdentifier()->IsOptional();
3202     if (*seenOptional && !currentIsOptinal) {
3203         ThrowSyntaxError("A required parameter cannot follow an optional parameter");
3204     }
3205 
3206     *seenOptional |= currentIsOptinal;
3207     const util::StringView &paramName = parameter->AsIdentifier()->Name();
3208 
3209     if (paramName.Is("this")) {
3210         if (!params.empty()) {
3211             ThrowSyntaxError("A 'this' parameter must be the first parameter");
3212         }
3213 
3214         if (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) {
3215             ThrowSyntaxError("A constructor cannot have a 'this' parameter");
3216         }
3217 
3218         if (context_.Status() & ParserStatus::ARROW_FUNCTION) {
3219             ThrowSyntaxError("An arrow function cannot have a 'this' parameter");
3220         }
3221 
3222         if (context_.Status() & ParserStatus::ACCESSOR_FUNCTION) {
3223             ThrowSyntaxError("'get' and 'set' accessors cannot declare 'this' parameters");
3224         }
3225     }
3226 
3227     if (paramName.Is("constructor") && (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION)) {
3228         ThrowSyntaxError("'constructor' cannot be used as a parameter property name");
3229     }
3230 }
3231 
ParseFunctionParams(bool isDeclare,ArenaVector<ir::ParamDecorators> * paramDecorators)3232 ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams(bool isDeclare,
3233                                                               ArenaVector<ir::ParamDecorators> *paramDecorators)
3234 {
3235     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
3236     lexer_->NextToken();
3237 
3238     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3239     bool seenOptional = false;
3240 
3241     size_t index = 0;
3242     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3243         if (context_.Status() & ParserStatus::IN_METHOD_DEFINITION) {
3244             auto decorators = ParseDecorators();
3245             if (!decorators.empty()) {
3246                 ASSERT(paramDecorators != nullptr);
3247                 paramDecorators->push_back({index, std::move(decorators)});
3248             }
3249         }
3250 
3251         ir::Expression *parameter = ParseFunctionParameter(isDeclare);
3252         ValidateFunctionParam(params, parameter, &seenOptional);
3253 
3254         params.push_back(parameter);
3255 
3256         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
3257             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3258             ThrowSyntaxError(", expected");
3259         }
3260 
3261         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3262             lexer_->NextToken();
3263         }
3264 
3265         index++;
3266     }
3267 
3268     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
3269     lexer_->NextToken();
3270 
3271     return params;
3272 }
3273 
CheckTypeNameIsReserved(const util::StringView & paramName)3274 bool ParserImpl::CheckTypeNameIsReserved(const util::StringView &paramName)
3275 {
3276     return paramName.Is("number") || paramName.Is("any") || paramName.Is("unknown") || paramName.Is("never") ||
3277            paramName.Is("bigint") || paramName.Is("boolean") || paramName.Is("string") || paramName.Is("string") ||
3278            paramName.Is("void") || paramName.Is("object");
3279 }
3280 
ParseTsTypeParameter(bool throwError,bool addBinding)3281 ir::TSTypeParameter *ParserImpl::ParseTsTypeParameter(bool throwError, bool addBinding)
3282 {
3283     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3284 
3285     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3286         if (!throwError) {
3287             return nullptr;
3288         }
3289 
3290         ThrowSyntaxError("Type parameter declaration expected");
3291     }
3292 
3293     const auto &ident = lexer_->GetToken().Ident();
3294 
3295     if (CheckTypeNameIsReserved(ident)) {
3296         if (!throwError) {
3297             return nullptr;
3298         }
3299 
3300         ThrowSyntaxError("Invalid type parameter name");
3301     }
3302 
3303     auto *paramIdent = AllocNode<ir::Identifier>(ident);
3304 
3305     if (addBinding) {
3306         Binder()->AddDecl<binder::LetDecl>(lexer_->GetToken().Start(), false, ident);
3307     }
3308 
3309     paramIdent->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
3310 
3311     lexer_->NextToken();
3312 
3313     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3314 
3315     if (throwError) {
3316         options |= TypeAnnotationParsingOptions::THROW_ERROR;
3317     }
3318 
3319     ir::Expression *constraint = nullptr;
3320     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
3321         lexer_->NextToken();
3322         constraint = ParseTsTypeAnnotation(&options);
3323     }
3324 
3325     ir::Expression *defaultType = nullptr;
3326     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3327         lexer_->NextToken();
3328         defaultType = ParseTsTypeAnnotation(&options);
3329     }
3330 
3331     auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType);
3332 
3333     typeParam->SetRange({startLoc, lexer_->GetToken().End()});
3334 
3335     return typeParam;
3336 }
3337 
ParseTsTypeParameterDeclaration(bool throwError)3338 ir::TSTypeParameterDeclaration *ParserImpl::ParseTsTypeParameterDeclaration(bool throwError)
3339 {
3340     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3341 
3342     auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
3343 
3344     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3345     ArenaVector<ir::TSTypeParameter *> params(Allocator()->Adapter());
3346     bool seenDefault = false;
3347     size_t requiredParams = 0;
3348     lexer_->NextToken();  // eat '<'
3349 
3350     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3351         ir::TSTypeParameter *currentParam = ParseTsTypeParameter(throwError, true);
3352 
3353         if (!currentParam) {
3354             ASSERT(!throwError);
3355             return nullptr;
3356         }
3357 
3358         if (currentParam->DefaultType()) {
3359             seenDefault = true;
3360         } else if (seenDefault) {
3361             ThrowSyntaxError("Required type parameters may not follow optional type parameters.");
3362         } else {
3363             requiredParams++;
3364         }
3365 
3366         params.push_back(currentParam);
3367 
3368         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3369             lexer_->NextToken();
3370             continue;
3371         }
3372 
3373         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3374             if (!throwError) {
3375                 return nullptr;
3376             }
3377 
3378             ThrowSyntaxError("'>' expected");
3379         }
3380     }
3381 
3382     if (params.empty()) {
3383         ThrowSyntaxError("Type parameter list cannot be empty.");
3384     }
3385 
3386     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3387     lexer_->NextToken();  // eat '>'
3388 
3389     auto *typeParamDecl =
3390         AllocNode<ir::TSTypeParameterDeclaration>(localCtx.GetScope(), std::move(params), requiredParams);
3391     typeParamDecl->SetRange({startLoc, endLoc});
3392     localCtx.GetScope()->BindNode(typeParamDecl);
3393 
3394     return typeParamDecl;
3395 }
3396 
ParseTsTypeParameterInstantiation(bool throwError)3397 ir::TSTypeParameterInstantiation *ParserImpl::ParseTsTypeParameterInstantiation(bool throwError)
3398 {
3399     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3400     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3401     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3402     lexer_->NextToken();  // eat '<'
3403 
3404     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3405         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3406 
3407         if (throwError) {
3408             options |= TypeAnnotationParsingOptions::THROW_ERROR;
3409         }
3410 
3411         ir::Expression *currentParam = ParseTsTypeAnnotation(&options);
3412 
3413         if (!currentParam) {
3414             return nullptr;
3415         }
3416 
3417         params.push_back(currentParam);
3418 
3419         switch (lexer_->GetToken().Type()) {
3420             case lexer::TokenType::PUNCTUATOR_COMMA: {
3421                 lexer_->NextToken();
3422                 continue;
3423             }
3424             case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: {
3425                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 1);
3426                 break;
3427             }
3428             case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
3429                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 2);
3430                 break;
3431             }
3432             case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
3433                 break;
3434             }
3435             default: {
3436                 if (throwError) {
3437                     ThrowSyntaxError("'>' expected");
3438                 }
3439 
3440                 return nullptr;
3441             }
3442         }
3443     }
3444 
3445     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3446     lexer_->NextToken();
3447 
3448     auto *typeParamInst = AllocNode<ir::TSTypeParameterInstantiation>(std::move(params));
3449 
3450     typeParamInst->SetRange({startLoc, endLoc});
3451 
3452     return typeParamInst;
3453 }
3454 
ParseFunction(ParserStatus newStatus,bool isDeclare,ArenaVector<ir::ParamDecorators> * paramDecorators)3455 ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus,
3456                                               bool isDeclare,
3457                                               ArenaVector<ir::ParamDecorators> *paramDecorators)
3458 {
3459     FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
3460 
3461     FunctionParameterContext funcParamContext(&context_, Binder());
3462     auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
3463 
3464     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3465 
3466     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
3467     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
3468         typeParamDecl = ParseTsTypeParameterDeclaration();
3469     }
3470 
3471     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
3472         ThrowSyntaxError("Unexpected token, expected '('");
3473     }
3474 
3475     if (newStatus & (ParserStatus::ASYNC_FUNCTION | ParserStatus::FUNCTION_DECLARATION)) {
3476         context_.Status() |= ParserStatus::DISALLOW_AWAIT;
3477     }
3478 
3479     ArenaVector<ir::Expression *> params = ParseFunctionParams(isDeclare, paramDecorators);
3480 
3481     ir::Expression *returnTypeAnnotation = nullptr;
3482 
3483     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3484         lexer_->NextToken();  // eat ':'
3485         TypeAnnotationParsingOptions options =
3486             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
3487         returnTypeAnnotation = ParseTsTypeAnnotation(&options);
3488     }
3489 
3490     auto functionCtx = binder::LexicalScope<binder::FunctionScope>(Binder());
3491     auto *functionScope = functionCtx.GetScope();
3492     functionScope->BindParamScope(funcParamScope);
3493     funcParamScope->BindFunctionScope(functionScope);
3494 
3495     ir::BlockStatement *body = nullptr;
3496     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3497     bool letDeclare = true;
3498 
3499     if (newStatus & ParserStatus::ASYNC_FUNCTION) {
3500         context_.Status() &= ~ParserStatus::DISALLOW_AWAIT;
3501     } else {
3502         context_.Status() |= ParserStatus::DISALLOW_AWAIT;
3503     }
3504 
3505     if (newStatus & ParserStatus::GENERATOR_FUNCTION) {
3506         context_.Status() |= ParserStatus::ALLOW_YIELD;
3507     }
3508 
3509     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3510         if (Extension() == ScriptExtension::TS && (newStatus & ParserStatus::FUNCTION_DECLARATION)) {
3511             ValidateTsFunctionOverloadParams(params);
3512             functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
3513         } else if (!isDeclare && !(context_.Status() & ParserStatus::IN_METHOD_DEFINITION)) {
3514             ThrowSyntaxError("Unexpected token, expected '{'");
3515         } else {
3516             letDeclare = false;
3517             functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
3518         }
3519     } else if (isDeclare) {
3520         ThrowSyntaxError("An implementation cannot be declared in ambient contexts.");
3521     } else {
3522         body = ParseBlockStatement(functionScope);
3523         endLoc = body->End();
3524     }
3525 
3526     auto *funcNode =
3527         AllocNode<ir::ScriptFunction>(functionScope, std::move(params), typeParamDecl, body, returnTypeAnnotation,
3528                                       functionContext.Flags(), isDeclare && letDeclare,
3529                                       Extension() == ScriptExtension::TS);
3530     functionScope->BindNode(funcNode);
3531     funcParamScope->BindNode(funcNode);
3532     funcNode->SetRange({startLoc, endLoc});
3533 
3534     return funcNode;
3535 }
3536 
ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression * > & params)3537 void ParserImpl::ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression *> &params)
3538 {
3539     for (auto *it : params) {
3540         if (it->IsAssignmentPattern()) {
3541             ThrowSyntaxError(
3542                 "A parameter initializer is only allowed in a function "
3543                 "or constructor implementation.",
3544                 it->Start());
3545         }
3546     }
3547 }
3548 
ParseSpreadElement(ExpressionParseFlags flags)3549 ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
3550 {
3551     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
3552     lexer::SourcePosition startLocation = lexer_->GetToken().Start();
3553     bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN);
3554     lexer_->NextToken();
3555 
3556     ir::Expression *argument {};
3557     if (inPattern) {
3558         argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
3559         if ((flags & ExpressionParseFlags::OBJECT_PATTERN) && !argument->IsIdentifier()) {
3560             ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
3561         }
3562     } else {
3563         argument = ParseExpression(flags);
3564     }
3565 
3566     ir::Expression *typeAnnotation = nullptr;
3567 
3568     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3569         lexer_->NextToken();  // eat ':'
3570         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
3571         typeAnnotation = ParseTsTypeAnnotation(&options);
3572     }
3573 
3574     if (inPattern && argument->IsAssignmentExpression()) {
3575         ThrowSyntaxError("RestParameter does not support an initializer");
3576     }
3577 
3578     lexer::SourcePosition endLoc = typeAnnotation ? typeAnnotation->End() : argument->End();
3579 
3580     auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
3581     auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, argument);
3582     spreadElementNode->SetRange({startLocation, endLoc});
3583 
3584     if (typeAnnotation) {
3585         spreadElementNode->SetTsTypeAnnotation(typeAnnotation);
3586     }
3587 
3588     return spreadElementNode;
3589 }
3590 
CreateTsParameterProperty(ir::Expression * parameter,ir::ModifierFlags modifiers)3591 ir::TSParameterProperty *ParserImpl::CreateTsParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
3592 {
3593     auto accessibility = ir::AccessibilityOption::NO_OPTS;
3594     bool readonly = false;
3595     bool isStatic = false;
3596     bool isExport = false;
3597 
3598     if (modifiers & ir::ModifierFlags::PRIVATE) {
3599         accessibility = ir::AccessibilityOption::PRIVATE;
3600     } else if ((modifiers & ir::ModifierFlags::PUBLIC)) {
3601         accessibility = ir::AccessibilityOption::PUBLIC;
3602     } else if (modifiers & ir::ModifierFlags::PROTECTED) {
3603         accessibility = ir::AccessibilityOption::PROTECTED;
3604     }
3605 
3606     if (modifiers & ir::ModifierFlags::READONLY) {
3607         readonly = true;
3608     }
3609 
3610     if (modifiers & ir::ModifierFlags::STATIC) {
3611         isStatic = true;
3612     }
3613 
3614     // TODO(Csaba Repasi): Handle export property of TSParameterProperty
3615 
3616     return AllocNode<ir::TSParameterProperty>(accessibility, parameter, readonly, isStatic, isExport);
3617 }
3618 
ParseFunctionParameter(bool isDeclare)3619 ir::Expression *ParserImpl::ParseFunctionParameter(bool isDeclare)
3620 {
3621     if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_THIS) {
3622         lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
3623     }
3624 
3625     lexer::SourcePosition parameterStart = lexer_->GetToken().Start();
3626     ir::ModifierFlags modifiers = ParseModifiers();
3627     // TODO(Csaba Repasi): throw error if using strick mode reserved keyword here
3628     if (!(context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) && modifiers != ir::ModifierFlags::NONE) {
3629         ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
3630     }
3631 
3632     lexer::TokenType tokenType = lexer_->GetToken().Type();
3633     if (tokenType == lexer::TokenType::LITERAL_IDENT &&
3634         (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ARGUMENTS ||
3635          lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EVAL)) {
3636         ThrowSyntaxError(
3637             "'eval' or 'arguments' can't be defined or assigned to "
3638             "in strict mode code",
3639             lexer_->GetToken().Start());
3640     }
3641 
3642     ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true, isDeclare);
3643 
3644     if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
3645         ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
3646     }
3647 
3648     if (modifiers != ir::ModifierFlags::NONE &&
3649         (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
3650          (functionParameter->IsAssignmentPattern() &&
3651           (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
3652            functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
3653         ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
3654     }
3655 
3656     if (modifiers != ir::ModifierFlags::NONE) {
3657         functionParameter = CreateTsParameterProperty(functionParameter, modifiers);
3658         functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
3659     }
3660 
3661     Binder()->AddParamDecl(functionParameter);
3662 
3663     return functionParameter;
3664 }
3665 
ValidateLvalueAssignmentTarget(ir::Expression * node) const3666 void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node) const
3667 {
3668     switch (node->Type()) {
3669         case ir::AstNodeType::IDENTIFIER: {
3670             // Check the prevoius ident name
3671             if (node->AsIdentifier()->Name().Is("arguments")) {
3672                 ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
3673             } else if (node->AsIdentifier()->Name().Is("eval")) {
3674                 ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
3675             }
3676             break;
3677         }
3678         case ir::AstNodeType::MEMBER_EXPRESSION: {
3679             break;
3680         }
3681         case ir::AstNodeType::TS_AS_EXPRESSION: {
3682             ValidateLvalueAssignmentTarget(node->AsTSAsExpression()->Expr());
3683             break;
3684         }
3685         case ir::AstNodeType::TS_TYPE_ASSERTION: {
3686             ValidateLvalueAssignmentTarget(node->AsTSTypeAssertion()->GetExpression());
3687             break;
3688         }
3689         default: {
3690             ThrowSyntaxError("Invalid left-hand side in assignment expression");
3691         }
3692     }
3693 }
3694 
ValidateAssignmentTarget(ExpressionParseFlags flags,ir::Expression * node)3695 void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
3696 {
3697     switch (node->Type()) {
3698         case ir::AstNodeType::ARRAY_PATTERN:
3699         case ir::AstNodeType::OBJECT_PATTERN: {
3700             break;
3701         }
3702         case ir::AstNodeType::ARRAY_EXPRESSION:
3703         case ir::AstNodeType::OBJECT_EXPRESSION: {
3704             if (flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) {
3705                 return;
3706             }
3707 
3708             [[fallthrough]];
3709         }
3710         default: {
3711             return ValidateLvalueAssignmentTarget(node);
3712         }
3713     }
3714 }
3715 
ValidateArrowParameterBindings(const ir::Expression * node)3716 void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
3717 {
3718     switch (node->Type()) {
3719         case ir::AstNodeType::IDENTIFIER: {
3720             const util::StringView &identifier = node->AsIdentifier()->Name();
3721 
3722             if (context_.IsAsync() && identifier.Is("await")) {
3723                 ThrowSyntaxError("'await' in formal parameter is invalid.", node->Start());
3724             }
3725             break;
3726         }
3727         case ir::AstNodeType::OMITTED_EXPRESSION: {
3728             break;
3729         }
3730         case ir::AstNodeType::REST_ELEMENT: {
3731             ValidateArrowParameterBindings(node->AsRestElement()->Argument());
3732             break;
3733         }
3734         case ir::AstNodeType::PROPERTY: {
3735             break;
3736         }
3737         case ir::AstNodeType::OBJECT_PATTERN: {
3738             const auto &props = node->AsObjectPattern()->Properties();
3739 
3740             for (auto *it : props) {
3741                 ValidateArrowParameterBindings(it);
3742             }
3743             break;
3744         }
3745         case ir::AstNodeType::ARRAY_PATTERN: {
3746             const auto &elements = node->AsArrayPattern()->Elements();
3747 
3748             for (auto *it : elements) {
3749                 ValidateArrowParameterBindings(it);
3750             }
3751             break;
3752         }
3753         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
3754             ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
3755             break;
3756         }
3757         default: {
3758             ThrowSyntaxError("Unexpected ArrowParameter element");
3759         }
3760     }
3761 }
3762 
CurrentTokenIsModifier(char32_t nextCp) const3763 bool ParserImpl::CurrentTokenIsModifier(char32_t nextCp) const
3764 {
3765     return (Extension() == ScriptExtension::TS &&
3766             (nextCp != LEX_CHAR_EQUALS || nextCp != LEX_CHAR_SEMICOLON || nextCp != LEX_CHAR_LEFT_PAREN));
3767 }
3768 
ThrowParameterModifierError(ir::ModifierFlags status) const3769 void ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const
3770 {
3771     ThrowSyntaxError(
3772         {"'", (status & ir::ModifierFlags::STATIC) ? "static" : ((status & ir::ModifierFlags::ASYNC) ? "async" : "declare") ,
3773          "' modifier cannot appear on a parameter."},
3774         lexer_->GetToken().Start());
3775 }
3776 
ThrowSyntaxError(std::string_view errorMessage) const3777 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage) const
3778 {
3779     ThrowSyntaxError(errorMessage, lexer_->GetToken().Start());
3780 }
3781 
ThrowSyntaxError(std::initializer_list<std::string_view> list) const3782 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const
3783 {
3784     ThrowSyntaxError(list, lexer_->GetToken().Start());
3785 }
3786 
ThrowSyntaxError(std::initializer_list<std::string_view> list,const lexer::SourcePosition & pos) const3787 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const
3788 {
3789     std::stringstream ss;
3790 
3791     for (const auto &it : list) {
3792         ss << it;
3793     }
3794 
3795     std::string err = ss.str();
3796 
3797     ThrowSyntaxError(std::string_view {err}, pos);
3798 }
3799 
ThrowSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos) const3800 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
3801 {
3802     lexer::LineIndex index(program_.SourceCode());
3803     lexer::SourceLocation loc = index.GetLocation(pos);
3804 
3805     throw Error {ErrorType::SYNTAX, errorMessage, loc.line, loc.col};
3806 }
3807 
Extension() const3808 ScriptExtension ParserImpl::Extension() const
3809 {
3810     return program_.Extension();
3811 }
3812 
GetSourceTextModuleRecord()3813 parser::SourceTextModuleRecord *ParserImpl::GetSourceTextModuleRecord()
3814 {
3815     return Binder()->Program()->ModuleRecord();
3816 }
3817 
GetSourceTextTypeModuleRecord()3818 parser::SourceTextModuleRecord *ParserImpl::GetSourceTextTypeModuleRecord()
3819 {
3820     return Binder()->Program()->TypeModuleRecord();
3821 }
3822 
AddPatchFixHelper(util::PatchFix * patchFixHelper)3823 void ParserImpl::AddPatchFixHelper(util::PatchFix *patchFixHelper)
3824 {
3825     program_.AddPatchFixHelper(patchFixHelper);
3826 }
3827 
IsDtsFile() const3828 bool ParserImpl::IsDtsFile() const
3829 {
3830     return program_.IsDtsFile();
3831 }
3832 
CheckStrictReservedWord() const3833 void ParserImpl::CheckStrictReservedWord() const
3834 {
3835     if (Extension() == ScriptExtension::JS) {
3836         if (lexer_->GetToken().IsJsStrictReservedWord()) {
3837             ThrowSyntaxError("Unexpected reserved word in strict mode.");
3838         }
3839     } else {
3840         if (lexer_->GetToken().KeywordType() >= lexer::TokenType::KEYW_ARGUMENTS) {
3841             ThrowSyntaxError("Unexpected reserved word in strict mode.");
3842         }
3843     }
3844 }
3845 
3846 }  // namespace panda::es2panda::parser
3847