* 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.
*/
#ifndef ES2PANDA_AOT_ARKTSCONFIG_H
#define ES2PANDA_AOT_ARKTSCONFIG_H
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "util/language.h"
#include "util/diagnostic.h"
#include "libarkbase/utils/json_builder.h"
#include "libarkbase/utils/json_parser.h"
#if not defined PANDA_TARGET_MOBILE
#define ARKTSCONFIG_USE_FILESYSTEM
#endif
#ifndef ARKTSCONFIG_USE_FILESYSTEM
#include <dirent.h>
#include <sys/types.h>
#else
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
#endif
namespace ark::es2panda::util {
class DiagnosticEngine;
}
namespace ark::es2panda {
struct CompareByLength {
using is_transparent = void;
template <typename T1, typename T2>
bool operator()(const T1 &x, const T2 &y) const
{
return x.size() == y.size() ? x > y : x.size() > y.size();
}
};
class ArkTsConfig {
using PathsMap = std::map<std::string, std::vector<std::string>, CompareByLength>;
public:
#ifdef ARKTSCONFIG_USE_FILESYSTEM
class Pattern {
public:
Pattern() = default;
Pattern(std::string value, std::string base);
bool IsPattern() const;
std::string GetSearchRoot() const;
bool Match(const std::string &path) const;
private:
std::string value_ {};
std::string base_ {};
};
#endif
class ExternalModuleData {
public:
explicit ExternalModuleData(Language lang, std::string path, std::string sourceFilePath, std::string ohmUrl,
std::string mainFile, std::vector<std::string> alias = {})
: lang_(lang),
path_(std::move(path)),
sourceFilePath_(std::move(sourceFilePath)),
ohmUrl_(std::move(ohmUrl)),
mainFile_(std::move(mainFile)),
alias_(std::move(alias))
{
}
Language GetLanguage() const
{
return lang_;
}
const std::string &Path() const
{
return path_;
}
std::string_view SourceFilePath() const
{
return sourceFilePath_;
}
std::string_view OhmUrl() const
{
return ohmUrl_;
}
std::string_view MainFile() const
{
return mainFile_;
}
const std::vector<std::string> &Alias() const
{
return alias_;
}
private:
Language lang_;
std::string path_ {};
std::string sourceFilePath_ {};
std::string ohmUrl_ {};
std::string mainFile_ {};
std::vector<std::string> alias_;
};
explicit ArkTsConfig(std::string_view configPath, util::DiagnosticEngine &de)
: configPath_(configPath), diagnosticEngine_(de)
{
}
bool Parse();
std::optional<std::string> ResolvePath(std::string_view path, bool isDynamic = false) const;
void FixupWithStdlibOption(const std::string &stdlib);
void FixupWithoutStdlibOption();
void ResolveAllDependenciesInArkTsConfig();
const std::string &ConfigPath() const
{
return configPath_;
}
const std::string &Package() const
{
return package_;
}
const std::string &BaseUrl() const
{
return baseUrl_;
}
const std::string &RootDir() const
{
return rootDir_;
}
const std::string &OutDir() const
{
return outDir_;
}
const std::string &CacheDir() const
{
return cacheDir_;
}
const std::string &DeclgenV2OutPath() const
{
return declgenV2OutPath_;
}
const std::vector<std::string> &Files() const
{
return files_;
}
const bool &UseUrl() const
{
return useUrl_;
}
const PathsMap &Paths() const
{
return paths_;
}
const std::map<std::string, ExternalModuleData, CompareByLength> &Dependencies() const
{
return dependencies_;
}
const std::map<std::string_view, std::string_view> &SourcePathMap() const
{
return sourcePathMap_;
}
using DependenciesLookupResult = std::optional<std::pair<const std::string &, const ExternalModuleData &>>;
DependenciesLookupResult FindInDependencies(std::string_view importString) const;
DependenciesLookupResult FindInDependencies(const std::string &importString) const
{
return FindInDependencies(std::string_view {importString});
}
#ifdef ARKTSCONFIG_USE_FILESYSTEM
const std::vector<Pattern> &Include() const
{
return include_;
}
const std::vector<Pattern> &Exclude() const
{
return exclude_;
}
fs::path ComputeDestination(const fs::path &src, const fs::path &rootDir, const fs::path &outDir) const;
#endif
bool Check(bool cond, const diagnostic::DiagnosticKind &diag, const util::DiagnosticMessageParams ¶ms) const;
void GenerateSourcePathMap();
private:
bool ParseCompilerOptions(std::string &arktsConfigDir, const JsonObject *arktsConfig);
std::optional<ArkTsConfig> ParseExtends(const std::string &configPath, const std::string &extends,
const std::string &configDir);
std::optional<std::string> ResolveImportPath(std::string_view path, const std::string &alias,
const std::vector<std::string> &filePaths) const;
bool ParsePaths(const JsonObject::JsonObjPointer *options, PathsMap &pathsMap, const std::string &baseUrl);
bool ParseDependencies(const JsonObject::JsonObjPointer *options,
std::map<std::string, ExternalModuleData, CompareByLength> &dependenciesMap);
template <class Collection, class Function>
bool ParseCollection(const JsonObject *config, Collection &out, const std::string &target, Function &&constructor);
std::optional<std::string> ReadConfig(const std::string &path);
std::vector<std::string> ParseStringArray(const std::unique_ptr<ark::JsonObject> *alias, std::string_view key);
private:
static constexpr const char *PACKAGE = "package";
static constexpr const char *BASE_URL = "baseUrl";
static constexpr const char *COMPILER_OPTIONS = "compilerOptions";
static constexpr const char *EXCLUDE = "exclude";
static constexpr const char *EXTENDS = "extends";
static constexpr const char *FILES = "files";
static constexpr const char *USE_EMPTY_PACKAGE = "useEmptyPackage";
static constexpr const char *INCLUDE = "include";
static constexpr const char *OUT_DIR = "outDir";
static constexpr const char *ROOT_DIR = "rootDir";
static constexpr const char *DEPENDENCIES = "dependencies";
static constexpr const char *CACHE_DIR = "cacheDir";
static constexpr const char *DECLGEN_V2_OUT_PATH =
"declgenV2OutPath";
void Inherit(const ArkTsConfig &base);
bool ParseDependency(size_t keyIdx, const std::unique_ptr<ark::JsonObject> *dependencies,
std::map<std::string, ExternalModuleData, CompareByLength> &dependenciesMap);
std::optional<std::string> TryResolveWithDependencies(std::string_view path) const;
std::optional<std::string> TryResolveWithDependencyAliases(std::string_view path) const;
std::optional<std::string> TryResolveWithPaths(std::string_view path) const;
std::optional<std::string> ResolvePath(std::string_view path) const;
bool isParsed_ = false;
std::string configPath_;
std::string package_ {};
std::string baseUrl_ {};
bool useUrl_ = false;
std::string outDir_ {};
std::string rootDir_ {};
std::string cacheDir_ {};
std::string declgenV2OutPath_ {};
PathsMap paths_ {};
std::map<std::string, ExternalModuleData, CompareByLength> dependencies_ {};
std::map<std::string_view, std::string_view> sourcePathMap_ {};
std::vector<std::string> files_ {};
#ifdef ARKTSCONFIG_USE_FILESYSTEM
std::vector<Pattern> include_ {};
std::vector<Pattern> exclude_ {};
#endif
util::DiagnosticEngine &diagnosticEngine_;
};
std::vector<std::pair<std::string, std::string>> FindProjectSources(const ArkTsConfig &arktsConfig);
std::string JoinPaths(const std::string &a, const std::string &b);
std::string ParentPath(const std::string &path);
}
#endif