• 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_PARSER_INCLUDE_PROGRAM_H
17 #define ES2PANDA_PARSER_INCLUDE_PROGRAM_H
18 
19 #include "util/es2pandaMacros.h"
20 #include "mem/pool_manager.h"
21 #include "os/filesystem.h"
22 #include "util/ustring.h"
23 #include "util/path.h"
24 #include "util/importPathManager.h"
25 #include "varbinder/varbinder.h"
26 #include <lexer/token/sourceLocation.h>
27 #include "util/enumbitops.h"
28 
29 #include <set>
30 
31 namespace ark::es2panda::ir {
32 class BlockStatement;
33 }  // namespace ark::es2panda::ir
34 
35 namespace ark::es2panda::varbinder {
36 class VarBinder;
37 class FunctionScope;
38 }  // namespace ark::es2panda::varbinder
39 
40 namespace ark::es2panda::compiler {
41 class CFG;
42 }  // namespace ark::es2panda::compiler
43 
44 namespace ark::es2panda::parser {
45 enum class ScriptKind { SCRIPT, MODULE, STDLIB, GENEXTERNAL };
46 enum EntityType { CLASS_PROPERTY = 0, METHOD_DEFINITION = 1, CLASS_DEFINITION = 2, TS_INTERFACE_DECLARATION = 3 };
47 
48 #ifndef NDEBUG
49 constexpr uint32_t POISON_VALUE {0x12346789};
50 #endif
51 
52 using ENUMBITOPS_OPERATORS;
53 
54 enum class ProgramFlags : uint32_t {
55     NONE = 0U,
56     AST_CHECKED = 1U << 0U,
57     AST_CHECK_PROCESSED = 1U << 1U,
58     AST_ENUM_LOWERED = 1U << 2U,
59     AST_BOXED_TYPE_LOWERED = 1U << 3U,
60     AST_CONSTANT_EXPRESSION_LOWERED = 1U << 5U,
61     AST_STRING_CONSTANT_LOWERED = 1U << 6U,
62     AST_IDENTIFIER_ANALYZED = 1U << 7U,
63     AST_HAS_SCOPES_INITIALIZED = 1U << 8U,
64     AST_HAS_OPTIONAL_PARAMETER_ANNOTATION = 1U << 9U,
65 };
66 
67 class Program {
68 public:
69     using ExternalSource = ArenaUnorderedMap<util::StringView, ArenaVector<Program *>>;
70     using DirectExternalSource = ArenaUnorderedMap<util::StringView, ArenaVector<Program *>>;
71 
72     using ETSNolintsCollectionMap = ArenaUnorderedMap<const ir::AstNode *, ArenaSet<ETSWarnings>>;
73 
74     template <typename T>
75     static Program NewProgram(ArenaAllocator *allocator, varbinder::VarBinder *varBinder = nullptr)
76     {
77         if (varBinder == nullptr) {
78             auto *vb = allocator->New<T>(allocator);
79             return Program(allocator, vb);
80         }
81         return Program(allocator, varBinder);
82     }
83 
84     Program(ArenaAllocator *allocator, varbinder::VarBinder *varbinder);
85 
86     ~Program();
87 
SetKind(ScriptKind kind)88     void SetKind(ScriptKind kind)
89     {
90         kind_ = kind;
91     }
92 
93     NO_COPY_SEMANTIC(Program);
94     DEFAULT_MOVE_SEMANTIC(Program);
95 
Allocator()96     ArenaAllocator *Allocator() const
97     {
98         return allocator_;
99     }
100 
VarBinder()101     const varbinder::VarBinder *VarBinder() const
102     {
103         return varbinder_;
104     }
105 
VarBinder()106     varbinder::VarBinder *VarBinder()
107     {
108         return varbinder_;
109     }
110 
SetVarBinder(varbinder::VarBinder * varbinder)111     void SetVarBinder(varbinder::VarBinder *varbinder)
112     {
113         varbinder_ = varbinder;
114     }
115 
Extension()116     ScriptExtension Extension() const
117     {
118         return extension_;
119     }
120 
Kind()121     ScriptKind Kind() const
122     {
123         return kind_;
124     }
125 
SourceCode()126     util::StringView SourceCode() const
127     {
128         return sourceCode_;
129     }
130 
SourceFilePath()131     const util::StringView &SourceFilePath() const
132     {
133         return sourceFile_.GetPath();
134     }
135 
SourceFile()136     const util::Path &SourceFile() const
137     {
138         return sourceFile_;
139     }
140 
SourceFileFolder()141     util::StringView SourceFileFolder() const
142     {
143         return sourceFileFolder_;
144     }
145 
FileName()146     util::StringView FileName() const
147     {
148         return sourceFile_.GetFileName();
149     }
150 
FileNameWithExtension()151     util::StringView FileNameWithExtension() const
152     {
153         return sourceFile_.GetFileNameWithExtension();
154     }
155 
AbsoluteName()156     util::StringView AbsoluteName() const
157     {
158         return sourceFile_.GetAbsolutePath();
159     }
160 
ResolvedFilePath()161     util::StringView ResolvedFilePath() const
162     {
163         return resolvedFilePath_;
164     }
165 
RelativeFilePath()166     util::StringView RelativeFilePath() const
167     {
168         // for js source files, just return file name.
169         return relativeFilePath_.Empty() ? FileNameWithExtension() : relativeFilePath_;
170     }
171 
SetRelativeFilePath(const util::StringView & relPath)172     void SetRelativeFilePath(const util::StringView &relPath)
173     {
174         relativeFilePath_ = relPath;
175     }
176 
Ast()177     ir::BlockStatement *Ast()
178     {
179         return ast_;
180     }
181 
Ast()182     const ir::BlockStatement *Ast() const
183     {
184         return ast_;
185     }
186 
SetAst(ir::BlockStatement * ast)187     void SetAst(ir::BlockStatement *ast)
188     {
189         ast_ = ast;
190         MaybeTransformToDeclarationModule();
191     }
192 
GlobalClass()193     ir::ClassDefinition *GlobalClass()
194     {
195         return globalClass_;
196     }
197 
GlobalClass()198     const ir::ClassDefinition *GlobalClass() const
199     {
200         return globalClass_;
201     }
202 
SetGlobalClass(ir::ClassDefinition * globalClass)203     void SetGlobalClass(ir::ClassDefinition *globalClass)
204     {
205         globalClass_ = globalClass;
206     }
207 
ExternalSources()208     ExternalSource &ExternalSources()
209     {
210         return externalSources_;
211     }
212 
ExternalSources()213     const ExternalSource &ExternalSources() const
214     {
215         return externalSources_;
216     }
217 
DirectExternalSources()218     DirectExternalSource &DirectExternalSources()
219     {
220         return directExternalSources_;
221     }
222 
DirectExternalSources()223     const DirectExternalSource &DirectExternalSources() const
224     {
225         return directExternalSources_;
226     }
227 
PackageStart()228     const lexer::SourcePosition &PackageStart() const
229     {
230         return packageStartPosition_;
231     }
232 
SetPackageStart(const lexer::SourcePosition & start)233     void SetPackageStart(const lexer::SourcePosition &start)
234     {
235         packageStartPosition_ = start;
236     }
237 
SetSource(const util::StringView & sourceCode,const util::StringView & sourceFilePath,const util::StringView & sourceFileFolder)238     void SetSource(const util::StringView &sourceCode, const util::StringView &sourceFilePath,
239                    const util::StringView &sourceFileFolder)
240     {
241         sourceCode_ = sourceCode;
242         sourceFile_ = util::Path(sourceFilePath, Allocator());
243         sourceFileFolder_ = sourceFileFolder;
244     }
245 
SetSource(const ark::es2panda::SourceFile & sourceFile)246     void SetSource(const ark::es2panda::SourceFile &sourceFile)
247     {
248         sourceCode_ = util::UString(sourceFile.source, Allocator()).View();
249         sourceFile_ = util::Path(sourceFile.filePath, Allocator());
250         sourceFileFolder_ = util::UString(sourceFile.fileFolder, Allocator()).View();
251         resolvedFilePath_ = util::UString(sourceFile.resolvedPath, Allocator()).View();
252         moduleInfo_.isDeclForDynamicStaticInterop = sourceFile.isDeclForDynamicStaticInterop;
253     }
254 
255     void SetPackageInfo(const util::StringView &name, util::ModuleKind kind);
256 
ModuleInfo()257     const auto &ModuleInfo() const
258     {
259         return moduleInfo_;
260     }
261 
ModuleName()262     util::StringView ModuleName() const
263     {
264         return moduleInfo_.moduleName;
265     }
266 
ModulePrefix()267     util::StringView ModulePrefix() const
268     {
269         return moduleInfo_.modulePrefix;
270     }
271 
IsSeparateModule()272     bool IsSeparateModule() const
273     {
274         return moduleInfo_.kind == util::ModuleKind::MODULE;
275     }
276 
IsDeclarationModule()277     bool IsDeclarationModule() const
278     {
279         return moduleInfo_.kind == util::ModuleKind::DECLARATION;
280     }
281 
IsPackage()282     bool IsPackage() const
283     {
284         return moduleInfo_.kind == util::ModuleKind::PACKAGE;
285     }
286 
287     void SetFlag(ProgramFlags flag);
288     bool GetFlag(ProgramFlags flag) const;
289     void SetASTChecked();
290     void ClearASTCheckedStatus();
291     bool IsASTChecked();
292 
IsStdLib()293     bool IsStdLib() const
294     {
295         // NOTE (hurton): temporary solution, needs rework when std sources are renamed
296         return (ModuleName().Mutf8().rfind("std.", 0) == 0) || (ModuleName().Mutf8().rfind("escompat", 0) == 0) ||
297                (FileName().Is("etsstdlib"));
298     }
299 
300     bool IsGenAbcForExternal() const;
301 
302     void SetGenAbcForExternalSources(bool genAbc = true)
303     {
304         genAbcForExternalSource_ = genAbc;
305     }
306 
307     varbinder::ClassScope *GlobalClassScope();
308     const varbinder::ClassScope *GlobalClassScope() const;
309 
310     varbinder::GlobalScope *GlobalScope();
311     const varbinder::GlobalScope *GlobalScope() const;
312 
313     std::string Dump() const;
314 
315     void DumpSilent() const;
316 
317     void AddNodeToETSNolintCollection(const ir::AstNode *node, const std::set<ETSWarnings> &warningsCollection);
318     bool NodeContainsETSNolint(const ir::AstNode *node, ETSWarnings warning);
319 
DeclGenExportNodes()320     std::vector<std::pair<std::string, ir::AstNode *>> &DeclGenExportNodes()
321     {
322         // NOTE: ExportNodes is not supported now.
323         return declGenExportNodes_;
324     }
325 
AddDeclGenExportNode(const std::string & declGenExportStr,ir::AstNode * node)326     void AddDeclGenExportNode(const std::string &declGenExportStr, ir::AstNode *node)
327     {
328         declGenExportNodes_.emplace_back(declGenExportStr, node);
329     }
330 
331     // The name "IsDied", because correct value of canary is a necessary condition for the life of "Program", but
332     // not sufficient
IsDied()333     bool IsDied() const
334     {
335         // You can't add one method to ignore list of es2panda_lib generation,
336         // so in release mode method is exist, return "false" and is not used anywhere.
337 #ifndef NDEBUG
338         return poisonValue_ != POISON_VALUE;
339 #else
340         return false;
341 #endif
342     }
343 
344     compiler::CFG *GetCFG();
345     const compiler::CFG *GetCFG() const;
346 
Functions()347     [[nodiscard]] const ArenaVector<varbinder::FunctionScope *> &Functions() const noexcept
348     {
349         return functionScopes_;
350     }
351 
Functions()352     [[nodiscard]] ArenaVector<varbinder::FunctionScope *> &Functions() noexcept
353     {
354         return functionScopes_;
355     }
356 
AddToFunctionScopes(varbinder::FunctionScope * funcScope)357     void AddToFunctionScopes(varbinder::FunctionScope *funcScope)
358     {
359         functionScopes_.push_back(funcScope);
360     }
361 
GetFileDependencies()362     std::unordered_map<std::string, std::unordered_set<std::string>> &GetFileDependencies()
363     {
364         return fileDependencies_;
365     }
366 
AddFileDependencies(const std::string & file,const std::string & depFile)367     void AddFileDependencies(const std::string &file, const std::string &depFile)
368     {
369         if (fileDependencies_.count(file) == 0U) {
370             fileDependencies_[file] = std::unordered_set<std::string>();
371         }
372         fileDependencies_[file].insert(depFile);
373     }
374 
375 private:
376     void MaybeTransformToDeclarationModule();
377 
378     ArenaAllocator *allocator_ {};
379     varbinder::VarBinder *varbinder_ {nullptr};
380     ir::BlockStatement *ast_ {};
381     ir::ClassDefinition *globalClass_ {};
382     util::StringView sourceCode_ {};
383     util::Path sourceFile_ {};
384     util::StringView sourceFileFolder_ {};
385     util::StringView resolvedFilePath_ {};
386     util::StringView relativeFilePath_ {};
387     ExternalSource externalSources_;
388     DirectExternalSource directExternalSources_;
389     ScriptKind kind_ {};
390     bool genAbcForExternalSource_ {false};
391     ScriptExtension extension_ {};
392     ETSNolintsCollectionMap etsnolintCollection_;
393     util::ModuleInfo moduleInfo_;
394     lexer::SourcePosition packageStartPosition_ {};
395     compiler::CFG *cfg_;
396     std::vector<std::pair<std::string, ir::AstNode *>> declGenExportNodes_;
397     ArenaVector<varbinder::FunctionScope *> functionScopes_;
398     std::unordered_map<std::string, std::unordered_set<std::string>> fileDependencies_;
399 
400 #ifndef NDEBUG
401     uint32_t poisonValue_ {POISON_VALUE};
402 #endif
403     ProgramFlags programFlags_ {};
404 };
405 }  // namespace ark::es2panda::parser
406 
407 namespace enumbitops {
408 
409 template <>
410 struct IsAllowedType<ark::es2panda::parser::ProgramFlags> : std::true_type {
411 };
412 
413 }  // namespace enumbitops
414 
415 #endif
416