1 /*
2 * Copyright (c) 2021 - 2023 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 "ETSBinder.h"
17
18 #include "ir/expressions/identifier.h"
19 #include "ir/expressions/thisExpression.h"
20 #include "ir/expressions/memberExpression.h"
21 #include "ir/expressions/callExpression.h"
22 #include "ir/expressions/functionExpression.h"
23 #include "ir/base/methodDefinition.h"
24 #include "ir/base/scriptFunction.h"
25 #include "ir/base/classElement.h"
26 #include "ir/base/classDefinition.h"
27 #include "ir/base/classProperty.h"
28 #include "ir/base/classStaticBlock.h"
29 #include "ir/statements/blockStatement.h"
30 #include "ir/statements/classDeclaration.h"
31 #include "ir/statements/variableDeclarator.h"
32 #include "ir/statements/functionDeclaration.h"
33 #include "ir/statements/returnStatement.h"
34 #include "ir/ets/etsPrimitiveType.h"
35 #include "ir/ets/etsTypeReferencePart.h"
36 #include "ir/ets/etsNewClassInstanceExpression.h"
37 #include "ir/ets/etsTypeReference.h"
38 #include "ir/ets/etsFunctionType.h"
39 #include "ir/ets/etsScript.h"
40 #include "ir/ets/etsImportDeclaration.h"
41 #include "ir/ts/tsInterfaceDeclaration.h"
42 #include "ir/ts/tsTypeParameterDeclaration.h"
43 #include "ir/ts/tsTypeParameterInstantiation.h"
44 #include "ir/ts/tsClassImplements.h"
45 #include "ir/ts/tsEnumDeclaration.h"
46 #include "ir/ts/tsEnumMember.h"
47 #include "ir/ts/tsInterfaceHeritage.h"
48 #include "ir/ts/tsInterfaceBody.h"
49 #include "ir/ts/tsFunctionType.h"
50 #include "ir/ts/tsQualifiedName.h"
51 #include "ir/module/importDefaultSpecifier.h"
52 #include "ir/module/importNamespaceSpecifier.h"
53 #include "ir/module/importDeclaration.h"
54 #include "ir/module/importSpecifier.h"
55 #include "ir/expressions/literals/stringLiteral.h"
56 #include "parser/program/program.h"
57 #include "util/helpers.h"
58 #include "util/ustring.h"
59 #include "checker/types/type.h"
60 #include "checker/types/ets/types.h"
61
62 namespace panda::es2panda::varbinder {
63
IdentifierAnalysis()64 void ETSBinder::IdentifierAnalysis()
65 {
66 ASSERT(Program()->Ast());
67 ASSERT(GetScope() == TopScope());
68 ASSERT(VarScope() == TopScope());
69
70 recordTable_->SetProgram(Program());
71 globalRecordTable_.SetClassDefinition(Program()->GlobalClass());
72 externalRecordTable_.insert({Program(), &globalRecordTable_});
73
74 BuildProgram();
75
76 ASSERT(globalRecordTable_.ClassDefinition() == Program()->GlobalClass());
77 }
78
LookupTypeArgumentReferences(ir::ETSTypeReference * typeRef)79 void ETSBinder::LookupTypeArgumentReferences(ir::ETSTypeReference *typeRef)
80 {
81 auto *iter = typeRef->Part();
82
83 while (iter != nullptr) {
84 if (iter->TypeParams() == nullptr) {
85 iter = iter->Previous();
86 continue;
87 }
88
89 ResolveReferences(iter->TypeParams());
90 iter = iter->Previous();
91 }
92 }
93
LookupTypeReference(ir::Identifier * ident,bool allowDynamicNamespaces)94 void ETSBinder::LookupTypeReference(ir::Identifier *ident, bool allowDynamicNamespaces)
95 {
96 const auto &name = ident->Name();
97 auto *iter = GetScope();
98
99 while (iter != nullptr) {
100 auto res = iter->Find(name, ResolveBindingOptions::DECLARATION | ResolveBindingOptions::TYPE_ALIASES);
101 if (res.variable == nullptr) {
102 break;
103 }
104
105 if (IsDynamicModuleVariable(res.variable)) {
106 ident->SetVariable(res.variable);
107 return;
108 }
109
110 if (allowDynamicNamespaces && IsDynamicNamespaceVariable(res.variable)) {
111 ident->SetVariable(res.variable);
112 return;
113 }
114
115 switch (res.variable->Declaration()->Node()->Type()) {
116 case ir::AstNodeType::CLASS_DECLARATION:
117 case ir::AstNodeType::CLASS_DEFINITION:
118 case ir::AstNodeType::STRUCT_DECLARATION:
119 case ir::AstNodeType::TS_ENUM_DECLARATION:
120 case ir::AstNodeType::TS_INTERFACE_DECLARATION:
121 case ir::AstNodeType::TS_TYPE_PARAMETER:
122 case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION:
123 case ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER: {
124 ident->SetVariable(res.variable);
125 return;
126 }
127 default: {
128 iter = iter->Parent();
129 }
130 }
131 }
132
133 ThrowUnresolvableType(ident->Start(), name);
134 }
135
ResolveReferencesForScope(ir::AstNode const * const parent,Scope * const scope)136 void ETSBinder::ResolveReferencesForScope(ir::AstNode const *const parent, Scope *const scope)
137 {
138 parent->Iterate([this, scope](auto *node) { ResolveReferenceForScope(node, scope); });
139 }
140
ResolveReferenceForScope(ir::AstNode * const node,Scope * const scope)141 void ETSBinder::ResolveReferenceForScope(ir::AstNode *const node, Scope *const scope)
142 {
143 switch (node->Type()) {
144 case ir::AstNodeType::IDENTIFIER: {
145 auto *ident = node->AsIdentifier();
146 if (ident->Variable() != nullptr) {
147 break;
148 }
149 if (auto const res = scope->Find(ident->Name(), ResolveBindingOptions::ALL); res.variable != nullptr) {
150 ident->SetVariable(res.variable);
151 }
152 break;
153 }
154 case ir::AstNodeType::VARIABLE_DECLARATOR: {
155 auto scopeCtx = LexicalScope<Scope>::Enter(this, scope);
156 BuildVarDeclarator(node->AsVariableDeclarator());
157 break;
158 }
159 /* Maybe will be used
160 case ir::AstNodeType::BLOCK_STATEMENT: {
161 auto scope_ctx = LexicalScope<Scope>::Enter(this, node->AsBlockStatement()->Scope());
162 ResolveReferences(node);
163 break;
164 }
165 */
166 default: {
167 ResolveReferencesForScope(node, scope);
168 break;
169 }
170 }
171 }
172
LookupIdentReference(ir::Identifier * ident)173 void ETSBinder::LookupIdentReference(ir::Identifier *ident)
174 {
175 const auto &name = ident->Name();
176 auto res = GetScope()->Find(name, ResolveBindingOptions::ALL);
177 if (res.level != 0) {
178 ASSERT(res.variable != nullptr);
179
180 auto *outerFunction = GetScope()->EnclosingVariableScope()->Node();
181
182 if ((!outerFunction->IsScriptFunction() || !outerFunction->AsScriptFunction()->IsArrow()) &&
183 !res.variable->IsGlobalVariable() && res.level > 1) {
184 ThrowInvalidCapture(ident->Start(), name);
185 }
186 }
187
188 if (res.variable == nullptr) {
189 return;
190 }
191
192 if (ident->IsReference() && res.variable->Declaration()->IsLetOrConstDecl() &&
193 !res.variable->HasFlag(VariableFlags::INITIALIZED)) {
194 ThrowTDZ(ident->Start(), name);
195 }
196 }
197
BuildClassProperty(const ir::ClassProperty * prop)198 void ETSBinder::BuildClassProperty(const ir::ClassProperty *prop)
199 {
200 ResolveReferences(prop);
201 }
202
InitializeInterfaceIdent(ir::TSInterfaceDeclaration * decl)203 void ETSBinder::InitializeInterfaceIdent(ir::TSInterfaceDeclaration *decl)
204 {
205 auto res = GetScope()->Find(decl->Id()->Name());
206
207 ASSERT(res.variable && res.variable->Declaration()->IsInterfaceDecl());
208 res.variable->AddFlag(VariableFlags::INITIALIZED);
209 decl->Id()->SetVariable(res.variable);
210 }
211
ResolveEnumDeclaration(ir::TSEnumDeclaration * enumDecl)212 void ETSBinder::ResolveEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
213 {
214 auto enumScopeCtx = LexicalScope<LocalScope>::Enter(this, enumDecl->Scope());
215
216 for (auto *member : enumDecl->Members()) {
217 ResolveReference(member);
218 }
219 }
220
ResolveInterfaceDeclaration(ir::TSInterfaceDeclaration * decl)221 void ETSBinder::ResolveInterfaceDeclaration(ir::TSInterfaceDeclaration *decl)
222 {
223 auto boundCtx = BoundContext(recordTable_, decl);
224
225 for (auto *extend : decl->Extends()) {
226 ResolveReference(extend);
227 }
228
229 auto scopeCtx = LexicalScope<ClassScope>::Enter(this, decl->Scope()->AsClassScope());
230
231 for (auto *stmt : decl->Body()->Body()) {
232 if (!stmt->IsClassProperty()) {
233 continue;
234 }
235
236 ResolveReference(stmt);
237
238 auto fieldVar =
239 ResolvePropertyReference(stmt->AsClassProperty(), decl->Scope()->AsClassScope())
240 ->FindLocal(stmt->AsClassProperty()->Id()->Name(), varbinder::ResolveBindingOptions::BINDINGS);
241 fieldVar->AddFlag(VariableFlags::INITIALIZED);
242 }
243
244 for (auto *stmt : decl->Body()->Body()) {
245 if (stmt->IsClassProperty()) {
246 continue;
247 }
248 ResolveReference(stmt);
249 }
250 }
251
BuildInterfaceDeclaration(ir::TSInterfaceDeclaration * decl)252 void ETSBinder::BuildInterfaceDeclaration(ir::TSInterfaceDeclaration *decl)
253 {
254 if (decl->TypeParams() != nullptr) {
255 auto typeParamScopeCtx = LexicalScope<LocalScope>::Enter(this, decl->TypeParams()->Scope());
256 ResolveReferences(decl->TypeParams());
257 ResolveInterfaceDeclaration(decl);
258 return;
259 }
260
261 ResolveInterfaceDeclaration(decl);
262 }
263
BuildMethodDefinition(ir::MethodDefinition * methodDef)264 void ETSBinder::BuildMethodDefinition(ir::MethodDefinition *methodDef)
265 {
266 if (methodDef->Function()->TypeParams() != nullptr) {
267 auto scopeCtx = LexicalScope<LocalScope>::Enter(this, methodDef->Function()->TypeParams()->Scope());
268 ResolveReferences(methodDef->Function()->TypeParams());
269 ResolveMethodDefinition(methodDef);
270 return;
271 }
272
273 ResolveMethodDefinition(methodDef);
274 }
275
ResolveMethodDefinition(ir::MethodDefinition * methodDef)276 void ETSBinder::ResolveMethodDefinition(ir::MethodDefinition *methodDef)
277 {
278 auto *func = methodDef->Function();
279 ResolveReferences(methodDef);
280
281 if (methodDef->IsStatic() || func->IsStaticBlock()) {
282 return;
283 }
284
285 auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, func->Scope()->ParamScope());
286
287 auto params = func->Scope()->ParamScope()->Params();
288 if (!params.empty() && params.front()->Name() == MANDATORY_PARAM_THIS) {
289 return; // Implicit this parameter is already inserted by ResolveReferences(), don't insert it twice.
290 }
291
292 auto *thisParam = AddMandatoryParam(MANDATORY_PARAM_THIS);
293 thisParam->Declaration()->BindNode(thisParam_);
294 }
295
BuildMemberExpression(ir::MemberExpression * memberExpr)296 void ETSBinder::BuildMemberExpression(ir::MemberExpression *memberExpr)
297 {
298 ResolveReference(memberExpr->Object());
299
300 if (memberExpr->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS) {
301 ResolveReference(memberExpr->Property());
302 }
303 }
304
BuildClassDefinition(ir::ClassDefinition * classDef)305 void ETSBinder::BuildClassDefinition(ir::ClassDefinition *classDef)
306 {
307 auto boundCtx = BoundContext(recordTable_, classDef);
308
309 if (classDef->TypeParams() != nullptr) {
310 auto scopeCtx = LexicalScope<LocalScope>::Enter(this, classDef->TypeParams()->Scope());
311 ResolveReferences(classDef->TypeParams());
312 BuildClassDefinitionImpl(classDef);
313 return;
314 }
315
316 BuildClassDefinitionImpl(classDef);
317 }
318
ResolvePropertyReference(ir::ClassProperty * prop,ClassScope * scope)319 LocalScope *ETSBinder::ResolvePropertyReference(ir::ClassProperty *prop, ClassScope *scope)
320 {
321 ResolveReferences(prop);
322
323 if (prop->IsStatic()) {
324 return scope->StaticFieldScope();
325 }
326
327 return scope->InstanceFieldScope();
328 }
329
BuildClassDefinitionImpl(ir::ClassDefinition * classDef)330 void ETSBinder::BuildClassDefinitionImpl(ir::ClassDefinition *classDef)
331 {
332 auto classCtx = LexicalScope<ClassScope>::Enter(this, classDef->Scope()->AsClassScope());
333
334 if (classDef->Super() != nullptr) {
335 ResolveReference(classDef->Super());
336 }
337
338 for (auto *impl : classDef->Implements()) {
339 ResolveReference(impl);
340 }
341
342 for (auto *stmt : classDef->Body()) {
343 if (!stmt->IsClassProperty()) {
344 continue;
345 }
346
347 auto fieldScope = ResolvePropertyReference(stmt->AsClassProperty(), classDef->Scope()->AsClassScope());
348 auto fieldName = stmt->AsClassProperty()->Id()->Name();
349 auto fieldVar = fieldScope->FindLocal(fieldName, varbinder::ResolveBindingOptions::BINDINGS);
350 fieldVar->AddFlag(VariableFlags::INITIALIZED);
351 if (fieldVar->Declaration()->IsConstDecl() && stmt->AsClassProperty()->Value() == nullptr) {
352 fieldVar->AddFlag(VariableFlags::EXPLICIT_INIT_REQUIRED);
353 }
354 }
355
356 for (auto *stmt : classDef->Body()) {
357 if (stmt->IsClassProperty()) {
358 continue;
359 }
360 ResolveReference(stmt);
361 }
362 }
363
AddLambdaFunctionThisParam(ir::ScriptFunction * func)364 void ETSBinder::AddLambdaFunctionThisParam(ir::ScriptFunction *func)
365 {
366 auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, func->Scope()->ParamScope());
367 auto *thisParam = AddMandatoryParam(MANDATORY_PARAM_THIS);
368 thisParam->Declaration()->BindNode(thisParam_);
369 if (!func->IsAsyncFunc()) {
370 Functions().push_back(func->Scope());
371 }
372 }
373
AddInvokeFunctionThisParam(ir::ScriptFunction * func)374 void ETSBinder::AddInvokeFunctionThisParam(ir::ScriptFunction *func)
375 {
376 auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, func->Scope()->ParamScope());
377 auto *thisParam = AddMandatoryParam(MANDATORY_PARAM_THIS);
378 thisParam->Declaration()->BindNode(thisParam_);
379 }
380
BuildProxyMethod(ir::ScriptFunction * func,const util::StringView & containingClassName,bool isStatic)381 void ETSBinder::BuildProxyMethod(ir::ScriptFunction *func, const util::StringView &containingClassName, bool isStatic)
382 {
383 ASSERT(!containingClassName.Empty());
384 func->Scope()->BindName(containingClassName);
385
386 if (!isStatic) {
387 auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, func->Scope()->ParamScope());
388 auto *thisParam = AddMandatoryParam(MANDATORY_PARAM_THIS);
389 thisParam->Declaration()->BindNode(thisParam_);
390 }
391
392 if (!func->IsAsyncFunc()) {
393 Functions().push_back(func->Scope());
394 }
395 }
396
BuildLambdaObject(ir::AstNode * refNode,ir::ClassDefinition * lambdaObject,checker::Signature * signature)397 void ETSBinder::BuildLambdaObject(ir::AstNode *refNode, ir::ClassDefinition *lambdaObject,
398 checker::Signature *signature)
399 {
400 auto boundCtx = BoundContext(GetGlobalRecordTable(), lambdaObject);
401 const auto &lambdaBody = lambdaObject->Body();
402
403 AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 2U]->AsMethodDefinition()->Function());
404 AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function());
405
406 LambdaObjects().insert({refNode, {lambdaObject, signature}});
407 }
408
BuildFunctionType(ir::ETSFunctionType * funcType)409 void ETSBinder::BuildFunctionType(ir::ETSFunctionType *funcType)
410 {
411 auto boundCtx = BoundContext(GetGlobalRecordTable(), funcType->FunctionalInterface());
412
413 auto *invokeFunc = funcType->FunctionalInterface()->Body()->Body()[0]->AsMethodDefinition()->Function();
414 auto *funcScope = invokeFunc->Scope();
415 funcScope->BindName(recordTable_->RecordName());
416 AddInvokeFunctionThisParam(invokeFunc);
417
418 GetGlobalRecordTable()->Signatures().push_back(funcScope);
419 }
420
AddDynamicSpecifiersToTopBindings(ir::AstNode * const specifier,const ir::ETSImportDeclaration * const import)421 void ETSBinder::AddDynamicSpecifiersToTopBindings(ir::AstNode *const specifier,
422 const ir::ETSImportDeclaration *const import)
423 {
424 const auto name = [specifier]() {
425 if (specifier->IsImportNamespaceSpecifier()) {
426 return specifier->AsImportNamespaceSpecifier()->Local()->Name();
427 }
428
429 return specifier->AsImportSpecifier()->Local()->Name();
430 }();
431
432 auto *const decl = Allocator()->New<varbinder::LetDecl>(name, specifier);
433 auto *const var = Allocator()->New<varbinder::LocalVariable>(decl, varbinder::VariableFlags::STATIC);
434 var->AddFlag(VariableFlags::INITIALIZED);
435
436 dynamicImportVars_.emplace(var, DynamicImportData {import, specifier, var});
437
438 TopScope()->InsertDynamicBinding(name, var);
439 }
440
InsertForeignBinding(ir::AstNode * const specifier,const ir::ETSImportDeclaration * const import,const util::StringView & name,Variable * var)441 void ETSBinder::InsertForeignBinding(ir::AstNode *const specifier, const ir::ETSImportDeclaration *const import,
442 const util::StringView &name, Variable *var)
443 {
444 if (import->Language().IsDynamic()) {
445 dynamicImportVars_.emplace(var, DynamicImportData {import, specifier, var});
446 }
447
448 TopScope()->InsertForeignBinding(name, var);
449 }
450
ImportAllForeignBindings(ir::AstNode * const specifier,const varbinder::Scope::VariableMap & globalBindings,const parser::Program * const importProgram,const varbinder::GlobalScope * const importGlobalScope,const ir::ETSImportDeclaration * const import)451 void ETSBinder::ImportAllForeignBindings(ir::AstNode *const specifier,
452 const varbinder::Scope::VariableMap &globalBindings,
453 const parser::Program *const importProgram,
454 const varbinder::GlobalScope *const importGlobalScope,
455 const ir::ETSImportDeclaration *const import)
456 {
457 for (const auto [bindingName, var] : globalBindings) {
458 if (bindingName.Is(compiler::Signatures::ETS_GLOBAL)) {
459 const auto *const classDef = var->Declaration()->Node()->AsClassDeclaration()->Definition();
460 ImportGlobalProperties(classDef);
461 continue;
462 }
463
464 if (!importGlobalScope->IsForeignBinding(bindingName) && !var->Declaration()->Node()->IsDefaultExported()) {
465 InsertForeignBinding(specifier, import, bindingName, var);
466 }
467 }
468
469 for (const auto [bindingName, var] : importProgram->GlobalClassScope()->StaticMethodScope()->Bindings()) {
470 if (!var->Declaration()->Node()->IsDefaultExported()) {
471 InsertForeignBinding(specifier, import, bindingName, var);
472 }
473 }
474
475 for (const auto [bindingName, var] : importProgram->GlobalClassScope()->StaticFieldScope()->Bindings()) {
476 if (!var->Declaration()->Node()->IsDefaultExported()) {
477 InsertForeignBinding(specifier, import, bindingName, var);
478 }
479 }
480 }
481
AddImportNamespaceSpecifiersToTopBindings(ir::AstNode * const specifier,const varbinder::Scope::VariableMap & globalBindings,const parser::Program * const importProgram,const varbinder::GlobalScope * const importGlobalScope,const ir::ETSImportDeclaration * const import)482 bool ETSBinder::AddImportNamespaceSpecifiersToTopBindings(ir::AstNode *const specifier,
483 const varbinder::Scope::VariableMap &globalBindings,
484 const parser::Program *const importProgram,
485 const varbinder::GlobalScope *const importGlobalScope,
486 const ir::ETSImportDeclaration *const import)
487 {
488 if (!specifier->IsImportNamespaceSpecifier()) {
489 return false;
490 }
491 const auto *const namespaceSpecifier = specifier->AsImportNamespaceSpecifier();
492
493 if (namespaceSpecifier->Local()->Name().Empty()) {
494 ImportAllForeignBindings(specifier, globalBindings, importProgram, importGlobalScope, import);
495 }
496
497 std::unordered_set<std::string> exportedNames;
498 for (auto item : ReExportImports()) {
499 if (auto source = import->ResolvedSource()->Str().Mutf8(),
500 program = item->GetProgramPath().Mutf8().substr(0, item->GetProgramPath().Mutf8().find_last_of('.'));
501 source == program || (source + "/index") == program) {
502 // clang-format off
503 ir::StringLiteral dirName(util::UString(util::StringView(item->GetProgramPath().Mutf8().substr(
504 0, item->GetProgramPath().Mutf8().find_last_of('/'))),
505 Allocator())
506 .View());
507 // clang-format on
508 dirName.SetStart(item->GetETSImportDeclarations()->Source()->Start());
509
510 for (auto it : item->GetETSImportDeclarations()->Specifiers()) {
511 if (it->IsImportNamespaceSpecifier() &&
512 !specifier->AsImportNamespaceSpecifier()->Local()->Name().Empty()) {
513 std::cerr << "Warning: import with alias cannot be used with re-export\n";
514 continue;
515 }
516
517 AddSpecifiersToTopBindings(it, item->GetETSImportDeclarations(),
518 dirName.Str().Is(".") ? item->GetETSImportDeclarations()->Source()
519 : &dirName);
520 if (it->IsImportSpecifier() &&
521 !exportedNames.insert(it->AsImportSpecifier()->Local()->Name().Mutf8()).second) {
522 ThrowError(import->Start(), "Ambiguous import \"" +
523 it->AsImportSpecifier()->Local()->Name().Mutf8() +
524 "\" has multiple matching exports");
525 }
526 }
527 }
528 }
529
530 return true;
531 }
532
FindImportSpecifiersVariable(const util::StringView & imported,const varbinder::Scope::VariableMap & globalBindings,const ArenaVector<parser::Program * > & recordRes)533 Variable *ETSBinder::FindImportSpecifiersVariable(const util::StringView &imported,
534 const varbinder::Scope::VariableMap &globalBindings,
535 const ArenaVector<parser::Program *> &recordRes)
536 {
537 auto foundVar = globalBindings.find(imported);
538 if (foundVar == globalBindings.end()) {
539 const auto &staticMethodBindings = recordRes.front()->GlobalClassScope()->StaticMethodScope()->Bindings();
540 foundVar = staticMethodBindings.find(imported);
541 if (foundVar != staticMethodBindings.end()) {
542 return foundVar->second;
543 }
544 bool found = false;
545 for (auto res : recordRes) {
546 const auto &staticFieldBindings = res->GlobalClassScope()->StaticFieldScope()->Bindings();
547 foundVar = staticFieldBindings.find(imported);
548 if (foundVar != staticFieldBindings.end()) {
549 found = true;
550 foundVar->second->AsLocalVariable()->AddFlag(VariableFlags::INITIALIZED);
551 break;
552 }
553 }
554 if (!found) {
555 return nullptr;
556 }
557 }
558
559 return foundVar->second;
560 }
561
AddImportSpecifiersToTopBindings(ir::AstNode * const specifier,const varbinder::Scope::VariableMap & globalBindings,const ir::ETSImportDeclaration * const import,const ArenaVector<parser::Program * > & recordRes,std::vector<ir::ETSImportDeclaration * > viewedReExport)562 bool ETSBinder::AddImportSpecifiersToTopBindings(ir::AstNode *const specifier,
563 const varbinder::Scope::VariableMap &globalBindings,
564 const ir::ETSImportDeclaration *const import,
565 const ArenaVector<parser::Program *> &recordRes,
566 std::vector<ir::ETSImportDeclaration *> viewedReExport)
567 {
568 if (!specifier->IsImportSpecifier()) {
569 return false;
570 }
571 const ir::StringLiteral *const importPath = import->Source();
572 auto insertForeignBinding = [this, specifier, import](const util::StringView &name, Variable *var) {
573 if (import->Language().IsDynamic()) {
574 dynamicImportVars_.emplace(var, DynamicImportData {import, specifier, var});
575 }
576
577 TopScope()->InsertForeignBinding(name, var);
578 };
579
580 const auto *const importSpecifier = specifier->AsImportSpecifier();
581
582 if (!importSpecifier->Imported()->IsIdentifier()) {
583 return true;
584 }
585
586 const auto &imported = importSpecifier->Imported()->AsIdentifier()->Name();
587
588 auto *const var = FindImportSpecifiersVariable(imported, globalBindings, recordRes);
589
590 const auto &localName = [this, importSpecifier, &imported, &importPath]() {
591 if (importSpecifier->Local() != nullptr) {
592 auto fnc = [&importPath, &imported](const auto &savedSpecifier) {
593 return importPath->Str() != savedSpecifier.first && imported == savedSpecifier.second;
594 };
595 if (!std::any_of(importSpecifiers_.begin(), importSpecifiers_.end(), fnc)) {
596 TopScope()->EraseBinding(imported);
597 }
598
599 importSpecifiers_.push_back(std::make_pair(importPath->Str(), imported));
600
601 return importSpecifier->Local()->Name();
602 }
603
604 return imported;
605 }();
606
607 if (var == nullptr) {
608 for (auto item : ReExportImports()) {
609 if (auto source = import->ResolvedSource()->Str().Mutf8(),
610 program = item->GetProgramPath().Mutf8().substr(0, item->GetProgramPath().Mutf8().find_last_of('.'));
611 source == program || (source + "/index") == program) {
612 // clang-format off
613 ir::StringLiteral dirName(util::UString(util::StringView(item->GetProgramPath().Mutf8().substr(
614 0, item->GetProgramPath().Mutf8().find_last_of('/'))),
615 Allocator())
616 .View());
617 // clang-format on
618 dirName.SetStart(item->GetETSImportDeclarations()->Source()->Start());
619
620 viewedReExport.push_back(item->GetETSImportDeclarations());
621 AddSpecifiersToTopBindings(
622 specifier, item->GetETSImportDeclarations(),
623 dirName.Str().Is(".") ? item->GetETSImportDeclarations()->Source() : &dirName, viewedReExport);
624 return true;
625 }
626 }
627 ThrowError(importPath->Start(), "Cannot find imported element " + imported.Mutf8());
628 }
629
630 if (var->Declaration()->Node()->IsDefaultExported()) {
631 ThrowError(importPath->Start(), "Use the default import syntax to import a default exported element");
632 }
633
634 insertForeignBinding(localName, var);
635 return true;
636 }
637
FindStaticBinding(const ArenaVector<parser::Program * > & recordRes,const ir::StringLiteral * const importPath)638 varbinder::Variable *ETSBinder::FindStaticBinding(const ArenaVector<parser::Program *> &recordRes,
639 const ir::StringLiteral *const importPath)
640 {
641 auto predicateFunc = [](const auto &item) { return item.second->Declaration()->Node()->IsDefaultExported(); };
642 const auto &staticMethodBindings = recordRes.front()->GlobalClassScope()->StaticMethodScope()->Bindings();
643 auto result = std::find_if(staticMethodBindings.begin(), staticMethodBindings.end(), predicateFunc);
644 if (result == staticMethodBindings.end()) {
645 const auto &staticFieldBindings = recordRes.front()->GlobalClassScope()->StaticFieldScope()->Bindings();
646 result = std::find_if(staticFieldBindings.begin(), staticFieldBindings.end(), predicateFunc);
647 if (result == staticFieldBindings.end()) {
648 ThrowError(importPath->Start(), "Cannot find default imported element in the target");
649 }
650 }
651 return result->second;
652 }
653
GetExternalProgram(const util::StringView & sourceName,const ir::StringLiteral * importPath)654 ArenaVector<parser::Program *> ETSBinder::GetExternalProgram(const util::StringView &sourceName,
655 const ir::StringLiteral *importPath)
656 {
657 const auto &extRecords = globalRecordTable_.Program()->ExternalSources();
658 auto recordRes = [this, extRecords, sourceName]() {
659 auto res = extRecords.find(sourceName);
660 if (res != extRecords.end()) {
661 return res;
662 }
663
664 if (res = extRecords.find({sourceName.Mutf8() + "/index"}); res != extRecords.end()) {
665 return res;
666 }
667
668 res = extRecords.find(GetResolvedImportPath(sourceName));
669 if (res == extRecords.end()) {
670 res = extRecords.find(GetResolvedImportPath({sourceName.Mutf8() + "/index"}));
671 }
672
673 return res;
674 }();
675 if (recordRes == extRecords.end()) {
676 ThrowError(importPath->Start(), "Cannot find import: " + std::string(sourceName));
677 }
678
679 ASSERT(!recordRes->second.empty());
680
681 return recordRes->second;
682 }
683
AddSpecifiersToTopBindings(ir::AstNode * const specifier,const ir::ETSImportDeclaration * const import,ir::StringLiteral * path,std::vector<ir::ETSImportDeclaration * > viewedReExport)684 void ETSBinder::AddSpecifiersToTopBindings(ir::AstNode *const specifier, const ir::ETSImportDeclaration *const import,
685 ir::StringLiteral *path,
686 std::vector<ir::ETSImportDeclaration *> viewedReExport)
687 {
688 const ir::StringLiteral *const importPath = path;
689
690 if (import->IsPureDynamic()) {
691 AddDynamicSpecifiersToTopBindings(specifier, import);
692 return;
693 }
694
695 const util::StringView sourceName = [import, importPath, this, &path]() {
696 if (import->Module() == nullptr) {
697 return importPath->Str();
698 }
699 char pathDelimiter = panda::os::file::File::GetPathDelim().at(0);
700 auto strImportPath = importPath->Str().Mutf8();
701 if (strImportPath.find(pathDelimiter) == (strImportPath.size() - 1)) {
702 return util::UString(strImportPath + import->Module()->Str().Mutf8(), Allocator()).View();
703 }
704
705 std::string importFilePath;
706 if (!import->Source()->Str().Is(path->Str().Mutf8()) && !import->Source()->Str().Empty() &&
707 import->Source()->Str().Mutf8().substr(0, 1) == ".") {
708 importFilePath =
709 import->Source()->Str().Mutf8().substr(import->Source()->Str().Mutf8().find_first_not_of('.'));
710 if (importFilePath.size() == 1) {
711 importFilePath = "";
712 }
713 }
714
715 return util::UString(strImportPath + importFilePath + pathDelimiter + import->Module()->Str().Mutf8(),
716 Allocator())
717 .View();
718 }();
719
720 auto record = GetExternalProgram(sourceName, importPath);
721 const auto *const importProgram = record.front();
722 const auto *const importGlobalScope = importProgram->GlobalScope();
723 const auto &globalBindings = importGlobalScope->Bindings();
724
725 auto insertForeignBinding = [this, specifier, import](const util::StringView &name, Variable *var) {
726 if (import->Language().IsDynamic()) {
727 dynamicImportVars_.emplace(var, DynamicImportData {import, specifier, var});
728 }
729
730 TopScope()->InsertForeignBinding(name, var);
731 };
732
733 if (AddImportNamespaceSpecifiersToTopBindings(specifier, globalBindings, importProgram, importGlobalScope,
734 import)) {
735 return;
736 }
737
738 if (AddImportSpecifiersToTopBindings(specifier, globalBindings, import, record, std::move(viewedReExport))) {
739 return;
740 }
741
742 ASSERT(specifier->IsImportDefaultSpecifier());
743 auto predicateFunc = [](const auto &item) { return item.second->Declaration()->Node()->IsDefaultExported(); };
744
745 auto item = std::find_if(globalBindings.begin(), globalBindings.end(), predicateFunc);
746 if (item == globalBindings.end()) {
747 insertForeignBinding(specifier->AsImportDefaultSpecifier()->Local()->Name(),
748 FindStaticBinding(record, importPath));
749 return;
750 }
751
752 insertForeignBinding(specifier->AsImportDefaultSpecifier()->Local()->Name(), item->second);
753 }
754
HandleCustomNodes(ir::AstNode * childNode)755 void ETSBinder::HandleCustomNodes(ir::AstNode *childNode)
756 {
757 switch (childNode->Type()) {
758 case ir::AstNodeType::ETS_TYPE_REFERENCE: {
759 auto *typeRef = childNode->AsETSTypeReference();
760 auto *baseName = typeRef->BaseName();
761 ASSERT(baseName->IsReference());
762 // We allow to resolve following types in pure dynamic mode:
763 // import * as I from "@dynamic"
764 // let x : I.X.Y
765 bool allowDynamicNamespaces = typeRef->Part()->Name() != baseName;
766 LookupTypeReference(baseName, allowDynamicNamespaces);
767 LookupTypeArgumentReferences(typeRef);
768 break;
769 }
770 case ir::AstNodeType::TS_INTERFACE_DECLARATION: {
771 BuildInterfaceDeclaration(childNode->AsTSInterfaceDeclaration());
772 break;
773 }
774 case ir::AstNodeType::TS_ENUM_DECLARATION: {
775 ResolveEnumDeclaration(childNode->AsTSEnumDeclaration());
776 break;
777 }
778 case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
779 break;
780 }
781 case ir::AstNodeType::ETS_IMPORT_DECLARATION: {
782 BuildImportDeclaration(childNode->AsETSImportDeclaration());
783 break;
784 }
785 case ir::AstNodeType::MEMBER_EXPRESSION: {
786 BuildMemberExpression(childNode->AsMemberExpression());
787 break;
788 }
789 case ir::AstNodeType::METHOD_DEFINITION: {
790 BuildMethodDefinition(childNode->AsMethodDefinition());
791 break;
792 }
793 case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: {
794 BuildETSNewClassInstanceExpression(childNode->AsETSNewClassInstanceExpression());
795 break;
796 }
797 case ir::AstNodeType::ETS_FUNCTION_TYPE: {
798 BuildSignatureDeclarationBaseParams(childNode);
799 break;
800 }
801 default: {
802 ResolveReferences(childNode);
803 break;
804 }
805 }
806 }
807
BuildInternalName(ir::ScriptFunction * scriptFunc)808 bool ETSBinder::BuildInternalName(ir::ScriptFunction *scriptFunc)
809 {
810 if (scriptFunc->IsArrow()) {
811 return true;
812 }
813
814 auto *funcScope = scriptFunc->Scope();
815 funcScope->BindName(recordTable_->RecordName());
816 bool isExternal = recordTable_->IsExternal();
817
818 bool compilable = scriptFunc->Body() != nullptr && !isExternal;
819 if (!compilable) {
820 recordTable_->Signatures().push_back(funcScope);
821 }
822
823 if (isExternal) {
824 scriptFunc->AddFlag(ir::ScriptFunctionFlags::EXTERNAL);
825 }
826
827 return compilable;
828 }
829
AddCompilableFunction(ir::ScriptFunction * func)830 void ETSBinder::AddCompilableFunction(ir::ScriptFunction *func)
831 {
832 if (func->IsArrow() || func->IsAsyncFunc()) {
833 return;
834 }
835
836 AddCompilableFunctionScope(func->Scope());
837 }
838
BuildFunctionName(const ir::ScriptFunction * func) const839 void ETSBinder::BuildFunctionName(const ir::ScriptFunction *func) const
840 {
841 auto *funcScope = func->Scope();
842
843 std::stringstream ss;
844 ASSERT(func->IsArrow() || !funcScope->Name().Empty());
845 ss << funcScope->Name() << compiler::Signatures::METHOD_SEPARATOR;
846
847 const auto *signature = func->Signature();
848
849 if (func->IsStaticBlock()) {
850 ss << compiler::Signatures::CCTOR;
851 } else if (func->IsConstructor()) {
852 ss << compiler::Signatures::CTOR;
853 } else {
854 if (func->IsGetter()) {
855 ss << compiler::Signatures::GETTER_BEGIN;
856 } else if (func->IsSetter()) {
857 ss << compiler::Signatures::SETTER_BEGIN;
858 }
859 ss << util::Helpers::FunctionName(Allocator(), func);
860 }
861
862 signature->ToAssemblerType(GetCompilerContext(), ss);
863
864 util::UString internalName(ss.str(), Allocator());
865 funcScope->BindInternalName(internalName.View());
866 }
867
FormLambdaName(util::UString & name,const util::StringView & signature)868 void ETSBinder::FormLambdaName(util::UString &name, const util::StringView &signature)
869 {
870 name.Append(compiler::Signatures::LAMBDA_SEPARATOR);
871 auto replaced = std::string(signature.Utf8());
872 std::replace(replaced.begin(), replaced.end(), '.', '-');
873 std::replace(replaced.begin(), replaced.end(), ':', '-');
874 std::replace(replaced.begin(), replaced.end(), ';', '-');
875 replaced.append(std::to_string(0));
876 name.Append(replaced);
877 }
878
FormFunctionalInterfaceName(util::UString & name,const util::StringView & signature)879 void ETSBinder::FormFunctionalInterfaceName(util::UString &name, const util::StringView &signature)
880 {
881 auto replaced = std::string(signature.Utf8());
882 std::replace(replaced.begin(), replaced.end(), '.', '-');
883 std::replace(replaced.begin(), replaced.end(), ':', '-');
884 std::replace(replaced.begin(), replaced.end(), ';', '-');
885 replaced.append(std::to_string(0));
886 name.Append(replaced);
887 }
888
BuildLambdaObjectName(const ir::AstNode * refNode)889 void ETSBinder::BuildLambdaObjectName(const ir::AstNode *refNode)
890 {
891 auto found = lambdaObjects_.find(refNode);
892 ASSERT(found != lambdaObjects_.end());
893 auto *lambdaClass = found->second.first;
894 auto *signatureRef = found->second.second;
895
896 util::UString lambdaObjectName(lambdaClass->Ident()->Name(), Allocator());
897 FormLambdaName(lambdaObjectName, signatureRef->InternalName());
898 lambdaClass->Ident()->SetName(lambdaObjectName.View());
899 lambdaClass->SetInternalName(lambdaClass->Ident()->Name());
900
901 util::StringView assemblerName(lambdaClass->Ident()->Name());
902 auto *program = static_cast<const ir::ETSScript *>(refNode->GetTopStatement())->Program();
903 util::StringView prefix = program->GetPackageName();
904 if (!prefix.Empty()) {
905 util::UString fullPath(prefix, Allocator());
906 fullPath.Append('.');
907 fullPath.Append(assemblerName);
908 assemblerName = fullPath.View();
909 }
910
911 checker::ETSObjectType *lambdaObject = lambdaClass->TsType()->AsETSObjectType();
912 lambdaObject->SetName(lambdaClass->Ident()->Name());
913 lambdaObject->SetAssemblerName(lambdaClass->Ident()->Name());
914
915 const auto &lambdaBody = lambdaClass->Body();
916 auto *ctorFunc = lambdaBody[lambdaBody.size() - 2]->AsMethodDefinition()->Function();
917 auto *ctorFuncScope = ctorFunc->Scope();
918 ctorFuncScope->BindName(lambdaClass->Ident()->Name());
919
920 auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function();
921 auto *invokeFuncScope = invokeFunc->Scope();
922 invokeFuncScope->BindName(lambdaClass->Ident()->Name());
923 }
924
BuildFunctionalInterfaceName(ir::ETSFunctionType * funcType)925 void ETSBinder::BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType)
926 {
927 auto *functionalInterface = funcType->FunctionalInterface();
928 auto *invokeFunc = functionalInterface->Body()->Body()[0]->AsMethodDefinition()->Function();
929 util::UString functionalInterfaceName(functionalInterface->Id()->Name(), Allocator());
930 std::stringstream ss;
931 invokeFunc->Signature()->ToAssemblerType(GetCompilerContext(), ss);
932 std::string signatureString = ss.str();
933 util::StringView signatureName(signatureString);
934 FormFunctionalInterfaceName(functionalInterfaceName, signatureName);
935 functionalInterface->Id()->SetName(functionalInterfaceName.View());
936 util::UString internalName(Program()->GetPackageName(), Allocator());
937 if (!(internalName.View().Empty())) {
938 internalName.Append(compiler::Signatures::METHOD_SEPARATOR);
939 }
940 internalName.Append(functionalInterface->Id()->Name());
941 functionalInterface->SetInternalName(internalName.View());
942
943 checker::ETSObjectType *functionalInterfaceType = functionalInterface->TsType()->AsETSObjectType();
944 functionalInterfaceType->SetName(functionalInterface->Id()->Name());
945 functionalInterfaceType->SetAssemblerName(internalName.View());
946
947 auto *invokeFuncScope = invokeFunc->Scope();
948 invokeFuncScope->BindName(functionalInterface->Id()->Name());
949
950 util::UString invokeInternalName(Program()->GetPackageName(), Allocator());
951 if (!(invokeInternalName.View().Empty())) {
952 invokeInternalName.Append(compiler::Signatures::METHOD_SEPARATOR);
953 }
954 invokeInternalName.Append(invokeFuncScope->Name());
955 invokeInternalName.Append(compiler::Signatures::METHOD_SEPARATOR);
956 invokeInternalName.Append(invokeFunc->Id()->Name());
957 std::stringstream invokeSignatureSs;
958 invokeFunc->Signature()->ToAssemblerType(GetCompilerContext(), invokeSignatureSs);
959 invokeInternalName.Append(invokeSignatureSs.str());
960 invokeFuncScope->BindInternalName(invokeInternalName.View());
961 }
962
InitImplicitThisParam()963 void ETSBinder::InitImplicitThisParam()
964 {
965 thisParam_ = Allocator()->New<ir::Identifier>("this", Allocator());
966 }
967
BuildProgram()968 void ETSBinder::BuildProgram()
969 {
970 for (auto &[_, extPrograms] : Program()->ExternalSources()) {
971 (void)_;
972 for (auto *extProg : extPrograms) {
973 BuildExternalProgram(extProg);
974 }
975 }
976
977 for (auto *defaultImport : defaultImports_) {
978 BuildImportDeclaration(defaultImport);
979 }
980
981 auto &stmts = Program()->Ast()->Statements();
982 const auto etsGlobal = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) {
983 return stmt->IsClassDeclaration() &&
984 stmt->AsClassDeclaration()->Definition()->Ident()->Name().Is(compiler::Signatures::ETS_GLOBAL);
985 });
986 if (etsGlobal != stmts.end()) {
987 const auto begin = std::find_if(stmts.rbegin(), stmts.rend(), [](const ir::Statement *stmt) {
988 return stmt->IsETSImportDeclaration() || stmt->IsETSPackageDeclaration();
989 }).base();
990
991 const size_t index = std::distance(begin, etsGlobal);
992 std::rotate(begin, begin + index, begin + index + 1);
993 }
994
995 for (auto *stmt : stmts) {
996 ResolveReference(stmt);
997 }
998 }
999
BuildExternalProgram(parser::Program * extProgram)1000 void ETSBinder::BuildExternalProgram(parser::Program *extProgram)
1001 {
1002 auto *savedProgram = Program();
1003 auto *savedRecordTable = recordTable_;
1004 auto *savedTopScope = TopScope();
1005
1006 auto flags = Program()->VarBinder()->IsGenStdLib() ? RecordTableFlags::NONE : RecordTableFlags::EXTERNAL;
1007 auto *extRecordTable = Allocator()->New<RecordTable>(Allocator(), extProgram, flags);
1008 externalRecordTable_.insert({extProgram, extRecordTable});
1009
1010 ResetTopScope(extProgram->GlobalScope());
1011 recordTable_ = extRecordTable;
1012 SetProgram(extProgram);
1013
1014 BuildProgram();
1015
1016 SetProgram(savedProgram);
1017 recordTable_ = savedRecordTable;
1018 ResetTopScope(savedTopScope);
1019 }
1020
BuildETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression * classInstance)1021 void ETSBinder::BuildETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *classInstance)
1022 {
1023 BoundContext boundCtx(recordTable_, classInstance->ClassDefinition());
1024 ResolveReference(classInstance->GetTypeRef());
1025
1026 for (auto *arg : classInstance->GetArguments()) {
1027 ResolveReference(arg);
1028 }
1029
1030 if (classInstance->ClassDefinition() == nullptr) {
1031 return;
1032 }
1033
1034 ResolveReference(classInstance->ClassDefinition());
1035 }
1036
BuildImportDeclaration(ir::ETSImportDeclaration * decl)1037 void ETSBinder::BuildImportDeclaration(ir::ETSImportDeclaration *decl)
1038 {
1039 if (decl->Source()->Str() == Program()->AbsoluteName()) {
1040 return;
1041 }
1042
1043 auto specifiers = decl->Specifiers();
1044
1045 for (auto specifier : specifiers) {
1046 AddSpecifiersToTopBindings(specifier, decl, decl->Source());
1047 }
1048 }
1049
ImportGlobalPropertiesForNotDefaultedExports(varbinder::Variable * var,const util::StringView & name,const ir::ClassElement * classElement)1050 bool ETSBinder::ImportGlobalPropertiesForNotDefaultedExports(varbinder::Variable *var, const util::StringView &name,
1051 const ir::ClassElement *classElement)
1052 {
1053 if (var->Declaration()->Node()->IsDefaultExported()) {
1054 return false;
1055 }
1056
1057 const auto insRes = TopScope()->InsertForeignBinding(name, var);
1058 if (!(!insRes.second && insRes.first != TopScope()->Bindings().end()) || !(insRes.first->second != var)) {
1059 return true;
1060 }
1061 if (insRes.first->second->Declaration()->IsFunctionDecl() && var->Declaration()->IsFunctionDecl()) {
1062 auto *const currentNode = insRes.first->second->Declaration()->Node();
1063 auto *const method = var->Declaration()->Node()->AsMethodDefinition();
1064 if (!currentNode->AsMethodDefinition()->HasOverload(method)) {
1065 currentNode->AsMethodDefinition()->AddOverload(method);
1066 method->Function()->Id()->SetVariable(insRes.first->second);
1067 method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
1068 }
1069 return true;
1070 }
1071
1072 auto str = util::Helpers::AppendAll("Variable '", name.Utf8(), "'");
1073 if (insRes.first->second->Declaration()->Type() == var->Declaration()->Type()) {
1074 str += " is already defined.";
1075 } else {
1076 str += " is already defined with different type.";
1077 }
1078 ThrowError(classElement->Id()->Start(), str);
1079 }
1080
ImportGlobalProperties(const ir::ClassDefinition * const classDef)1081 void ETSBinder::ImportGlobalProperties(const ir::ClassDefinition *const classDef)
1082 {
1083 const auto scopeCtx = LexicalScope<ClassScope>::Enter(this, classDef->Scope()->AsClassScope());
1084
1085 for (const auto *const prop : classDef->Body()) {
1086 const auto *const classElement = prop->AsClassElement();
1087
1088 if (classElement->IsClassStaticBlock()) {
1089 continue;
1090 }
1091
1092 ASSERT(classElement->IsStatic());
1093 const auto &name = classElement->Id()->Name();
1094 auto *const var = scopeCtx.GetScope()->FindLocal(name, ResolveBindingOptions::ALL);
1095 ASSERT(var != nullptr);
1096
1097 if (ImportGlobalPropertiesForNotDefaultedExports(var, name, classElement)) {
1098 return;
1099 }
1100 }
1101 }
1102
DynamicImportDataForVar(const Variable * var) const1103 const DynamicImportData *ETSBinder::DynamicImportDataForVar(const Variable *var) const
1104 {
1105 auto it = dynamicImportVars_.find(var);
1106 if (it == dynamicImportVars_.cend()) {
1107 return nullptr;
1108 }
1109
1110 return &it->second;
1111 }
1112
IsDynamicModuleVariable(const Variable * var) const1113 bool ETSBinder::IsDynamicModuleVariable(const Variable *var) const
1114 {
1115 auto *data = DynamicImportDataForVar(var);
1116 if (data == nullptr) {
1117 return false;
1118 }
1119
1120 return data->specifier->IsImportSpecifier();
1121 }
1122
IsDynamicNamespaceVariable(const Variable * var) const1123 bool ETSBinder::IsDynamicNamespaceVariable(const Variable *var) const
1124 {
1125 auto *data = DynamicImportDataForVar(var);
1126 if (data == nullptr) {
1127 return false;
1128 }
1129
1130 return data->specifier->IsImportNamespaceSpecifier();
1131 }
1132
1133 } // namespace panda::es2panda::varbinder
1134