diff --git a/CMakeLists.txt b/CMakeLists.txt index 7768bd82..d73ce893 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,7 @@ target_sources(ccls PRIVATE src/clang_translation_unit.cc src/clang_utils.cc src/command_line.cc + src/config.cc src/diagnostics_engine.cc src/file_consumer.cc src/file_contents.cc @@ -209,7 +210,6 @@ target_sources(ccls PRIVATE src/timestamp_manager.cc src/type_printer.cc src/utils.cc - src/work_thread.cc src/working_files.cc) target_sources(ccls PRIVATE @@ -217,7 +217,6 @@ target_sources(ccls PRIVATE src/messages/ccls_call_hierarchy.cc src/messages/ccls_callers.cc src/messages/ccls_derived.cc - src/messages/ccls_did_view.cc src/messages/ccls_file_info.cc src/messages/ccls_freshen_index.cc src/messages/ccls_index_file.cc @@ -225,7 +224,6 @@ target_sources(ccls PRIVATE src/messages/ccls_member_hierarchy.cc src/messages/ccls_random.cc src/messages/ccls_vars.cc - src/messages/ccls_wait.cc src/messages/exit.cc src/messages/initialize.cc src/messages/shutdown.cc diff --git a/src/clang_indexer.cc b/src/clang_indexer.cc index 2032056b..f8950eac 100644 --- a/src/clang_indexer.cc +++ b/src/clang_indexer.cc @@ -9,10 +9,10 @@ #include +#include #include #include #include -#include #include // TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on @@ -861,7 +861,7 @@ CXIdxClientFile OnIndexIncludedFile(CXClientData client_data, IndexInclude include; include.line = line; include.resolved_path = FileName(file->file); - if (!include.resolved_path.empty()) + if (include.resolved_path.size()) db->includes.push_back(include); return nullptr; diff --git a/src/clang_utils.cc b/src/clang_utils.cc index cfd5ce6a..20b55ff5 100644 --- a/src/clang_utils.cc +++ b/src/clang_utils.cc @@ -1,5 +1,6 @@ #include "clang_utils.h" +#include "filesystem.hh" #include "platform.h" namespace { @@ -106,8 +107,11 @@ std::optional BuildAndDisposeDiagnostic(CXDiagnostic diagnostic, std::string FileName(CXFile file) { CXString cx_name = clang_getFileName(file); - std::string name = ToString(cx_name); - return NormalizePath(name); + std::string ret = NormalizePath(ToString(cx_name)); + // Resolve /usr/include/c++/7.3.0 symlink. + if (!StartsWith(ret, g_config.projectRoot)) + ret = fs::canonical(ret); + return ret; } std::string ToString(CXString cx_string) { diff --git a/src/command_line.cc b/src/command_line.cc index eda149ee..10027c34 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -22,7 +22,6 @@ #include "test.h" #include "timer.h" #include "timestamp_manager.h" -#include "work_thread.h" #include "working_files.h" #include @@ -35,7 +34,6 @@ #include #include #include -#include #include #include @@ -255,7 +253,7 @@ void LaunchStdinLoop(Config* config, // clients. std::cin.tie(nullptr); - WorkThread::StartThread("stdin", [request_times]() { + StartThread("stdin", [request_times]() { auto* queue = QueueManager::instance(); while (true) { std::unique_ptr message; @@ -295,7 +293,7 @@ void LaunchStdinLoop(Config* config, void LaunchStdoutThread(std::unordered_map* request_times, MultiQueueWaiter* waiter) { - WorkThread::StartThread("stdout", [=]() { + StartThread("stdout", [=]() { auto* queue = QueueManager::instance(); while (true) { diff --git a/src/config.cc b/src/config.cc new file mode 100644 index 00000000..a98b1a1a --- /dev/null +++ b/src/config.cc @@ -0,0 +1,3 @@ +#include "config.h" + +Config g_config; diff --git a/src/config.h b/src/config.h index d7353f81..5968b91c 100644 --- a/src/config.h +++ b/src/config.h @@ -281,5 +281,4 @@ MAKE_REFLECT_STRUCT(Config, dumpAST); -// Expected client version. We show an error if this doesn't match. -constexpr const int kExpectedClientVersion = 3; +extern Config g_config; diff --git a/src/file_consumer.cc b/src/file_consumer.cc index 3b1d6759..c237c5b7 100644 --- a/src/file_consumer.cc +++ b/src/file_consumer.cc @@ -104,4 +104,4 @@ void FileConsumer::EmitError(CXFile file) const { LOG_S(ERROR) << "Could not get unique file id for " << file_name << " when parsing " << parse_file_; } -} \ No newline at end of file +} diff --git a/src/include_complete.cc b/src/include_complete.cc index dcbaf8bc..2e2ef83e 100644 --- a/src/include_complete.cc +++ b/src/include_complete.cc @@ -5,9 +5,6 @@ #include "project.h" #include "standard_includes.h" #include "timer.h" -#include "work_thread.h" - -#include namespace { @@ -116,7 +113,7 @@ void IncludeComplete::Rescan() { config_->completion.includeBlacklist); is_scanning = true; - WorkThread::StartThread("scan_includes", [this]() { + StartThread("scan_includes", [this]() { Timer timer; InsertStlIncludes(); diff --git a/src/messages/ccls_did_view.cc b/src/messages/ccls_did_view.cc deleted file mode 100644 index ece233b3..00000000 --- a/src/messages/ccls_did_view.cc +++ /dev/null @@ -1,40 +0,0 @@ -#include "clang_complete.h" -#include "message_handler.h" -#include "working_files.h" - -namespace { -MethodType kMethodType = "$ccls/textDocumentDidView"; - -struct In_CclsTextDocumentDidView : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - struct Params { - lsDocumentUri textDocumentUri; - }; - Params params; -}; -MAKE_REFLECT_STRUCT(In_CclsTextDocumentDidView::Params, textDocumentUri); -MAKE_REFLECT_STRUCT(In_CclsTextDocumentDidView, params); -REGISTER_IN_MESSAGE(In_CclsTextDocumentDidView); - -struct Handler_CclsDidView - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_CclsTextDocumentDidView* request) override { - std::string path = request->params.textDocumentUri.GetPath(); - - WorkingFile* working_file = working_files->GetFileByFilename(path); - if (!working_file) - return; - QueryFile* file = nullptr; - if (!FindFileOrFail(db, project, std::nullopt, path, &file)) - return; - - clang_complete->NotifyView(path); - if (file->def) { - EmitInactiveLines(working_file, file->def->inactive_regions); - EmitSemanticHighlighting(db, semantic_cache, working_file, file); - } - } -}; -REGISTER_MESSAGE_HANDLER(Handler_CclsDidView); -} // namespace diff --git a/src/messages/ccls_wait.cc b/src/messages/ccls_wait.cc deleted file mode 100644 index 1e9c9b3b..00000000 --- a/src/messages/ccls_wait.cc +++ /dev/null @@ -1,47 +0,0 @@ -#include "import_manager.h" -#include "import_pipeline.h" -#include "message_handler.h" -#include "queue_manager.h" - -#include - -namespace { -MethodType kMethodType = "$ccls/wait"; - -struct In_CclsWait : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } -}; -MAKE_REFLECT_EMPTY_STRUCT(In_CclsWait); -REGISTER_IN_MESSAGE(In_CclsWait); - -struct Handler_CclsWait : MessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(std::unique_ptr request) override { - // TODO: use status message system here, then run querydb as normal? Maybe - // this cannot be a normal message, ie, it needs to be re-entrant. - - LOG_S(INFO) << "Waiting for idle"; - int idle_count = 0; - while (true) { - bool has_work = false; - has_work |= import_pipeline_status->num_active_threads != 0; - has_work |= QueueManager::instance()->HasWork(); - has_work |= - QueryDb_ImportMain(config, db, import_manager, import_pipeline_status, - semantic_cache, working_files); - if (!has_work) - ++idle_count; - else - idle_count = 0; - - // There are race conditions between each of the three checks above, - // so we retry a bunch of times to try to avoid any. - if (idle_count > 10) - break; - } - LOG_S(INFO) << "Done waiting for idle"; - } -}; -REGISTER_MESSAGE_HANDLER(Handler_CclsWait); -} // namespace diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index fd42cd34..d10b971a 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -8,7 +8,6 @@ #include "queue_manager.h" #include "serializers/json.h" #include "timer.h" -#include "work_thread.h" #include "working_files.h" #include @@ -270,45 +269,13 @@ struct lsTextDocumentClientCapabilities { // The client supports the following `CompletionItem` specific // capabilities. std::optional completionItem; - }; - // Capabilities specific to the `textDocument/completion` - std::optional completion; + } completion; struct lsGenericDynamicReg { // Whether foo supports dynamic registration. std::optional dynamicRegistration; }; - // Capabilities specific to the `textDocument/hover` - std::optional hover; - - // Capabilities specific to the `textDocument/signatureHelp` - std::optional signatureHelp; - - // Capabilities specific to the `textDocument/references` - std::optional references; - - // Capabilities specific to the `textDocument/documentHighlight` - std::optional documentHighlight; - - // Capabilities specific to the `textDocument/documentSymbol` - std::optional documentSymbol; - - // Capabilities specific to the `textDocument/formatting` - std::optional formatting; - - // Capabilities specific to the `textDocument/rangeFormatting` - std::optional rangeFormatting; - - // Capabilities specific to the `textDocument/onTypeFormatting` - std::optional onTypeFormatting; - - // Capabilities specific to the `textDocument/definition` - std::optional definition; - - // Capabilities specific to the `textDocument/codeAction` - std::optional codeAction; - struct CodeLensRegistrationOptions : public lsGenericDynamicReg { // Code lens has a resolve provider as well. bool resolveProvider; @@ -317,9 +284,6 @@ struct lsTextDocumentClientCapabilities { // Capabilities specific to the `textDocument/codeLens` std::optional codeLens; - // Capabilities specific to the `textDocument/documentLink` - std::optional documentLink; - // Capabilities specific to the `textDocument/rename` std::optional rename; }; @@ -344,18 +308,6 @@ MAKE_REFLECT_STRUCT( MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, synchronization, completion, - hover, - signatureHelp, - references, - documentHighlight, - documentSymbol, - formatting, - rangeFormatting, - onTypeFormatting, - definition, - codeAction, - codeLens, - documentLink, rename); struct lsClientCapabilities { @@ -512,29 +464,9 @@ struct Handler_Initialize : BaseMessageHandler { // Client capabilities { const auto& cap = request->params.capabilities.textDocument; - if (cap.completion && cap.completion->completionItem) + if (cap.completion.completionItem) config->client.snippetSupport = - cap.completion->completionItem->snippetSupport.value_or(false); - } - - // Check client version. - if (config->clientVersion.has_value() && - *config->clientVersion != kExpectedClientVersion) { - Out_ShowLogMessage out; - out.display_type = Out_ShowLogMessage::DisplayType::Show; - out.params.type = lsMessageType::Error; - out.params.message = - "ccls client (v" + std::to_string(*config->clientVersion) + - ") and server (v" + std::to_string(kExpectedClientVersion) + - ") version mismatch. Please update "; - if (config->clientVersion > kExpectedClientVersion) - out.params.message += "the ccls binary."; - else - out.params.message += - "your extension client (VSIX file). Make sure to uninstall " - "the ccls extension and restart vscode before " - "reinstalling."; - out.Write(std::cout); + cap.completion.completionItem->snippetSupport.value_or(false); } // Ensure there is a resource directory. @@ -576,6 +508,7 @@ struct Handler_Initialize : BaseMessageHandler { MakeDirectoryRecursive(config->cacheDirectory + '@' + EscapeFileName(config->projectRoot)); + g_config = *config; Timer time; diag_engine->Init(config); semantic_cache->Init(config); @@ -599,7 +532,7 @@ struct Handler_Initialize : BaseMessageHandler { } LOG_S(INFO) << "Starting " << config->index.threads << " indexers"; for (int i = 0; i < config->index.threads; ++i) { - WorkThread::StartThread("indexer" + std::to_string(i), [=]() { + StartThread("indexer" + std::to_string(i), [=]() { Indexer_Main(config, diag_engine, file_consumer_shared, timestamp_manager, import_manager, import_pipeline_status, project, working_files, waiter); diff --git a/src/messages/text_document_did_open.cc b/src/messages/text_document_did_open.cc index 7c10ebf8..e1261c95 100644 --- a/src/messages/text_document_did_open.cc +++ b/src/messages/text_document_did_open.cc @@ -72,9 +72,8 @@ struct Handler_TextDocumentDidOpen clang_complete->FlushSession(entry.filename); LOG_S(INFO) << "Flushed clang complete sessions for " << entry.filename; - if (params.args.size()) { - project->SetFlagsForFile(params.args, path); - } + if (params.args.size()) + project->SetFlagsForFile(params.args, path); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen); diff --git a/src/messages/text_document_formatting.cc b/src/messages/text_document_formatting.cc deleted file mode 100644 index 49290b54..00000000 --- a/src/messages/text_document_formatting.cc +++ /dev/null @@ -1,62 +0,0 @@ -#include "clang_format.h" -#include "message_handler.h" -#include "queue_manager.h" -#include "working_files.h" - -#include - -namespace { -MethodType kMethodType = "textDocument/formatting"; - -struct In_TextDocumentFormatting : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - struct Params { - lsTextDocumentIdentifier textDocument; - lsFormattingOptions options; - }; - Params params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentFormatting::Params, textDocument, options); -MAKE_REFLECT_STRUCT(In_TextDocumentFormatting, id, params); -REGISTER_IN_MESSAGE(In_TextDocumentFormatting); - -struct Out_TextDocumentFormatting - : public lsOutMessage { - lsRequestId id; - std::vector result; -}; -MAKE_REFLECT_STRUCT(Out_TextDocumentFormatting, jsonrpc, id, result); - -struct Handler_TextDocumentFormatting - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_TextDocumentFormatting* request) override { - Out_TextDocumentFormatting response; - response.id = request->id; -#if USE_CLANG_CXX - QueryFile* file; - if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { - return; - } - - WorkingFile* working_file = - working_files->GetFileByFilename(file->def->path); - - response.result = ConvertClangReplacementsIntoTextEdits( - working_file->buffer_content, - ClangFormatDocument(working_file, 0, - working_file->buffer_content.size(), - request->params.options)); -#else - LOG_S(WARNING) << "You must compile ccls with --use-clang-cxx to use " - "textDocument/formatting."; - // TODO: Fallback to execute the clang-format binary? - response.result = {}; -#endif - - QueueManager::WriteStdout(kMethodType, response); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentFormatting); -} // namespace diff --git a/src/platform_posix.cc b/src/platform_posix.cc index ad861320..b03ec4b7 100644 --- a/src/platform_posix.cc +++ b/src/platform_posix.cc @@ -277,7 +277,7 @@ void TraceMe() { // If the environment variable is defined, wait for a debugger. // In gdb, you need to invoke `signal SIGCONT` if you want ccls to continue // after detaching. - if (getenv("CQUERY_TRACEME")) + if (getenv("CCLS_TRACEME")) raise(SIGTSTP); } diff --git a/src/port.cc b/src/port.cc index adb4cde6..d48df06a 100644 --- a/src/port.cc +++ b/src/port.cc @@ -5,6 +5,6 @@ void ccls_unreachable_internal(const char* msg, const char* file, int line) { fprintf(stderr, "unreachable %s:%d %s\n", file, line, msg); - CQUERY_BUILTIN_UNREACHABLE; + CCLS_BUILTIN_UNREACHABLE; abort(); } diff --git a/src/port.h b/src/port.h index 5680bfa9..ef19d772 100644 --- a/src/port.h +++ b/src/port.h @@ -12,17 +12,17 @@ // TODO GCC #if __has_builtin(__builtin_unreachable) -#define CQUERY_BUILTIN_UNREACHABLE __builtin_unreachable() +#define CCLS_BUILTIN_UNREACHABLE __builtin_unreachable() #elif defined(_MSC_VER) -#define CQUERY_BUILTIN_UNREACHABLE __assume(false) +#define CCLS_BUILTIN_UNREACHABLE __assume(false) #else -#define CQUERY_BUILTIN_UNREACHABLE +#define CCLS_BUILTIN_UNREACHABLE #endif void ccls_unreachable_internal(const char* msg, const char* file, int line); #ifndef NDEBUG -#define CQUERY_UNREACHABLE(msg) \ +#define CCLS_UNREACHABLE(msg) \ ccls_unreachable_internal(msg, __FILE__, __LINE__) #else -#define CQUERY_UNREACHABLE(msg) +#define CCLS_UNREACHABLE(msg) #endif diff --git a/src/project.cc b/src/project.cc index 4ff67a2a..fe1f88f3 100644 --- a/src/project.cc +++ b/src/project.cc @@ -2,6 +2,7 @@ #include "cache_manager.h" #include "clang_utils.h" +#include "filesystem.hh" #include "language.h" #include "match.h" #include "platform.h" @@ -27,41 +28,22 @@ #include #include -extern bool gTestOutputMode; - struct CompileCommandsEntry { - std::string directory; + fs::path directory; std::string file; std::string command; std::vector args; + + fs::path ResolveIfRelative(fs::path path) const { + if (path.is_absolute()) + return path; + return directory / path; + } }; MAKE_REFLECT_STRUCT(CompileCommandsEntry, directory, file, command, args); namespace { -bool g_disable_normalize_path_for_test = false; - -std::string NormalizePathWithTestOptOut(const std::string& path) { - if (g_disable_normalize_path_for_test) { - // Add a & so we can test to verify a path is normalized. - return "&" + path; - } - return NormalizePath(path); -} - -bool IsUnixAbsolutePath(const std::string& path) { - return !path.empty() && path[0] == '/'; -} - -bool IsWindowsAbsolutePath(const std::string& path) { - auto is_drive_letter = [](char c) { - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); - }; - - return path.size() > 3 && path[1] == ':' && - (path[2] == '/' || path[2] == '\\') && is_drive_letter(path[0]); -} - enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand }; struct ProjectConfig { @@ -127,22 +109,8 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( Config* init_opts, ProjectConfig* config, const CompileCommandsEntry& entry) { - auto cleanup_maybe_relative_path = [&](const std::string& path) { - // TODO/FIXME: Normalization will fail for paths that do not exist. Should - // it return an std::optional? - assert(!path.empty()); - if (entry.directory.empty() || IsUnixAbsolutePath(path) || - IsWindowsAbsolutePath(path)) { - // We still want to normalize, as the path may contain .. characters. - return NormalizePathWithTestOptOut(path); - } - if (EndsWith(entry.directory, "/")) - return NormalizePathWithTestOptOut(entry.directory + path); - return NormalizePathWithTestOptOut(entry.directory + "/" + path); - }; - Project::Entry result; - result.filename = NormalizePathWithTestOptOut(entry.file); + result.filename = entry.file; const std::string base_name = GetBaseName(entry.file); // Expand %c %cpp %clang @@ -185,7 +153,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( // Add -working-directory if not provided. if (!AnyStartsWith(args, "-working-directory")) - result.args.emplace_back("-working-directory=" + entry.directory); + result.args.emplace_back("-working-directory=" + entry.directory.string()); bool next_flag_is_path = false; bool add_next_flag_to_quote_dirs = false; @@ -212,7 +180,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( // Finish processing path for the previous argument, which was a switch. // {"-I", "foo"} style. if (next_flag_is_path) { - std::string normalized_arg = cleanup_maybe_relative_path(arg); + std::string normalized_arg = entry.ResolveIfRelative(arg); if (add_next_flag_to_quote_dirs) config->quote_dirs.insert(normalized_arg); if (add_next_flag_to_angle_dirs) @@ -238,7 +206,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( if (StartsWith(arg, flag_type)) { std::string path = arg.substr(flag_type.size()); assert(!path.empty()); - path = cleanup_maybe_relative_path(path); + path = entry.ResolveIfRelative(path); if (clang_cl || StartsWithAny(arg, kNormalizePathArgs)) arg = flag_type + path; if (ShouldAddToQuoteIncludes(flag_type)) @@ -254,7 +222,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( // slow. See // https://github.com/cquery-project/cquery/commit/af63df09d57d765ce12d40007bf56302a0446678. if (EndsWith(arg, base_name)) - arg = cleanup_maybe_relative_path(arg); + arg = entry.ResolveIfRelative(arg); // TODO Exclude .a .o to make link command in compile_commands.json work. // Also, clang_parseTranslationUnit2FullArgv does not seem to accept // multiple source filenames. @@ -450,13 +418,7 @@ std::vector LoadCompilationEntriesFromDirectory( our_time.Resume(); entry.directory = directory; - std::string absolute_filename; - if (IsUnixAbsolutePath(relative_filename) || - IsWindowsAbsolutePath(relative_filename)) - absolute_filename = relative_filename; - else - absolute_filename = directory + "/" + relative_filename; - entry.file = NormalizePathWithTestOptOut(absolute_filename); + entry.file = entry.ResolveIfRelative(relative_filename); result.push_back( GetCompilationEntryFromCompileCommandEntry(config, project, entry)); @@ -513,8 +475,8 @@ void Project::Load(Config* config, const std::string& root_directory) { } // Setup project entries. - absolute_path_to_entry_index_.resize(entries.size()); - for (int i = 0; i < entries.size(); ++i) + absolute_path_to_entry_index_.reserve(entries.size()); + for (size_t i = 0; i < entries.size(); ++i) absolute_path_to_entry_index_[entries[i].filename] = i; } @@ -616,9 +578,6 @@ TEST_SUITE("Project") { void CheckFlags(const std::string& directory, const std::string& file, std::vector raw, std::vector expected) { - g_disable_normalize_path_for_test = true; - gTestOutputMode = true; - Config config; ProjectConfig project; project.project_dir = "/w/c/s/"; @@ -656,7 +615,7 @@ TEST_SUITE("Project") { CheckFlags( /* raw */ {"clang", "-lstdc++", "myfile.cc"}, /* expected */ - {"clang", "-working-directory=/dir/", "-lstdc++", "&/dir/myfile.cc", + {"clang", "-working-directory=/dir/", "-lstdc++", "/dir/myfile.cc", "-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option", "-fparse-all-comments"}); @@ -668,17 +627,18 @@ TEST_SUITE("Project") { "-fparse-all-comments"}); } +#ifdef _WIN32 TEST_CASE("Windows path normalization") { CheckFlags("E:/workdir", "E:/workdir/bar.cc", /* raw */ {"clang", "bar.cc"}, /* expected */ - {"clang", "-working-directory=E:/workdir", "&E:/workdir/bar.cc", + {"clang", "-working-directory=E:/workdir", "E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option", "-fparse-all-comments"}); CheckFlags("E:/workdir", "E:/workdir/bar.cc", /* raw */ {"clang", "E:/workdir/bar.cc"}, /* expected */ - {"clang", "-working-directory=E:/workdir", "&E:/workdir/bar.cc", + {"clang", "-working-directory=E:/workdir", "E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option", "-fparse-all-comments"}); @@ -686,7 +646,7 @@ TEST_SUITE("Project") { /* raw */ {"clang-cl.exe", "/I./test", "E:/workdir/bar.cc"}, /* expected */ {"clang-cl.exe", "-working-directory=E:/workdir", - "/I&E:/workdir/./test", "&E:/workdir/bar.cc", + "/I&E:/workdir/./test", "E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option", "-fparse-all-comments"}); @@ -696,28 +656,20 @@ TEST_SUITE("Project") { /* expected */ {"cl.exe", "-working-directory=E:/workdir", "/I&E:/workdir/../third_party/test/include", - "&E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/", + "E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option", "-fparse-all-comments"}); } +#endif TEST_CASE("Path in args") { CheckFlags("/home/user", "/home/user/foo/bar.c", /* raw */ {"cc", "-O0", "foo/bar.c"}, /* expected */ {"cc", "-working-directory=/home/user", "-O0", - "&/home/user/foo/bar.c", "-resource-dir=/w/resource_dir/", + "/home/user/foo/bar.c", "-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option", "-fparse-all-comments"}); } - TEST_CASE("Implied binary") { - CheckFlags("/home/user", "/home/user/foo/bar.cc", - /* raw */ {"clang", "-DDONT_IGNORE_ME"}, - /* expected */ - {"clang", "-working-directory=/home/user", "-DDONT_IGNORE_ME", - "-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option", - "-fparse-all-comments"}); - } - TEST_CASE("Directory extraction") { Config init_opts; ProjectConfig config; @@ -752,11 +704,11 @@ TEST_SUITE("Project") { GetCompilationEntryFromCompileCommandEntry(&init_opts, &config, entry); std::unordered_set angle_expected{ - "&/a_absolute1", "&/a_absolute2", "&/base/a_relative1", - "&/base/a_relative2"}; + "/a_absolute1", "/a_absolute2", "/base/a_relative1", + "/base/a_relative2"}; std::unordered_set quote_expected{ - "&/q_absolute1", "&/q_absolute2", "&/base/q_relative1", - "&/base/q_relative2"}; + "/q_absolute1", "/q_absolute2", "/base/q_relative1", + "/base/q_relative2"}; REQUIRE(config.angle_dirs == angle_expected); REQUIRE(config.quote_dirs == quote_expected); } @@ -817,23 +769,6 @@ TEST_SUITE("Project") { } } - TEST_CASE("IsWindowsAbsolutePath works correctly") { - REQUIRE(IsWindowsAbsolutePath("C:/Users/projects/")); - REQUIRE(IsWindowsAbsolutePath("C:/Users/projects")); - REQUIRE(IsWindowsAbsolutePath("C:/Users/projects")); - REQUIRE(IsWindowsAbsolutePath("C:\\Users\\projects")); - REQUIRE(IsWindowsAbsolutePath("C:\\\\Users\\\\projects")); - REQUIRE(IsWindowsAbsolutePath("c:\\\\Users\\\\projects")); - REQUIRE(IsWindowsAbsolutePath("A:\\\\Users\\\\projects")); - - REQUIRE(!IsWindowsAbsolutePath("C:/")); - REQUIRE(!IsWindowsAbsolutePath("../abc/test")); - REQUIRE(!IsWindowsAbsolutePath("5:/test")); - REQUIRE(!IsWindowsAbsolutePath("ccls/project/file.cc")); - REQUIRE(!IsWindowsAbsolutePath("")); - REQUIRE(!IsWindowsAbsolutePath("/etc/linux/path")); - } - TEST_CASE("Entry inference prefers same file endings") { Project p; { diff --git a/src/project.h b/src/project.h index 18e7bbd8..71fbd19a 100644 --- a/src/project.h +++ b/src/project.h @@ -3,13 +3,12 @@ #include "config.h" #include "method.h" -#include -#include -#include - #include #include +#include #include +#include +#include #include class QueueManager; @@ -29,7 +28,7 @@ struct Project { std::vector angle_include_directories; std::vector entries; - spp::sparse_hash_map absolute_path_to_entry_index_; + std::unordered_map absolute_path_to_entry_index_; // Loads a project for the given |directory|. // diff --git a/src/query.h b/src/query.h index 9fb8fcd9..0ff4f3ef 100644 --- a/src/query.h +++ b/src/query.h @@ -270,7 +270,7 @@ struct QueryDatabase { std::vector vars; // Lookup symbol based on a usr. - spp::sparse_hash_map usr_to_file; + std::unordered_map usr_to_file; spp::sparse_hash_map usr_to_type; spp::sparse_hash_map usr_to_func; spp::sparse_hash_map usr_to_var; diff --git a/src/utils.cc b/src/utils.cc index 59b1c28d..593cf0a8 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include using namespace std::placeholders; @@ -277,6 +278,13 @@ std::string GetDefaultResourceDirectory() { return NormalizePath(result); } +void StartThread(const std::string& thread_name, std::function entry) { + new std::thread([thread_name, entry]() { + SetCurrentThreadName(thread_name); + entry(); + }); +} + TEST_SUITE("StripFileType") { TEST_CASE("all") { REQUIRE(StripFileType("") == ""); diff --git a/src/utils.h b/src/utils.h index 16685885..baba2774 100644 --- a/src/utils.h +++ b/src/utils.h @@ -149,3 +149,5 @@ inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) { } std::string GetDefaultResourceDirectory(); + +void StartThread(const std::string& thread_name, std::function entry); diff --git a/src/work_thread.cc b/src/work_thread.cc deleted file mode 100644 index b627485f..00000000 --- a/src/work_thread.cc +++ /dev/null @@ -1,12 +0,0 @@ -#include "work_thread.h" - -#include "platform.h" - -// static -void WorkThread::StartThread(const std::string& thread_name, - std::function entry_point) { - new std::thread([thread_name, entry_point]() { - SetCurrentThreadName(thread_name); - entry_point(); - }); -} \ No newline at end of file diff --git a/src/work_thread.h b/src/work_thread.h deleted file mode 100644 index d11c237a..00000000 --- a/src/work_thread.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -// Helper methods for starting threads that do some work. Enables test code to -// wait for all work to complete. -struct WorkThread { - // Launch a new thread. |entry_point| will be called continously. It should - // return true if it there is still known work to be done. - static void StartThread(const std::string& thread_name, - std::function entry_point); - - // Static-only class. - WorkThread() = delete; -}; \ No newline at end of file