From 3cbae14b63eeef42d49788dd150278f1a52c9bfd Mon Sep 17 00:00:00 2001 From: ykiko Date: Sat, 21 Sep 2024 19:21:43 +0800 Subject: [PATCH] update config. --- docs/{option.toml => clice.toml} | 18 ++++-- include/Server/Config.h | 32 +++++++++++ include/Server/Option.h | 26 --------- include/Server/Server.h | 2 - include/Support/JSON.h | 4 +- include/Support/Reflection.h | 25 ++++++--- include/Support/URI.h | 4 +- src/Server/Config.cpp | 95 ++++++++++++++++++++++++++++++++ src/Server/Option.cpp | 26 --------- src/Server/Server.cpp | 12 ++-- src/Support/URI.cpp | 13 +++++ 11 files changed, 182 insertions(+), 75 deletions(-) rename docs/{option.toml => clice.toml} (92%) create mode 100644 include/Server/Config.h delete mode 100644 include/Server/Option.h create mode 100644 src/Server/Config.cpp delete mode 100644 src/Server/Option.cpp diff --git a/docs/option.toml b/docs/clice.toml similarity index 92% rename from docs/option.toml rename to docs/clice.toml index b0a5e763..174dfd10 100644 --- a/docs/option.toml +++ b/docs/clice.toml @@ -1,16 +1,22 @@ -[clang] -# the -compile-commands-directory = "" - -# the path of builtin headers that clang uses -resource-directory = "${executable}/../lib/clang/${version}" +[server] +# "pipe" or "socket" +mode = "pipe" +port = 50051 +address = "127.0.0.1" +[frontend] # the commands that will be appended to the command line append = [] # the commands that will be removed from the command line remove = [] +# the +compile-commands-directory = "" + +# the path of builtin headers that clang uses +resource-directory = "${executable}/../lib/clang/${version}" + [diagnostic] # the maximum number of diagnostics that will be displayed max-diagnostic = 100 diff --git a/include/Server/Config.h b/include/Server/Config.h new file mode 100644 index 00000000..d6779ce7 --- /dev/null +++ b/include/Server/Config.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +namespace clice::config { + +/// read the config file, call when the program starts. +int parse(int argc, const char** argv); + +/// initialize the config, replace all predefined variables in the config file. +/// called in `Server::initialize`. +void initialize(std::string_view workplace); + +struct ServerOption { + std::string mode; + unsigned int port; + std::string address; +}; + +struct FrontendOption { + std::vector append; + std::vector remove; + std::string resource_dictionary = "${executable}/../lib/clang/${llvm_version}"; + std::string compile_commands_directory = "${workplace}/build"; +}; + +ServerOption& server(); + +FrontendOption& frontend(); + +}; // namespace clice::config + diff --git a/include/Server/Option.h b/include/Server/Option.h deleted file mode 100644 index d5b7d2b8..00000000 --- a/include/Server/Option.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -namespace clice { - -struct Option { - /// predefined variables. - struct { - int argc; - const char** argv; - /// clice binary dictionary. - std::string binary; - /// workplace dictionary. - std::string workplace; - /// clang version. - std::string clang_version = "20"; - }; - - std::string resource_dictionary; - std::string compile_commands_directory; - - void parse(std::string_view workplace); -}; - -} // namespace clice diff --git a/include/Server/Server.h b/include/Server/Server.h index 08b5a4ec..9fce09dc 100644 --- a/include/Server/Server.h +++ b/include/Server/Server.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -9,7 +8,6 @@ namespace clice { struct Server { using Handler = llvm::unique_function; - Option option; Scheduler scheduler; CompilationDatabase CDB; llvm::StringMap handlers; diff --git a/include/Support/JSON.h b/include/Support/JSON.h index be902dc9..995d7cbc 100644 --- a/include/Support/JSON.h +++ b/include/Support/JSON.h @@ -51,7 +51,7 @@ json::Value serialize(const Value& value) { return array; } else { json::Object object; - for_each(value, [&](llvm::StringRef name, const auto& field) { + refl::foreach(value, [&](llvm::StringRef name, const auto& field) { object.try_emplace(name, serialize(field)); }); return object; @@ -76,7 +76,7 @@ Value deserialize(const json::Value& object) { return array; } else { Value value; - for_each(value, [&](llvm::StringRef name, auto& field) { + refl::foreach(value, [&](llvm::StringRef name, auto& field) { if(auto element = object.getAsObject()->get(name)) { field = deserialize>(*element); } diff --git a/include/Support/Reflection.h b/include/Support/Reflection.h index 00e6a6f6..62bb5251 100644 --- a/include/Support/Reflection.h +++ b/include/Support/Reflection.h @@ -218,7 +218,7 @@ using replace_cv_ref_t = typename replace_cv_ref::type; } // namespace clice::impl -namespace clice { +namespace clice::refl { template struct Record; @@ -231,17 +231,17 @@ constexpr inline bool is_record_v> = true; #define CLICE_RECORD(name, ...) \ struct name##Body; \ - using name = Record<__VA_ARGS__, name##Body>; \ + using name = clice::refl::Record<__VA_ARGS__, name##Body>; \ struct name##Body template concept Reflectable = std::is_aggregate_v> && std::is_default_constructible_v>; template -constexpr void for_each(Object&& object, const Callback& callback) { +constexpr void foreach(Object&& object, const Callback& callback) { using T = std::decay_t; if constexpr(is_record_v) { - T::for_each(std::forward(object), callback); + T::foreach(std::forward(object), callback); } else { constexpr auto count = impl::member_count(); auto members = impl::collcet_members(object); @@ -256,11 +256,22 @@ constexpr void for_each(Object&& object, const Callback& callback) { template struct Record : Ts... { template - static void for_each(Object&& object, const Callback& callback) { - (clice::for_each(static_cast>(object), callback), ...); + static void foreach(Object&& object, const Callback& callback) { + (clice::refl::foreach(static_cast>(object), callback), ...); } }; +template +constexpr void walk(Object&& object, const Callback& callback) { + clice::refl::foreach(object, [&](std::string_view name, Field& field) { + if constexpr(Reflectable) { + walk(field, callback); + } else { + callback(name, field); + } + }); +} + template requires std::is_enum_v constexpr auto enum_name(T value) { @@ -271,4 +282,4 @@ constexpr auto enum_name(T value) { return names[static_cast(value)]; } -}; // namespace clice +}; // namespace clice::refl diff --git a/include/Support/URI.h b/include/Support/URI.h index f4c9e79c..10205029 100644 --- a/include/Support/URI.h +++ b/include/Support/URI.h @@ -23,7 +23,9 @@ public: /// Returns decoded body e.g. "/D41946" llvm::StringRef body() const { return m_body; } - static llvm::Expected parse(llvm::StringRef text); + static llvm::Expected parse(llvm::StringRef content); + + static std::string resolve(llvm::StringRef content); private: std::string m_scheme; diff --git a/src/Server/Config.cpp b/src/Server/Config.cpp new file mode 100644 index 00000000..52b90780 --- /dev/null +++ b/src/Server/Config.cpp @@ -0,0 +1,95 @@ +#include + +#include +#include +#include +#include + +namespace clice::config { + +struct Config { + ServerOption server; + FrontendOption frontend; +}; + +namespace { + +llvm::StringMap predefined = { + {"workplace", "" }, /// the directory of the workplace. + {"executable", "" }, /// the directory of the executable. + {"version", "0.0.1"}, /// the version of the clice. + {"llvm_version", "20" }, /// the version of dependent llvm. +}; + +/// global config instance. +Config config = {}; + +/// replace all predefined variables in the text. +std::string replace(std::string_view text) { + std::string result; + std::size_t pos = 0; + while((pos = text.find("${", pos)) != std::string::npos) { + result.append(text.substr(0, pos)); + + auto end = text.find('}', pos + 2); + if(end == std::string::npos) { + result.append(text.substr(pos)); + break; + } + + auto variable = text.substr(pos + 2, end - (pos + 2)); + + if(auto iter = predefined.find(variable); iter != predefined.end()) { + result.append(iter->second); + } else { + result.append(text.substr(pos, end - pos + 1)); + } + + text.remove_prefix(end + 1); + pos = 0; + } + + result.append(text); + return result; +} + +} // namespace + +int parse(int argc, const char** argv) { + predefined["executable"] = argv[0]; + + // FIXME: + // if(version) { + // llvm::outs() << "clice version: " << predefined.version << '\n'; + // return 0; + // } + // + // if(config_filepath.empty()) { + // llvm::errs() << "config file path is empty.\n"; + // return -1; + //} else { + // auto toml = toml::parse_file(config_filepath); + // auto frontend = toml["frontend"]; + // return 0; + //} + return 0; +} + +void initialize(std::string_view workplace) { + predefined["workplace"] = workplace; + + refl::walk(config, [&](std::string_view name, Field& field) { + if constexpr(std::is_same_v) { + llvm::outs() << "replace: " << field << '\n'; + field = replace(field); + llvm::outs() << "with: " << field << '\n'; + } + }); + return; +} + +ServerOption& server() { return config.server; } + +FrontendOption& frontend() { return config.frontend; } + +} // namespace clice::config diff --git a/src/Server/Option.cpp b/src/Server/Option.cpp deleted file mode 100644 index f34d33d1..00000000 --- a/src/Server/Option.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "toml++/toml.hpp" -#include "Server/Option.h" -#include - -namespace clice { - -// TODO: replace builtin variable in Setting -// e.g `{execute}` -> `execpath` - -void Option::parse(std::string_view workplace) { - llvm::SmallString<128> buffer; - this->workplace = workplace; - if(auto error = fs::real_path(argv[0], buffer)) { - // FIXME: handle error - } - binary = path::parent_path(buffer); - buffer.clear(); - path::append(buffer, path::parent_path(binary), "lib", "clang", clang_version); - resource_dictionary = buffer.str(); - - buffer.clear(); - path::append(buffer, workplace, "build"); - compile_commands_directory = buffer.str(); -} - -} // namespace clice diff --git a/src/Server/Server.cpp b/src/Server/Server.cpp index ac1816cf..9411dd4a 100644 --- a/src/Server/Server.cpp +++ b/src/Server/Server.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include namespace clice { @@ -143,19 +145,19 @@ void eventloop(uv_idle_t* handle) { } auto Server::initialize(protocol::InitializeParams params) -> protocol::InitializeResult { - - instance.option.parse("/home/ykiko/C++/test"); - + config::initialize(URI::resolve(params.workspaceFolders[0].uri)); return protocol::InitializeResult(); } int Server::run(int argc, const char** argv) { std::this_thread::sleep_for(std::chrono::seconds(2)); - option.argc = argc; - option.argv = argv; logger::init("console", argv[0]); + if(auto err = config::parse(argc, argv); err < 0) { + return err; + }; + unique_loop = uv_default_loop(); Socket::initialize("127.0.0.1", 50505); diff --git a/src/Support/URI.cpp b/src/Support/URI.cpp index 97b9ec66..9e6bde84 100644 --- a/src/Support/URI.cpp +++ b/src/Support/URI.cpp @@ -1,4 +1,5 @@ #include +#include namespace clice { @@ -61,4 +62,16 @@ llvm::Expected URI::parse(llvm::StringRef content) { return result; } +std::string URI::resolve(llvm::StringRef content) { + auto uri = parse(content); + if(!uri) { + std::terminate(); + } + llvm::SmallString<128> result; + if(auto err = fs::real_path(uri->body(), result)) { + std::terminate(); + } + return result.str().str(); +} + } // namespace clice