• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #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 &params) 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