nixir/src/irc/resolver.cpp
NotAShelf 98fd1bfc52
various: format with clang-format
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ib9abc9d2dcd036d3680c5aa3dc919bfa6a6a6964
2026-02-22 00:18:21 +03:00

114 lines
3 KiB
C++

#include "resolver.h"
#include "parser.h"
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
namespace nix_irc {
namespace fs = std::filesystem;
struct Resolver::Impl {
ResolverConfig config;
std::vector<std::pair<std::string, std::string>> resolved_imports;
std::unordered_set<std::string> visited;
Parser parser;
Impl(const ResolverConfig& cfg) : config(cfg) {}
std::string resolve_path(const std::string& path, const std::string& from_file) {
fs::path p(path);
if (p.is_absolute()) {
if (fs::exists(p))
return path;
return "";
}
fs::path from_dir = fs::path(from_file).parent_path();
fs::path candidate = from_dir / p;
if (fs::exists(candidate))
return candidate.string();
for (const auto& search : config.search_paths) {
candidate = fs::path(search) / p;
if (fs::exists(candidate))
return candidate.string();
}
return "";
}
ImportResult do_resolve(const std::string& path, const std::string& from_file) {
std::string resolved = resolve_path(path, from_file);
if (resolved.empty()) {
return {false, "", "Cannot find file: " + path, nullptr};
}
if (visited.count(resolved)) {
return {true, resolved, "", nullptr};
}
visited.insert(resolved);
try {
auto ast = parser.parse_file(resolved);
return {true, resolved, "", ast};
} catch (const std::exception& e) {
return {false, "", e.what(), nullptr};
}
}
};
Resolver::Resolver(const ResolverConfig& config) : pImpl(std::make_unique<Impl>(config)) {}
Resolver::~Resolver() = default;
void Resolver::add_search_path(const std::string& path) {
pImpl->config.search_paths.push_back(path);
}
void Resolver::set_search_paths(const std::vector<std::string>& paths) {
pImpl->config.search_paths = paths;
}
ImportResult Resolver::resolve_import(const std::string& path, const std::string& from_file) {
auto result = pImpl->do_resolve(path, from_file);
if (result.success && result.ast) {
pImpl->resolved_imports.push_back({path, result.path});
}
return result;
}
ImportResult Resolver::resolve_import(const Node& import_node, const std::string& from_file) {
const ConstPathNode* path_node = import_node.get_if<ConstPathNode>();
if (!path_node) {
return {false, "", "Dynamic import not supported", nullptr};
}
return resolve_import(path_node->value, from_file);
}
std::vector<std::string> Resolver::get_resolved_files() const {
std::vector<std::string> files;
for (const auto& [orig, resolved] : pImpl->resolved_imports) {
(void) orig;
files.push_back(resolved);
}
return files;
}
std::vector<std::pair<std::string, std::string>> Resolver::get_imports() const {
return pImpl->resolved_imports;
}
bool is_static_import(const Node& node) {
return node.holds<ConstPathNode>();
}
std::string normalize_path(const std::string& path) {
fs::path p(path);
return fs::absolute(p).string();
}
} // namespace nix_irc