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