mirror of
https://github.com/MaskRay/ccls.git
synced 2025-05-11 10:55:21 +00:00
wip global symbol search
This commit is contained in:
parent
2db753ff92
commit
7a160a5269
168
command_line.cc
168
command_line.cc
@ -229,6 +229,58 @@ IpcMessageId IpcMessage_DocumentSymbolsResponse::kId = "IpcMessage_DocumentSymbo
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct IpcMessage_WorkspaceSymbolsRequest : public BaseIpcMessage<IpcMessage_WorkspaceSymbolsRequest> {
|
||||||
|
language_server_api::RequestId id;
|
||||||
|
std::string query;
|
||||||
|
|
||||||
|
// BaseIpcMessage:
|
||||||
|
static IpcMessageId kId;
|
||||||
|
void Serialize(Writer& writer) override {
|
||||||
|
using namespace language_server_api;
|
||||||
|
auto& value = *this;
|
||||||
|
|
||||||
|
writer.StartObject();
|
||||||
|
SERIALIZE_MEMBER(id);
|
||||||
|
SERIALIZE_MEMBER(query);
|
||||||
|
writer.EndObject();
|
||||||
|
}
|
||||||
|
void Deserialize(Reader& reader) override {
|
||||||
|
using namespace language_server_api;
|
||||||
|
auto& value = *this;
|
||||||
|
|
||||||
|
DESERIALIZE_MEMBER(id);
|
||||||
|
DESERIALIZE_MEMBER(query);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
IpcMessageId IpcMessage_WorkspaceSymbolsRequest::kId = "IpcMessage_WorkspaceSymbolsRequest";
|
||||||
|
|
||||||
|
struct IpcMessage_WorkspaceSymbolsResponse : public BaseIpcMessage<IpcMessage_WorkspaceSymbolsResponse> {
|
||||||
|
language_server_api::RequestId id;
|
||||||
|
std::vector<language_server_api::SymbolInformation> symbols;
|
||||||
|
|
||||||
|
// BaseIpcMessage:
|
||||||
|
static IpcMessageId kId;
|
||||||
|
void Serialize(Writer& writer) override {
|
||||||
|
using namespace language_server_api;
|
||||||
|
auto& value = *this;
|
||||||
|
|
||||||
|
writer.StartObject();
|
||||||
|
SERIALIZE_MEMBER(id);
|
||||||
|
SERIALIZE_MEMBER(symbols);
|
||||||
|
writer.EndObject();
|
||||||
|
}
|
||||||
|
void Deserialize(Reader& reader) override {
|
||||||
|
using namespace language_server_api;
|
||||||
|
auto& value = *this;
|
||||||
|
|
||||||
|
DESERIALIZE_MEMBER(id);
|
||||||
|
DESERIALIZE_MEMBER(symbols);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
IpcMessageId IpcMessage_WorkspaceSymbolsResponse::kId = "IpcMessage_WorkspaceSymbolsResponse";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -363,6 +415,90 @@ void QueryDbMainLoop(IpcServer* ipc, QueryableDatabase* db) {
|
|||||||
ipc->SendToClient(0, &response);
|
ipc->SendToClient(0, &response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (IpcMessage_WorkspaceSymbolsRequest::kId == message->runtime_id()) {
|
||||||
|
auto msg = static_cast<IpcMessage_WorkspaceSymbolsRequest*>(message.get());
|
||||||
|
|
||||||
|
IpcMessage_WorkspaceSymbolsResponse response;
|
||||||
|
response.id = msg->id;
|
||||||
|
|
||||||
|
std::cerr << "- Considering " << db->qualified_names.size() << " candidates " << std::endl;
|
||||||
|
|
||||||
|
for (int i = 0; i < db->qualified_names.size(); ++i) {
|
||||||
|
const std::string& name = db->qualified_names[i];
|
||||||
|
//std::cerr << "- Considering " << name << std::endl;
|
||||||
|
|
||||||
|
if (name.find(msg->query) != std::string::npos) {
|
||||||
|
|
||||||
|
SymbolInformation info;
|
||||||
|
info.name = name;
|
||||||
|
|
||||||
|
SymbolIdx symbol = db->symbols[i];
|
||||||
|
|
||||||
|
// TODO: dedup this code w/ above (ie, add ctor to convert symbol to SymbolInformation)
|
||||||
|
switch (symbol.kind) {
|
||||||
|
// TODO: file
|
||||||
|
case ::SymbolKind::Type:
|
||||||
|
{
|
||||||
|
QueryableTypeDef& def = db->types[symbol.idx];
|
||||||
|
info.name = def.def.qualified_name;
|
||||||
|
info.kind = language_server_api::SymbolKind::Class;
|
||||||
|
|
||||||
|
if (def.def.definition.has_value()) {
|
||||||
|
info.location.range.start.line = def.def.definition->line - 1;
|
||||||
|
info.location.range.start.character = def.def.definition->column - 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ::SymbolKind::Func:
|
||||||
|
{
|
||||||
|
QueryableFuncDef& def = db->funcs[symbol.idx];
|
||||||
|
info.name = def.def.qualified_name;
|
||||||
|
if (def.def.declaring_type.has_value()) {
|
||||||
|
info.kind = language_server_api::SymbolKind::Method;
|
||||||
|
Usr declaring = def.def.declaring_type.value();
|
||||||
|
info.containerName = db->types[db->usr_to_symbol[declaring].idx].def.qualified_name;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
info.kind = language_server_api::SymbolKind::Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def.def.definition.has_value()) {
|
||||||
|
info.location.range.start.line = def.def.definition->line - 1;
|
||||||
|
info.location.range.start.character = def.def.definition->column - 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ::SymbolKind::Var:
|
||||||
|
{
|
||||||
|
QueryableVarDef& def = db->vars[symbol.idx];
|
||||||
|
info.name = def.def.qualified_name;
|
||||||
|
info.kind = language_server_api::SymbolKind::Variable;
|
||||||
|
|
||||||
|
if (def.def.definition.has_value()) {
|
||||||
|
info.location.range.start.line = def.def.definition->line - 1;
|
||||||
|
info.location.range.start.character = def.def.definition->column - 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: store range information.
|
||||||
|
info.location.range.end.line = info.location.range.start.line;
|
||||||
|
info.location.range.end.character = info.location.range.start.character;
|
||||||
|
|
||||||
|
response.symbols.push_back(info);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ipc->SendToClient(0, &response);
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
std::cerr << "Unhandled IPC message with kind " << message->runtime_id() << " (hash " << message->hashed_runtime_id() << ")" << std::endl;
|
std::cerr << "Unhandled IPC message with kind " << message->runtime_id() << " (hash " << message->hashed_runtime_id() << ")" << std::endl;
|
||||||
@ -425,7 +561,7 @@ void LanguageServerStdinLoop(IpcClient* ipc) {
|
|||||||
auto request = static_cast<In_InitializeRequest*>(message.get());
|
auto request = static_cast<In_InitializeRequest*>(message.get());
|
||||||
if (request->params.rootUri) {
|
if (request->params.rootUri) {
|
||||||
std::string project_path = request->params.rootUri->GetPath();
|
std::string project_path = request->params.rootUri->GetPath();
|
||||||
std::cerr << "Initialize in directory " << project_path << std::endl;
|
std::cerr << "Initialize in directory " << project_path << " with uri " << request->params.rootUri->raw_uri << std::endl;
|
||||||
IpcMessage_OpenProject open_project;
|
IpcMessage_OpenProject open_project;
|
||||||
open_project.project_path = project_path;
|
open_project.project_path = project_path;
|
||||||
ipc->SendToServer(&open_project);
|
ipc->SendToServer(&open_project);
|
||||||
@ -434,6 +570,7 @@ void LanguageServerStdinLoop(IpcClient* ipc) {
|
|||||||
auto response = Out_InitializeResponse();
|
auto response = Out_InitializeResponse();
|
||||||
response.id = message->id.value();
|
response.id = message->id.value();
|
||||||
response.result.capabilities.documentSymbolProvider = true;
|
response.result.capabilities.documentSymbolProvider = true;
|
||||||
|
response.result.capabilities.workspaceSymbolProvider = true;
|
||||||
response.Send();
|
response.Send();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -451,6 +588,17 @@ void LanguageServerStdinLoop(IpcClient* ipc) {
|
|||||||
ipc->SendToServer(&ipc_request);
|
ipc->SendToServer(&ipc_request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MethodId::WorkspaceSymbol:
|
||||||
|
{
|
||||||
|
auto request = static_cast<In_WorkspaceSymbolRequest*>(message.get());
|
||||||
|
IpcMessage_WorkspaceSymbolsRequest ipc_request;
|
||||||
|
ipc_request.id = request->id.value();
|
||||||
|
ipc_request.query = request->params.query;
|
||||||
|
std::cerr << "Request query=" << ipc_request.query << std::endl;
|
||||||
|
ipc->SendToServer(&ipc_request);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -475,6 +623,16 @@ void LanguageServerMainLoop(IpcClient* ipc) {
|
|||||||
std::cerr << "Send symbol response to client (" << response.result.size() << " symbols)" << std::endl;
|
std::cerr << "Send symbol response to client (" << response.result.size() << " symbols)" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (IpcMessage_WorkspaceSymbolsResponse::kId == message->runtime_id()) {
|
||||||
|
auto msg = static_cast<IpcMessage_WorkspaceSymbolsResponse*>(message.get());
|
||||||
|
|
||||||
|
auto response = Out_WorkspaceSymbolResponse();
|
||||||
|
response.id = msg->id;
|
||||||
|
response.result = msg->symbols;
|
||||||
|
response.Send();
|
||||||
|
std::cerr << "Send symbol response to client (" << response.result.size() << " symbols)" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
std::cerr << "Unhandled IPC message with kind " << message->runtime_id() << " (hash " << message->hashed_runtime_id() << ")" << std::endl;
|
std::cerr << "Unhandled IPC message with kind " << message->runtime_id() << " (hash " << message->hashed_runtime_id() << ")" << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -519,8 +677,8 @@ void LanguageServerMain(std::string process_name) {
|
|||||||
/*stderr*/[](const char* bytes, size_t n) {
|
/*stderr*/[](const char* bytes, size_t n) {
|
||||||
for (int i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
std::cerr << bytes[i];
|
std::cerr << bytes[i];
|
||||||
},
|
},
|
||||||
/*open_stdin*/false);
|
/*open_stdin*/false);
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
// Pass empty process name so we only try to start the querydb once.
|
// Pass empty process name so we only try to start the querydb once.
|
||||||
LanguageServerMain("");
|
LanguageServerMain("");
|
||||||
@ -621,10 +779,14 @@ int main(int argc, char** argv) {
|
|||||||
IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsRequest>();
|
IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsRequest>();
|
||||||
IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsResponse>();
|
IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsResponse>();
|
||||||
|
|
||||||
|
IpcRegistry::instance()->Register<IpcMessage_WorkspaceSymbolsRequest>();
|
||||||
|
IpcRegistry::instance()->Register<IpcMessage_WorkspaceSymbolsResponse>();
|
||||||
|
|
||||||
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_CancelRequest>();
|
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_CancelRequest>();
|
||||||
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_InitializeRequest>();
|
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_InitializeRequest>();
|
||||||
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_InitializedNotification>();
|
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_InitializedNotification>();
|
||||||
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_DocumentSymbolRequest>();
|
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_DocumentSymbolRequest>();
|
||||||
|
language_server_api::MessageRegistry::instance()->Register<language_server_api::In_WorkspaceSymbolRequest>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -349,6 +349,7 @@ namespace language_server_api {
|
|||||||
Initialize,
|
Initialize,
|
||||||
Initialized,
|
Initialized,
|
||||||
TextDocumentDocumentSymbol,
|
TextDocumentDocumentSymbol,
|
||||||
|
WorkspaceSymbol,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* MethodIdToString(MethodId id) {
|
const char* MethodIdToString(MethodId id) {
|
||||||
@ -361,6 +362,8 @@ namespace language_server_api {
|
|||||||
return "initialized";
|
return "initialized";
|
||||||
case MethodId::TextDocumentDocumentSymbol:
|
case MethodId::TextDocumentDocumentSymbol:
|
||||||
return "textDocument/documentSymbol";
|
return "textDocument/documentSymbol";
|
||||||
|
case MethodId::WorkspaceSymbol:
|
||||||
|
return "workspace/symbol";
|
||||||
default:
|
default:
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -1389,6 +1392,37 @@ namespace language_server_api {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct WorkspaceSymbolParams {
|
||||||
|
std::string query;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Deserialize(const Reader& reader, WorkspaceSymbolParams& value) {
|
||||||
|
DESERIALIZE_MEMBER(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct In_WorkspaceSymbolRequest : public InRequestMessage {
|
||||||
|
const static MethodId kMethod = MethodId::WorkspaceSymbol;
|
||||||
|
|
||||||
|
WorkspaceSymbolParams params;
|
||||||
|
|
||||||
|
In_WorkspaceSymbolRequest(optional<RequestId> id, const Reader& reader)
|
||||||
|
: InRequestMessage(kMethod, id, reader) {
|
||||||
|
Deserialize(reader, params);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Out_WorkspaceSymbolResponse : public OutResponseMessage {
|
||||||
|
std::vector<SymbolInformation> result;
|
||||||
|
|
||||||
|
// OutResponseMessage:
|
||||||
|
void WriteResult(Writer& writer) override {
|
||||||
|
Serialize(writer, result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ struct PlatformSharedMemory {
|
|||||||
char* shared_start;
|
char* shared_start;
|
||||||
};
|
};
|
||||||
|
|
||||||
const int shmem_size = 1024 * 256; // number of chars/bytes (256kb)
|
const int shmem_size = 1024 * 1024 * 32; // number of chars/bytes (32mb)
|
||||||
|
|
||||||
std::unique_ptr<PlatformMutex> CreatePlatformMutex(const std::string& name);
|
std::unique_ptr<PlatformMutex> CreatePlatformMutex(const std::string& name);
|
||||||
std::unique_ptr<PlatformScopedMutexLock> CreatePlatformScopedMutexLock(PlatformMutex* mutex);
|
std::unique_ptr<PlatformScopedMutexLock> CreatePlatformScopedMutexLock(PlatformMutex* mutex);
|
||||||
|
27
query.cc
27
query.cc
@ -507,10 +507,13 @@ void QueryableDatabase::RemoveUsrs(const std::vector<Usr>& to_remove) {
|
|||||||
// the entry instead of actually removing the data. The index could be massive.
|
// the entry instead of actually removing the data. The index could be massive.
|
||||||
for (Usr usr : to_remove)
|
for (Usr usr : to_remove)
|
||||||
usr_to_symbol[usr].kind = SymbolKind::Invalid;
|
usr_to_symbol[usr].kind = SymbolKind::Invalid;
|
||||||
|
// TODO: also remove from qualified_names?
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryableDatabase::Import(const std::vector<QueryableFile>& defs) {
|
void QueryableDatabase::Import(const std::vector<QueryableFile>& defs) {
|
||||||
for (auto& def : defs) {
|
for (auto& def : defs) {
|
||||||
|
qualified_names.push_back(def.file_id);
|
||||||
|
symbols.push_back(SymbolIdx(SymbolKind::File, files.size()));
|
||||||
usr_to_symbol[def.file_id] = SymbolIdx(SymbolKind::File, files.size());
|
usr_to_symbol[def.file_id] = SymbolIdx(SymbolKind::File, files.size());
|
||||||
files.push_back(def);
|
files.push_back(def);
|
||||||
}
|
}
|
||||||
@ -518,6 +521,8 @@ void QueryableDatabase::Import(const std::vector<QueryableFile>& defs) {
|
|||||||
|
|
||||||
void QueryableDatabase::Import(const std::vector<QueryableTypeDef>& defs) {
|
void QueryableDatabase::Import(const std::vector<QueryableTypeDef>& defs) {
|
||||||
for (auto& def : defs) {
|
for (auto& def : defs) {
|
||||||
|
qualified_names.push_back(def.def.qualified_name);
|
||||||
|
symbols.push_back(SymbolIdx(SymbolKind::Type, types.size()));
|
||||||
usr_to_symbol[def.def.usr] = SymbolIdx(SymbolKind::Type, types.size());
|
usr_to_symbol[def.def.usr] = SymbolIdx(SymbolKind::Type, types.size());
|
||||||
types.push_back(def);
|
types.push_back(def);
|
||||||
}
|
}
|
||||||
@ -525,6 +530,8 @@ void QueryableDatabase::Import(const std::vector<QueryableTypeDef>& defs) {
|
|||||||
|
|
||||||
void QueryableDatabase::Import(const std::vector<QueryableFuncDef>& defs) {
|
void QueryableDatabase::Import(const std::vector<QueryableFuncDef>& defs) {
|
||||||
for (auto& def : defs) {
|
for (auto& def : defs) {
|
||||||
|
qualified_names.push_back(def.def.qualified_name);
|
||||||
|
symbols.push_back(SymbolIdx(SymbolKind::Func, funcs.size()));
|
||||||
usr_to_symbol[def.def.usr] = SymbolIdx(SymbolKind::Func, funcs.size());
|
usr_to_symbol[def.def.usr] = SymbolIdx(SymbolKind::Func, funcs.size());
|
||||||
funcs.push_back(def);
|
funcs.push_back(def);
|
||||||
}
|
}
|
||||||
@ -532,6 +539,8 @@ void QueryableDatabase::Import(const std::vector<QueryableFuncDef>& defs) {
|
|||||||
|
|
||||||
void QueryableDatabase::Import(const std::vector<QueryableVarDef>& defs) {
|
void QueryableDatabase::Import(const std::vector<QueryableVarDef>& defs) {
|
||||||
for (auto& def : defs) {
|
for (auto& def : defs) {
|
||||||
|
qualified_names.push_back(def.def.qualified_name);
|
||||||
|
symbols.push_back(SymbolIdx(SymbolKind::Var, vars.size()));
|
||||||
usr_to_symbol[def.def.usr] = SymbolIdx(SymbolKind::Var, vars.size());
|
usr_to_symbol[def.def.usr] = SymbolIdx(SymbolKind::Var, vars.size());
|
||||||
vars.push_back(def);
|
vars.push_back(def);
|
||||||
}
|
}
|
||||||
@ -561,24 +570,6 @@ void QueryableDatabase::Update(const std::vector<QueryableVarDef::DefUpdate>& up
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename TDef, typename TId>
|
|
||||||
void AddAll(std::unordered_map<TId, int>* id_map, std::vector<TDef>* defs, const std::vector<TDef>& to_add) {
|
|
||||||
for (const TDef& def : to_add) {
|
|
||||||
(*id_map)[def.def.id] = defs->size();
|
|
||||||
defs->push_back(def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TDef, typename TId>
|
|
||||||
void ApplyUpdates(std::unordered_map<TId, int>* id_map, std::vector<TDef>* defs, const std::vector<typename TDef::DefUpdate>& updates) {
|
|
||||||
for (const typename TDef::DefUpdate& def : updates) {
|
|
||||||
TId id = def.id;
|
|
||||||
int index = (*id_map)[id];
|
|
||||||
(*defs)[index].def = def;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QueryableDatabase::ApplyIndexUpdate(IndexUpdate* update) {
|
void QueryableDatabase::ApplyIndexUpdate(IndexUpdate* update) {
|
||||||
#define HANDLE_MERGEABLE(update_var_name, def_var_name, storage_name) \
|
#define HANDLE_MERGEABLE(update_var_name, def_var_name, storage_name) \
|
||||||
for (auto merge_update : update->update_var_name) { \
|
for (auto merge_update : update->update_var_name) { \
|
||||||
|
Loading…
Reference in New Issue
Block a user