mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 17:11:59 +00:00
Simplify; improve $ccls/inheritanceHierarchy
This commit is contained in:
parent
f5ce45fd55
commit
a6094ef714
@ -2,6 +2,8 @@
|
|||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "queue_manager.h"
|
#include "queue_manager.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "$ccls/inheritanceHierarchy";
|
MethodType kMethodType = "$ccls/inheritanceHierarchy";
|
||||||
|
|
||||||
@ -79,19 +81,22 @@ bool ExpandHelper(MessageHandler* m,
|
|||||||
int levels,
|
int levels,
|
||||||
Q& entity) {
|
Q& entity) {
|
||||||
const auto* def = entity.AnyDef();
|
const auto* def = entity.AnyDef();
|
||||||
if (!def) {
|
if (def) {
|
||||||
|
entry->name = def->Name(qualified);
|
||||||
|
if (def->spell) {
|
||||||
|
if (auto loc = GetLsLocation(m->db, m->working_files, *def->spell))
|
||||||
|
entry->location = *loc;
|
||||||
|
}
|
||||||
|
} else if (!derived) {
|
||||||
entry->numChildren = 0;
|
entry->numChildren = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
entry->name = def->Name(qualified);
|
std::unordered_set<Usr> seen;
|
||||||
if (def->spell) {
|
|
||||||
if (std::optional<lsLocation> loc =
|
|
||||||
GetLsLocation(m->db, m->working_files, *def->spell))
|
|
||||||
entry->location = *loc;
|
|
||||||
}
|
|
||||||
if (derived) {
|
if (derived) {
|
||||||
if (levels > 0) {
|
if (levels > 0) {
|
||||||
for (auto usr : entity.derived) {
|
for (auto usr : entity.derived) {
|
||||||
|
if (seen.insert(usr).second)
|
||||||
|
continue;
|
||||||
Out_CclsInheritanceHierarchy::Entry entry1;
|
Out_CclsInheritanceHierarchy::Entry entry1;
|
||||||
entry1.id = std::to_string(usr);
|
entry1.id = std::to_string(usr);
|
||||||
entry1.usr = usr;
|
entry1.usr = usr;
|
||||||
@ -105,6 +110,8 @@ bool ExpandHelper(MessageHandler* m,
|
|||||||
} else {
|
} else {
|
||||||
if (levels > 0) {
|
if (levels > 0) {
|
||||||
for (auto usr : def->bases) {
|
for (auto usr : def->bases) {
|
||||||
|
if (seen.insert(usr).second)
|
||||||
|
continue;
|
||||||
Out_CclsInheritanceHierarchy::Entry entry1;
|
Out_CclsInheritanceHierarchy::Entry entry1;
|
||||||
entry1.id = std::to_string(usr);
|
entry1.id = std::to_string(usr);
|
||||||
entry1.usr = usr;
|
entry1.usr = usr;
|
||||||
|
@ -267,12 +267,8 @@ struct lsTextDocumentClientCapabilities {
|
|||||||
// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
|
// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
|
||||||
// the end of the snippet. Placeholders with equal identifiers are linked,
|
// the end of the snippet. Placeholders with equal identifiers are linked,
|
||||||
// that is typing in one will update others too.
|
// that is typing in one will update others too.
|
||||||
std::optional<bool> snippetSupport;
|
bool snippetSupport = false;
|
||||||
};
|
} completionItem;
|
||||||
|
|
||||||
// The client supports the following `CompletionItem` specific
|
|
||||||
// capabilities.
|
|
||||||
std::optional<lsCompletionItem> completionItem;
|
|
||||||
} completion;
|
} completion;
|
||||||
|
|
||||||
struct lsGenericDynamicReg {
|
struct lsGenericDynamicReg {
|
||||||
@ -426,58 +422,56 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
MethodType GetMethodType() const override { return kMethodType; }
|
MethodType GetMethodType() const override { return kMethodType; }
|
||||||
|
|
||||||
void Run(In_InitializeRequest* request) override {
|
void Run(In_InitializeRequest* request) override {
|
||||||
// Log initialization parameters.
|
auto& params = request->params;
|
||||||
|
if (!params.rootUri)
|
||||||
|
return;
|
||||||
|
{
|
||||||
rapidjson::StringBuffer output;
|
rapidjson::StringBuffer output;
|
||||||
rapidjson::Writer<rapidjson::StringBuffer> writer(output);
|
rapidjson::Writer<rapidjson::StringBuffer> writer(output);
|
||||||
JsonWriter json_writer(&writer);
|
JsonWriter json_writer(&writer);
|
||||||
Reflect(json_writer, request->params.initializationOptions);
|
Reflect(json_writer, params.initializationOptions);
|
||||||
LOG_S(INFO) << "Init parameters: " << output.GetString();
|
LOG_S(INFO) << "initializationOptions: " << output.GetString();
|
||||||
std::unique_ptr<Config> config;
|
}
|
||||||
|
|
||||||
if (request->params.rootUri) {
|
std::string project_path = NormalizePath(params.rootUri->GetPath());
|
||||||
std::string project_path =
|
LOG_S(INFO) << "initialize in directory " << project_path << " with uri "
|
||||||
NormalizePath(request->params.rootUri->GetPath());
|
<< params.rootUri->raw_uri;
|
||||||
LOG_S(INFO) << "[querydb] Initialize in directory " << project_path
|
|
||||||
<< " with uri " << request->params.rootUri->raw_uri;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
if (request->params.initializationOptions)
|
if (params.initializationOptions)
|
||||||
config = std::make_unique<Config>(*request->params.initializationOptions);
|
g_config = std::make_unique<Config>(*params.initializationOptions);
|
||||||
else
|
else
|
||||||
config = std::make_unique<Config>();
|
g_config = std::make_unique<Config>();
|
||||||
rapidjson::Document reader;
|
rapidjson::Document reader;
|
||||||
reader.Parse(g_init_options.c_str());
|
reader.Parse(g_init_options.c_str());
|
||||||
if (!reader.HasParseError()) {
|
if (!reader.HasParseError()) {
|
||||||
JsonReader json_reader{&reader};
|
JsonReader json_reader{&reader};
|
||||||
try {
|
try {
|
||||||
Reflect(json_reader, *config);
|
Reflect(json_reader, *g_config);
|
||||||
} catch (std::invalid_argument&) {
|
} catch (std::invalid_argument&) {
|
||||||
// This will not trigger because parse error is handled in
|
// This will not trigger because parse error is handled in
|
||||||
// MessageRegistry::Parse in lsp.cc
|
// MessageRegistry::Parse in lsp.cc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->cacheDirectory.empty()) {
|
if (g_config->cacheDirectory.empty()) {
|
||||||
LOG_S(ERROR) << "cacheDirectory cannot be empty.";
|
LOG_S(ERROR) << "cacheDirectory cannot be empty.";
|
||||||
exit(1);
|
exit(1);
|
||||||
} else {
|
} else {
|
||||||
config->cacheDirectory = NormalizePath(config->cacheDirectory);
|
g_config->cacheDirectory = NormalizePath(g_config->cacheDirectory);
|
||||||
EnsureEndsInSlash(config->cacheDirectory);
|
EnsureEndsInSlash(g_config->cacheDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client capabilities
|
// Client capabilities
|
||||||
{
|
const auto& capabilities = params.capabilities;
|
||||||
const auto& cap = request->params.capabilities.textDocument;
|
g_config->client.snippetSupport =
|
||||||
if (cap.completion.completionItem)
|
capabilities.textDocument.completion.completionItem.snippetSupport;
|
||||||
config->client.snippetSupport =
|
|
||||||
cap.completion.completionItem->snippetSupport.value_or(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure there is a resource directory.
|
// Ensure there is a resource directory.
|
||||||
if (config->clang.resourceDir.empty())
|
if (g_config->clang.resourceDir.empty())
|
||||||
config->clang.resourceDir = GetDefaultResourceDirectory();
|
g_config->clang.resourceDir = GetDefaultResourceDirectory();
|
||||||
LOG_S(INFO) << "Using -resource-dir=" << config->clang.resourceDir;
|
LOG_S(INFO) << "Using -resource-dir=" << g_config->clang.resourceDir;
|
||||||
|
|
||||||
// Send initialization before starting indexers, so we don't send a
|
// Send initialization before starting indexers, so we don't send a
|
||||||
// status update too early.
|
// status update too early.
|
||||||
@ -491,15 +485,14 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
|
|
||||||
// Set project root.
|
// Set project root.
|
||||||
EnsureEndsInSlash(project_path);
|
EnsureEndsInSlash(project_path);
|
||||||
config->projectRoot = project_path;
|
g_config->projectRoot = project_path;
|
||||||
// Create two cache directories for files inside and outside of the
|
// Create two cache directories for files inside and outside of the
|
||||||
// project.
|
// project.
|
||||||
sys::fs::create_directories(config->cacheDirectory +
|
sys::fs::create_directories(g_config->cacheDirectory +
|
||||||
EscapeFileName(config->projectRoot));
|
EscapeFileName(g_config->projectRoot));
|
||||||
sys::fs::create_directories(config->cacheDirectory + '@' +
|
sys::fs::create_directories(g_config->cacheDirectory + '@' +
|
||||||
EscapeFileName(config->projectRoot));
|
EscapeFileName(g_config->projectRoot));
|
||||||
|
|
||||||
g_config = std::move(config);
|
|
||||||
Timer time;
|
Timer time;
|
||||||
diag_engine->Init();
|
diag_engine->Init();
|
||||||
semantic_cache->Init();
|
semantic_cache->Init();
|
||||||
@ -534,7 +527,6 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
// We need to support multiple concurrent index processes.
|
// We need to support multiple concurrent index processes.
|
||||||
time.ResetAndPrint("[perf] Dispatched initial index requests");
|
time.ResetAndPrint("[perf] Dispatched initial index requests");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
REGISTER_MESSAGE_HANDLER(Handler_Initialize);
|
REGISTER_MESSAGE_HANDLER(Handler_Initialize);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -26,17 +26,11 @@ struct Handler_TextDocumentDidChange
|
|||||||
std::string path = request->params.textDocument.uri.GetPath();
|
std::string path = request->params.textDocument.uri.GetPath();
|
||||||
working_files->OnChange(request->params);
|
working_files->OnChange(request->params);
|
||||||
if (g_config->index.onDidChange) {
|
if (g_config->index.onDidChange) {
|
||||||
std::optional<std::string> content = ReadContent(path);
|
|
||||||
if (!content) {
|
|
||||||
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
|
||||||
} else {
|
|
||||||
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
||||||
QueueManager::instance()->index_request.PushBack(
|
QueueManager::instance()->index_request.PushBack(
|
||||||
Index_Request(entry.filename, entry.args, true /*is_interactive*/,
|
Index_Request(entry.filename, entry.args, true /*is_interactive*/),
|
||||||
*content),
|
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
clang_complete->NotifyEdit(path);
|
clang_complete->NotifyEdit(path);
|
||||||
clang_complete->DiagnosticsUpdate(
|
clang_complete->DiagnosticsUpdate(
|
||||||
request->params.textDocument.AsTextDocumentIdentifier());
|
request->params.textDocument.AsTextDocumentIdentifier());
|
||||||
|
@ -65,7 +65,7 @@ struct Handler_TextDocumentDidOpen
|
|||||||
QueueManager::instance()->index_request.PushBack(
|
QueueManager::instance()->index_request.PushBack(
|
||||||
Index_Request(entry.filename,
|
Index_Request(entry.filename,
|
||||||
params.args.size() ? params.args : entry.args,
|
params.args.size() ? params.args : entry.args,
|
||||||
true /*is_interactive*/, params.textDocument.text),
|
true /*is_interactive*/),
|
||||||
true /* priority */);
|
true /* priority */);
|
||||||
|
|
||||||
clang_complete->FlushSession(entry.filename);
|
clang_complete->FlushSession(entry.filename);
|
||||||
|
@ -48,17 +48,11 @@ struct Handler_TextDocumentDidSave
|
|||||||
// if so, ignore that index response.
|
// if so, ignore that index response.
|
||||||
// TODO: send as priority request
|
// TODO: send as priority request
|
||||||
if (!g_config->index.onDidChange) {
|
if (!g_config->index.onDidChange) {
|
||||||
std::optional<std::string> content = ReadContent(path);
|
|
||||||
if (!content) {
|
|
||||||
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
|
||||||
} else {
|
|
||||||
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
Project::Entry entry = project->FindCompilationEntryForFile(path);
|
||||||
QueueManager::instance()->index_request.PushBack(
|
QueueManager::instance()->index_request.PushBack(
|
||||||
Index_Request(entry.filename, entry.args, true /*is_interactive*/,
|
Index_Request(entry.filename, entry.args, true /*is_interactive*/),
|
||||||
*content),
|
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
clang_complete->NotifySave(path);
|
clang_complete->NotifySave(path);
|
||||||
}
|
}
|
||||||
|
@ -54,20 +54,15 @@ struct Handler_WorkspaceDidChangeWatchedFiles
|
|||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case lsFileChangeType::Created:
|
case lsFileChangeType::Created:
|
||||||
case lsFileChangeType::Changed: {
|
case lsFileChangeType::Changed: {
|
||||||
std::optional<std::string> content = ReadContent(path);
|
|
||||||
if (!content)
|
|
||||||
LOG_S(ERROR) << "Unable to read file content after saving " << path;
|
|
||||||
else {
|
|
||||||
QueueManager::instance()->index_request.PushBack(
|
QueueManager::instance()->index_request.PushBack(
|
||||||
Index_Request(path, entry.args, is_interactive, *content));
|
Index_Request(path, entry.args, is_interactive));
|
||||||
if (is_interactive)
|
if (is_interactive)
|
||||||
clang_complete->NotifySave(path);
|
clang_complete->NotifySave(path);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lsFileChangeType::Deleted:
|
case lsFileChangeType::Deleted:
|
||||||
QueueManager::instance()->index_request.PushBack(
|
QueueManager::instance()->index_request.PushBack(
|
||||||
Index_Request(path, entry.args, is_interactive, std::string()));
|
Index_Request(path, entry.args, is_interactive));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,19 +458,13 @@ void Project::Index(QueueManager* queue,
|
|||||||
WorkingFiles* wfiles,
|
WorkingFiles* wfiles,
|
||||||
lsRequestId id) {
|
lsRequestId id) {
|
||||||
ForAllFilteredFiles([&](int i, const Project::Entry& entry) {
|
ForAllFilteredFiles([&](int i, const Project::Entry& entry) {
|
||||||
std::optional<std::string> content = ReadContent(entry.filename);
|
|
||||||
if (!content) {
|
|
||||||
LOG_S(ERROR) << "When loading project, canont read file "
|
|
||||||
<< entry.filename;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bool is_interactive = wfiles->GetFileByFilename(entry.filename) != nullptr;
|
bool is_interactive = wfiles->GetFileByFilename(entry.filename) != nullptr;
|
||||||
queue->index_request.PushBack(Index_Request(entry.filename, entry.args,
|
queue->index_request.PushBack(
|
||||||
is_interactive, *content, id));
|
Index_Request(entry.filename, entry.args, is_interactive, id));
|
||||||
});
|
});
|
||||||
// Dummy request to indicate that project is loaded and
|
// Dummy request to indicate that project is loaded and
|
||||||
// trigger refreshing semantic highlight for all working files.
|
// trigger refreshing semantic highlight for all working files.
|
||||||
queue->index_request.PushBack(Index_Request("", {}, false, ""));
|
queue->index_request.PushBack(Index_Request("", {}, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_SUITE("Project") {
|
TEST_SUITE("Project") {
|
||||||
|
@ -6,17 +6,11 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
Index_Request::Index_Request(
|
Index_Request::Index_Request(const std::string& path,
|
||||||
const std::string& path,
|
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
bool is_interactive,
|
bool is_interactive,
|
||||||
const std::string& contents,
|
|
||||||
lsRequestId id)
|
lsRequestId id)
|
||||||
: path(path),
|
: path(path), args(args), is_interactive(is_interactive), id(id) {}
|
||||||
args(args),
|
|
||||||
is_interactive(is_interactive),
|
|
||||||
contents(contents),
|
|
||||||
id(id) {}
|
|
||||||
|
|
||||||
Index_OnIndexed::Index_OnIndexed(IndexUpdate&& update,
|
Index_OnIndexed::Index_OnIndexed(IndexUpdate&& update,
|
||||||
PerformanceImportFile perf)
|
PerformanceImportFile perf)
|
||||||
|
@ -19,13 +19,11 @@ struct Index_Request {
|
|||||||
// TODO: make |args| a string that is parsed lazily.
|
// TODO: make |args| a string that is parsed lazily.
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
bool is_interactive;
|
bool is_interactive;
|
||||||
std::string contents; // Preloaded contents.
|
|
||||||
lsRequestId id;
|
lsRequestId id;
|
||||||
|
|
||||||
Index_Request(const std::string& path,
|
Index_Request(const std::string& path,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
bool is_interactive,
|
bool is_interactive,
|
||||||
const std::string& contents,
|
|
||||||
lsRequestId id = {});
|
lsRequestId id = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user