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