* Copyright (c) 2023-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "arktsconfig.h"
#include "importPathManager.h"
#include "libarkbase/os/filesystem.h"
#include "util/language.h"
#include "util/diagnosticEngine.h"
#include "util/path.h"
#include "generated/signatures.h"
#include "util/helpers.h"
#include <fstream>
#include <memory>
#include <regex>
#include <sstream>
#include <system_error>
namespace ark::es2panda {
bool ArkTsConfig::Check(bool cond, const diagnostic::DiagnosticKind &diag,
const util::DiagnosticMessageParams ¶ms) const
{
if (!cond) {
diagnosticEngine_.LogDiagnostic(diag, params);
return false;
}
return true;
}
void ArkTsConfig::GenerateSourcePathMap()
{
if (!sourcePathMap_.empty()) {
return;
}
for (auto &keyValPair : dependencies_) {
if (!keyValPair.second.SourceFilePath().empty()) {
sourcePathMap_.insert({keyValPair.second.SourceFilePath(), keyValPair.first});
}
}
}
static bool IsAbsolute(const std::string &path)
{
#ifndef ARKTSCONFIG_USE_FILESYSTEM
return !path.empty() && path[0] == '/';
#else
return fs::path(path).is_absolute();
#endif
}
#ifndef ARKTSCONFIG_USE_FILESYSTEM
#else
fs::path NormalizePath(const fs::path &p)
{
fs::path result;
for (const auto &part : p) {
if (part == ".") {
continue;
}
if (part == "..") {
if (!result.empty() && result.filename() != "..") {
result = result.parent_path();
} else {
result /= part;
}
} else {
result /= part;
}
}
if (fs::exists(result)) {
return fs::canonical(result);
}
return result;
}
#endif
std::string JoinPaths(const std::string &a, const std::string &b)
{
#ifndef ARKTSCONFIG_USE_FILESYSTEM
return a + '/' + b;
#else
return NormalizePath(fs::path(a) / b).string();
#endif
}
std::string ParentPath(const std::string &path)
{
#ifndef ARKTSCONFIG_USE_FILESYSTEM
auto pos = path.find('/');
return pos == std::string::npos ? path : path.substr(0, pos);
#else
return fs::path(path).parent_path().string();
#endif
}
static std::string MakeAbsolute(const std::string &path, const std::string &base)
{
return IsAbsolute(path) ? path : JoinPaths(base, path);
}
#ifdef ARKTSCONFIG_USE_FILESYSTEM
ArkTsConfig::Pattern::Pattern(std::string value, std::string base) : value_(std::move(value)), base_(std::move(base))
{
ES2PANDA_ASSERT(fs::path(base_).is_absolute());
}
bool ArkTsConfig::Pattern::IsPattern() const
{
return (value_.find('*') != std::string::npos) || (value_.find('?') != std::string::npos);
}
std::string ArkTsConfig::Pattern::GetSearchRoot() const
{
fs::path relative;
if (!IsPattern()) {
relative = value_;
} else {
auto foundStar = value_.find_first_of('*');
auto foundQuestion = value_.find_first_of('?');
relative = value_.substr(0, std::min(foundStar, foundQuestion));
relative = relative.parent_path();
}
return MakeAbsolute(relative.string(), base_);
}
bool ArkTsConfig::Pattern::Match(const std::string &path) const
{
ES2PANDA_ASSERT(fs::path(path).is_absolute());
fs::path value = fs::path(value_);
std::string pattern = value.is_absolute() ? value.string() : (base_ / value).string();
if (IsPattern()) {
pattern = std::regex_replace(pattern, std::regex("\\*\\*/"), ".*");
pattern = std::regex_replace(pattern, std::regex("([^\\.])\\*"), "$1[^/]*");
pattern = std::regex_replace(pattern, std::regex("\\?"), "[^/]");
pattern = std::regex_replace(pattern, std::regex("\\.\\/"), "");
pattern = std::regex_replace(pattern, std::regex(R"(\[\^\/\]\*\.)"), "[^/]*\\.");
}
if (!value.has_extension()) {
pattern += R"(.*(\.ts|\.ets|\.sts)$)";
}
std::smatch m;
auto res = std::regex_match(path, m, std::regex(pattern));
return res;
}
static std::string ResolveConfigLocation(const std::string &relPath, const std::string &base)
{
auto resolvedPath = MakeAbsolute(relPath, base);
auto newBase = base;
while (!fs::exists(resolvedPath)) {
resolvedPath = MakeAbsolute(relPath, JoinPaths(newBase, "node_modules"));
if (newBase == ParentPath(newBase)) {
return "";
}
newBase = ParentPath(newBase);
}
return resolvedPath;
}
std::optional<ArkTsConfig> ArkTsConfig::ParseExtends(const std::string &configPath, const std::string &extends,
const std::string &configDir)
{
auto basePath = ResolveConfigLocation(extends, configDir);
if (!Check(!basePath.empty(), diagnostic::UNRESOLVABLE_CONFIG_PATH, {extends})) {
return {};
}
if (!Check(basePath != configPath, diagnostic::CYCLIC_IMPORT, {})) {
return {};
}
auto base = ArkTsConfig(basePath, diagnosticEngine_);
if (!Check(base.Parse(), diagnostic::WRONG_BASE_CONFIG, {extends})) {
return {};
}
return base;
}
#endif
ArkTsConfig::DependenciesLookupResult ArkTsConfig::FindInDependencies(std::string_view importString) const
{
auto res = std::find_if(dependencies_.begin(), dependencies_.end(), [importString](auto &dep) {
if (dep.first == importString) {
return true;
}
if (importString.rfind(dep.first, 0) == 0 &&
util::Helpers::EndsWith(dep.second.Path(), util::ImportPathManager::ABC_SUFFIX)) {
return true;
}
return false;
});
if (res != dependencies_.end()) {
return ArkTsConfig::DependenciesLookupResult {{res->first, res->second}};
}
return std::nullopt;
}
static std::string ValidLanguages()
{
JsonArrayBuilder builder;
for (auto &l : Language::All()) {
builder.Add(l.ToString());
}
return std::move(builder).Build();
}
bool ArkTsConfig::ParsePaths(const JsonObject::JsonObjPointer *options, PathsMap &pathsMap, const std::string &baseUrl)
{
auto paths = options->get()->GetValue<JsonObject::JsonObjPointer>("paths");
if (paths == nullptr) {
return true;
}
for (size_t keyIdx = 0; keyIdx < paths->get()->GetSize(); ++keyIdx) {
auto &key = paths->get()->GetKeyByIndex(keyIdx);
auto iter = pathsMap.find(key);
if (iter == pathsMap.end()) {
iter = pathsMap.emplace(key, PathsMap::mapped_type {}).first;
}
auto values = paths->get()->GetValue<JsonObject::ArrayT>(key);
if (!Check(values != nullptr, diagnostic::INVALID_VALUE, {"path", key})) {
return false;
}
if (!Check(!values->empty(), diagnostic::EMPTY_ARRAY_SUBSTITOTIONS, {key})) {
return false;
}
for (auto &v : *values) {
auto p = *v.Get<JsonObject::StringT>();
iter->second.emplace_back(MakeAbsolute(p, baseUrl));
}
}
return true;
}
static constexpr auto LANGUAGE = "language";
static constexpr auto PATH = "path";
static constexpr auto OHM_URL = "ohmUrl";
static constexpr auto ALIAS = "alias";
static constexpr auto SOURCEFILEPATH = "sourceFilePath";
static constexpr auto MAIN_FILE = "mainFile";
static void ParseLanguage(const std::string *langValue, std::optional<Language> &lang)
{
if (langValue != nullptr) {
lang = Language::FromString(*langValue);
} else {
lang = Language {Language::Id::ETS};
}
}
static std::string MakeAbsolutePath(const std::string &path, const std::string &base)
{
return IsAbsolute(path) ? ark::os::GetAbsolutePath(path) : MakeAbsolute(path, base);
}
bool ArkTsConfig::ParseDependency(size_t keyIdx, const std::unique_ptr<ark::JsonObject> *dependencies,
std::map<std::string, ExternalModuleData, CompareByLength> &dependenciesMap)
{
auto &key = dependencies->get()->GetKeyByIndex(keyIdx);
if (IsAbsolute(key)) {
diagnosticEngine_.LogDiagnostic(diagnostic::DEPENDENCIES_ABSOLUTE, util::DiagnosticMessageParams {key});
}
auto data = dependencies->get()->GetValue<JsonObject::JsonObjPointer>(key);
if (!Check(data != nullptr, diagnostic::INVALID_VALUE, {"dependency", key})) {
return false;
}
auto langValue = data->get()->GetValue<JsonObject::StringT>(LANGUAGE);
std::optional<Language> lang = std::nullopt;
ParseLanguage(langValue, lang);
const auto &diagParams = util::DiagnosticMessageParams {LANGUAGE, key, ValidLanguages()};
if (!Check(lang != std::nullopt && lang->IsValid(), diagnostic::INVALID_LANGUAGE, diagParams)) {
return false;
}
auto isSupportLang = compiler::Signatures::Dynamic::IsSupported(*lang);
if (lang->IsDynamic() && !Check(isSupportLang, diagnostic::UNSUPPORTED_LANGUAGE_FOR_INTEROP, {lang->ToString()})) {
return false;
}
auto ohmUrl = data->get()->GetValue<JsonObject::StringT>(OHM_URL);
if (ohmUrl == nullptr && lang && lang->IsDynamic()) {
diagnosticEngine_.LogDiagnostic(diagnostic::NO_OHMURL, util::DiagnosticMessageParams {key});
}
std::string ohmUrlValue = (ohmUrl == nullptr) ? "" : *ohmUrl;
auto pathValue = data->get()->GetValue<JsonObject::StringT>(PATH);
std::string normalizedPath {};
if (pathValue != nullptr) {
normalizedPath = MakeAbsolutePath(*pathValue, baseUrl_);
if (!Check(ark::os::IsFileExists(normalizedPath), diagnostic::INVALID_PATH, {normalizedPath, key, baseUrl_})) {
return false;
}
} else {
if (!Check(lang && lang->IsDynamic(), diagnostic::INVALID_PATH, {key})) {
return false;
}
}
auto mainFile = data->get()->GetValue<JsonObject::StringT>(MAIN_FILE);
std::string mainFilevalue = (mainFile == nullptr) ? "" : *mainFile;
auto sourcePathValue = data->get()->GetValue<JsonObject::StringT>(SOURCEFILEPATH);
std::string sourcePath {};
if (sourcePathValue != nullptr) {
sourcePath = MakeAbsolutePath(*sourcePathValue, baseUrl_);
}
std::vector<std::string> aliases = ParseStringArray(data, ALIAS);
auto res =
dependenciesMap.insert({key, ArkTsConfig::ExternalModuleData(*lang, normalizedPath, sourcePath, ohmUrlValue,
mainFilevalue, std::move(aliases))});
return Check(res.second, diagnostic::DUPLICATED_DEPENDENCIES, {normalizedPath, key});
}
bool ArkTsConfig::ParseDependencies(const JsonObject::JsonObjPointer *options,
std::map<std::string, ExternalModuleData, CompareByLength> &dependenciesMap)
{
if (options == nullptr) {
return true;
}
auto dependencies = options->get()->GetValue<JsonObject::JsonObjPointer>(DEPENDENCIES);
if (dependencies == nullptr) {
return true;
}
for (size_t keyIdx = 0; keyIdx < dependencies->get()->GetSize(); ++keyIdx) {
if (!ParseDependency(keyIdx, dependencies, dependenciesMap)) {
return false;
}
}
return true;
}
template <class Collection, class Function>
bool ArkTsConfig::ParseCollection(const JsonObject *config, Collection &out, const std::string &target,
Function &&constructor)
{
auto *arr = config->GetValue<JsonObject::ArrayT>(target);
if (!Check(arr != nullptr, diagnostic::INVALID_JSON_TYPE, {target, "array"})) {
return false;
}
out = {};
if (!Check(!arr->empty(), diagnostic::EMPTY_LIST, {target})) {
return false;
}
for (auto &i : *arr) {
out.emplace_back(constructor(*i.Get<JsonObject::StringT>()));
}
return true;
}
std::optional<std::string> ArkTsConfig::ReadConfig(const std::string &path)
{
std::ifstream inputStream(path);
if (!Check(!inputStream.fail(), diagnostic::FAILED_TO_OPEN_FILE, {path})) {
return {};
}
std::stringstream ss;
ss << inputStream.rdbuf();
return ss.str();
}
static std::string ValueOrEmptyString(const JsonObject::JsonObjPointer *json, const std::string &key)
{
ES2PANDA_ASSERT(json != nullptr);
auto res = json->get()->GetValue<JsonObject::StringT>(key);
return (res != nullptr) ? *res : "";
}
void ArkTsConfig::FixupWithStdlibOption(const std::string &stdlib)
{
for (std::string prefix : {"std", "arkruntime"}) {
std::string path = stdlib + util::PATH_DELIMITER;
path += prefix;
auto stdlibRealpath = ark::os::GetAbsolutePath(path);
ES2PANDA_ASSERT(!stdlibRealpath.empty());
paths_[prefix] = {stdlibRealpath};
}
}
void ArkTsConfig::FixupWithoutStdlibOption()
{
auto it = paths_.find({"std"});
if (it != paths_.end() && it->second.size() == 1) {
auto path = it->second.at(0);
path = path.substr(0, path.rfind(util::PATH_DELIMITER) + 1) + "arkruntime";
paths_.insert({{"arkruntime"}, {path}});
}
}
void ArkTsConfig::ResolveAllDependenciesInArkTsConfig()
{
for (auto &dependencyPath : paths_) {
for (auto &path : dependencyPath.second) {
auto normalized = ark::os::NormalizePath(path);
if (auto real = ark::os::GetAbsolutePath(normalized); !real.empty()) {
path = real;
} else {
path = normalized;
}
}
}
}
static void CreateDirectoriesWithParents(const std::string &path)
{
auto parent = ark::os::GetParentDir(path);
if (!parent.empty() && !ark::os::IsDirExists(parent)) {
CreateDirectoriesWithParents(parent);
}
if (!path.empty()) {
ark::os::CreateDirectories(path);
}
}
bool ArkTsConfig::ParseCompilerOptions(std::string &arktsConfigDir, const JsonObject *arktsConfig)
{
auto compilerOptions = arktsConfig->GetValue<JsonObject::JsonObjPointer>(COMPILER_OPTIONS);
package_ = ValueOrEmptyString(compilerOptions, PACKAGE);
baseUrl_ = MakeAbsolute(ValueOrEmptyString(compilerOptions, BASE_URL), arktsConfigDir);
outDir_ = MakeAbsolute(ValueOrEmptyString(compilerOptions, OUT_DIR), arktsConfigDir);
rootDir_ = ValueOrEmptyString(compilerOptions, ROOT_DIR);
if (!rootDir_.empty() &&
!Check(ark::os::file::File::IsDirectory(rootDir_), diagnostic::NOT_A_DIR, {"rootDir " + rootDir_})) {
return false;
}
if (rootDir_.empty()) {
rootDir_ = ".";
}
cacheDir_ = ValueOrEmptyString(compilerOptions, CACHE_DIR);
CreateDirectoriesWithParents(cacheDir_);
declgenV2OutPath_ = MakeAbsolute(ValueOrEmptyString(compilerOptions, DECLGEN_V2_OUT_PATH), arktsConfigDir);
if (compilerOptions->get()->HasKey(USE_EMPTY_PACKAGE)) {
auto *useUrl = compilerOptions->get()->GetValue<JsonObject::BoolT>(USE_EMPTY_PACKAGE);
ES2PANDA_ASSERT(useUrl != nullptr);
useUrl_ = *useUrl;
}
if (!ParsePaths(compilerOptions, paths_, baseUrl_)) {
return false;
}
if (!ParseDependencies(compilerOptions, dependencies_)) {
return false;
}
return true;
}
bool ArkTsConfig::Parse()
{
ES2PANDA_ASSERT(!isParsed_);
isParsed_ = true;
auto arktsConfigDir = ParentPath(ark::os::GetAbsolutePath(configPath_));
auto tsConfigSource = ReadConfig(configPath_);
if (!Check(tsConfigSource.has_value(), diagnostic::UNRESOLVABLE_CONFIG_PATH, {configPath_})) {
return false;
}
auto arktsConfig = std::make_unique<JsonObject>(*tsConfigSource);
if (!Check(arktsConfig->IsValid(), diagnostic::INVALID_JSON, {})) {
return false;
}
#ifdef ARKTSCONFIG_USE_FILESYSTEM
if (arktsConfig->HasKey(EXTENDS)) {
auto *extends = arktsConfig->GetValue<JsonObject::StringT>(EXTENDS);
if (!Check(extends != nullptr, diagnostic::INVALID_JSON_TYPE, {EXTENDS, "string"})) {
return false;
}
const auto &base = ParseExtends(configPath_, *extends, arktsConfigDir);
if (!base.has_value()) {
return false;
}
Inherit(*base);
}
#endif
if (arktsConfig->HasKey(COMPILER_OPTIONS) && !ParseCompilerOptions(arktsConfigDir, arktsConfig.get())) {
return false;
}
auto concatPath = [&arktsConfigDir](const auto &val) { return MakeAbsolute(val, arktsConfigDir); };
if (arktsConfig->HasKey(FILES) && !ParseCollection(arktsConfig.get(), files_, FILES, concatPath)) {
return false;
}
#ifdef ARKTSCONFIG_USE_FILESYSTEM
auto consPattern = [&arktsConfigDir](const auto &val) { return Pattern {val, arktsConfigDir}; };
if (arktsConfig->HasKey(INCLUDE) && !ParseCollection(arktsConfig.get(), include_, INCLUDE, consPattern)) {
return false;
}
if (arktsConfig->HasKey(EXCLUDE) && !ParseCollection(arktsConfig.get(), exclude_, EXCLUDE, consPattern)) {
return false;
}
#endif
return true;
}
void ArkTsConfig::Inherit(const ArkTsConfig &base)
{
package_ = base.package_;
baseUrl_ = base.baseUrl_;
outDir_ = base.outDir_;
rootDir_ = base.rootDir_;
declgenV2OutPath_ = base.declgenV2OutPath_;
paths_ = base.paths_;
files_ = base.files_;
#ifdef ARKTSCONFIG_USE_FILESYSTEM
include_ = base.include_;
exclude_ = base.exclude_;
#endif
}
static std::string TrimPath(const std::string &path)
{
std::string trimmedPath = path;
while (!trimmedPath.empty() && (trimmedPath.back() == '*' || trimmedPath.back() == '/')) {
trimmedPath.pop_back();
}
return trimmedPath;
}
static bool CheckFilePath(const std::string &path)
{
for (const auto &extension : util::ImportPathManager::supportedExtensions) {
if (ark::os::file::File::IsRegularFile(path + std::string(extension))) {
return true;
}
}
return false;
}
std::optional<std::string> ArkTsConfig::ResolveImportPath(std::string_view path, const std::string &alias,
const std::vector<std::string> &filePaths) const
{
for (const auto &filePath : filePaths) {
auto resolved = std::string(path);
std::string newPrefix = TrimPath(filePath);
resolved.replace(0, alias.length(), newPrefix);
if (ark::os::file::File::IsDirectory(resolved) || ark::os::file::File::IsRegularFile(resolved)) {
return resolved;
}
if (CheckFilePath(resolved)) {
return resolved;
}
}
return std::nullopt;
}
std::optional<std::string> ArkTsConfig::TryResolveWithPaths(std::string_view path) const
{
if (auto indexIt = paths_.find(std::string(path) + "/Index"); indexIt != paths_.end()) {
auto result = ResolveImportPath(path, TrimPath(indexIt->first), indexIt->second);
if (result.has_value()) {
return result;
}
}
for (const auto &[alias, paths] : paths_) {
auto trimmedAlias = TrimPath(alias);
if (path.rfind(trimmedAlias, 0) == 0) {
return ResolveImportPath(path, trimmedAlias, paths);
}
}
return std::nullopt;
}
std::optional<std::string> ArkTsConfig::TryResolveWithDependencies(std::string_view path) const
{
for (const auto &[dynPath, dependence] : dependencies_) {
if (path == dynPath && !util::Helpers::EndsWith(dependence.Path(), util::ImportPathManager::ABC_SUFFIX)) {
return dynPath;
}
if (path == dynPath && util::Helpers::IsStdLib(path)) {
ES2PANDA_ASSERT(util::Helpers::EndsWith(dependence.Path(), util::ImportPathManager::ABC_SUFFIX));
return dynPath;
}
if (path == dynPath && util::Helpers::EndsWith(dependence.Path(), util::ImportPathManager::ABC_SUFFIX)) {
return dynPath + "." + std::string {dependence.MainFile()};
}
if (path != dynPath && path.rfind(dynPath, 0) == 0 &&
util::Helpers::EndsWith(dependence.Path(), util::ImportPathManager::ABC_SUFFIX)) {
return std::string {path};
}
}
return std::nullopt;
}
std::optional<std::string> ArkTsConfig::TryResolveWithDependencyAliases(std::string_view path) const
{
for (const auto &[dynPath, dependence] : dependencies_) {
const auto &aliases = dependence.Alias();
if (std::find(aliases.begin(), aliases.end(), path) != aliases.end()) {
return dynPath;
}
}
return std::nullopt;
}
std::optional<std::string> ArkTsConfig::ResolvePath(std::string_view path, bool isDynamic) const
{
std::optional<std::string> result = TryResolveWithDependencies(path);
if (result) {
return result;
}
if (isDynamic) {
result = TryResolveWithDependencyAliases(path);
if (result) {
return result;
}
result = TryResolveWithPaths(path);
} else {
result = TryResolveWithPaths(path);
if (result) {
return result;
}
result = TryResolveWithDependencyAliases(path);
}
return result;
}
std::vector<std::string> ArkTsConfig::ParseStringArray(const std::unique_ptr<ark::JsonObject> *alias,
std::string_view key)
{
std::vector<std::string> result;
const auto *array = alias->get()->GetValue<JsonObject::ArrayT>(std::string(key));
if (array != nullptr) {
for (const auto &val : *array) {
const auto *str = val.template Get<JsonObject::StringT>();
if (str != nullptr && !str->empty()) {
result.emplace_back(*str);
}
}
}
return result;
}
#ifdef ARKTSCONFIG_USE_FILESYSTEM
static bool MatchExcludes(const fs::path &path, const std::vector<ArkTsConfig::Pattern> &excludes)
{
for (auto &e : excludes) {
if (e.Match(path.string())) {
return true;
}
}
return false;
}
std::vector<fs::path> GetSourceList(const ArkTsConfig &arktsConfig)
{
auto includes = arktsConfig.Include();
auto excludes = arktsConfig.Exclude();
auto files = arktsConfig.Files();
auto configDir = fs::absolute(fs::path(arktsConfig.ConfigPath())).parent_path();
if (files.empty() && includes.empty()) {
includes = {ArkTsConfig::Pattern("**/*", configDir.string())};
}
if (fs::exists(arktsConfig.OutDir()) && !fs::equivalent(arktsConfig.OutDir(), configDir)) {
excludes.emplace_back("**/*", arktsConfig.OutDir());
}
std::vector<fs::path> sourceList;
for (auto &f : files) {
if (!arktsConfig.Check(fs::exists(f) && fs::path(f).has_filename(), diagnostic::NO_FILE, {f})) {
return {};
}
sourceList.emplace_back(f);
}
for (auto &include : includes) {
auto traverseRoot = fs::path(include.GetSearchRoot());
if (!fs::exists(traverseRoot)) {
continue;
}
if (!fs::is_directory(traverseRoot)) {
if (include.Match(traverseRoot.string()) && !MatchExcludes(traverseRoot, excludes)) {
sourceList.emplace_back(traverseRoot);
}
continue;
}
for (const auto &dirEntry : fs::recursive_directory_iterator(traverseRoot)) {
if (include.Match(dirEntry.path().string()) && !MatchExcludes(dirEntry, excludes) &&
!fs::is_directory(dirEntry)) {
sourceList.emplace_back(dirEntry);
}
}
}
return sourceList;
}
static fs::path Relative(const fs::path &src, const fs::path &base)
{
fs::path tmpPath = src;
fs::path relPath;
while (!fs::equivalent(tmpPath, base)) {
relPath = relPath.empty() ? tmpPath.filename() : tmpPath.filename() / relPath;
if (tmpPath == tmpPath.parent_path()) {
return fs::path();
}
tmpPath = tmpPath.parent_path();
}
return relPath;
}
fs::path ArkTsConfig::ComputeDestination(const fs::path &src, const fs::path &rootDir, const fs::path &outDir) const
{
auto rel = Relative(src, rootDir);
std::stringstream sRootDir;
sRootDir << rootDir;
std::stringstream sSrc;
sSrc << src;
if (!Check(!rel.empty(), diagnostic::NOT_ROOT_DIR, {sRootDir.str(), sSrc.str()})) {
return {};
}
auto dst = outDir / rel;
fs::create_directories(dst.parent_path());
return dst.replace_extension("abc");
}
std::vector<std::pair<std::string, std::string>> FindProjectSources(const ArkTsConfig &arktsConfig)
{
auto sourceFiles = GetSourceList(arktsConfig);
std::vector<std::pair<std::string, std::string>> compilationList;
for (auto &src : sourceFiles) {
auto dst = arktsConfig.ComputeDestination(src, arktsConfig.RootDir(), arktsConfig.OutDir());
if (!arktsConfig.Check(!dst.empty(), diagnostic::INVALID_DESTINATION_FILE, {})) {
return {};
}
compilationList.emplace_back(src.string(), dst.string());
}
return compilationList;
}
#else
std::vector<std::pair<std::string, std::string>> FindProjectSources([[maybe_unused]] const ArkTsConfig &arktsConfig)
{
ES2PANDA_ASSERT(false);
return {};
}
#endif
}