mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 17:11:59 +00:00
.
This commit is contained in:
parent
a58a38c32d
commit
c96631d1ee
@ -179,6 +179,7 @@ target_sources(ccls PRIVATE
|
|||||||
src/clang_translation_unit.cc
|
src/clang_translation_unit.cc
|
||||||
src/clang_utils.cc
|
src/clang_utils.cc
|
||||||
src/command_line.cc
|
src/command_line.cc
|
||||||
|
src/config.cc
|
||||||
src/diagnostics_engine.cc
|
src/diagnostics_engine.cc
|
||||||
src/file_consumer.cc
|
src/file_consumer.cc
|
||||||
src/file_contents.cc
|
src/file_contents.cc
|
||||||
@ -209,7 +210,6 @@ target_sources(ccls PRIVATE
|
|||||||
src/timestamp_manager.cc
|
src/timestamp_manager.cc
|
||||||
src/type_printer.cc
|
src/type_printer.cc
|
||||||
src/utils.cc
|
src/utils.cc
|
||||||
src/work_thread.cc
|
|
||||||
src/working_files.cc)
|
src/working_files.cc)
|
||||||
|
|
||||||
target_sources(ccls PRIVATE
|
target_sources(ccls PRIVATE
|
||||||
@ -217,7 +217,6 @@ target_sources(ccls PRIVATE
|
|||||||
src/messages/ccls_call_hierarchy.cc
|
src/messages/ccls_call_hierarchy.cc
|
||||||
src/messages/ccls_callers.cc
|
src/messages/ccls_callers.cc
|
||||||
src/messages/ccls_derived.cc
|
src/messages/ccls_derived.cc
|
||||||
src/messages/ccls_did_view.cc
|
|
||||||
src/messages/ccls_file_info.cc
|
src/messages/ccls_file_info.cc
|
||||||
src/messages/ccls_freshen_index.cc
|
src/messages/ccls_freshen_index.cc
|
||||||
src/messages/ccls_index_file.cc
|
src/messages/ccls_index_file.cc
|
||||||
@ -225,7 +224,6 @@ target_sources(ccls PRIVATE
|
|||||||
src/messages/ccls_member_hierarchy.cc
|
src/messages/ccls_member_hierarchy.cc
|
||||||
src/messages/ccls_random.cc
|
src/messages/ccls_random.cc
|
||||||
src/messages/ccls_vars.cc
|
src/messages/ccls_vars.cc
|
||||||
src/messages/ccls_wait.cc
|
|
||||||
src/messages/exit.cc
|
src/messages/exit.cc
|
||||||
src/messages/initialize.cc
|
src/messages/initialize.cc
|
||||||
src/messages/shutdown.cc
|
src/messages/shutdown.cc
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <climits>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on
|
// 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;
|
IndexInclude include;
|
||||||
include.line = line;
|
include.line = line;
|
||||||
include.resolved_path = FileName(file->file);
|
include.resolved_path = FileName(file->file);
|
||||||
if (!include.resolved_path.empty())
|
if (include.resolved_path.size())
|
||||||
db->includes.push_back(include);
|
db->includes.push_back(include);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "clang_utils.h"
|
#include "clang_utils.h"
|
||||||
|
|
||||||
|
#include "filesystem.hh"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -106,8 +107,11 @@ std::optional<lsDiagnostic> BuildAndDisposeDiagnostic(CXDiagnostic diagnostic,
|
|||||||
|
|
||||||
std::string FileName(CXFile file) {
|
std::string FileName(CXFile file) {
|
||||||
CXString cx_name = clang_getFileName(file);
|
CXString cx_name = clang_getFileName(file);
|
||||||
std::string name = ToString(cx_name);
|
std::string ret = NormalizePath(ToString(cx_name));
|
||||||
return NormalizePath(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) {
|
std::string ToString(CXString cx_string) {
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "timestamp_manager.h"
|
#include "timestamp_manager.h"
|
||||||
#include "work_thread.h"
|
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
|
||||||
#include <doctest/doctest.h>
|
#include <doctest/doctest.h>
|
||||||
@ -35,7 +34,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -255,7 +253,7 @@ void LaunchStdinLoop(Config* config,
|
|||||||
// clients.
|
// clients.
|
||||||
std::cin.tie(nullptr);
|
std::cin.tie(nullptr);
|
||||||
|
|
||||||
WorkThread::StartThread("stdin", [request_times]() {
|
StartThread("stdin", [request_times]() {
|
||||||
auto* queue = QueueManager::instance();
|
auto* queue = QueueManager::instance();
|
||||||
while (true) {
|
while (true) {
|
||||||
std::unique_ptr<InMessage> message;
|
std::unique_ptr<InMessage> message;
|
||||||
@ -295,7 +293,7 @@ void LaunchStdinLoop(Config* config,
|
|||||||
|
|
||||||
void LaunchStdoutThread(std::unordered_map<MethodType, Timer>* request_times,
|
void LaunchStdoutThread(std::unordered_map<MethodType, Timer>* request_times,
|
||||||
MultiQueueWaiter* waiter) {
|
MultiQueueWaiter* waiter) {
|
||||||
WorkThread::StartThread("stdout", [=]() {
|
StartThread("stdout", [=]() {
|
||||||
auto* queue = QueueManager::instance();
|
auto* queue = QueueManager::instance();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
3
src/config.cc
Normal file
3
src/config.cc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
Config g_config;
|
@ -281,5 +281,4 @@ MAKE_REFLECT_STRUCT(Config,
|
|||||||
|
|
||||||
dumpAST);
|
dumpAST);
|
||||||
|
|
||||||
// Expected client version. We show an error if this doesn't match.
|
extern Config g_config;
|
||||||
constexpr const int kExpectedClientVersion = 3;
|
|
||||||
|
@ -5,9 +5,6 @@
|
|||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "standard_includes.h"
|
#include "standard_includes.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "work_thread.h"
|
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -116,7 +113,7 @@ void IncludeComplete::Rescan() {
|
|||||||
config_->completion.includeBlacklist);
|
config_->completion.includeBlacklist);
|
||||||
|
|
||||||
is_scanning = true;
|
is_scanning = true;
|
||||||
WorkThread::StartThread("scan_includes", [this]() {
|
StartThread("scan_includes", [this]() {
|
||||||
Timer timer;
|
Timer timer;
|
||||||
|
|
||||||
InsertStlIncludes();
|
InsertStlIncludes();
|
||||||
|
@ -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<In_CclsTextDocumentDidView> {
|
|
||||||
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
|
|
@ -1,47 +0,0 @@
|
|||||||
#include "import_manager.h"
|
|
||||||
#include "import_pipeline.h"
|
|
||||||
#include "message_handler.h"
|
|
||||||
#include "queue_manager.h"
|
|
||||||
|
|
||||||
#include <loguru.hpp>
|
|
||||||
|
|
||||||
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<InMessage> 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
|
|
@ -8,7 +8,6 @@
|
|||||||
#include "queue_manager.h"
|
#include "queue_manager.h"
|
||||||
#include "serializers/json.h"
|
#include "serializers/json.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "work_thread.h"
|
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
@ -270,45 +269,13 @@ struct lsTextDocumentClientCapabilities {
|
|||||||
// The client supports the following `CompletionItem` specific
|
// The client supports the following `CompletionItem` specific
|
||||||
// capabilities.
|
// capabilities.
|
||||||
std::optional<lsCompletionItem> completionItem;
|
std::optional<lsCompletionItem> completionItem;
|
||||||
};
|
} completion;
|
||||||
// Capabilities specific to the `textDocument/completion`
|
|
||||||
std::optional<lsCompletion> completion;
|
|
||||||
|
|
||||||
struct lsGenericDynamicReg {
|
struct lsGenericDynamicReg {
|
||||||
// Whether foo supports dynamic registration.
|
// Whether foo supports dynamic registration.
|
||||||
std::optional<bool> dynamicRegistration;
|
std::optional<bool> dynamicRegistration;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/hover`
|
|
||||||
std::optional<lsGenericDynamicReg> hover;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/signatureHelp`
|
|
||||||
std::optional<lsGenericDynamicReg> signatureHelp;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/references`
|
|
||||||
std::optional<lsGenericDynamicReg> references;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/documentHighlight`
|
|
||||||
std::optional<lsGenericDynamicReg> documentHighlight;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/documentSymbol`
|
|
||||||
std::optional<lsGenericDynamicReg> documentSymbol;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/formatting`
|
|
||||||
std::optional<lsGenericDynamicReg> formatting;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/rangeFormatting`
|
|
||||||
std::optional<lsGenericDynamicReg> rangeFormatting;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/onTypeFormatting`
|
|
||||||
std::optional<lsGenericDynamicReg> onTypeFormatting;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/definition`
|
|
||||||
std::optional<lsGenericDynamicReg> definition;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/codeAction`
|
|
||||||
std::optional<lsGenericDynamicReg> codeAction;
|
|
||||||
|
|
||||||
struct CodeLensRegistrationOptions : public lsGenericDynamicReg {
|
struct CodeLensRegistrationOptions : public lsGenericDynamicReg {
|
||||||
// Code lens has a resolve provider as well.
|
// Code lens has a resolve provider as well.
|
||||||
bool resolveProvider;
|
bool resolveProvider;
|
||||||
@ -317,9 +284,6 @@ struct lsTextDocumentClientCapabilities {
|
|||||||
// Capabilities specific to the `textDocument/codeLens`
|
// Capabilities specific to the `textDocument/codeLens`
|
||||||
std::optional<CodeLensRegistrationOptions> codeLens;
|
std::optional<CodeLensRegistrationOptions> codeLens;
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/documentLink`
|
|
||||||
std::optional<lsGenericDynamicReg> documentLink;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/rename`
|
// Capabilities specific to the `textDocument/rename`
|
||||||
std::optional<lsGenericDynamicReg> rename;
|
std::optional<lsGenericDynamicReg> rename;
|
||||||
};
|
};
|
||||||
@ -344,18 +308,6 @@ MAKE_REFLECT_STRUCT(
|
|||||||
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities,
|
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities,
|
||||||
synchronization,
|
synchronization,
|
||||||
completion,
|
completion,
|
||||||
hover,
|
|
||||||
signatureHelp,
|
|
||||||
references,
|
|
||||||
documentHighlight,
|
|
||||||
documentSymbol,
|
|
||||||
formatting,
|
|
||||||
rangeFormatting,
|
|
||||||
onTypeFormatting,
|
|
||||||
definition,
|
|
||||||
codeAction,
|
|
||||||
codeLens,
|
|
||||||
documentLink,
|
|
||||||
rename);
|
rename);
|
||||||
|
|
||||||
struct lsClientCapabilities {
|
struct lsClientCapabilities {
|
||||||
@ -512,29 +464,9 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
// Client capabilities
|
// Client capabilities
|
||||||
{
|
{
|
||||||
const auto& cap = request->params.capabilities.textDocument;
|
const auto& cap = request->params.capabilities.textDocument;
|
||||||
if (cap.completion && cap.completion->completionItem)
|
if (cap.completion.completionItem)
|
||||||
config->client.snippetSupport =
|
config->client.snippetSupport =
|
||||||
cap.completion->completionItem->snippetSupport.value_or(false);
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure there is a resource directory.
|
// Ensure there is a resource directory.
|
||||||
@ -576,6 +508,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
MakeDirectoryRecursive(config->cacheDirectory + '@' +
|
MakeDirectoryRecursive(config->cacheDirectory + '@' +
|
||||||
EscapeFileName(config->projectRoot));
|
EscapeFileName(config->projectRoot));
|
||||||
|
|
||||||
|
g_config = *config;
|
||||||
Timer time;
|
Timer time;
|
||||||
diag_engine->Init(config);
|
diag_engine->Init(config);
|
||||||
semantic_cache->Init(config);
|
semantic_cache->Init(config);
|
||||||
@ -599,7 +532,7 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
}
|
}
|
||||||
LOG_S(INFO) << "Starting " << config->index.threads << " indexers";
|
LOG_S(INFO) << "Starting " << config->index.threads << " indexers";
|
||||||
for (int i = 0; i < config->index.threads; ++i) {
|
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,
|
Indexer_Main(config, diag_engine, file_consumer_shared,
|
||||||
timestamp_manager, import_manager,
|
timestamp_manager, import_manager,
|
||||||
import_pipeline_status, project, working_files, waiter);
|
import_pipeline_status, project, working_files, waiter);
|
||||||
|
@ -72,9 +72,8 @@ struct Handler_TextDocumentDidOpen
|
|||||||
|
|
||||||
clang_complete->FlushSession(entry.filename);
|
clang_complete->FlushSession(entry.filename);
|
||||||
LOG_S(INFO) << "Flushed clang complete sessions for " << entry.filename;
|
LOG_S(INFO) << "Flushed clang complete sessions for " << entry.filename;
|
||||||
if (params.args.size()) {
|
if (params.args.size())
|
||||||
project->SetFlagsForFile(params.args, path);
|
project->SetFlagsForFile(params.args, path);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen);
|
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen);
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
#include "clang_format.h"
|
|
||||||
#include "message_handler.h"
|
|
||||||
#include "queue_manager.h"
|
|
||||||
#include "working_files.h"
|
|
||||||
|
|
||||||
#include <loguru.hpp>
|
|
||||||
|
|
||||||
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<Out_TextDocumentFormatting> {
|
|
||||||
lsRequestId id;
|
|
||||||
std::vector<lsTextEdit> result;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(Out_TextDocumentFormatting, jsonrpc, id, result);
|
|
||||||
|
|
||||||
struct Handler_TextDocumentFormatting
|
|
||||||
: BaseMessageHandler<In_TextDocumentFormatting> {
|
|
||||||
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
|
|
@ -277,7 +277,7 @@ void TraceMe() {
|
|||||||
// If the environment variable is defined, wait for a debugger.
|
// If the environment variable is defined, wait for a debugger.
|
||||||
// In gdb, you need to invoke `signal SIGCONT` if you want ccls to continue
|
// In gdb, you need to invoke `signal SIGCONT` if you want ccls to continue
|
||||||
// after detaching.
|
// after detaching.
|
||||||
if (getenv("CQUERY_TRACEME"))
|
if (getenv("CCLS_TRACEME"))
|
||||||
raise(SIGTSTP);
|
raise(SIGTSTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,6 @@
|
|||||||
|
|
||||||
void ccls_unreachable_internal(const char* msg, const char* file, int line) {
|
void ccls_unreachable_internal(const char* msg, const char* file, int line) {
|
||||||
fprintf(stderr, "unreachable %s:%d %s\n", file, line, msg);
|
fprintf(stderr, "unreachable %s:%d %s\n", file, line, msg);
|
||||||
CQUERY_BUILTIN_UNREACHABLE;
|
CCLS_BUILTIN_UNREACHABLE;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
10
src/port.h
10
src/port.h
@ -12,17 +12,17 @@
|
|||||||
|
|
||||||
// TODO GCC
|
// TODO GCC
|
||||||
#if __has_builtin(__builtin_unreachable)
|
#if __has_builtin(__builtin_unreachable)
|
||||||
#define CQUERY_BUILTIN_UNREACHABLE __builtin_unreachable()
|
#define CCLS_BUILTIN_UNREACHABLE __builtin_unreachable()
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define CQUERY_BUILTIN_UNREACHABLE __assume(false)
|
#define CCLS_BUILTIN_UNREACHABLE __assume(false)
|
||||||
#else
|
#else
|
||||||
#define CQUERY_BUILTIN_UNREACHABLE
|
#define CCLS_BUILTIN_UNREACHABLE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ccls_unreachable_internal(const char* msg, const char* file, int line);
|
void ccls_unreachable_internal(const char* msg, const char* file, int line);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define CQUERY_UNREACHABLE(msg) \
|
#define CCLS_UNREACHABLE(msg) \
|
||||||
ccls_unreachable_internal(msg, __FILE__, __LINE__)
|
ccls_unreachable_internal(msg, __FILE__, __LINE__)
|
||||||
#else
|
#else
|
||||||
#define CQUERY_UNREACHABLE(msg)
|
#define CCLS_UNREACHABLE(msg)
|
||||||
#endif
|
#endif
|
||||||
|
121
src/project.cc
121
src/project.cc
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "cache_manager.h"
|
#include "cache_manager.h"
|
||||||
#include "clang_utils.h"
|
#include "clang_utils.h"
|
||||||
|
#include "filesystem.hh"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
@ -27,41 +28,22 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
extern bool gTestOutputMode;
|
|
||||||
|
|
||||||
struct CompileCommandsEntry {
|
struct CompileCommandsEntry {
|
||||||
std::string directory;
|
fs::path directory;
|
||||||
std::string file;
|
std::string file;
|
||||||
std::string command;
|
std::string command;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> 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);
|
MAKE_REFLECT_STRUCT(CompileCommandsEntry, directory, file, command, args);
|
||||||
|
|
||||||
namespace {
|
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 };
|
enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand };
|
||||||
|
|
||||||
struct ProjectConfig {
|
struct ProjectConfig {
|
||||||
@ -127,22 +109,8 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
Config* init_opts,
|
Config* init_opts,
|
||||||
ProjectConfig* config,
|
ProjectConfig* config,
|
||||||
const CompileCommandsEntry& entry) {
|
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<std::string>?
|
|
||||||
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;
|
Project::Entry result;
|
||||||
result.filename = NormalizePathWithTestOptOut(entry.file);
|
result.filename = entry.file;
|
||||||
const std::string base_name = GetBaseName(entry.file);
|
const std::string base_name = GetBaseName(entry.file);
|
||||||
|
|
||||||
// Expand %c %cpp %clang
|
// Expand %c %cpp %clang
|
||||||
@ -185,7 +153,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
|
|
||||||
// Add -working-directory if not provided.
|
// Add -working-directory if not provided.
|
||||||
if (!AnyStartsWith(args, "-working-directory"))
|
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 next_flag_is_path = false;
|
||||||
bool add_next_flag_to_quote_dirs = 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.
|
// Finish processing path for the previous argument, which was a switch.
|
||||||
// {"-I", "foo"} style.
|
// {"-I", "foo"} style.
|
||||||
if (next_flag_is_path) {
|
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)
|
if (add_next_flag_to_quote_dirs)
|
||||||
config->quote_dirs.insert(normalized_arg);
|
config->quote_dirs.insert(normalized_arg);
|
||||||
if (add_next_flag_to_angle_dirs)
|
if (add_next_flag_to_angle_dirs)
|
||||||
@ -238,7 +206,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
if (StartsWith(arg, flag_type)) {
|
if (StartsWith(arg, flag_type)) {
|
||||||
std::string path = arg.substr(flag_type.size());
|
std::string path = arg.substr(flag_type.size());
|
||||||
assert(!path.empty());
|
assert(!path.empty());
|
||||||
path = cleanup_maybe_relative_path(path);
|
path = entry.ResolveIfRelative(path);
|
||||||
if (clang_cl || StartsWithAny(arg, kNormalizePathArgs))
|
if (clang_cl || StartsWithAny(arg, kNormalizePathArgs))
|
||||||
arg = flag_type + path;
|
arg = flag_type + path;
|
||||||
if (ShouldAddToQuoteIncludes(flag_type))
|
if (ShouldAddToQuoteIncludes(flag_type))
|
||||||
@ -254,7 +222,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
// slow. See
|
// slow. See
|
||||||
// https://github.com/cquery-project/cquery/commit/af63df09d57d765ce12d40007bf56302a0446678.
|
// https://github.com/cquery-project/cquery/commit/af63df09d57d765ce12d40007bf56302a0446678.
|
||||||
if (EndsWith(arg, base_name))
|
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.
|
// TODO Exclude .a .o to make link command in compile_commands.json work.
|
||||||
// Also, clang_parseTranslationUnit2FullArgv does not seem to accept
|
// Also, clang_parseTranslationUnit2FullArgv does not seem to accept
|
||||||
// multiple source filenames.
|
// multiple source filenames.
|
||||||
@ -450,13 +418,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
|
|
||||||
our_time.Resume();
|
our_time.Resume();
|
||||||
entry.directory = directory;
|
entry.directory = directory;
|
||||||
std::string absolute_filename;
|
entry.file = entry.ResolveIfRelative(relative_filename);
|
||||||
if (IsUnixAbsolutePath(relative_filename) ||
|
|
||||||
IsWindowsAbsolutePath(relative_filename))
|
|
||||||
absolute_filename = relative_filename;
|
|
||||||
else
|
|
||||||
absolute_filename = directory + "/" + relative_filename;
|
|
||||||
entry.file = NormalizePathWithTestOptOut(absolute_filename);
|
|
||||||
|
|
||||||
result.push_back(
|
result.push_back(
|
||||||
GetCompilationEntryFromCompileCommandEntry(config, project, entry));
|
GetCompilationEntryFromCompileCommandEntry(config, project, entry));
|
||||||
@ -513,8 +475,8 @@ void Project::Load(Config* config, const std::string& root_directory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup project entries.
|
// Setup project entries.
|
||||||
absolute_path_to_entry_index_.resize(entries.size());
|
absolute_path_to_entry_index_.reserve(entries.size());
|
||||||
for (int i = 0; i < entries.size(); ++i)
|
for (size_t i = 0; i < entries.size(); ++i)
|
||||||
absolute_path_to_entry_index_[entries[i].filename] = 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,
|
void CheckFlags(const std::string& directory, const std::string& file,
|
||||||
std::vector<std::string> raw,
|
std::vector<std::string> raw,
|
||||||
std::vector<std::string> expected) {
|
std::vector<std::string> expected) {
|
||||||
g_disable_normalize_path_for_test = true;
|
|
||||||
gTestOutputMode = true;
|
|
||||||
|
|
||||||
Config config;
|
Config config;
|
||||||
ProjectConfig project;
|
ProjectConfig project;
|
||||||
project.project_dir = "/w/c/s/";
|
project.project_dir = "/w/c/s/";
|
||||||
@ -656,7 +615,7 @@ TEST_SUITE("Project") {
|
|||||||
CheckFlags(
|
CheckFlags(
|
||||||
/* raw */ {"clang", "-lstdc++", "myfile.cc"},
|
/* raw */ {"clang", "-lstdc++", "myfile.cc"},
|
||||||
/* expected */
|
/* 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",
|
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||||
"-fparse-all-comments"});
|
"-fparse-all-comments"});
|
||||||
|
|
||||||
@ -668,17 +627,18 @@ TEST_SUITE("Project") {
|
|||||||
"-fparse-all-comments"});
|
"-fparse-all-comments"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
TEST_CASE("Windows path normalization") {
|
TEST_CASE("Windows path normalization") {
|
||||||
CheckFlags("E:/workdir", "E:/workdir/bar.cc", /* raw */ {"clang", "bar.cc"},
|
CheckFlags("E:/workdir", "E:/workdir/bar.cc", /* raw */ {"clang", "bar.cc"},
|
||||||
/* expected */
|
/* 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",
|
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||||
"-fparse-all-comments"});
|
"-fparse-all-comments"});
|
||||||
|
|
||||||
CheckFlags("E:/workdir", "E:/workdir/bar.cc",
|
CheckFlags("E:/workdir", "E:/workdir/bar.cc",
|
||||||
/* raw */ {"clang", "E:/workdir/bar.cc"},
|
/* raw */ {"clang", "E:/workdir/bar.cc"},
|
||||||
/* expected */
|
/* 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",
|
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||||
"-fparse-all-comments"});
|
"-fparse-all-comments"});
|
||||||
|
|
||||||
@ -686,7 +646,7 @@ TEST_SUITE("Project") {
|
|||||||
/* raw */ {"clang-cl.exe", "/I./test", "E:/workdir/bar.cc"},
|
/* raw */ {"clang-cl.exe", "/I./test", "E:/workdir/bar.cc"},
|
||||||
/* expected */
|
/* expected */
|
||||||
{"clang-cl.exe", "-working-directory=E:/workdir",
|
{"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",
|
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||||
"-fparse-all-comments"});
|
"-fparse-all-comments"});
|
||||||
|
|
||||||
@ -696,28 +656,20 @@ TEST_SUITE("Project") {
|
|||||||
/* expected */
|
/* expected */
|
||||||
{"cl.exe", "-working-directory=E:/workdir",
|
{"cl.exe", "-working-directory=E:/workdir",
|
||||||
"/I&E:/workdir/../third_party/test/include",
|
"/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"});
|
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_CASE("Path in args") {
|
TEST_CASE("Path in args") {
|
||||||
CheckFlags("/home/user", "/home/user/foo/bar.c",
|
CheckFlags("/home/user", "/home/user/foo/bar.c",
|
||||||
/* raw */ {"cc", "-O0", "foo/bar.c"},
|
/* raw */ {"cc", "-O0", "foo/bar.c"},
|
||||||
/* expected */
|
/* expected */
|
||||||
{"cc", "-working-directory=/home/user", "-O0",
|
{"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"});
|
"-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") {
|
TEST_CASE("Directory extraction") {
|
||||||
Config init_opts;
|
Config init_opts;
|
||||||
ProjectConfig config;
|
ProjectConfig config;
|
||||||
@ -752,11 +704,11 @@ TEST_SUITE("Project") {
|
|||||||
GetCompilationEntryFromCompileCommandEntry(&init_opts, &config, entry);
|
GetCompilationEntryFromCompileCommandEntry(&init_opts, &config, entry);
|
||||||
|
|
||||||
std::unordered_set<std::string> angle_expected{
|
std::unordered_set<std::string> angle_expected{
|
||||||
"&/a_absolute1", "&/a_absolute2", "&/base/a_relative1",
|
"/a_absolute1", "/a_absolute2", "/base/a_relative1",
|
||||||
"&/base/a_relative2"};
|
"/base/a_relative2"};
|
||||||
std::unordered_set<std::string> quote_expected{
|
std::unordered_set<std::string> quote_expected{
|
||||||
"&/q_absolute1", "&/q_absolute2", "&/base/q_relative1",
|
"/q_absolute1", "/q_absolute2", "/base/q_relative1",
|
||||||
"&/base/q_relative2"};
|
"/base/q_relative2"};
|
||||||
REQUIRE(config.angle_dirs == angle_expected);
|
REQUIRE(config.angle_dirs == angle_expected);
|
||||||
REQUIRE(config.quote_dirs == quote_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") {
|
TEST_CASE("Entry inference prefers same file endings") {
|
||||||
Project p;
|
Project p;
|
||||||
{
|
{
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "method.h"
|
#include "method.h"
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <sparsepp/spp.h>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class QueueManager;
|
class QueueManager;
|
||||||
@ -29,7 +28,7 @@ struct Project {
|
|||||||
std::vector<std::string> angle_include_directories;
|
std::vector<std::string> angle_include_directories;
|
||||||
|
|
||||||
std::vector<Entry> entries;
|
std::vector<Entry> entries;
|
||||||
spp::sparse_hash_map<std::string, int> absolute_path_to_entry_index_;
|
std::unordered_map<std::string, int> absolute_path_to_entry_index_;
|
||||||
|
|
||||||
// Loads a project for the given |directory|.
|
// Loads a project for the given |directory|.
|
||||||
//
|
//
|
||||||
|
@ -270,7 +270,7 @@ struct QueryDatabase {
|
|||||||
std::vector<QueryVar> vars;
|
std::vector<QueryVar> vars;
|
||||||
|
|
||||||
// Lookup symbol based on a usr.
|
// Lookup symbol based on a usr.
|
||||||
spp::sparse_hash_map<std::string, QueryFileId> usr_to_file;
|
std::unordered_map<std::string, QueryFileId> usr_to_file;
|
||||||
spp::sparse_hash_map<Usr, QueryTypeId> usr_to_type;
|
spp::sparse_hash_map<Usr, QueryTypeId> usr_to_type;
|
||||||
spp::sparse_hash_map<Usr, QueryFuncId> usr_to_func;
|
spp::sparse_hash_map<Usr, QueryFuncId> usr_to_func;
|
||||||
spp::sparse_hash_map<Usr, QueryVarId> usr_to_var;
|
spp::sparse_hash_map<Usr, QueryVarId> usr_to_var;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
@ -277,6 +278,13 @@ std::string GetDefaultResourceDirectory() {
|
|||||||
return NormalizePath(result);
|
return NormalizePath(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StartThread(const std::string& thread_name, std::function<void()> entry) {
|
||||||
|
new std::thread([thread_name, entry]() {
|
||||||
|
SetCurrentThreadName(thread_name);
|
||||||
|
entry();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
TEST_SUITE("StripFileType") {
|
TEST_SUITE("StripFileType") {
|
||||||
TEST_CASE("all") {
|
TEST_CASE("all") {
|
||||||
REQUIRE(StripFileType("") == "");
|
REQUIRE(StripFileType("") == "");
|
||||||
|
@ -149,3 +149,5 @@ inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDefaultResourceDirectory();
|
std::string GetDefaultResourceDirectory();
|
||||||
|
|
||||||
|
void StartThread(const std::string& thread_name, std::function<void()> entry);
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
#include "work_thread.h"
|
|
||||||
|
|
||||||
#include "platform.h"
|
|
||||||
|
|
||||||
// static
|
|
||||||
void WorkThread::StartThread(const std::string& thread_name,
|
|
||||||
std::function<void()> entry_point) {
|
|
||||||
new std::thread([thread_name, entry_point]() {
|
|
||||||
SetCurrentThreadName(thread_name);
|
|
||||||
entry_point();
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <functional>
|
|
||||||
#include <mutex>
|
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// 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<void()> entry_point);
|
|
||||||
|
|
||||||
// Static-only class.
|
|
||||||
WorkThread() = delete;
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user