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