mirror of
https://github.com/MaskRay/ccls.git
synced 2025-03-24 01:26:54 +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);
|
||||
}
|
||||
|
||||
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 {
|
||||
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());
|
||||
if (request->params.rootUri) {
|
||||
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;
|
||||
open_project.project_path = project_path;
|
||||
ipc->SendToServer(&open_project);
|
||||
@ -434,6 +570,7 @@ void LanguageServerStdinLoop(IpcClient* ipc) {
|
||||
auto response = Out_InitializeResponse();
|
||||
response.id = message->id.value();
|
||||
response.result.capabilities.documentSymbolProvider = true;
|
||||
response.result.capabilities.workspaceSymbolProvider = true;
|
||||
response.Send();
|
||||
break;
|
||||
}
|
||||
@ -451,6 +588,17 @@ void LanguageServerStdinLoop(IpcClient* ipc) {
|
||||
ipc->SendToServer(&ipc_request);
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
std::cerr << "Unhandled IPC message with kind " << message->runtime_id() << " (hash " << message->hashed_runtime_id() << ")" << std::endl;
|
||||
exit(1);
|
||||
@ -519,8 +677,8 @@ void LanguageServerMain(std::string process_name) {
|
||||
/*stderr*/[](const char* bytes, size_t n) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
std::cerr << bytes[i];
|
||||
},
|
||||
/*open_stdin*/false);
|
||||
},
|
||||
/*open_stdin*/false);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
// Pass empty process name so we only try to start the querydb once.
|
||||
LanguageServerMain("");
|
||||
@ -621,10 +779,14 @@ int main(int argc, char** argv) {
|
||||
IpcRegistry::instance()->Register<IpcMessage_DocumentSymbolsRequest>();
|
||||
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_InitializeRequest>();
|
||||
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_WorkspaceSymbolRequest>();
|
||||
|
||||
|
||||
|
||||
|
@ -349,6 +349,7 @@ namespace language_server_api {
|
||||
Initialize,
|
||||
Initialized,
|
||||
TextDocumentDocumentSymbol,
|
||||
WorkspaceSymbol,
|
||||
};
|
||||
|
||||
const char* MethodIdToString(MethodId id) {
|
||||
@ -361,6 +362,8 @@ namespace language_server_api {
|
||||
return "initialized";
|
||||
case MethodId::TextDocumentDocumentSymbol:
|
||||
return "textDocument/documentSymbol";
|
||||
case MethodId::WorkspaceSymbol:
|
||||
return "workspace/symbol";
|
||||
default:
|
||||
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;
|
||||
};
|
||||
|
||||
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<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.
|
||||
for (Usr usr : to_remove)
|
||||
usr_to_symbol[usr].kind = SymbolKind::Invalid;
|
||||
// TODO: also remove from qualified_names?
|
||||
}
|
||||
|
||||
void QueryableDatabase::Import(const std::vector<QueryableFile>& 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());
|
||||
files.push_back(def);
|
||||
}
|
||||
@ -518,6 +521,8 @@ void QueryableDatabase::Import(const std::vector<QueryableFile>& defs) {
|
||||
|
||||
void QueryableDatabase::Import(const std::vector<QueryableTypeDef>& 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());
|
||||
types.push_back(def);
|
||||
}
|
||||
@ -525,6 +530,8 @@ void QueryableDatabase::Import(const std::vector<QueryableTypeDef>& defs) {
|
||||
|
||||
void QueryableDatabase::Import(const std::vector<QueryableFuncDef>& 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());
|
||||
funcs.push_back(def);
|
||||
}
|
||||
@ -532,6 +539,8 @@ void QueryableDatabase::Import(const std::vector<QueryableFuncDef>& defs) {
|
||||
|
||||
void QueryableDatabase::Import(const std::vector<QueryableVarDef>& 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());
|
||||
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) {
|
||||
#define HANDLE_MERGEABLE(update_var_name, def_var_name, storage_name) \
|
||||
for (auto merge_update : update->update_var_name) { \
|
||||
|
Loading…
Reference in New Issue
Block a user