diff --git a/include/Basic/Location.h b/include/Basic/Location.h index 0971272c..7672cc25 100644 --- a/include/Basic/Location.h +++ b/include/Basic/Location.h @@ -41,7 +41,7 @@ struct TextEdit { struct Location { DocumentUri uri; - + Range range; }; diff --git a/include/Compiler/Command.h b/include/Compiler/Command.h deleted file mode 100644 index 1f3453f2..00000000 --- a/include/Compiler/Command.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/Allocator.h" -#include "clang/Tooling/CompilationDatabase.h" - -namespace clice { - -class CommandManager { -public: - /// FIXME: support multiple compilation databases. - CommandManager(llvm::StringRef path); - - llvm::ArrayRef lookup(llvm::StringRef file); - - // TODO: add a function for scaning module dependencies. - - struct Data { - std::uint64_t index; - std::uint64_t size; - }; - -private: - std::vector args; - llvm::BumpPtrAllocator allocator; - - llvm::StringMap cache; - - /// module name -> file path - llvm::StringMap moduleMap; - - std::unique_ptr CDB; -}; - -} // namespace clice diff --git a/include/Server/Command.h b/include/Server/Command.h new file mode 100644 index 00000000..ed889637 --- /dev/null +++ b/include/Server/Command.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Support/Support.h" +#include "clang/Tooling/CompilationDatabase.h" + +namespace clice { + +class CommandManager { +public: + void update(llvm::StringRef dir); + + std::vector lookup(llvm::StringRef file); +private: + llvm::StringMap> CDBs; +}; + +} // namespace clice diff --git a/include/Server/Scheduler.h b/include/Server/Scheduler.h index 5aad7502..d7e8d300 100644 --- a/include/Server/Scheduler.h +++ b/include/Server/Scheduler.h @@ -3,7 +3,9 @@ #include #include "Server/Async.h" +#include "Server/Command.h" #include "Server/Protocol.h" +#include "Server/Trace.h" #include "Compiler/Compiler.h" namespace clice { @@ -42,9 +44,9 @@ struct llvm::DenseMapInfo { }; namespace clice { + struct File2 { bool isIdle = true; - bool isHeader = false; llvm::DenseMap contexts; }; @@ -123,6 +125,7 @@ public: private: llvm::StringMap pchs; llvm::StringMap files; + CommandManager cmdMgr; }; } // namespace clice diff --git a/include/Server/Trace.h b/include/Server/Trace.h index 58710e48..e595fb36 100644 --- a/include/Server/Trace.h +++ b/include/Server/Trace.h @@ -1,8 +1,16 @@ #pragma once +#include + namespace clice { +struct Tracer { + std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); + auto duration() { + return std::chrono::duration_cast( + std::chrono::system_clock::now() - start); + } +}; - -} \ No newline at end of file +} // namespace clice diff --git a/src/Compiler/Command.cpp b/src/Compiler/Command.cpp deleted file mode 100644 index 8a28ee93..00000000 --- a/src/Compiler/Command.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "Compiler/Command.h" -#include "clang/Tooling/DependencyScanning/DependencyScanningTool.h" - -namespace clice { - -namespace clice {} - -CommandManager::CommandManager(llvm::StringRef path) { - std::string error; - CDB = clang::tooling::CompilationDatabase::loadFromDirectory(path, error); - if(!CDB) { - llvm::errs() << "Failed to load compilation database: " << error << "\n"; - return; - } - - /// FIXME: module support - // using namespace clang::tooling::dependencies; - // DependencyScanningService service(ScanningMode::DependencyDirectivesScan, - // ScanningOutputFormat::P1689); - // DependencyScanningTool tool(service); - // - // for(auto& command: CDB->getAllCompileCommands()) { - // auto rule = tool.getP1689ModuleDependencyFile(command, command.Directory); - // if(rule) { - // moduleMap[rule->Provides->ModuleName] = command.Filename; - // } else { - // llvm::errs() << std::format("Failed to scan module dependencies for {}, Because: - // {}\n", - // command.Filename, - // llvm::toString(rule.takeError())); - // } - //} -} - -llvm::ArrayRef CommandManager::lookup(llvm::StringRef file) { - auto iter = cache.find(file); - if(iter != cache.end()) { - return llvm::ArrayRef(args).slice(iter->second.index, iter->second.size); - } - - auto commands = CDB->getCompileCommands(file); - assert(commands.size() == 1); - auto& command = commands[0]; - - std::size_t index = args.size(); - for(auto& arg: command.CommandLine) { - auto data = allocator.Allocate(arg.size() + 1); - std::copy(arg.begin(), arg.end(), data); - data[arg.size()] = '\0'; - args.push_back(data); - } - - cache.try_emplace(file, Data{index, args.size() - index}); - return llvm::ArrayRef(args).slice(index, args.size() - index); -} - -} // namespace clice diff --git a/src/Server/Command.cpp b/src/Server/Command.cpp new file mode 100644 index 00000000..e652c451 --- /dev/null +++ b/src/Server/Command.cpp @@ -0,0 +1,49 @@ +#include "Server/Command.h" +#include "Server/Config.h" +#include "Server/Logger.h" + +namespace clice { + +void CommandManager::update(llvm::StringRef dir) { + std::string error; + auto CDB = clang::tooling::CompilationDatabase::loadFromDirectory(dir, error); + if(!CDB) { + log::fatal("Failed to load compilation database from {0}, because {1}", dir, error); + return; + } + + CDBs.try_emplace(dir, std::move(CDB)); + log::info("Successfully loaded compilation database from {0}.", dir); +} + +std::vector CommandManager::lookup(llvm::StringRef file) { + std::vector result; + for(const auto& [dir, CDB]: CDBs) { + auto commands = CDB->getCompileCommands(file); + if(commands.empty()) { + continue; + } + + auto& args = commands[0].CommandLine; + for(auto iter = args.begin(); iter != args.end(); ++iter) { + if(iter->starts_with("-o")) { + iter++; + continue; + } else if(iter->starts_with("-c")) { + continue; + } else if(*iter == "--") { + continue; + } + + result.push_back(std::move(*iter)); + } + break; + } + + result.push_back("-resource-dir="); + result.back() += config::frontend().resource_dictionary; + + return result; +} + +} // namespace clice diff --git a/src/Server/Scheduler.cpp b/src/Server/Scheduler.cpp index eb60edaf..747e2cb4 100644 --- a/src/Server/Scheduler.cpp +++ b/src/Server/Scheduler.cpp @@ -4,15 +4,6 @@ namespace clice { -struct Tracer { - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - - auto duration() { - return std::chrono::duration_cast( - std::chrono::system_clock::now() - start); - } -}; - async::promise Scheduler::updatePCH(llvm::StringRef filepath, llvm::StringRef content, llvm::ArrayRef args) { @@ -80,21 +71,31 @@ async::promise Scheduler::buildAST(llvm::StringRef filepath, llvm::StringR files[filepath].isIdle = false; + static bool initCmd = false; + if(!initCmd) { + cmdMgr.update(config::frontend().compile_commands_directorys[0]); + initCmd = true; + } + /// FIXME: lookup from CDB file and adjust and remove unnecessary arguments.1 - llvm::SmallVector args = { - "clang++", - "-std=c++20", - path.c_str(), - "-resource-dir", - "/home/ykiko/C++/clice2/build/lib/clang/20", - }; + auto cmd = cmdMgr.lookup(filepath); + llvm::SmallVector args; + for(auto& arg: cmd) { + args.push_back(arg.c_str()); + } /// through arguments to judge is it a module. bool isModule = false; co_await (isModule ? updatePCM() : updatePCH(filepath, content, args)); Tracer tracer; - log::info("Start building AST for {0}", filepath); + + llvm::SmallString<128> command; + llvm::raw_svector_ostream os(command); + for(auto arg: args) { + os << arg << " "; + } + log::info("Start building AST for {0}, command: [{1}]", filepath, command.str()); CompliationParams params; params.path = path; diff --git a/src/Server/Server.cpp b/src/Server/Server.cpp index fae2330e..d4ed5f94 100644 --- a/src/Server/Server.cpp +++ b/src/Server/Server.cpp @@ -31,18 +31,21 @@ int Server::run(int argc, const char** argv) { auto params = object->get("params"); if(auto id = object->get("id")) { if(auto iter = requests.find(name); iter != requests.end()) { - log::info("Request: {0}", name.str()); + auto tracer = Tracer(); + log::info("Receive request: {0}", name); co_await iter->second(std::move(*id), params ? std::move(*params) : json::Value(nullptr)); + log::info("Request {0} is done, elapsed {1}", name, tracer.duration()); + } else { - log::warn("Unknown request: {0}", name.str()); + log::warn("Unknown request: {0}", name); } } else { if(auto iter = notifications.find(name); iter != notifications.end()) { - log::info("Notification: {0}", name.str()); + log::info("Notification: {0}", name); co_await iter->second(params ? std::move(*params) : json::Value(nullptr)); } else { - log::warn("Unknown notification: {0}", name.str()); + log::warn("Unknown notification: {0}", name); } } } diff --git a/unittests/Compiler/Command.cpp b/unittests/Compiler/Command.cpp index 03f63457..74aee129 100644 --- a/unittests/Compiler/Command.cpp +++ b/unittests/Compiler/Command.cpp @@ -1,15 +1,16 @@ #include "../Test.h" -#include "Compiler/Command.h" -namespace { - -TEST(clice, CommandManager) { - clice::CommandManager manager("/home/ykiko/C++/clice2/tests"); - auto args = manager.lookup("another_file.cpp"); - for(auto arg: args) { - llvm::outs() << arg << " "; - } - llvm::outs() << "\n"; -} - -} // namespace +// #include "Compiler/Command.h" +// +// namespace { +// +// TEST(clice, CommandManager) { +// clice::CommandManager manager("/home/ykiko/C++/clice2/tests"); +// auto args = manager.lookup("another_file.cpp"); +// for(auto arg: args) { +// llvm::outs() << arg << " "; +// } +// llvm::outs() << "\n"; +// } +// +// } // namespace