• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 "scopesInitPhase.h"
17 #include "util/diagnosticEngine.h"
18 #include "compiler/lowering/util.h"
19 
20 namespace ark::es2panda::compiler {
21 
22 template <typename T>
LexicalScopeCreateOrEnter(varbinder::VarBinder * varBinder,ir::AstNode * ast)23 varbinder::LexicalScope<T> LexicalScopeCreateOrEnter(varbinder::VarBinder *varBinder, ir::AstNode *ast)
24 {
25     if (ast != nullptr && ast->Scope() != nullptr) {
26         return varbinder::LexicalScope<T>::Enter(varBinder, reinterpret_cast<T *>(ast->Scope()));
27     }
28     return varbinder::LexicalScope<T>(varBinder);
29 }
30 
31 template <typename T, typename... Args>
AddOrGetDecl(varbinder::VarBinder * varBinder,util::StringView name,ir::AstNode * ast,const lexer::SourcePosition & pos,Args &&...args)32 T *AddOrGetDecl(varbinder::VarBinder *varBinder, util::StringView name, ir::AstNode *ast,
33                 const lexer::SourcePosition &pos, Args &&...args)
34 {
35     if (name.Is(ERROR_LITERAL)) {
36         return nullptr;
37     }
38 
39     if (auto *var = varBinder->GetScope()->FindLocal(name, varbinder::ResolveBindingOptions::BINDINGS);
40         var != nullptr && var->Declaration() != nullptr && var->Declaration()->Node() == ast) {
41         return reinterpret_cast<T *>(var->Declaration());
42     }
43 
44     return varBinder->AddDecl<T>(pos, args...);
45 }
46 
Perform(PhaseContext * ctx,parser::Program * program)47 bool ScopesInitPhase::Perform(PhaseContext *ctx, parser::Program *program)
48 {
49     Prepare(ctx, program);
50     program->VarBinder()->InitTopScope();
51     HandleBlockStmt(program->Ast(), GetScope());
52     Finalize();
53     return true;
54 }
55 
VisitScriptFunction(ir::ScriptFunction * scriptFunction)56 void ScopesInitPhase::VisitScriptFunction(ir::ScriptFunction *scriptFunction)
57 {
58     if (auto *const id = scriptFunction->Id(); id != nullptr && id->Variable() == nullptr) {
59         auto const *const curScope = VarBinder()->GetScope();
60         auto const &functionName = id->Name();
61         auto const res =
62             curScope->Find(functionName, scriptFunction->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC
63                                                                     : varbinder::ResolveBindingOptions::ALL_NON_STATIC);
64         if (res.variable != nullptr && res.variable->Declaration()->IsFunctionDecl()) {
65             id->SetVariable(res.variable);
66         }
67     }
68 
69     HandleFunction(scriptFunction);
70 }
71 
VisitBlockStatement(ir::BlockStatement * blockStmt)72 void ScopesInitPhase::VisitBlockStatement(ir::BlockStatement *blockStmt)
73 {
74     auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), blockStmt);
75     HandleBlockStmt(blockStmt, GetScope());
76 }
77 
VisitImportDeclaration(ir::ImportDeclaration * importDeclaration)78 void ScopesInitPhase::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration)
79 {
80     ImportDeclarationContext importCtx(VarBinder());
81     Iterate(importDeclaration);
82     importCtx.BindImportDecl(importDeclaration);
83 }
84 
VisitClassStaticBlock(ir::ClassStaticBlock * staticBlock)85 void ScopesInitPhase::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock)
86 {
87     Iterate(staticBlock);
88 }
89 
VisitMethodDefinition(ir::MethodDefinition * methodDefinition)90 void ScopesInitPhase::VisitMethodDefinition(ir::MethodDefinition *methodDefinition)
91 {
92     Iterate(methodDefinition);
93 }
94 
HandleFunctionSig(ir::TSTypeParameterDeclaration * typeParams,const ArenaVector<ir::Expression * > & params,ir::TypeNode * returnType)95 varbinder::FunctionParamScope *ScopesInitPhase::HandleFunctionSig(ir::TSTypeParameterDeclaration *typeParams,
96                                                                   const ArenaVector<ir::Expression *> &params,
97                                                                   ir::TypeNode *returnType)
98 {
99     auto typeParamsCtx = varbinder::LexicalScope<varbinder::LocalScope>(VarBinder());
100     CallNode(typeParams);
101 
102     auto lexicalScope = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder());
103     CallFuncParams(params);
104     CallNode(returnType);
105 
106     return lexicalScope.GetScope();
107 }
108 
HandleFunction(ir::ScriptFunction * function)109 void ScopesInitPhase::HandleFunction(ir::ScriptFunction *function)
110 {
111     CallNode(function->Id());
112 
113     // NOTE(gogabr): this will skip type/value parameters when they are added to an existing function sig
114     auto funcParamScope = (function->Scope() == nullptr) ? HandleFunctionSig(function->TypeParams(), function->Params(),
115                                                                              function->ReturnTypeAnnotation())
116                                                          : function->Scope()->ParamScope();
117     auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(VarBinder(), funcParamScope, false);
118 
119     auto functionCtx = LexicalScopeCreateOrEnter<varbinder::FunctionScope>(VarBinder(), function);
120     auto *functionScope = functionCtx.GetScope();
121     BindFunctionScopes(functionScope, funcParamScope);
122 
123     if (function->Body() != nullptr && function->Body()->IsBlockStatement()) {
124         HandleBlockStmt(function->Body()->AsBlockStatement(), functionScope);
125     } else {
126         Iterate(function->Body());
127     }
128     BindScopeNode(functionScope, function);
129     funcParamScope->BindNode(function);
130 
131     CallNode(function->Annotations());
132 }
133 
HandleBlockStmt(ir::BlockStatement * block,varbinder::Scope * scope)134 void ScopesInitPhase::HandleBlockStmt(ir::BlockStatement *block, varbinder::Scope *scope)
135 {
136     if (block->Scope() == nullptr) {
137         BindScopeNode(scope, block);
138     }
139     Iterate(block);
140 }
141 
VisitClassDefinition(ir::ClassDefinition * classDef)142 void ScopesInitPhase::VisitClassDefinition(ir::ClassDefinition *classDef)
143 {
144     auto classCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef);
145     AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), classDef->InternalName(), classDef, classDef->Start(),
146                                        classDef->InternalName());
147     BindClassName(classDef);
148 
149     auto *classScope = classCtx.GetScope();
150     BindScopeNode(classScope, classDef);
151     Iterate(classDef);
152 }
153 
VisitForUpdateStatement(ir::ForUpdateStatement * forUpdateStmt)154 void ScopesInitPhase::VisitForUpdateStatement(ir::ForUpdateStatement *forUpdateStmt)
155 {
156     auto declCtx = (forUpdateStmt->Scope() == nullptr)
157                        ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
158                        : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
159                              // CC-OFFNXT(G.FMT.06-CPP) project code style
160                              VarBinder(), forUpdateStmt->Scope()->DeclScope());
161     CallNode(forUpdateStmt->Init());
162 
163     auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forUpdateStmt);
164     AttachLabelToScope(forUpdateStmt);
165     CallNode(forUpdateStmt->Test());
166     CallNode(forUpdateStmt->Update());
167     CallNode(forUpdateStmt->Body());
168     lexicalScope.GetScope()->BindDecls(declCtx.GetScope());
169     HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forUpdateStmt);
170 }
171 
VisitForInStatement(ir::ForInStatement * forInStmt)172 void ScopesInitPhase::VisitForInStatement(ir::ForInStatement *forInStmt)
173 {
174     auto declCtx = (forInStmt->Scope() == nullptr)
175                        ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
176                        : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
177                              // CC-OFFNXT(G.FMT.06-CPP) project code style
178                              VarBinder(), forInStmt->Scope()->DeclScope());
179     CallNode(forInStmt->Left());
180 
181     auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forInStmt);
182     CallNode(forInStmt->Right());
183     CallNode(forInStmt->Body());
184     HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forInStmt);
185 }
186 
VisitForOfStatement(ir::ForOfStatement * forOfStmt)187 void ScopesInitPhase::VisitForOfStatement(ir::ForOfStatement *forOfStmt)
188 {
189     auto declCtx = (forOfStmt->Scope() == nullptr)
190                        ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
191                        : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
192                              // CC-OFFNXT(G.FMT.06-CPP) project code style
193                              VarBinder(), forOfStmt->Scope()->DeclScope());
194     CallNode(forOfStmt->Left());
195 
196     auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forOfStmt);
197     AttachLabelToScope(forOfStmt);
198     CallNode(forOfStmt->Right());
199     CallNode(forOfStmt->Body());
200     HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forOfStmt);
201 }
202 
VisitCatchClause(ir::CatchClause * catchClause)203 void ScopesInitPhase::VisitCatchClause(ir::CatchClause *catchClause)
204 {
205     auto catchParamCtx = (catchClause->Scope() == nullptr)
206                              ? varbinder::LexicalScope<varbinder::CatchParamScope>(VarBinder())
207                              : varbinder::LexicalScope<varbinder::CatchParamScope>::Enter(
208                                    // CC-OFFNXT(G.FMT.06-CPP) project code style
209                                    VarBinder(), catchClause->Scope()->ParamScope());
210     auto *catchParamScope = catchParamCtx.GetScope();
211     auto *param = catchClause->Param();
212 
213     CallNode(param);
214 
215     if (param != nullptr) {
216         auto *const var = VarBinder()->AddParamDecl(param);
217         if (param->IsIdentifier()) {
218             var->SetScope(catchParamScope);
219             param->AsIdentifier()->SetVariable(var);
220         }
221     }
222 
223     // Catch Clause is scope bearer
224     catchParamScope->BindNode(catchClause);
225 
226     auto catchCtx = LexicalScopeCreateOrEnter<varbinder::CatchScope>(VarBinder(), catchClause);
227     auto *catchScope = catchCtx.GetScope();
228 
229     catchScope->AssignParamScope(catchParamScope);
230     auto body = catchClause->Body();
231     HandleBlockStmt(body, catchScope);
232 
233     BindScopeNode(catchScope, catchClause);
234 }
235 
VisitVariableDeclarator(ir::VariableDeclarator * varDecl)236 void ScopesInitPhase::VisitVariableDeclarator(ir::VariableDeclarator *varDecl)
237 {
238     auto init = varDecl->Id();
239     std::vector<ir::Identifier *> bindings = util::Helpers::CollectBindingNames(VarBinder(), init);
240     for (auto *binding : bindings) {
241         auto [decl, var] = AddOrGetVarDecl(varDecl->Flag(), binding);
242         BindVarDecl(binding, init, decl, var);
243     }
244     Iterate(varDecl);
245 }
246 
VisitSwitchStatement(ir::SwitchStatement * switchStmt)247 void ScopesInitPhase::VisitSwitchStatement(ir::SwitchStatement *switchStmt)
248 {
249     CallNode(switchStmt->Discriminant());
250     auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), switchStmt);
251     AttachLabelToScope(switchStmt);
252     BindScopeNode(localCtx.GetScope(), switchStmt);
253     CallNode(switchStmt->Cases());
254 }
255 
VisitWhileStatement(ir::WhileStatement * whileStmt)256 void ScopesInitPhase::VisitWhileStatement(ir::WhileStatement *whileStmt)
257 {
258     CallNode(whileStmt->Test());
259     auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), whileStmt);
260     AttachLabelToScope(whileStmt);
261     BindScopeNode(lexicalScope.GetScope(), whileStmt);
262     CallNode(whileStmt->Body());
263 }
264 
VisitETSStructDeclaration(ir::ETSStructDeclaration * structDecl)265 void ScopesInitPhase::VisitETSStructDeclaration(ir::ETSStructDeclaration *structDecl)
266 {
267     LogDiagnostic(diagnostic::UNEXPECTED_STRUCT, structDecl->Start());
268     // For multiple error report
269     Iterate(structDecl);
270     BindClassDefinition(structDecl->Definition());
271 }
272 
VisitClassDeclaration(ir::ClassDeclaration * classDecl)273 void ScopesInitPhase::VisitClassDeclaration(ir::ClassDeclaration *classDecl)
274 {
275     Iterate(classDecl);
276     BindClassDefinition(classDecl->Definition());
277 }
278 
VisitAnnotationDeclaration(ir::AnnotationDeclaration * annoDecl)279 void ScopesInitPhase::VisitAnnotationDeclaration(ir::AnnotationDeclaration *annoDecl)
280 {
281     // First check if there is any redefinition in the current scope
282     const auto locStart = annoDecl->GetBaseName()->Start();
283     const auto &annoName = annoDecl->GetBaseName()->Name();
284     AddOrGetDecl<varbinder::AnnotationDecl>(VarBinder(), annoName, annoDecl, locStart, annoName, annoDecl);
285     // Create and enter annotation scope
286     auto annoCtx = LexicalScopeCreateOrEnter<varbinder::AnnotationScope>(VarBinder(), annoDecl);
287     auto *classScope = annoCtx.GetScope();
288     BindScopeNode(classScope, annoDecl);
289     Iterate(annoDecl);
290 }
291 
VisitAnnotationUsage(ir::AnnotationUsage * annoUsage)292 void ScopesInitPhase::VisitAnnotationUsage(ir::AnnotationUsage *annoUsage)
293 {
294     auto annoCtx = LexicalScopeCreateOrEnter<varbinder::AnnotationParamScope>(VarBinder(), annoUsage);
295     auto *curScope = annoCtx.GetScope();
296     BindScopeNode(curScope, annoUsage);
297     Iterate(annoUsage);
298 }
299 
VisitDoWhileStatement(ir::DoWhileStatement * doWhileStmt)300 void ScopesInitPhase::VisitDoWhileStatement(ir::DoWhileStatement *doWhileStmt)
301 {
302     auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), doWhileStmt);
303     AttachLabelToScope(doWhileStmt);
304     BindScopeNode(lexicalScope.GetScope(), doWhileStmt);
305     Iterate(doWhileStmt);
306 }
307 
VisitFunctionDeclaration(ir::FunctionDeclaration * funcDecl)308 void ScopesInitPhase::VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl)
309 {
310     const auto func = funcDecl->Function();
311     if (!funcDecl->IsAnonymous()) {
312         CreateFuncDecl(func);
313     }
314     Iterate(funcDecl);
315 }
316 
VisitExportAllDeclaration(ir::ExportAllDeclaration * exportAllDecl)317 void ScopesInitPhase::VisitExportAllDeclaration(ir::ExportAllDeclaration *exportAllDecl)
318 {
319     Iterate(exportAllDecl);
320     const auto name = exportAllDecl->Exported() != nullptr ? exportAllDecl->Exported()->Name() : "*";
321     auto *decl =
322         AddOrGetDecl<varbinder::ExportDecl>(VarBinder(), name, exportAllDecl, exportAllDecl->Start(), name, "*");
323     VarBinder()->GetScope()->AsModuleScope()->AddExportDecl(exportAllDecl, decl);
324 }
325 
VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier * importSpec)326 void ScopesInitPhase::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec)
327 {
328     Iterate(importSpec);
329     AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(), "*",
330                                         importSpec->Local()->Name(), importSpec);
331 }
332 
VisitImportSpecifier(ir::ImportSpecifier * importSpec)333 void ScopesInitPhase::VisitImportSpecifier(ir::ImportSpecifier *importSpec)
334 {
335     Iterate(importSpec);
336     const auto *imported = importSpec->Imported();
337     AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(),
338                                         imported->Name(), importSpec->Local()->Name(), importSpec);
339 }
340 
VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier * importSpec)341 void ScopesInitPhase::VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier *importSpec)
342 {
343     Iterate(importSpec);
344     const auto *local = importSpec->Local();
345     AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), local->Name(), importSpec, local->Start(), "default",
346                                         local->Name(), importSpec);
347 }
348 
VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration * exportDecl)349 void ScopesInitPhase::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl)
350 {
351     ExportDeclarationContext exportDeclCtx(VarBinder());
352     Iterate(exportDecl);
353     exportDeclCtx.BindExportDecl(exportDecl);
354 }
355 
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowExpr)356 void ScopesInitPhase::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr)
357 {
358     Iterate(arrowExpr);
359 }
360 
VisitDirectEvalExpression(ir::DirectEvalExpression * directCallExpr)361 void ScopesInitPhase::VisitDirectEvalExpression(ir::DirectEvalExpression *directCallExpr)
362 {
363     VarBinder()->PropagateDirectEval();
364     Iterate(directCallExpr);
365 }
366 
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)367 void ScopesInitPhase::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
368 {
369     if (exportDecl->Decl() != nullptr) {
370         ExportDeclarationContext exportDeclCtx(VarBinder());
371         Iterate(exportDecl);
372         exportDeclCtx.BindExportDecl(exportDecl);
373     } else {
374         varbinder::ModuleScope::ExportDeclList exportDecls(program_->Allocator()->Adapter());
375 
376         for (auto *spec : exportDecl->Specifiers()) {
377             auto *decl =
378                 AddOrGetDecl<varbinder::ExportDecl>(VarBinder(), spec->Local()->Name(), spec, exportDecl->Start(),
379                                                     spec->Exported()->Name(), spec->Local()->Name(), spec);
380             exportDecls.push_back(decl);
381         }
382         VarBinder()->GetScope()->AsModuleScope()->AddExportDecl(exportDecl, std::move(exportDecls));
383     }
384 }
385 
VisitTSFunctionType(ir::TSFunctionType * funcType)386 void ScopesInitPhase::VisitTSFunctionType(ir::TSFunctionType *funcType)
387 {
388     auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::FunctionParamScope>(VarBinder(), funcType);
389     auto *funcParamScope = lexicalScope.GetScope();
390     BindScopeNode(funcParamScope, funcType);
391     Iterate(funcType);
392 }
393 
SetProgram(parser::Program * program)394 void ScopesInitPhase::SetProgram(parser::Program *program) noexcept
395 {
396     program_ = program;
397 }
398 
CallFuncParams(const ArenaVector<ir::Expression * > & params)399 void ScopesInitPhase::CallFuncParams(const ArenaVector<ir::Expression *> &params)
400 {
401     // NOTE: extract params to separate class
402     for (auto *param : params) {
403         if (!param->IsETSParameterExpression()) {
404             VarBinder()->AddParamDecl(param);
405         }
406     }
407     CallNode(params);
408 }
409 
IterateNoTParams(ir::ClassDefinition * classDef)410 void ScopesInitPhase::IterateNoTParams(ir::ClassDefinition *classDef)
411 {
412     CallNode(classDef->Super());
413     CallNode(classDef->SuperTypeParams());
414     CallNode(classDef->Annotations());
415     CallNode(classDef->Implements());
416     CallNode(classDef->Ctor());
417     CallNode(classDef->Body());
418 }
419 
LogDiagnostic(const diagnostic::DiagnosticKind & kind,const util::DiagnosticMessageParams & params,const lexer::SourcePosition & pos) const420 void ScopesInitPhase::LogDiagnostic(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams &params,
421                                     const lexer::SourcePosition &pos) const
422 {
423     ctx_->diagnosticEngine->LogDiagnostic(kind, params, pos);
424 }
425 
CreateFuncDecl(ir::ScriptFunction * func)426 void ScopesInitPhase::CreateFuncDecl(ir::ScriptFunction *func)
427 {
428     AddOrGetDecl<varbinder::FunctionDecl>(VarBinder(), func->Id()->Name(), func, func->Id()->Start(), Allocator(),
429                                           func->Id()->Name(), func);
430 }
431 
FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier * id)432 util::StringView ScopesInitPhase::FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id)
433 {
434     return id->Name();
435 }
436 
BindClassName(ir::ClassDefinition * classDef)437 varbinder::Decl *ScopesInitPhase::BindClassName(ir::ClassDefinition *classDef)
438 {
439     const auto identNode = classDef->Ident();
440     if (identNode == nullptr) {
441         return nullptr;
442     }
443 
444     auto identDecl = AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), identNode->Name(), classDef, identNode->Start(),
445                                                         identNode->Name());
446     if (identDecl != nullptr) {
447         identDecl->BindNode(classDef);
448     }
449     return identDecl;
450 }
451 
BindFunctionScopes(varbinder::FunctionScope * scope,varbinder::FunctionParamScope * paramScope)452 void ScopesInitPhase::BindFunctionScopes(varbinder::FunctionScope *scope, varbinder::FunctionParamScope *paramScope)
453 {
454     scope->BindParamScope(paramScope);
455     paramScope->BindFunctionScope(scope);
456 }
457 
BindClassDefinition(ir::ClassDefinition * classDef)458 void ScopesInitPhase::BindClassDefinition(ir::ClassDefinition *classDef)
459 {
460     if (classDef->IsGlobal()) {
461         return;  // We handle it in ClassDeclaration
462     }
463     const auto locStart = classDef->Ident()->Start();
464     const auto &className = classDef->Ident()->Name();
465     if ((classDef->Modifiers() & ir::ClassDefinitionModifiers::CLASS_DECL) != 0U) {
466         AddOrGetDecl<varbinder::ClassDecl>(VarBinder(), className, classDef, locStart, className, classDef);
467     } else {
468         AddOrGetDecl<varbinder::LetDecl>(VarBinder(), className, classDef, locStart, className, classDef);
469     }
470 }
471 
AddOrGetVarDecl(ir::VariableDeclaratorFlag flag,const ir::Identifier * id)472 std::tuple<varbinder::Decl *, varbinder::Variable *> ScopesInitPhase::AddOrGetVarDecl(ir::VariableDeclaratorFlag flag,
473                                                                                       const ir::Identifier *id)
474 {
475     auto name = id->Name();
476     auto scope = VarBinder()->GetScope();
477     if (auto var = id->Variable(); var != nullptr) {
478         if (!name.Is(ERROR_LITERAL) &&
479             (scope->FindLocal(name, varbinder::ResolveBindingOptions::ALL_VARIABLES) == nullptr)) {
480             var = scope->AddDecl(Allocator(), var->Declaration(), VarBinder()->Extension());
481         }
482         return {var->Declaration(), var};
483     }
484 
485     if (name.Is(ERROR_LITERAL)) {
486         name = compiler::GenName(Allocator()).View();
487     } else if (VarBinder()->IsETSBinder()) {
488         if (auto var = scope->FindLocal(name, varbinder::ResolveBindingOptions::ALL_VARIABLES); var != nullptr) {
489             VarBinder()->ThrowRedeclaration(id->Start(), name, var->Declaration()->Type());
490             return {var->Declaration(), var};
491         }
492     }
493 
494     switch (flag) {
495         case ir::VariableDeclaratorFlag::LET:
496             return VarBinder()->NewVarDecl<varbinder::LetDecl>(id->Start(), name);
497         case ir::VariableDeclaratorFlag::VAR:
498             return VarBinder()->NewVarDecl<varbinder::VarDecl>(id->Start(), name);
499         case ir::VariableDeclaratorFlag::CONST:
500             return VarBinder()->NewVarDecl<varbinder::ConstDecl>(id->Start(), name);
501         default:
502             ES2PANDA_UNREACHABLE();
503     }
504 }
505 
BindVarDecl(ir::Identifier * binding,ir::Expression * init,varbinder::Decl * decl,varbinder::Variable * var)506 void ScopesInitPhase::BindVarDecl([[maybe_unused]] ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
507                                   [[maybe_unused]] varbinder::Variable *var)
508 {
509     decl->BindNode(init);
510 }
511 
AttachLabelToScope(ir::AstNode * node)512 void ScopesInitPhase::AttachLabelToScope([[maybe_unused]] ir::AstNode *node) {}
513 
VisitFunctionExpression(ir::FunctionExpression * funcExpr)514 void ScopesInitPhase::VisitFunctionExpression(ir::FunctionExpression *funcExpr)
515 {
516     Iterate(funcExpr);
517     if (!funcExpr->IsAnonymous()) {
518         auto func = funcExpr->Function();
519         auto id = funcExpr->Id();
520         auto *funcParamScope = func->Scope()->ParamScope();
521         funcParamScope->BindName(Allocator(), id->Name());
522         func->SetIdent(id->Clone(Allocator(), nullptr));
523     }
524 }
525 
Prepare(ScopesInitPhase::PhaseContext * ctx,parser::Program * program)526 void ScopesInitPhase::Prepare(ScopesInitPhase::PhaseContext *ctx, parser::Program *program)
527 {
528     ctx_ = ctx;
529     program_ = program;
530 }
531 
Finalize()532 void ScopesInitPhase::Finalize()
533 {
534     ES2PANDA_ASSERT(program_->Ast() != nullptr);
535 
536     auto const removeDuplicates = [](ir::AstNode *ast) -> void {
537         if (!ast->IsTSInterfaceBody()) {
538             return;
539         }
540 
541         auto &body = ast->AsTSInterfaceBody()->Body();
542         auto it = body.begin();
543         while (it != body.end()) {
544             if ((*it)->IsMethodDefinition() &&
545                 ((*it)->AsMethodDefinition()->Function()->Flags() &
546                  (ir::ScriptFunctionFlags::OVERLOAD | ir::ScriptFunctionFlags::EXTERNAL_OVERLOAD)) != 0U) {
547                 it = body.erase(it);
548             } else {
549                 ++it;
550             }
551         }
552     };
553 
554     //  Remove duplicates for overloaded methods.
555     program_->Ast()->IterateRecursively(removeDuplicates);
556 
557     AnalyzeExports();
558 }
559 
AnalyzeExports()560 void ScopesInitPhase::AnalyzeExports()
561 {
562     if (Program()->Kind() == parser::ScriptKind::MODULE && VarBinder()->TopScope()->IsModuleScope() &&
563         !VarBinder()->TopScope()->AsModuleScope()->ExportAnalysis()) {
564         LogDiagnostic(diagnostic::INVALID_EXPORT, Program()->Ast()->End());
565     }
566 }
567 
VisitTSModuleDeclaration(ir::TSModuleDeclaration * moduleDecl)568 void ScopeInitTyped::VisitTSModuleDeclaration(ir::TSModuleDeclaration *moduleDecl)
569 {
570     if (!moduleDecl->IsExternalOrAmbient()) {
571         auto name = moduleDecl->Name()->AsIdentifier()->Name();
572         auto *decl = AddOrGetDecl<varbinder::VarDecl>(VarBinder(), name, moduleDecl, moduleDecl->Name()->Start(), name);
573         ES2PANDA_ASSERT(decl != nullptr);
574         decl->BindNode(moduleDecl);
575     }
576     auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), moduleDecl);
577     BindScopeNode(localCtx.GetScope(), moduleDecl);
578     Iterate(moduleDecl);
579 }
580 
VisitTSModuleBlock(ir::TSModuleBlock * block)581 void ScopeInitTyped::VisitTSModuleBlock(ir::TSModuleBlock *block)
582 {
583     auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), block);
584     Iterate(block);
585     BindScopeNode(localCtx.GetScope(), block);
586 }
587 
VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration * typeAliasDecl)588 void ScopeInitTyped::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl)
589 {
590     const auto id = typeAliasDecl->Id();
591     varbinder::TSBinding tsBinding(Allocator(), id->Name());
592     auto *decl = VarBinder()->AddTsDecl<varbinder::TypeAliasDecl>(id->Start(), tsBinding.View());
593     auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), typeAliasDecl->TypeParams());
594     decl->BindNode(typeAliasDecl);
595     Iterate(typeAliasDecl);
596 }
597 
FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier * id)598 util::StringView ScopeInitTyped::FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id)
599 {
600     varbinder::TSBinding tsBinding(Allocator(), id->Name());
601     return tsBinding.View();
602 }
603 
VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration * interfDecl)604 void ScopeInitTyped::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfDecl)
605 {
606     const auto &bindings = VarBinder()->GetScope()->Bindings();
607     const auto ident = interfDecl->Id();
608     const auto name = FormInterfaceOrEnumDeclarationIdBinding(ident);
609     auto res = bindings.find(name);
610 
611     varbinder::InterfaceDecl *decl {};
612 
613     bool alreadyExists = false;
614     if (res == bindings.end()) {
615         decl = VarBinder()->AddTsDecl<varbinder::InterfaceDecl>(ident->Start(), Allocator(), name);
616     } else if (!AllowInterfaceRedeclaration()) {
617         LogDiagnostic(diagnostic::INTERFACE_REDECLARED, interfDecl->Start());
618         return;
619     } else if (!res->second->Declaration()->IsInterfaceDecl()) {
620         VarBinder()->ThrowRedeclaration(ident->Start(), ident->Name(), res->second->Declaration()->Type());
621         return;
622     } else {
623         decl = res->second->Declaration()->AsInterfaceDecl();
624         alreadyExists = true;
625     }
626 
627     CallNode(ident);
628     auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfDecl->TypeParams());
629     CallNode(interfDecl->TypeParams());
630     CallNode(interfDecl->Extends());
631 
632     auto localScope = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfDecl);
633     auto *identDecl =
634         AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), ident->Name(), interfDecl, ident->Start(), ident->Name());
635     ES2PANDA_ASSERT(identDecl != nullptr);
636     identDecl->BindNode(interfDecl);
637     BindScopeNode(localScope.GetScope(), interfDecl);
638 
639     CallNode(interfDecl->Body());
640     if (decl == nullptr) {  // Error processing.
641         return;
642     }
643 
644     if (!alreadyExists) {
645         decl->BindNode(interfDecl);
646     }
647     decl->Add(interfDecl);
648 }
649 
VisitTSEnumMember(ir::TSEnumMember * enumMember)650 void ScopeInitTyped::VisitTSEnumMember(ir::TSEnumMember *enumMember)
651 {
652     const auto key = enumMember->Key();
653     util::StringView name;
654     if (key->IsIdentifier()) {
655         name = key->AsIdentifier()->Name();
656     } else if (key->IsStringLiteral()) {
657         name = key->AsStringLiteral()->Str();
658     } else {
659         ES2PANDA_UNREACHABLE();
660     }
661     if (auto *decl = AddOrGetDecl<varbinder::EnumDecl>(VarBinder(), name, enumMember, key->Start(), name);
662         decl != nullptr) {
663         decl->BindNode(enumMember);
664     }
665 }
666 
VisitTSEnumDeclaration(ir::TSEnumDeclaration * enumDecl)667 void ScopeInitTyped::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
668 {
669     util::StringView ident = FormInterfaceOrEnumDeclarationIdBinding(enumDecl->Key());
670     const auto &bindings = VarBinder()->GetScope()->Bindings();
671     varbinder::EnumLiteralDecl *decl {};
672 
673     if (auto res = bindings.find(ident); res == bindings.end()) {
674         decl = VarBinder()->AddTsDecl<varbinder::EnumLiteralDecl>(enumDecl->Start(), ident, enumDecl->IsConst());
675         varbinder::LexicalScope enumCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), enumDecl);
676         decl->BindScope(enumCtx.GetScope());
677         BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), enumDecl);
678     } else {
679         if (!res->second->Declaration()->IsEnumLiteralDecl() ||
680             (enumDecl->IsConst() ^ res->second->Declaration()->AsEnumLiteralDecl()->IsConst()) != 0) {
681             VarBinder()->ThrowRedeclaration(enumDecl->Key()->Start(), enumDecl->Key()->Name(),
682                                             res->second->Declaration()->Type());
683             return;
684         }
685         decl = res->second->Declaration()->AsEnumLiteralDecl();
686         auto scopeCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(VarBinder(), decl->Scope());
687     }
688     decl->BindNode(enumDecl);
689     Iterate(enumDecl);
690 }
691 
VisitTSTypeParameter(ir::TSTypeParameter * typeParam)692 void ScopeInitTyped::VisitTSTypeParameter(ir::TSTypeParameter *typeParam)
693 {
694     auto name = typeParam->Name()->Name();
695     if (auto *decl = AddOrGetDecl<varbinder::TypeParameterDecl>(VarBinder(), name, typeParam, typeParam->Start(), name);
696         decl != nullptr) {
697         decl->BindNode(typeParam);
698     }
699     Iterate(typeParam);
700 }
701 
VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration * paramDecl)702 void ScopeInitTyped::VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration *paramDecl)
703 {
704     BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), paramDecl);
705     Iterate(paramDecl);
706 }
707 
VisitClassDefinition(ir::ClassDefinition * classDef)708 void ScopeInitTyped::VisitClassDefinition(ir::ClassDefinition *classDef)
709 {
710     auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef->TypeParams());
711     CallNode(classDef->TypeParams());
712 
713     auto classCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef);
714     BindClassName(classDef);
715     AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), classDef->InternalName(), classDef, classDef->Start(),
716                                        classDef->InternalName());
717     BindScopeNode(classCtx.GetScope(), classDef);
718     IterateNoTParams(classDef);
719 }
720 
VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration * exportDecl)721 void InitScopesPhaseTs::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl)
722 {
723     ExportDeclarationContext exportDeclCtx(VarBinder());
724     Iterate(exportDecl);
725 }
726 
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)727 void InitScopesPhaseTs::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
728 {
729     ExportDeclarationContext exportDeclCtx(VarBinder());
730     Iterate(exportDecl);
731 }
732 
VisitImportDeclaration(ir::ImportDeclaration * importDeclaration)733 void InitScopesPhaseTs::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration)
734 {
735     ImportDeclarationContext importCtx(VarBinder());
736     Iterate(importDeclaration);
737 }
738 
VisitTSFunctionType(ir::TSFunctionType * constrType)739 void InitScopesPhaseTs::VisitTSFunctionType(ir::TSFunctionType *constrType)
740 {
741     auto lexicalScope =
742         (constrType->Scope() == nullptr)
743             ? HandleFunctionSig(constrType->TypeParams(), constrType->Params(), constrType->ReturnType())
744             : constrType->Scope();
745     BindScopeNode(lexicalScope, constrType);
746 }
747 
CreateFuncDecl(ir::ScriptFunction * func)748 void InitScopesPhaseTs::CreateFuncDecl(ir::ScriptFunction *func)
749 {
750     const auto identNode = func->Id();
751     const auto startLoc = identNode->Start();
752     const auto &bindings = VarBinder()->GetScope()->Bindings();
753     auto res = bindings.find(identNode->Name());
754     varbinder::FunctionDecl *decl {};
755 
756     if (res == bindings.end()) {
757         decl = VarBinder()->AddDecl<varbinder::FunctionDecl>(startLoc, Allocator(), identNode->Name(), func);
758     } else {
759         varbinder::Decl *currentDecl = res->second->Declaration();
760 
761         auto &existing = currentDecl->AsFunctionDecl()->Decls();
762         if (std::find(existing.begin(), existing.end(), func) != existing.end()) {
763             return;
764         }
765 
766         if (!currentDecl->IsFunctionDecl() ||
767             !currentDecl->AsFunctionDecl()->Node()->AsScriptFunction()->IsOverload()) {
768             VarBinder()->ThrowRedeclaration(startLoc, currentDecl->Name(), currentDecl->Type());
769             return;
770         }
771         decl = currentDecl->AsFunctionDecl();
772     }
773 
774     ES2PANDA_ASSERT(decl != nullptr);
775     decl->Add(func);
776 }
777 
VisitTSConstructorType(ir::TSConstructorType * constrT)778 void InitScopesPhaseTs::VisitTSConstructorType(ir::TSConstructorType *constrT)
779 {
780     auto funcParamScope = (constrT->Scope() == nullptr)
781                               ? HandleFunctionSig(constrT->TypeParams(), constrT->Params(), constrT->ReturnType())
782                               : constrT->Scope();
783     BindScopeNode(funcParamScope, constrT);
784 }
785 
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowFExpr)786 void InitScopesPhaseTs::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowFExpr)
787 {
788     auto typeParamsCtx =
789         LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), arrowFExpr->Function()->TypeParams());
790     Iterate(arrowFExpr);
791 }
792 
VisitTSSignatureDeclaration(ir::TSSignatureDeclaration * signDecl)793 void InitScopesPhaseTs::VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *signDecl)
794 {
795     auto funcParamScope = (signDecl->Scope() == nullptr) ? HandleFunctionSig(signDecl->TypeParams(), signDecl->Params(),
796                                                                              signDecl->ReturnTypeAnnotation())
797                                                          : signDecl->Scope();
798     BindScopeNode(funcParamScope, signDecl);
799 }
800 
VisitTSMethodSignature(ir::TSMethodSignature * methodSign)801 void InitScopesPhaseTs::VisitTSMethodSignature(ir::TSMethodSignature *methodSign)
802 {
803     auto funcParamScope =
804         (methodSign->Scope() == nullptr)
805             ? HandleFunctionSig(methodSign->TypeParams(), methodSign->Params(), methodSign->ReturnTypeAnnotation())
806             : methodSign->Scope();
807     BindScopeNode(funcParamScope, methodSign);
808 }
809 
RunExternalNode(ir::AstNode * node,varbinder::VarBinder * varbinder)810 void InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, varbinder::VarBinder *varbinder)
811 {
812     auto program = parser::Program(varbinder->Allocator(), varbinder);
813     RunExternalNode(node, &program);
814 }
815 
RunExternalNode(ir::AstNode * node,parser::Program * ctx)816 void InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, parser::Program *ctx)
817 {
818     auto scopesPhase = InitScopesPhaseETS();
819     scopesPhase.SetProgram(ctx);
820     scopesPhase.CallNode(node);
821 }
822 
Perform(PhaseContext * ctx,parser::Program * program)823 bool InitScopesPhaseETS::Perform(PhaseContext *ctx, parser::Program *program)
824 {
825     Prepare(ctx, program);
826 
827     if (program->VarBinder()->TopScope() == nullptr) {
828         program->VarBinder()->InitTopScope();
829         BindScopeNode(GetScope(), program->Ast());
830         AddGlobalToBinder(program);
831     } else if ((ctx->compilingState == public_lib::CompilingState::MULTI_COMPILING_FOLLOW) &&
832                program->GlobalClass()->Scope() == nullptr) {
833         BindScopeNode(GetScope(), program->Ast());
834         AddGlobalToBinder(program);
835     }
836     HandleProgram(program);
837     Finalize();
838     return true;
839 }
840 
HandleProgram(parser::Program * program)841 void InitScopesPhaseETS::HandleProgram(parser::Program *program)
842 {
843     for (auto &[_, progList] : program->ExternalSources()) {
844         (void)_;
845         auto savedTopScope(program->VarBinder()->TopScope());
846         auto mainProg = progList.front();
847         mainProg->VarBinder()->InitTopScope();
848         AddGlobalToBinder(mainProg);
849         BindScopeNode(mainProg->VarBinder()->GetScope(), mainProg->Ast());
850         auto globalClass = mainProg->GlobalClass();
851         auto globalScope = mainProg->GlobalScope();
852         for (auto &prog : progList) {
853             if (prog->GetFlag(parser::ProgramFlags::AST_HAS_SCOPES_INITIALIZED)) {
854                 continue;
855             }
856             prog->SetGlobalClass(globalClass);
857             BindScopeNode(prog->VarBinder()->GetScope(), prog->Ast());
858             prog->VarBinder()->ResetTopScope(globalScope);
859             if (mainProg->Ast() != nullptr) {
860                 InitScopesPhaseETS().Perform(Context(), prog);
861                 prog->SetFlag(parser::ProgramFlags::AST_HAS_SCOPES_INITIALIZED);
862             }
863         }
864         program->VarBinder()->ResetTopScope(savedTopScope);
865     }
866     ES2PANDA_ASSERT(program->Ast() != nullptr);
867 
868     auto *ast = program->Ast();
869     HandleETSModule(ast);
870 }
871 
BindVarDecl(ir::Identifier * binding,ir::Expression * init,varbinder::Decl * decl,varbinder::Variable * var)872 void InitScopesPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
873                                      varbinder::Variable *var)
874 {
875     binding->SetVariable(var);
876     var->SetScope(VarBinder()->GetScope());
877     var->AddFlag(varbinder::VariableFlags::LOCAL);
878     decl->BindNode(init);
879 }
880 
VisitBlockExpression(ir::BlockExpression * blockExpr)881 void InitScopesPhaseETS::VisitBlockExpression(ir::BlockExpression *blockExpr)
882 {
883     auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), blockExpr);
884     if (blockExpr->Scope() == nullptr) {
885         BindScopeNode(GetScope(), blockExpr);
886     }
887     Iterate(blockExpr);
888 }
889 
VisitClassStaticBlock(ir::ClassStaticBlock * staticBlock)890 void InitScopesPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock)
891 {
892     const auto func = staticBlock->Function();
893 
894     {
895         auto funcParamCtx = (func->Scope() == nullptr)
896                                 ? varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder())
897                                 : varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(
898                                       // CC-OFFNXT(G.FMT.06-CPP) project code style
899                                       VarBinder(), func->Scope()->ParamScope());
900         auto *funcParamScope = funcParamCtx.GetScope();
901         auto funcCtx = LexicalScopeCreateOrEnter<varbinder::FunctionScope>(VarBinder(), func);
902         auto *funcScope = funcCtx.GetScope();
903 
904         func->Body()->AsBlockStatement()->SetScope(funcScope);
905         BindScopeNode(funcScope, func);
906         funcParamScope->BindNode(func);
907         BindFunctionScopes(funcScope, funcParamScope);
908         Iterate(func->Body()->AsBlockStatement());
909     }
910 
911     auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(
912         VarBinder(), VarBinder()->GetScope()->AsClassScope()->StaticMethodScope());
913 
914     if (func->Id()->Variable() != nullptr) {
915         return;
916     }
917 
918     varbinder::Variable *var;
919     if (var = VarBinder()->GetScope()->FindLocal(func->Id()->Name(), varbinder::ResolveBindingOptions::STATIC_METHODS);
920         var == nullptr) {
921         var = std::get<1>(VarBinder()->NewVarDecl<varbinder::FunctionDecl>(func->Id()->Start(), Allocator(),
922                                                                            func->Id()->Name(), staticBlock));
923         var->AddFlag(varbinder::VariableFlags::METHOD);
924     }
925 
926     func->Id()->SetVariable(var);
927 }
928 
VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier * importSpec)929 void InitScopesPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec)
930 {
931     if (importSpec->Local()->Name().Empty()) {
932         return;
933     }
934     AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(),
935                                         importSpec->Local()->Name(), importSpec->Local()->Name(), importSpec);
936     auto var =
937         VarBinder()->GetScope()->FindLocal(importSpec->Local()->Name(), varbinder::ResolveBindingOptions::BINDINGS);
938     importSpec->Local()->SetVariable(var);
939     Iterate(importSpec);
940 }
941 
VisitImportSpecifier(ir::ImportSpecifier * importSpec)942 void InitScopesPhaseETS::VisitImportSpecifier(ir::ImportSpecifier *importSpec)
943 {
944     if (importSpec->Parent()->IsETSImportDeclaration() &&
945         importSpec->Parent()->AsETSImportDeclaration()->IsPureDynamic()) {
946         auto [decl, var] = VarBinder()->NewVarDecl<varbinder::LetDecl>(importSpec->Local()->Start(),
947                                                                        importSpec->Local()->Name(), importSpec);
948         var->AddFlag(varbinder::VariableFlags::INITIALIZED);
949     }
950     Iterate(importSpec);
951 }
952 
953 //  Auxiliary method to avoid extra nested levels and too large function size
AddOverload(ir::MethodDefinition * overload,varbinder::Variable * variable)954 void AddOverload(ir::MethodDefinition *overload, varbinder::Variable *variable) noexcept
955 {
956     auto *currentNode = variable->Declaration()->Node();
957     currentNode->AsMethodDefinition()->AddOverload(overload);
958     ES2PANDA_ASSERT(overload->Id() != nullptr);
959     overload->Id()->SetVariable(variable);
960     overload->SetParent(currentNode);
961 }
962 
DeclareClassMethod(ir::MethodDefinition * method)963 void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method)
964 {
965     ES2PANDA_ASSERT(VarBinder()->GetScope()->IsClassScope() && method->AsMethodDefinition()->Function() != nullptr);
966 
967     if ((method->AsMethodDefinition()->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD) != 0) {
968         return;
969     }
970 
971     const auto methodName = method->Id();
972     auto *const clsScope = VarBinder()->GetScope()->AsClassScope();
973     auto options =
974         method->IsStatic()
975             ? varbinder::ResolveBindingOptions::STATIC_VARIABLES | varbinder::ResolveBindingOptions::STATIC_DECLARATION
976             : varbinder::ResolveBindingOptions::VARIABLES | varbinder::ResolveBindingOptions::DECLARATION;
977     auto variable = clsScope->FindLocal(methodName->Name(), options);
978     if (variable != nullptr) {
979         VarBinder()->ThrowRedeclaration(methodName->Start(), methodName->Name(), variable->Declaration()->Type());
980     }
981 
982     varbinder::LocalScope *targetScope {};
983     if (method->IsStatic() || method->IsConstructor()) {
984         targetScope = clsScope->StaticMethodScope();
985     } else {
986         targetScope = clsScope->InstanceMethodScope();
987     }
988     auto *found = targetScope->FindLocal(methodName->Name(), varbinder::ResolveBindingOptions::BINDINGS);
989 
990     MaybeAddOverload(method, methodName, found, clsScope, targetScope);
991 }
992 
MaybeAddOverload(ir::MethodDefinition * method,ir::Identifier * methodName,varbinder::Variable * found,varbinder::ClassScope * clsScope,varbinder::LocalScope * targetScope)993 void InitScopesPhaseETS::MaybeAddOverload(ir::MethodDefinition *method, ir::Identifier *methodName,
994                                           varbinder::Variable *found, varbinder::ClassScope *clsScope,
995                                           varbinder::LocalScope *targetScope)
996 {
997     if (found == nullptr) {
998         auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(VarBinder(), targetScope);
999 
1000         auto *var = methodName->Variable();
1001         if (var == nullptr) {
1002             var = std::get<1>(VarBinder()->NewVarDecl<varbinder::FunctionDecl>(methodName->Start(), Allocator(),
1003                                                                                methodName->Name(), method));
1004             var->SetScope(clsScope);
1005             if (targetScope->HasFlag(varbinder::ScopeFlags::STATIC)) {
1006                 var->AddFlag(varbinder::VariableFlags::STATIC);
1007             }
1008             var->AddFlag(varbinder::VariableFlags::METHOD);
1009             methodName->SetVariable(var);
1010         }
1011         for (auto *overload : method->Overloads()) {
1012             ES2PANDA_ASSERT((overload->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD) ||
1013                             (overload->Function()->Flags() & ir::ScriptFunctionFlags::EXTERNAL_OVERLOAD));
1014             overload->Id()->SetVariable(var);
1015             overload->SetParent(var->Declaration()->Node());
1016         }
1017     } else {
1018         if (methodName->Name().Is(compiler::Signatures::MAIN) && clsScope->Parent()->IsGlobalScope()) {
1019             LogDiagnostic(diagnostic::OVERLOADED_MAIN, methodName->Start());
1020         }
1021         ES2PANDA_ASSERT(method->Function() != nullptr &&
1022                         (method->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD) == 0U);
1023 
1024         AddOverload(method, found);
1025         method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
1026 
1027         // default params overloads
1028         for (auto *overload : method->Overloads()) {
1029             ES2PANDA_ASSERT((overload->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD) != 0U);
1030             AddOverload(overload, found);
1031         }
1032         method->ClearOverloads();
1033     }
1034 }
1035 
VisitETSReExportDeclaration(ir::ETSReExportDeclaration * reExport)1036 void InitScopesPhaseETS::VisitETSReExportDeclaration(ir::ETSReExportDeclaration *reExport)
1037 {
1038     if (!reExport->GetETSImportDeclarations()->IsValid()) {
1039         return;
1040     }
1041     if (reExport->GetETSImportDeclarations()->Language().IsDynamic()) {
1042         VarBinder()->AsETSBinder()->AddDynamicImport(reExport->GetETSImportDeclarations());
1043     }
1044     VarBinder()->AsETSBinder()->AddReExportImport(reExport);
1045     Iterate(reExport);
1046 }
1047 
VisitETSParameterExpression(ir::ETSParameterExpression * paramExpr)1048 void InitScopesPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr)
1049 {
1050     auto *const var = VarBinder()->AddParamDecl(paramExpr);
1051     paramExpr->SetVariable(var);
1052     var->SetScope(VarBinder()->GetScope());
1053     var->AddFlag(varbinder::VariableFlags::INITIALIZED);
1054     Iterate(paramExpr);
1055 }
1056 
VisitETSImportDeclaration(ir::ETSImportDeclaration * importDecl)1057 void InitScopesPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl)
1058 {
1059     if (!importDecl->IsValid()) {
1060         return;
1061     }
1062     ImportDeclarationContext importCtx(VarBinder());
1063     if (importDecl->Language().IsDynamic()) {
1064         VarBinder()->AsETSBinder()->AddDynamicImport(importDecl);
1065     }
1066     Iterate(importDecl);
1067 }
1068 
VisitTSEnumMember(ir::TSEnumMember * enumMember)1069 void InitScopesPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enumMember)
1070 {
1071     auto ident = enumMember->Key()->AsIdentifier();
1072     if (ident->Variable() != nullptr) {
1073         return;
1074     }
1075 
1076     auto const &name = ident->Name();
1077     varbinder::Variable *var = nullptr;
1078 
1079     if (var = VarBinder()->GetScope()->FindLocal(name, varbinder::ResolveBindingOptions::STATIC_VARIABLES);
1080         var == nullptr) {
1081         varbinder::Decl *decl = nullptr;
1082         std::tie(decl, var) = VarBinder()->NewVarDecl<varbinder::LetDecl>(ident->Start(), name);
1083         var->SetScope(VarBinder()->GetScope());
1084         var->AddFlag(varbinder::VariableFlags::STATIC);
1085         decl->BindNode(enumMember);
1086     } else {
1087         VarBinder()->ThrowRedeclaration(ident->Start(), name, var->Declaration()->Type());
1088     }
1089 
1090     ident->SetVariable(var);
1091     Iterate(enumMember);
1092 }
1093 
VisitMethodDefinition(ir::MethodDefinition * method)1094 void InitScopesPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method)
1095 {
1096     ES2PANDA_ASSERT(method->Function() != nullptr);
1097     if (method->Function()->Scope() != nullptr) {
1098         return;
1099     }
1100 
1101     auto *curScope = VarBinder()->GetScope();
1102     const auto methodName = method->Id();
1103     auto res =
1104         curScope->Find(methodName->Name(), method->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC
1105                                                               : varbinder::ResolveBindingOptions::ALL_NON_STATIC);
1106     if (res.variable != nullptr && !res.variable->Declaration()->IsFunctionDecl() && res.scope == curScope) {
1107         VarBinder()->ThrowRedeclaration(methodName->Start(), res.name, varbinder::DeclType::METHOD);
1108     }
1109 
1110     auto result = curScope->FindLocal(methodName->Name(), varbinder::ResolveBindingOptions::ALL_DECLARATION);
1111     if (result != nullptr) {
1112         VarBinder()->ThrowLocalRedeclaration(methodName->Start(), result->Name());
1113     }
1114 
1115     Iterate(method);
1116     DeclareClassMethod(method);
1117 }
1118 
VisitETSFunctionType(ir::ETSFunctionType * funcType)1119 void InitScopesPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *funcType)
1120 {
1121     auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), funcType->TypeParams());
1122 
1123     // Check for existing scope
1124     // In some cases we can visit function again with scope that already exists
1125     // Example: async lambda, we "move" original function to another place and visit it again
1126     if (funcType->Scope() == nullptr) {
1127         varbinder::LexicalScope<varbinder::FunctionParamScope> lexicalScope(VarBinder());
1128         auto *funcParamScope = lexicalScope.GetScope();
1129         BindScopeNode(funcParamScope, funcType);
1130         Iterate(funcType);
1131     }
1132 }
1133 
VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression * newClassExpr)1134 void InitScopesPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr)
1135 {
1136     CallNode(newClassExpr->GetArguments());
1137     CallNode(newClassExpr->GetTypeRef());
1138 }
1139 
VisitTSTypeParameter(ir::TSTypeParameter * typeParam)1140 void InitScopesPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *typeParam)
1141 {
1142     if (typeParam->Name()->Variable() != nullptr) {
1143         return;
1144     }
1145     auto [decl, var] =
1146         VarBinder()->NewVarDecl<varbinder::TypeParameterDecl>(typeParam->Name()->Start(), typeParam->Name()->Name());
1147     typeParam->Name()->SetVariable(var);
1148     var->SetScope(VarBinder()->GetScope());
1149     var->AddFlag(varbinder::VariableFlags::TYPE_PARAMETER);
1150     decl->BindNode(typeParam);
1151     CallNode(typeParam->Annotations());
1152     CallNode(typeParam->DefaultType());
1153 }
1154 
VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration * interfaceDecl)1155 void InitScopesPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl)
1156 {
1157     {
1158         auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfaceDecl->TypeParams());
1159         CallNode(interfaceDecl->TypeParams());
1160         CallNode(interfaceDecl->Extends());
1161         auto localScope = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), interfaceDecl);
1162         CallNode(interfaceDecl->Body());
1163         CallNode(interfaceDecl->Annotations());
1164         BindScopeNode(localScope.GetScope(), interfaceDecl);
1165     }
1166     auto name = FormInterfaceOrEnumDeclarationIdBinding(interfaceDecl->Id());
1167     if (auto *decl = AddOrGetDecl<varbinder::InterfaceDecl>(VarBinder(), name, interfaceDecl, interfaceDecl->Start(),
1168                                                             Allocator(), name, interfaceDecl);
1169         decl != nullptr) {
1170         decl->AsInterfaceDecl()->Add(interfaceDecl);
1171     }
1172 }
1173 
VisitTSEnumDeclaration(ir::TSEnumDeclaration * enumDecl)1174 void InitScopesPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
1175 {
1176     {
1177         const auto enumCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), enumDecl);
1178         BindScopeNode(enumCtx.GetScope(), enumDecl);
1179         Iterate(enumDecl);
1180     }
1181     auto name = FormInterfaceOrEnumDeclarationIdBinding(enumDecl->Key());
1182     if (auto *decl = AddOrGetDecl<varbinder::EnumLiteralDecl>(VarBinder(), name, enumDecl, enumDecl->Key()->Start(),
1183                                                               name, enumDecl, enumDecl->IsConst());
1184         decl != nullptr) {
1185         decl->BindScope(enumDecl->Scope());
1186     }
1187 }
1188 
VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration * typeAlias)1189 void InitScopesPhaseETS::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAlias)
1190 {
1191     AddOrGetDecl<varbinder::TypeAliasDecl>(VarBinder(), typeAlias->Id()->Name(), typeAlias, typeAlias->Id()->Start(),
1192                                            typeAlias->Id()->Name(), typeAlias);
1193     auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), typeAlias->TypeParams());
1194     Iterate(typeAlias);
1195 }
1196 
AddGlobalToBinder(parser::Program * program)1197 void InitScopesPhaseETS::AddGlobalToBinder(parser::Program *program)
1198 {
1199     auto globalId = program->GlobalClass()->Ident();
1200     if (globalId->Variable() != nullptr) {
1201         return;
1202     }
1203 
1204     auto start = globalId->Start();
1205     auto name = globalId->Name();
1206     auto *varBinder = program->VarBinder();
1207     auto *ctx = varBinder->GetContext();
1208     if (ctx->compilingState == public_lib::CompilingState::MULTI_COMPILING_FOLLOW) {
1209         auto *scope = varBinder->GetScope();
1210         auto bindings = scope->Bindings();
1211         auto res = bindings.find(name);
1212         if (res != bindings.end()) {
1213             auto classCtx =
1214                 LexicalScopeCreateOrEnter<varbinder::ClassScope>(program->VarBinder(), program->GlobalClass());
1215             classCtx.GetScope()->BindNode(program->GlobalClass());
1216             program->GlobalClass()->SetScope(classCtx.GetScope());
1217             globalId->SetVariable(res->second);
1218             return;
1219         }
1220     }
1221     auto [decl2, var] = varBinder->NewVarDecl<varbinder::ClassDecl>(start, name);
1222 
1223     auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(program->VarBinder(), program->GlobalClass());
1224     classCtx.GetScope()->BindNode(program->GlobalClass());
1225     program->GlobalClass()->SetScope(classCtx.GetScope());
1226 
1227     auto *classDecl = program->GlobalClass()->Parent();
1228     decl2->BindNode(classDecl);
1229     globalId->SetVariable(var);
1230 }
1231 
HandleETSModule(ir::BlockStatement * script)1232 void InitScopesPhaseETS::HandleETSModule(ir::BlockStatement *script)
1233 {
1234     for (auto decl : script->Statements()) {
1235         if (decl->IsETSImportDeclaration() || decl->IsETSReExportDeclaration()) {
1236             CallNode(decl);
1237         } else {
1238             auto classCtx =
1239                 varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), Program()->GlobalClassScope());
1240             CallNode(decl);
1241         }
1242     }
1243     auto classCtx = varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), Program()->GlobalClassScope());
1244 
1245     for (auto decl : script->Statements()) {
1246         AddGlobalDeclaration(decl);
1247     }
1248 }
1249 
VisitClassDefinition(ir::ClassDefinition * classDef)1250 void InitScopesPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef)
1251 {
1252     if (classDef->IsGlobal()) {
1253         ParseGlobalClass(classDef);
1254         return;
1255     }
1256     auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef->TypeParams());
1257     CallNode(classDef->TypeParams());
1258     auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), classDef);
1259 
1260     IterateNoTParams(classDef);
1261     FilterOverloads(classDef->Body());
1262     auto *classScope = classCtx.GetScope();
1263     BindScopeNode(classScope, classDef);
1264 }
1265 
VisitTSInterfaceBody(ir::TSInterfaceBody * interfBody)1266 void InitScopesPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody)
1267 {
1268     Iterate(interfBody);
1269     FilterInterfaceOverloads(interfBody->Body());
1270 }
1271 
FilterInterfaceOverloads(ArenaVector<ir::AstNode *,false> & props)1272 void InitScopesPhaseETS::FilterInterfaceOverloads(ArenaVector<ir::AstNode *, false> &props)
1273 {
1274     auto condition = [](ir::AstNode *prop) {
1275         if (prop->IsMethodDefinition()) {
1276             const auto func = prop->AsMethodDefinition()->Function();
1277             return func->IsOverload() && func->Body() != nullptr;
1278         }
1279         return false;
1280     };
1281     props.erase(std::remove_if(props.begin(), props.end(), condition), props.end());
1282 }
1283 
FilterOverloads(ArenaVector<ir::AstNode *,false> & props)1284 void InitScopesPhaseETS::FilterOverloads(ArenaVector<ir::AstNode *, false> &props)
1285 {
1286     auto condition = [](ir::AstNode *prop) {
1287         if (prop->IsMethodDefinition()) {
1288             const auto func = prop->AsMethodDefinition()->Function();
1289             return func->IsOverload();
1290         }
1291         return false;
1292     };
1293     props.erase(std::remove_if(props.begin(), props.end(), condition), props.end());
1294 }
1295 
VisitClassProperty(ir::ClassProperty * classProp)1296 void InitScopesPhaseETS::VisitClassProperty(ir::ClassProperty *classProp)
1297 {
1298     auto curScope = VarBinder()->GetScope();
1299     const auto name = classProp->Key()->AsIdentifier()->Name();
1300 
1301     ES2PANDA_ASSERT(!classProp->IsClassStaticBlock());
1302 
1303     if (classProp->IsConst()) {
1304         ES2PANDA_ASSERT(curScope->Parent() != nullptr);
1305         const auto initializer = classProp->Value();
1306         if (initializer == nullptr && curScope->Parent()->IsGlobalScope() && !classProp->IsDeclare() &&
1307             !classProp->NeedInitInStaticBlock()) {
1308             auto pos = classProp->End();
1309             // NOTE: Just use property Name?
1310             if (classProp->TypeAnnotation() != nullptr && !classProp->TypeAnnotation()->IsETSPrimitiveType()) {
1311                 --(pos.index);
1312             }
1313             LogDiagnostic(diagnostic::CONST_WITHOUT_INIT, pos);
1314         }
1315         AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1316     } else if (classProp->IsReadonly()) {
1317         AddOrGetDecl<varbinder::ReadonlyDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1318     } else {
1319         AddOrGetDecl<varbinder::LetDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1320     }
1321     Iterate(classProp);
1322 }
1323 
VisitBreakStatement(ir::BreakStatement * stmt)1324 void InitScopesPhaseETS::VisitBreakStatement(ir::BreakStatement *stmt)
1325 {
1326     auto label = stmt->Ident();
1327     if (label != nullptr) {
1328         auto scope = VarBinder()->GetScope();
1329         auto var = scope->FindInFunctionScope(label->Name(), varbinder::ResolveBindingOptions::ALL).variable;
1330         label->SetVariable(var);
1331     }
1332 }
1333 
VisitContinueStatement(ir::ContinueStatement * stmt)1334 void InitScopesPhaseETS::VisitContinueStatement(ir::ContinueStatement *stmt)
1335 {
1336     auto label = stmt->Ident();
1337     if (label != nullptr) {
1338         auto scope = VarBinder()->GetScope();
1339         auto var = scope->FindInFunctionScope(label->Name(), varbinder::ResolveBindingOptions::ALL).variable;
1340         label->SetVariable(var);
1341     }
1342 }
1343 
AttachLabelToScope(ir::AstNode * node)1344 void InitScopesPhaseETS::AttachLabelToScope(ir::AstNode *node)
1345 {
1346     if (node->Parent() == nullptr) {
1347         return;
1348     }
1349 
1350     if (!node->Parent()->IsLabelledStatement()) {
1351         return;
1352     }
1353 
1354     auto stmt = node->Parent()->AsLabelledStatement();
1355     auto label = stmt->Ident();
1356     if (label == nullptr) {
1357         return;
1358     }
1359 
1360     auto decl = AddOrGetDecl<varbinder::LabelDecl>(VarBinder(), label->Name(), stmt, label->Start(), label->Name());
1361     if (decl == nullptr) {
1362         return;
1363     }
1364 
1365     decl->BindNode(stmt);
1366 
1367     auto var = VarBinder()->GetScope()->FindLocal(label->Name(), varbinder::ResolveBindingOptions::BINDINGS);
1368     if (var != nullptr) {
1369         label->SetVariable(var);
1370         var->SetScope(VarBinder()->GetScope());
1371         var->AddFlag(varbinder::VariableFlags::LOCAL);
1372     }
1373 }
1374 
ParseGlobalClass(ir::ClassDefinition * global)1375 void InitScopesPhaseETS::ParseGlobalClass(ir::ClassDefinition *global)
1376 {
1377     bool defaultExported = false;
1378     for (auto decl : global->Body()) {
1379         if (decl->IsDefaultExported()) {
1380             if (defaultExported) {
1381                 LogDiagnostic(diagnostic::MULTIPLE_DEFAULT_EXPORTS, decl->Start());
1382             }
1383             defaultExported = true;
1384         }
1385         CallNode(decl);
1386     }
1387     CallNode(global->Annotations());
1388     FilterOverloads(global->Body());
1389 }
1390 
AddGlobalDeclaration(ir::AstNode * node)1391 void InitScopesPhaseETS::AddGlobalDeclaration(ir::AstNode *node)
1392 {
1393     ir::Identifier *ident = nullptr;
1394     bool isBuiltin = false;
1395     switch (node->Type()) {
1396         case ir::AstNodeType::CLASS_DECLARATION: {
1397             auto def = node->AsClassDeclaration()->Definition();
1398             if (def->IsGlobal()) {
1399                 return;
1400             }
1401             ident = def->Ident();
1402             isBuiltin = def->IsFromExternal();
1403             break;
1404         }
1405         case ir::AstNodeType::ANNOTATION_DECLARATION: {
1406             ident = node->AsAnnotationDeclaration()->GetBaseName();
1407             isBuiltin = false;
1408             break;
1409         }
1410         case ir::AstNodeType::STRUCT_DECLARATION: {
1411             ident = node->AsETSStructDeclaration()->Definition()->Ident();
1412             isBuiltin = node->AsETSStructDeclaration()->Definition()->IsFromExternal();
1413             break;
1414         }
1415         case ir::AstNodeType::TS_INTERFACE_DECLARATION: {
1416             ident = node->AsTSInterfaceDeclaration()->Id();
1417             isBuiltin = node->AsTSInterfaceDeclaration()->IsFromExternal();
1418             break;
1419         }
1420         case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: {
1421             ident = node->AsTSTypeAliasDeclaration()->Id();
1422             break;
1423         }
1424         default: {
1425             break;
1426         }
1427     }
1428     if (ident != nullptr && ident->Variable() != nullptr) {
1429         VarBinder()->TopScope()->InsertBinding(ident->Name(), ident->Variable());
1430         if (isBuiltin) {
1431             ident->Variable()->AddFlag(varbinder::VariableFlags::BUILTIN_TYPE);
1432         }
1433     }
1434 }
1435 
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowExpr)1436 void InitScopesPhaseAS::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr)
1437 {
1438     Iterate(arrowExpr);
1439 }
1440 
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)1441 void InitScopesPhaseAS::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
1442 {
1443     ExportDeclarationContext exportDeclCtx(VarBinder());
1444     Iterate(exportDecl);
1445 }
1446 
1447 }  // namespace ark::es2panda::compiler
1448