diff --git a/.sh b/.sh index 3ce53603..8e384777 100755 --- a/.sh +++ b/.sh @@ -2,5 +2,6 @@ cmake -B build -G Ninja \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_C_COMPILER=clang \ --DCMAKE_BUILD_TYPE=Debug +-DCMAKE_BUILD_TYPE=Debug \ +-DCLICE_TEST=ON cmake --build build diff --git a/.vscode/launch.json b/.vscode/launch.json index ad1279b8..1bbdc0e5 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,10 +7,16 @@ { "type": "lldb", "request": "launch", - "name": "Debug", + "name": "Launch", "program": "${workspaceFolder}/build/clice", "args": [], "cwd": "${workspaceFolder}" - } + }, + //{ + // "type": "lldb", + // "request": "attach", + // "name": "Attach", + // "program": "${workspaceFolder}/build/clice" + //}, ] } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 49b0012e..6445610a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,43 +3,37 @@ project(clice) set(CMAKE_CXX_STANDARD 23) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_RELEASE} -g -O0 -fno-rtti ") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_RELEASE} -g -O0 -fno-rtti") set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/external/llvm/lib/cmake") find_package(LLVM REQUIRED CONFIG) find_package(Clang REQUIRED CONFIG) -separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) -add_definitions(${LLVM_DEFINITIONS_LIST}) +message(STATUS "LLVM_INCLUDE_DIRS: ${LLVM_INCLUDE_DIRS}") set(PCH_HEADER "${CMAKE_SOURCE_DIR}/include/Clang/Clang.h") set(JSON_BuildTests OFF CACHE INTERNAL "") -add_subdirectory(external/json) -add_subdirectory(external/libuv) -add_subdirectory(external/spdlog) +add_subdirectory("${CMAKE_SOURCE_DIR}/external/json") +add_subdirectory("${CMAKE_SOURCE_DIR}/external/libuv") +add_subdirectory("${CMAKE_SOURCE_DIR}/external/spdlog") -file(GLOB_RECURSE SOURCES src/*.cpp) -add_executable(clice ${SOURCES}) +set(INCLUDE_DIRS + "${CMAKE_SOURCE_DIR}/include" + "${CMAKE_SOURCE_DIR}/external/json/include" + "${CMAKE_SOURCE_DIR}/external/libuv/include" + "${CMAKE_SOURCE_DIR}/external/spdlog/include" + "${CMAKE_SOURCE_DIR}/external/llvm/include" + "${CMAKE_SOURCE_DIR}/external/llvm/tools/clang/include" +) -target_include_directories(clice PRIVATE "${CMAKE_SOURCE_DIR}/include") -target_include_directories(clice PRIVATE ${LLVM_INCLUDE_DIRS}) -target_include_directories(clice PRIVATE ${CLANG_INCLUDE_DIRS}) - -llvm_map_components_to_libnames(llvm_libs support core irreader) - -message(STATUS "LLVM_INCLUDE_DIRS: ${LLVM_INCLUDE_DIRS}") -message(STATUS "LLVM_LIBS: ${llvm_libs}") - -target_precompile_headers(clice PRIVATE ${PCH_HEADER}) - -target_link_libraries(clice PRIVATE nlohmann_json::nlohmann_json) -target_link_libraries(clice PRIVATE uv) -target_link_libraries(clice PRIVATE spdlog::spdlog) - -target_link_libraries(clice PRIVATE ${llvm_libs}) -target_link_libraries(clice PRIVATE - LLVMTargetParser +set(LINK_LIBS + nlohmann_json::nlohmann_json + uv + spdlog::spdlog + LLVMCore + LLVMSupport + LLVMIRReader clangAST clangASTMatchers clangBasic @@ -55,4 +49,27 @@ target_link_libraries(clice PRIVATE clangToolingInclusions clangToolingInclusionsStdlib clangToolingSyntax -) \ No newline at end of file +) + +file(GLOB_RECURSE SOURCES "${CMAKE_SOURCE_DIR}/src/*.cpp") +list(REMOVE_ITEM SOURCES "${CMAKE_SOURCE_DIR}/src/main.cpp") + +add_executable(clice src/main.cpp ${SOURCES}) +target_precompile_headers(clice PRIVATE ${PCH_HEADER}) +target_include_directories(clice PRIVATE ${INCLUDE_DIRS}) +target_link_libraries(clice PRIVATE ${LINK_LIBS}) + +if(CLICE_TEST) + file(GLOB_RECURSE TEST_SOURCES "${CMAKE_SOURCE_DIR}/tests/*.cpp") + include_directories(${CMAKE_SOURCE_DIR}/external/googletest/googletest/include) + add_subdirectory(external/googletest) + + if(WIN32) + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + endif() + + add_executable(clice_test ${SOURCES} ${TEST_SOURCES}) + target_precompile_headers(clice_test PRIVATE ${PCH_HEADER}) + target_include_directories(clice_test PRIVATE ${INCLUDE_DIRS}) + target_link_libraries(clice_test PRIVATE ${LINK_LIBS} GTest::gtest_main) +endif() \ No newline at end of file diff --git a/include/Clang/CompileDatabase.h b/include/Clang/CompileDatabase.h index 8cde84b1..2e294566 100644 --- a/include/Clang/CompileDatabase.h +++ b/include/Clang/CompileDatabase.h @@ -14,14 +14,7 @@ public: return instance; } - void load(std::string_view path) { - std::string error; - database = clang::tooling::CompilationDatabase::loadFromDirectory(path, error); - if(!database) { - llvm::errs() << "Failed to load compilation database. " << error << "\n"; - std::terminate(); - } - } + void load(std::string_view path); auto lookup(std::string_view path) { auto commands = database->getCompileCommands(path); diff --git a/include/Clang/ParsedAST.h b/include/Clang/ParsedAST.h index 7419df07..ec026b46 100644 --- a/include/Clang/ParsedAST.h +++ b/include/Clang/ParsedAST.h @@ -39,7 +39,7 @@ public: static std::unique_ptr build(std::string_view path, const std::shared_ptr& invocation, - const std::shared_ptr& preamble); + const Preamble& preamble); auto& Tokens() { return tokens.value; } diff --git a/include/LSP/Server.h b/include/LSP/Server.h index 6bc8d2b9..adce4f24 100644 --- a/include/LSP/Server.h +++ b/include/LSP/Server.h @@ -17,7 +17,7 @@ class Server { std::map methods; public: - int run(); + int run(int argc, char** argv); int exit(); void handle_message(std::string_view message); diff --git a/include/LSP/Setting.h b/include/LSP/Setting.h new file mode 100644 index 00000000..95045f10 --- /dev/null +++ b/include/LSP/Setting.h @@ -0,0 +1,16 @@ +#include + +namespace clice { + +/// Settings for the LSP server +struct Setting { + /// compile_commands.json file path + std::string compile_commands_dictionary = "/build"; + /// mode of the server: ["pipe", "socket", "index"] + std::string mode = "pipe"; +}; + +/// global setting instance +inline Setting setting = {}; + +} // namespace clice diff --git a/include/Support/Async.h b/include/Support/Async.h index 3d75b228..9ce65467 100644 --- a/include/Support/Async.h +++ b/include/Support/Async.h @@ -128,11 +128,11 @@ public: Task(handle_type handle) : handle(handle) {} - ~Task() { - if(handle && !handle.done()) { - handle.destroy(); - } - } + //~Task() { + // if(handle && !handle.done()) { + // handle.destroy(); + // } + //} void resume() { handle.resume(); } diff --git a/src/Clang/CodeCompletion.cpp b/src/Clang/CodeCompletion.cpp index 3fd2d244..db1696c6 100644 --- a/src/Clang/CodeCompletion.cpp +++ b/src/Clang/CodeCompletion.cpp @@ -7,228 +7,213 @@ std::unique_ptr datebase; class CodeCompleteConsumer : public clang::CodeCompleteConsumer { public: - std::shared_ptr Allocator; - clang::CodeCompletionTUInfo CCTUInfo; + std::shared_ptr Allocator; + clang::CodeCompletionTUInfo CCTUInfo; - CodeCompleteConsumer() - : clang::CodeCompleteConsumer(clang::CodeCompleteOptions{}), - Allocator(std::make_shared()), - CCTUInfo(Allocator) {} + CodeCompleteConsumer() : + clang::CodeCompleteConsumer(clang::CodeCompleteOptions{}), + Allocator(std::make_shared()), CCTUInfo(Allocator) {} - void ProcessCodeCompleteResults(clang::Sema &S, - clang::CodeCompletionContext Context, - clang::CodeCompletionResult *Results, - unsigned NumResults) override { + void ProcessCodeCompleteResults(clang::Sema& S, + clang::CodeCompletionContext Context, + clang::CodeCompletionResult* Results, + unsigned NumResults) override { - auto type = Context.getBaseType(); - type.dump(); - if (type->isDependentType()) { - const auto dependentType = type->getAs(); - // TODO: improve + auto type = Context.getBaseType(); + type.dump(); + if(type->isDependentType()) { + const auto dependentType = type->getAs(); + // TODO: improve + } + + for(unsigned i = 0; i < NumResults; ++i) { + clang::CodeCompletionResult& Result = Results[i]; + + switch(Result.Kind) { + case clang::CodeCompletionResult::RK_Declaration: { + llvm::outs() << "Declaration: "; + llvm::outs() << Result.Declaration->getNameAsString() << "\n"; + break; + } + + case clang::CodeCompletionResult::RK_Keyword: { + llvm::outs() << "Keyword: "; + llvm::outs() << Result.Keyword << "\n"; + break; + } + + case clang::CodeCompletionResult::RK_Macro: { + llvm::outs() << "Macro: "; + llvm::outs() << Result.Macro->getName() << "\n"; + break; + } + + case clang::CodeCompletionResult::RK_Pattern: { + llvm::outs() << "Pattern: "; + llvm::outs() << Result.Pattern->getAsString() << "\n"; + break; + } + } + } } - for (unsigned i = 0; i < NumResults; ++i) { - clang::CodeCompletionResult &Result = Results[i]; + virtual clang::CodeCompletionAllocator& getAllocator() override { return *Allocator; } - switch (Result.Kind) { - case clang::CodeCompletionResult::RK_Declaration: { - llvm::outs() << "Declaration: "; - llvm::outs() << Result.Declaration->getNameAsString() << "\n"; - break; - } - - case clang::CodeCompletionResult::RK_Keyword: { - llvm::outs() << "Keyword: "; - llvm::outs() << Result.Keyword << "\n"; - break; - } - - case clang::CodeCompletionResult::RK_Macro: { - llvm::outs() << "Macro: "; - llvm::outs() << Result.Macro->getName() << "\n"; - break; - } - - case clang::CodeCompletionResult::RK_Pattern: { - llvm::outs() << "Pattern: "; - llvm::outs() << Result.Pattern->getAsString() << "\n"; - break; - } - } - } - } - - virtual clang::CodeCompletionAllocator &getAllocator() override { - return *Allocator; - } - - virtual clang::CodeCompletionTUInfo &getCodeCompletionTUInfo() override { - return CCTUInfo; - } + virtual clang::CodeCompletionTUInfo& getCodeCompletionTUInfo() override { return CCTUInfo; } }; -auto GetCommands(std::string_view path, std::string_view compile_commands_path) - -> std::vector { - if (!datebase) { - std::string error; - datebase = tooling::CompilationDatabase::loadFromDirectory( - compile_commands_path, error); +auto GetCommands(std::string_view path, + std::string_view compile_commands_path) -> std::vector { + if(!datebase) { + std::string error; + datebase = tooling::CompilationDatabase::loadFromDirectory(compile_commands_path, error); - if (!datebase) { - llvm::errs() << "Failed to load compilation database. " << error << "\n"; - std::terminate(); + if(!datebase) { + llvm::errs() << "Failed to load compilation database. " << error << "\n"; + std::terminate(); + } } - } - return datebase->getCompileCommands(path); + return datebase->getCompileCommands(path); } auto createDiagnostic() { - clang::DiagnosticOptions DiagOpts; + clang::DiagnosticOptions DiagOpts; - clang::TextDiagnosticPrinter *DiagClient = - new clang::TextDiagnosticPrinter(llvm::errs(), &DiagOpts); + clang::TextDiagnosticPrinter* DiagClient = new clang::TextDiagnosticPrinter(llvm::errs(), &DiagOpts); - llvm::IntrusiveRefCntPtr DiagID = - new clang::DiagnosticIDs(); + llvm::IntrusiveRefCntPtr DiagID = new clang::DiagnosticIDs(); - return clang::DiagnosticsEngine(DiagID, &DiagOpts, DiagClient); + return clang::DiagnosticsEngine(DiagID, &DiagOpts, DiagClient); } -auto createInvocation(std::string_view path, - std::string_view compile_commands) { - auto commands = GetCommands(path, compile_commands); - llvm::ArrayRef command = commands[0].CommandLine; +auto createInvocation(std::string_view path, std::string_view compile_commands) { + auto commands = GetCommands(path, compile_commands); + llvm::ArrayRef command = commands[0].CommandLine; - std::vector args = {command.front().c_str(), "-Xclang", - "-no-round-trip-args"}; + std::vector args = {command.front().c_str(), "-Xclang", "-no-round-trip-args"}; - for (auto &arg : command.drop_front()) { - args.push_back(arg.c_str()); - } + for(auto& arg: command.drop_front()) { + args.push_back(arg.c_str()); + } - static auto engine = createDiagnostic(); - auto invocation = clang::createInvocation(args); + static auto engine = createDiagnostic(); + auto invocation = clang::createInvocation(args); - // set input file - auto &inputs = invocation->getFrontendOpts().Inputs; - inputs.push_back( - clang::FrontendInputFile(path, clang::InputKind{clang::Language::CXX})); + // set input file + auto& inputs = invocation->getFrontendOpts().Inputs; + inputs.push_back(clang::FrontendInputFile(path, clang::InputKind{clang::Language::CXX})); - // set code completion - auto &completionAt = invocation->getFrontendOpts().CodeCompletionAt; - completionAt.FileName = path.data(); - completionAt.Line = line; - completionAt.Column = column; + // set code completion + auto& completionAt = invocation->getFrontendOpts().CodeCompletionAt; + completionAt.FileName = path.data(); + completionAt.Line = line; + completionAt.Column = column; - return invocation; + return invocation; } struct DiagnosticConsumer : clang::DiagnosticConsumer { - void BeginSourceFile(const clang::LangOptions &LangOpts, - const clang::Preprocessor *PP) override {} + void BeginSourceFile(const clang::LangOptions& LangOpts, const clang::Preprocessor* PP) override {} - void EndSourceFile() override {} + void EndSourceFile() override {} - void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, - const clang::Diagnostic &Info) override { - if (DiagLevel == clang::DiagnosticsEngine::Level::Note) { - return; + void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic& Info) override { + if(DiagLevel == clang::DiagnosticsEngine::Level::Note) { + return; + } + + llvm::errs() << "Diagnostic: "; + llvm::SmallVector buf; + Info.FormatDiagnostic(buf); + llvm::errs().write(buf.data(), buf.size()); + llvm::errs() << "\n"; } - - llvm::errs() << "Diagnostic: "; - llvm::SmallVector buf; - Info.FormatDiagnostic(buf); - llvm::errs().write(buf.data(), buf.size()); - llvm::errs() << "\n"; - } }; auto createInstance(std::string_view path, std::string_view compile_commands) { - std::unique_ptr instance = - std::make_unique(); + std::unique_ptr instance = std::make_unique(); - auto invocation = createInvocation(path, compile_commands); - instance->setInvocation( - std::make_shared(*invocation)); + auto invocation = createInvocation(path, compile_commands); + instance->setInvocation(std::make_shared(*invocation)); - instance->createDiagnostics(new DiagnosticConsumer(), true); + instance->createDiagnostics(new DiagnosticConsumer(), true); - if (!instance->createTarget()) { - llvm::errs() << "Failed to create target\n"; - std::terminate(); - } + if(!instance->createTarget()) { + llvm::errs() << "Failed to create target\n"; + std::terminate(); + } - if (auto manager = instance->createFileManager()) { - instance->createSourceManager(*manager); - } else { - llvm::errs() << "Failed to create file manager\n"; - std::terminate(); - } + if(auto manager = instance->createFileManager()) { + instance->createSourceManager(*manager); + } else { + llvm::errs() << "Failed to create file manager\n"; + std::terminate(); + } - instance->createPreprocessor(clang::TranslationUnitKind::TU_Complete); + instance->createPreprocessor(clang::TranslationUnitKind::TU_Complete); - instance->createASTContext(); + instance->createASTContext(); - instance->setCodeCompletionConsumer(new CodeCompleteConsumer()); + instance->setCodeCompletionConsumer(new CodeCompleteConsumer()); - return instance; + return instance; } class AST { - clang::FrontendAction *action; - clang::CompilerInstance *instance; + clang::FrontendAction* action; + clang::CompilerInstance* instance; private: - AST() = default; + AST() = default; public: - AST(const AST &) = delete; + AST(const AST&) = delete; - AST(AST &&other) noexcept : action(other.action), instance(other.instance) { - other.action = nullptr; - other.instance = nullptr; - } - - ~AST() { - if (action) { - action->EndSourceFile(); - delete action; - delete instance; - } - } - - static AST create(std::string_view path, std::string_view compile_commands) { - AST ast; - - ast.instance = createInstance(path, compile_commands).release(); - ast.action = new clang::SyntaxOnlyAction(); - - const auto &input = ast.instance->getFrontendOpts().Inputs[0]; - - if (!ast.action->BeginSourceFile(*ast.instance, input)) { - llvm::errs() << "Failed to begin source file\n"; - std::terminate(); + AST(AST&& other) noexcept : action(other.action), instance(other.instance) { + other.action = nullptr; + other.instance = nullptr; } - if (llvm::Error error = ast.action->Execute()) { - llvm::errs() << "Failed to execute action: " << error << "\n"; - std::terminate(); + ~AST() { + if(action) { + action->EndSourceFile(); + delete action; + delete instance; + } } - return ast; - } + static AST create(std::string_view path, std::string_view compile_commands) { + AST ast; - auto &getASTContext() { return instance->getASTContext(); } + ast.instance = createInstance(path, compile_commands).release(); + ast.action = new clang::SyntaxOnlyAction(); - auto &getSourceManager() { return instance->getSourceManager(); } + const auto& input = ast.instance->getFrontendOpts().Inputs[0]; + + if(!ast.action->BeginSourceFile(*ast.instance, input)) { + llvm::errs() << "Failed to begin source file\n"; + std::terminate(); + } + + if(llvm::Error error = ast.action->Execute()) { + llvm::errs() << "Failed to execute action: " << error << "\n"; + std::terminate(); + } + + return ast; + } + + auto& getASTContext() { return instance->getASTContext(); } + + auto& getSourceManager() { return instance->getSourceManager(); } }; struct Visitor : clang::RecursiveASTVisitor { - bool VisitTranslationUnitDecl(clang::TranslationUnitDecl *tu) { - tu->dump(); - return true; - } + bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* tu) { + tu->dump(); + return true; + } - bool VisitCXXMethodDecl(clang::CXXMethodDecl *decl) { return true; } + bool VisitCXXMethodDecl(clang::CXXMethodDecl* decl) { return true; } }; diff --git a/src/Clang/CompileDatabase.cpp b/src/Clang/CompileDatabase.cpp new file mode 100644 index 00000000..28a9016c --- /dev/null +++ b/src/Clang/CompileDatabase.cpp @@ -0,0 +1,15 @@ + +#include +#include + +namespace clice { + +void CompileDatabase::load(std::string_view path) { + std::string error; + database = clang::tooling::CompilationDatabase::loadFromDirectory(path, error); + if(!database) { + logger::error("failed to load compilation database: {}", error); + } +} + +} // namespace clice diff --git a/src/Clang/ParsedAST.cpp b/src/Clang/ParsedAST.cpp index 4b3cfa48..b4715be0 100644 --- a/src/Clang/ParsedAST.cpp +++ b/src/Clang/ParsedAST.cpp @@ -1,14 +1,23 @@ #include +#include namespace clice { -std::unique_ptr ParsedAST::build(std::string_view path, std::string_view content){ - +std::unique_ptr ParsedAST::build(std::string_view path, std::string_view content) { + auto command = CompileDatabase::instance().lookup(path); + std::shared_ptr invocation = clang::createInvocation(command); + + auto& inputs = invocation->getFrontendOpts().Inputs; + inputs.push_back(clang::FrontendInputFile(path, clang::InputKind{clang::Language::CXX})); + + auto preamble = Preamble::build(path, content, *invocation); + + return build(path, invocation, preamble); } std::unique_ptr ParsedAST::build(std::string_view path, const std::shared_ptr& invocation, - const std::shared_ptr& preamble) { + const Preamble& preamble) { auto AST = new ParsedAST(); AST->path = path; @@ -18,15 +27,13 @@ std::unique_ptr ParsedAST::build(std::string_view path, instance.createDiagnostics(); if(!instance.createTarget()) { - llvm::errs() << "Failed to create target\n"; - std::terminate(); + logger::error("Failed to create target"); } if(auto manager = instance.createFileManager()) { instance.createSourceManager(*manager); } else { - llvm::errs() << "Failed to create file manager\n"; - std::terminate(); + logger::error("Failed to create file manager"); } instance.createPreprocessor(clang::TranslationUnitKind::TU_Complete); @@ -38,15 +45,13 @@ std::unique_ptr ParsedAST::build(std::string_view path, auto& action = AST->action; if(!action.BeginSourceFile(instance, input)) { - llvm::errs() << "Failed to begin source file\n"; - std::terminate(); + logger::error("Failed to begin source file"); } clang::syntax::TokenCollector collector = {instance.getPreprocessor()}; if(llvm::Error error = action.Execute()) { - llvm::errs() << "Failed to execute action: " << error << "\n"; - std::terminate(); + logger::error("Failed to execute action: {0}", llvm::errorToErrorCode(std::move(error)).message()); } AST->tokens.construct(std::move(collector).consume()); diff --git a/src/LSP/Scheduler.cpp b/src/LSP/Scheduler.cpp index ad724399..11a00998 100644 --- a/src/LSP/Scheduler.cpp +++ b/src/LSP/Scheduler.cpp @@ -1,14 +1,17 @@ #include "LSP/Scheduler.h" #include "Clang/ParsedAST.h" +#include "Support/Logger.h" namespace clice { Task Scheduler::update(std::string_view name, std::string_view content) { auto ast = co_await async([=] { + logger::info("start building AST for {}", name); return ParsedAST::build(name, content); }); parsedASTs[name] = std::move(ast); + logger::info("finished building AST for {}", name); } } // namespace clice diff --git a/src/LSP/Server.cpp b/src/LSP/Server.cpp index c89f6a94..1d99fb12 100644 --- a/src/LSP/Server.cpp +++ b/src/LSP/Server.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -9,12 +10,29 @@ namespace clice { Server server; -int Server::run() { +int Server::run(int argc, char** argv) { + assert(argc == 2); + logger::init(argv[0]); + + logger::info("reading settings..."); + setting = deserialize(json::parse(argv[1])); + logger::info("settings: {}", argv[1]); + loop = uv_default_loop(); - transport = std::make_unique(); + if(setting.mode == "pipe") { + transport = std::make_unique(); + } else if(setting.mode == "socket") { + // transport = std::make_unique(); + } else if(setting.mode == "index") { + transport = {}; + } else { + logger::error("invalid mode: {}", setting.mode); + return 1; + } // start the event loop + logger::info("starting the server..."); return uv_run(loop, UV_RUN_DEFAULT); } @@ -40,6 +58,8 @@ void Server::handle_message(std::string_view message) { // didOpen(); auto params = deserialize(input["params"]); logger::info("serialize successfully: {}", serialize(params).dump()); + auto task = didOpen(params); + task.resume(); } } catch(std::exception& e) { logger::error("failed to parse JSON: {}", e.what()); @@ -47,4 +67,10 @@ void Server::handle_message(std::string_view message) { } } +Task Server::didOpen(const DidOpenTextDocumentParams& params) { + logger::info("textDocument/didOpen: {}", params.textDocument.uri); + auto& textDocument = params.textDocument; + co_await scheduler.update(textDocument.uri, textDocument.text); +} + } // namespace clice diff --git a/src/main.cpp b/src/main.cpp index 3d480ed4..246852ed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,38 +1,6 @@ #include -#include -#include -#include -#include - -using namespace clice; - -Task foo() { - int n = 0; - int x = co_await async([]() -> int { - logger::info("Sleeping for 10 seconds..."); - std::this_thread::sleep_for(std::chrono::seconds(10)); - return 10; - }); - co_return x; -} - -Task bar() { - int x = co_await foo(); - logger::info("x = {}", x); - co_return; -} int main(int argc, char** argv) { - try { - clice::logger::init(argv[0]); - auto& server = clice::server; - clice::logger::info("Starting server..."); - auto c = bar(); - c.resume(); - server.run(); - } catch(std::exception& e) { - clice::logger::error("Failed to start server: {}", e.what()); - return 1; - } - return 0; + using namespace clice; + return server.run(argc, argv); } diff --git a/tests/Clang/Preamble.cpp b/tests/Clang/Preamble.cpp new file mode 100644 index 00000000..089e6d97 --- /dev/null +++ b/tests/Clang/Preamble.cpp @@ -0,0 +1,6 @@ +#include + +TEST(Preamble, Include) { + EXPECT_EQ(1, 1); + EXPECT_EQ(1 + 1, 2); +} diff --git a/vscode-clice/package.json b/vscode-clice/package.json index 43f972f8..461b0651 100644 --- a/vscode-clice/package.json +++ b/vscode-clice/package.json @@ -19,6 +19,11 @@ "properties": { "clice-client.trace.server": { "default": "verbose" + }, + "clice.compile_commands_dir": { + "type": "string", + "default": "/build", + "description": "The directory where compile_commands.json is located" } } } diff --git a/vscode-clice/src/Setting.ts b/vscode-clice/src/Setting.ts new file mode 100644 index 00000000..a4529365 --- /dev/null +++ b/vscode-clice/src/Setting.ts @@ -0,0 +1,12 @@ +import * as vscode from 'vscode'; + +interface Setting { + compile_commands_dir: string; +} + +export function readSetting(): Setting { + const config = vscode.workspace.getConfiguration('clice'); + return { + compile_commands_dir: config.get('compile_commands_dir') || '' + }; +} \ No newline at end of file diff --git a/vscode-clice/src/extension.ts b/vscode-clice/src/extension.ts index 0f07970a..617c8f4a 100644 --- a/vscode-clice/src/extension.ts +++ b/vscode-clice/src/extension.ts @@ -1,4 +1,5 @@ import * as path from 'path'; +import { readSetting } from './Setting'; import { workspace, window, ExtensionContext, OutputChannel } from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, Trace, TransportKind } from 'vscode-languageclient/node'; @@ -11,10 +12,11 @@ export async function activate(context: ExtensionContext) { let serverPath = "/home/ykiko/Project/C++/clice/build/clice"; - const serverOptions: ServerOptions = { - run: { command: serverPath, args: [] }, - debug: { command: serverPath, args: ['--inspect=6009'] } + let settings = JSON.stringify(readSetting()); + const serverOptions: ServerOptions = { + run: { command: serverPath, args: [settings] }, + debug: { command: serverPath, args: [settings] } }; const clientOptions: LanguageClientOptions = {