1 /* 2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ES2PANDA_VARBINDER_ETSBINDER_H 17 #define ES2PANDA_VARBINDER_ETSBINDER_H 18 19 #include "varbinder/TypedBinder.h" 20 #include "varbinder/recordTable.h" 21 #include "ir/ets/etsImportDeclaration.h" 22 #include "ir/ets/etsReExportDeclaration.h" 23 #include "ir/expressions/identifier.h" 24 #include "ir/module/importSpecifier.h" 25 #include "ir/statements/annotationDeclaration.h" 26 #include "parser/ETSparser.h" 27 28 namespace ark::es2panda::ir { 29 class ETSImportDeclaration; 30 class AstNode; 31 class Identifier; 32 class ObjectExpression; 33 class ETSTypeReference; 34 class MethodDefinition; 35 class AnnotationUsage; 36 class StringLiteral; 37 class ETSReExportDeclaration; 38 class TSEnumDeclaration; 39 class TSQualifiedName; 40 class ClassElement; 41 class ImportSpecifier; 42 class ETSNewClassInstanceExpression; 43 44 } // namespace ark::es2panda::ir 45 46 namespace ark::es2panda::varbinder { 47 using AliasesByExportedNames = ArenaMap<util::StringView, std::pair<util::StringView, ir::AstNode const *>>; 48 using ModulesToExportedNamesWithAliases = ArenaMap<util::StringView, AliasesByExportedNames>; 49 50 struct DynamicImportData { 51 const ir::ETSImportDeclaration *import; 52 const ir::AstNode *specifier; 53 Variable *variable; 54 }; 55 56 using DynamicImportVariables = ArenaUnorderedMap<const Variable *, DynamicImportData>; 57 58 class ETSBinder : public TypedBinder { 59 public: ETSBinder(ArenaAllocator * allocator)60 explicit ETSBinder(ArenaAllocator *allocator) 61 : TypedBinder(allocator), 62 globalRecordTable_(allocator, Program(), RecordTableFlags::NONE), 63 recordTable_(&globalRecordTable_), 64 externalRecordTable_(Allocator()->Adapter()), 65 defaultImports_(Allocator()->Adapter()), 66 dynamicImports_(Allocator()->Adapter()), 67 reExportImports_(Allocator()->Adapter()), 68 reexportedNames_(Allocator()->Adapter()), 69 dynamicImportVars_(Allocator()->Adapter()), 70 selectiveExportAliasMultimap_(Allocator()->Adapter()) 71 { 72 InitImplicitThisParam(); 73 } 74 75 ETSBinder() = delete; 76 NO_COPY_SEMANTIC(ETSBinder); 77 NO_MOVE_SEMANTIC(ETSBinder); 78 ~ETSBinder() override = default; 79 Extension()80 [[nodiscard]] ScriptExtension Extension() const noexcept override 81 { 82 return ScriptExtension::ETS; 83 } 84 BindingOptions()85 [[nodiscard]] ResolveBindingOptions BindingOptions() const noexcept override 86 { 87 return ResolveBindingOptions::BINDINGS; 88 } 89 GetRecordTable()90 [[nodiscard]] RecordTable *GetRecordTable() noexcept 91 { 92 return recordTable_; 93 } 94 GetRecordTable()95 [[nodiscard]] const RecordTable *GetRecordTable() const noexcept 96 { 97 return recordTable_; 98 } 99 SetRecordTable(RecordTable * table)100 void SetRecordTable(RecordTable *table) noexcept 101 { 102 recordTable_ = table; 103 } 104 GetGlobalRecordTable()105 [[nodiscard]] RecordTable *GetGlobalRecordTable() noexcept 106 { 107 return &globalRecordTable_; 108 } 109 GetGlobalRecordTable()110 [[nodiscard]] const RecordTable *GetGlobalRecordTable() const noexcept 111 { 112 return &globalRecordTable_; 113 } 114 GetExternalRecordTable()115 [[nodiscard]] ArenaMap<parser::Program *, RecordTable *> &GetExternalRecordTable() noexcept 116 { 117 return externalRecordTable_; 118 } 119 GetExternalRecordTable()120 [[nodiscard]] const ArenaMap<parser::Program *, RecordTable *> &GetExternalRecordTable() const noexcept 121 { 122 return externalRecordTable_; 123 } 124 125 void HandleCustomNodes(ir::AstNode *childNode) override; 126 127 void IdentifierAnalysis() override; 128 void BuildClassDefinition(ir::ClassDefinition *classDef) override; 129 void BuildObjectExpression(ir::ObjectExpression *obj); 130 void BuildETSTypeReference(ir::ETSTypeReference *typeRef); 131 void BuildClassProperty(const ir::ClassProperty *prop) override; 132 void LookupIdentReference(ir::Identifier *ident) override; 133 [[nodiscard]] bool BuildInternalName(ir::ScriptFunction *scriptFunc) override; 134 void AddCompilableFunction(ir::ScriptFunction *func) override; 135 136 [[nodiscard]] bool HandleDynamicVariables(ir::Identifier *ident, Variable *variable, bool allowDynamicNamespaces); 137 static bool IsSpecialName(const util::StringView &name); 138 [[nodiscard]] bool LookupInDebugInfoPlugin(ir::Identifier *ident); 139 void LookupTypeReference(ir::Identifier *ident, bool allowDynamicNamespaces); 140 void LookupTypeArgumentReferences(ir::ETSTypeReference *typeRef); 141 void BuildInterfaceDeclaration(ir::TSInterfaceDeclaration *decl); 142 void BuildMemberExpression(ir::MemberExpression *memberExpr); 143 void BuildMethodDefinition(ir::MethodDefinition *methodDef); 144 void BuildAnnotationDeclaration(ir::AnnotationDeclaration *annoDecl); 145 void BuildAnnotationUsage(ir::AnnotationUsage *annoUsage); 146 void BuildImportDeclaration(ir::ETSImportDeclaration *decl); 147 void ValidateReexportDeclaration(ir::ETSReExportDeclaration *decl); 148 void ValidateReexports(); 149 [[nodiscard]] bool ReexportPathMatchesImportPath(const ir::ETSReExportDeclaration *const reexport, 150 const ir::ETSImportDeclaration *const import) const; 151 Variable *ValidateImportSpecifier(const ir::ImportSpecifier *const specifier, 152 const ir::ETSImportDeclaration *const import); 153 void BuildETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *classInstance); 154 [[nodiscard]] bool DetectNameConflict(const util::StringView localName, Variable *const var, 155 Variable *const otherVar, const ir::StringLiteral *const importPath); 156 [[nodiscard]] ArenaVector<parser::Program *> GetExternalProgram(util::StringView sourceName, 157 const ir::StringLiteral *importPath); 158 159 std::pair<ir::ETSImportDeclaration *, ir::AstNode *> FindImportDeclInReExports( 160 const ir::ETSImportDeclaration *const import, const util::StringView &imported, 161 const ir::StringLiteral *const importPath); 162 std::pair<ir::ETSImportDeclaration *, ir::AstNode *> FindImportDeclInNamedExports( 163 const ir::ETSImportDeclaration *const import, const util::StringView &imported, 164 const ir::StringLiteral *const importPath); 165 std::pair<ir::ETSImportDeclaration *, ir::AstNode *> FindImportDeclInExports( 166 const ir::ETSImportDeclaration *const import, const util::StringView &imported, 167 const ir::StringLiteral *const importPath); 168 ir::ETSImportDeclaration *FindImportDeclIn(const ir::ETSImportDeclaration *const import, 169 const util::StringView &imported, 170 const ir::StringLiteral *const importPath); 171 void AddImportNamespaceSpecifiersToTopBindings(Span<parser::Program *const> records, 172 ir::ImportNamespaceSpecifier *namespaceSpecifier, 173 const ir::ETSImportDeclaration *import); 174 bool AddImportSpecifiersToTopBindings(Span<parser::Program *const> records, ir::ImportSpecifier *importSpecifier, 175 const ir::ETSImportDeclaration *import); 176 void AddImportDefaultSpecifiersToTopBindings(Span<parser::Program *const> records, 177 ir::ImportDefaultSpecifier *importDefaultSpecifier, 178 const ir::ETSImportDeclaration *import); 179 void ValidateImportVariable(const ir::AstNode *node, const util::StringView &imported, 180 const ir::StringLiteral *const importPath); 181 Variable *FindImportSpecifiersVariable(const util::StringView &imported, 182 const varbinder::Scope::VariableMap &globalBindings, 183 Span<parser::Program *const> record); 184 Variable *FindStaticBinding(Span<parser::Program *const> records, const ir::StringLiteral *importPath); 185 Variable *AddImportSpecifierFromReExport(ir::AstNode *importSpecifier, const ir::ETSImportDeclaration *const import, 186 const util::StringView &imported, 187 const ir::StringLiteral *const importPath); 188 void AddSpecifiersToTopBindings(ir::AstNode *const specifier, const ir::ETSImportDeclaration *const import); 189 void AddDynamicSpecifiersToTopBindings(ir::AstNode *const specifier, const ir::ETSImportDeclaration *const import); 190 191 void ResolveInterfaceDeclaration(ir::TSInterfaceDeclaration *decl); 192 void ResolveMethodDefinition(ir::MethodDefinition *methodDef); 193 LocalScope *ResolvePropertyReference(ir::ClassProperty *prop, ClassScope *scope); 194 void ResolveEnumDeclaration(ir::TSEnumDeclaration *enumDecl); 195 void InitializeInterfaceIdent(ir::TSInterfaceDeclaration *decl); 196 void BuildExternalProgram(parser::Program *extProgram); 197 void BuildProgram(); 198 199 void BuildFunctionName(const ir::ScriptFunction *func) const; 200 bool BuildInternalNameWithCustomRecordTable(ir::ScriptFunction *scriptFunc, RecordTable *recordTable); 201 void BuildProxyMethod(ir::ScriptFunction *func, const util::StringView &containingClassName, bool isExternal); 202 void AddFunctionThisParam(ir::ScriptFunction *func); 203 ThrowError(const lexer::SourcePosition & pos,const diagnostic::DiagnosticKind & kind)204 void ThrowError(const lexer::SourcePosition &pos, const diagnostic::DiagnosticKind &kind) const 205 { 206 ThrowError(pos, kind, util::DiagnosticMessageParams {}); 207 } 208 void ThrowError(const lexer::SourcePosition &pos, const diagnostic::DiagnosticKind &kind, 209 const util::DiagnosticMessageParams ¶ms) const override; 210 bool IsGlobalIdentifier(const util::StringView &str) const override; 211 SetDefaultImports(ArenaVector<ir::ETSImportDeclaration * > defaultImports)212 void SetDefaultImports(ArenaVector<ir::ETSImportDeclaration *> defaultImports) noexcept 213 { 214 defaultImports_ = std::move(defaultImports); 215 } 216 217 void AddDynamicImport(ir::ETSImportDeclaration *import); 218 DynamicImports()219 [[nodiscard]] const ArenaVector<ir::ETSImportDeclaration *> &DynamicImports() const noexcept 220 { 221 return dynamicImports_; 222 } 223 AddReExportImport(ir::ETSReExportDeclaration * reExport)224 void AddReExportImport(ir::ETSReExportDeclaration *reExport) noexcept 225 { 226 reExportImports_.push_back(reExport); 227 } 228 ReExportImports()229 [[nodiscard]] const ArenaVector<ir::ETSReExportDeclaration *> &ReExportImports() const noexcept 230 { 231 return reExportImports_; 232 } 233 DynamicImportVars()234 [[nodiscard]] const DynamicImportVariables &DynamicImportVars() const noexcept 235 { 236 return dynamicImportVars_; 237 } 238 DefaultExport()239 [[nodiscard]] const ir::AstNode *DefaultExport() noexcept 240 { 241 return defaultExport_; 242 } 243 SetDefaultExport(ir::AstNode * defaultExport)244 void SetDefaultExport(ir::AstNode *defaultExport) noexcept 245 { 246 defaultExport_ = defaultExport; 247 } 248 249 /* Returns the list of programs belonging to the same compilation unit based on a program path */ 250 [[nodiscard]] ArenaVector<parser::Program *> GetProgramList(const util::StringView &path) const noexcept; 251 252 [[nodiscard]] bool IsDynamicModuleVariable(const Variable *var) const noexcept; 253 [[nodiscard]] bool IsDynamicNamespaceVariable(const Variable *var) const noexcept; 254 [[nodiscard]] const DynamicImportData *DynamicImportDataForVar(const Variable *var) const noexcept; 255 256 void ResolveReferenceForScope(ir::AstNode *node, Scope *scope); 257 void ResolveReferencesForScope(ir::AstNode const *parent, Scope *scope); 258 259 void ResolveReferencesForScopeWithContext(ir::AstNode *node, Scope *scope); 260 261 [[nodiscard]] bool AddSelectiveExportAlias(parser::ETSParser *parser, util::StringView const &path, 262 util::StringView const &key, util::StringView const &value, 263 ir::AstNode const *decl) noexcept; 264 GetSelectiveExportAliasMultimap()265 [[nodiscard]] const ModulesToExportedNamesWithAliases &GetSelectiveExportAliasMultimap() const noexcept 266 { 267 return selectiveExportAliasMultimap_; 268 } 269 GetSelectiveExportAliasMultimap()270 [[nodiscard]] ModulesToExportedNamesWithAliases &GetSelectiveExportAliasMultimap() noexcept 271 { 272 return selectiveExportAliasMultimap_; 273 } 274 275 util::StringView FindNameInAliasMap(const util::StringView &pathAsKey, const util::StringView &aliasName); 276 const ir::AstNode *FindNodeInAliasMap(const util::StringView &pathAsKey, const util::StringView &aliasName); 277 CleanUp()278 void CleanUp() override 279 { 280 VarBinder::CleanUp(); 281 externalRecordTable_.clear(); 282 InitImplicitThisParam(); 283 dynamicImports_.clear(); 284 reexportedNames_.clear(); 285 reExportImports_.clear(); 286 dynamicImportVars_.clear(); 287 defaultExport_ = nullptr; 288 globalRecordTable_.CleanUp(); 289 } 290 291 private: 292 void BuildClassDefinitionImpl(ir::ClassDefinition *classDef); 293 void InitImplicitThisParam(); 294 void HandleStarImport(ir::TSQualifiedName *importName, util::StringView fullPath); 295 void ImportGlobalProperties(const ir::ClassDefinition *classDef); 296 bool ImportGlobalPropertiesForNotDefaultedExports(varbinder::Variable *var, const util::StringView &name, 297 const ir::ClassElement *classElement); 298 void InsertForeignBinding(ir::AstNode *specifier, const ir::ETSImportDeclaration *import, 299 const util::StringView &name, Variable *var); 300 void InsertOrAssignForeignBinding(ir::AstNode *specifier, const ir::ETSImportDeclaration *import, 301 const util::StringView &name, Variable *var); 302 void ImportAllForeignBindings(ir::AstNode *specifier, const varbinder::Scope::VariableMap &globalBindings, 303 const parser::Program *importProgram, const varbinder::GlobalScope *importGlobalScope, 304 const ir::ETSImportDeclaration *import); 305 void ThrowRedeclarationError(const lexer::SourcePosition &pos, const Variable *const var, 306 const Variable *const variable, util::StringView localName); 307 308 RecordTable globalRecordTable_; 309 RecordTable *recordTable_; 310 ArenaMap<parser::Program *, RecordTable *> externalRecordTable_; 311 ArenaVector<ir::ETSImportDeclaration *> defaultImports_; 312 ArenaVector<ir::ETSImportDeclaration *> dynamicImports_; 313 ArenaVector<ir::ETSReExportDeclaration *> reExportImports_; 314 ArenaSet<util::StringView> reexportedNames_; 315 DynamicImportVariables dynamicImportVars_; 316 ir::Identifier *thisParam_ {}; 317 ir::AstNode *defaultExport_ {}; 318 ModulesToExportedNamesWithAliases selectiveExportAliasMultimap_; 319 320 friend class RecordTableContext; 321 }; 322 323 class RecordTableContext { 324 public: RecordTableContext(ETSBinder * varBinder,parser::Program * extProgram)325 RecordTableContext(ETSBinder *varBinder, parser::Program *extProgram) 326 : varBinder_(varBinder), savedRecordTable_(varBinder->recordTable_) 327 { 328 if (extProgram != nullptr) { 329 varBinder->recordTable_ = varBinder->externalRecordTable_[extProgram]; 330 } 331 } 332 333 NO_COPY_SEMANTIC(RecordTableContext); 334 NO_MOVE_SEMANTIC(RecordTableContext); 335 ~RecordTableContext()336 ~RecordTableContext() 337 { 338 varBinder_->recordTable_ = savedRecordTable_; 339 } 340 341 private: 342 ETSBinder *varBinder_; 343 RecordTable *savedRecordTable_; 344 }; 345 346 } // namespace ark::es2panda::varbinder 347 348 #endif 349