1 /** 2 * Copyright (c) 2023-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_AOT_ARKTSCONFIG_H 17 #define ES2PANDA_AOT_ARKTSCONFIG_H 18 19 #include <map> 20 #include <memory> 21 #include <string> 22 #include <unordered_map> 23 #include <unordered_set> 24 #include <vector> 25 26 #include "util/language.h" 27 #include "util/diagnostic.h" 28 #include "libpandabase/utils/json_builder.h" 29 #include "libpandabase/utils/json_parser.h" 30 31 // NOTE(ivagin): If ARKTSCONFIG_USE_FILESYSTEM is not defined part of ArkTsConfig functionality is disabled. 32 // Only build configuration which prevents us from usage of std::filesystem is "MOBILE" build 33 // because of lack of std::filesystem in our current version of mobile nativ development kit. 34 // nativ development kit version should be updated and ARKTSCONFIG_USE_FILESYSTEM removed 35 #if not defined PANDA_TARGET_MOBILE 36 #define ARKTSCONFIG_USE_FILESYSTEM 37 #endif 38 39 #ifndef ARKTSCONFIG_USE_FILESYSTEM 40 #include <dirent.h> 41 #include <sys/types.h> 42 #else 43 #if __has_include(<filesystem>) 44 #include <filesystem> 45 namespace fs = std::filesystem; 46 #elif __has_include(<experimental/filesystem>) 47 #include <experimental/filesystem> 48 namespace fs = std::experimental::filesystem; 49 #endif 50 #endif 51 52 namespace ark::es2panda::util { 53 class DiagnosticEngine; 54 } // namespace ark::es2panda::util 55 56 namespace ark::es2panda { 57 58 struct CompareByLength { operatorCompareByLength59 bool operator()(const std::string &x, const std::string &y) const 60 { 61 return x.size() == y.size() ? x > y : x.size() > y.size(); 62 } 63 }; 64 65 class ArkTsConfig { 66 using PathsMap = std::map<std::string, std::vector<std::string>, CompareByLength>; 67 68 public: 69 #ifdef ARKTSCONFIG_USE_FILESYSTEM 70 // Pattern describes arktsconfig path pattern for 'include' or 'exclude' properties 71 // e.g. src/**, src/**/*, src/util?.ts 72 class Pattern { 73 public: 74 Pattern() = default; 75 Pattern(std::string value, std::string base); 76 77 bool IsPattern() const; 78 79 // Get root from which sources file search should be started 80 // e.g. src/** -> src; src/index?.ts -> src; src/component/*/index.ts -> src/component; src/index* -> src/ 81 std::string GetSearchRoot() const; 82 83 // Test if absolute path is matched by pattern 84 bool Match(const std::string &path) const; 85 86 private: 87 std::string value_ {}; 88 std::string base_ {}; 89 }; 90 #endif // ARKTSCONFIG_USE_FILESYSTEM 91 92 class DynamicImportData { 93 public: DynamicImportData(Language lang,std::string declPath,std::string ohmUrl)94 explicit DynamicImportData(Language lang, std::string declPath, std::string ohmUrl) 95 : lang_(lang), declPath_(std::move(declPath)), ohmUrl_(std::move(ohmUrl)) 96 { 97 } 98 GetLanguage()99 Language GetLanguage() const 100 { 101 return lang_; 102 } 103 DeclPath()104 std::string_view DeclPath() const 105 { 106 return declPath_; 107 } 108 OhmUrl()109 std::string_view OhmUrl() const 110 { 111 return ohmUrl_; 112 } 113 114 private: 115 Language lang_; 116 std::string declPath_ {}; 117 std::string ohmUrl_ {}; 118 }; 119 ArkTsConfig(std::string_view configPath,util::DiagnosticEngine & de)120 explicit ArkTsConfig(std::string_view configPath, util::DiagnosticEngine &de) 121 : configPath_(configPath), diagnosticEngine_(de) 122 { 123 } 124 bool Parse(std::unordered_set<std::string> &parsedConfigPath); 125 126 std::optional<std::string> ResolvePath(std::string_view path, bool isDynamic = false) const; 127 128 void ResolveAllDependenciesInArkTsConfig(); 129 ConfigPath()130 const std::string &ConfigPath() const 131 { 132 return configPath_; 133 } 134 Package()135 const std::string &Package() const 136 { 137 return package_; 138 } BaseUrl()139 const std::string &BaseUrl() const 140 { 141 return baseUrl_; 142 } RootDir()143 const std::string &RootDir() const 144 { 145 return rootDir_; 146 } OutDir()147 const std::string &OutDir() const 148 { 149 return outDir_; 150 } Dependencies()151 const std::unordered_map<std::string, std::shared_ptr<ArkTsConfig>> &Dependencies() const 152 { 153 return dependencies_; 154 } ResetDependencies()155 void ResetDependencies() 156 { 157 return dependencies_.clear(); 158 } Entry()159 const std::string &Entry() const 160 { 161 return entry_; 162 } Entries()163 const std::unordered_map<std::string, std::string> &Entries() const 164 { 165 return entries_; 166 } Files()167 const std::vector<std::string> &Files() const 168 { 169 return files_; 170 } UseUrl()171 const bool &UseUrl() const 172 { 173 return useUrl_; 174 } Paths()175 const PathsMap &Paths() const 176 { 177 return paths_; 178 } DynamicPaths()179 const std::map<std::string, DynamicImportData, CompareByLength> &DynamicPaths() const 180 { 181 return dynamicPaths_; 182 } 183 #ifdef ARKTSCONFIG_USE_FILESYSTEM Include()184 const std::vector<Pattern> &Include() const 185 { 186 return include_; 187 } Exclude()188 const std::vector<Pattern> &Exclude() const 189 { 190 return exclude_; 191 } 192 fs::path ComputeDestination(const fs::path &src, const fs::path &rootDir, const fs::path &outDir); 193 #endif // ARKTSCONFIG_USE_FILESYSTEM 194 bool Check(bool cond, const diagnostic::DiagnosticKind &diag, const util::DiagnosticMessageParams ¶ms); 195 196 private: 197 bool ParseCompilerOptions(std::string &arktsConfigDir, std::unordered_set<std::string> &parsedConfigPath, 198 const JsonObject *arktsConfig); 199 std::optional<ArkTsConfig> ParseExtends(const std::string &configPath, const std::string &extends, 200 const std::string &configDir, 201 std::unordered_set<std::string> &parsedConfigPath); 202 bool ParsePaths(const JsonObject::JsonObjPointer *options, PathsMap &pathsMap, const std::string &baseUrl); 203 bool ParseDynamicPaths(const JsonObject::JsonObjPointer *options, 204 std::map<std::string, DynamicImportData, CompareByLength> &dynamicPathsMap, 205 const std::string &baseUrl); 206 bool ParseSingleDynamicPath(const std::string &key, const JsonObject::JsonObjPointer *data, 207 std::map<std::string, DynamicImportData, CompareByLength> &dynamicPathsMap, 208 const std::string &baseUrl); 209 template <class Collection, class Function> 210 bool ParseCollection(const JsonObject *config, Collection &out, const std::string &target, Function &&constructor); 211 void ResolveConfigDependencies(std::unordered_map<std::string, std::shared_ptr<ArkTsConfig>> &dependencies, 212 std::vector<std::string> &dependencyPaths, 213 std::unordered_set<std::string> &parsedConfigPath); 214 std::optional<std::string> ReadConfig(const std::string &path); 215 216 private: 217 static constexpr const char *PACKAGE = "package"; // CC-OFF(G.NAM.03,G.NAM.03-CPP) project code style 218 static constexpr const char *BASE_URL = "baseUrl"; 219 static constexpr const char *COMPILER_OPTIONS = "compilerOptions"; 220 static constexpr const char *EXCLUDE = "exclude"; 221 static constexpr const char *EXTENDS = "extends"; 222 static constexpr const char *FILES = "files"; 223 static constexpr const char *USE_EMPTY_PACKAGE = "useEmptyPackage"; // CC-OFF(G.NAM.03-CPP) project code style 224 static constexpr const char *INCLUDE = "include"; 225 static constexpr const char *OUT_DIR = "outDir"; 226 static constexpr const char *ROOT_DIR = "rootDir"; 227 static constexpr const char *DEPENDENCIES = "dependencies"; // CC-OFF(G.NAM.03,G.NAM.03-CPP) project code style 228 static constexpr const char *ENTRY = "entry"; // CC-OFF(G.NAM.03,G.NAM.03-CPP) project code style 229 230 void Inherit(const ArkTsConfig &base); 231 232 bool isParsed_ = false; 233 std::string configPath_; 234 235 std::string package_ {}; 236 std::string baseUrl_ {}; 237 bool useUrl_ = false; 238 std::string outDir_ {}; 239 std::string rootDir_ {}; 240 std::string entry_ {}; 241 PathsMap paths_ {}; 242 std::map<std::string, DynamicImportData, CompareByLength> dynamicPaths_ {}; 243 std::vector<std::string> files_ {}; 244 std::unordered_map<std::string, std::shared_ptr<ArkTsConfig>> dependencies_ {}; 245 // key: package name; value: entry's absolute path 246 std::unordered_map<std::string, std::string> entries_; 247 #ifdef ARKTSCONFIG_USE_FILESYSTEM 248 std::vector<Pattern> include_ {}; 249 std::vector<Pattern> exclude_ {}; 250 #endif // ARKTSCONFIG_USE_FILESYSTEM 251 util::DiagnosticEngine &diagnosticEngine_; 252 }; 253 254 // Find source files and compute destination locations 255 // Return: vector of path pairs <source file, destination abc file> 256 std::vector<std::pair<std::string, std::string>> FindProjectSources(const std::shared_ptr<ArkTsConfig> &arktsConfig); 257 258 std::string JoinPaths(const std::string &a, const std::string &b); 259 std::string ParentPath(const std::string &path); 260 261 } // namespace ark::es2panda 262 263 #endif // ES2PANDA_AOT_TSCONFIG_H 264