diff --git a/command_line.cc b/command_line.cc index a892ed51..1205fcf4 100644 --- a/command_line.cc +++ b/command_line.cc @@ -229,6 +229,58 @@ IpcMessageId IpcMessage_DocumentSymbolsResponse::kId = "IpcMessage_DocumentSymbo +struct IpcMessage_WorkspaceSymbolsRequest : public BaseIpcMessage { + 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 { + language_server_api::RequestId id; + std::vector 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(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(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(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(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(); IpcRegistry::instance()->Register(); + IpcRegistry::instance()->Register(); + IpcRegistry::instance()->Register(); + language_server_api::MessageRegistry::instance()->Register(); language_server_api::MessageRegistry::instance()->Register(); language_server_api::MessageRegistry::instance()->Register(); language_server_api::MessageRegistry::instance()->Register(); + language_server_api::MessageRegistry::instance()->Register(); diff --git a/language_server_api.h b/language_server_api.h index cd824c6c..ae425641 100644 --- a/language_server_api.h +++ b/language_server_api.h @@ -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 id, const Reader& reader) + : InRequestMessage(kMethod, id, reader) { + Deserialize(reader, params); + } + }; + + + struct Out_WorkspaceSymbolResponse : public OutResponseMessage { + std::vector result; + + // OutResponseMessage: + void WriteResult(Writer& writer) override { + Serialize(writer, result); + } + }; + + + diff --git a/platform.h b/platform.h index 0202395e..a05fb95d 100644 --- a/platform.h +++ b/platform.h @@ -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 CreatePlatformMutex(const std::string& name); std::unique_ptr CreatePlatformScopedMutexLock(PlatformMutex* mutex); diff --git a/query.cc b/query.cc index aba9c925..9d4af271 100644 --- a/query.cc +++ b/query.cc @@ -507,10 +507,13 @@ void QueryableDatabase::RemoveUsrs(const std::vector& 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& 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& defs) { void QueryableDatabase::Import(const std::vector& 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& defs) { void QueryableDatabase::Import(const std::vector& 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& defs) { void QueryableDatabase::Import(const std::vector& 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& up } } - -template -void AddAll(std::unordered_map* id_map, std::vector* defs, const std::vector& to_add) { - for (const TDef& def : to_add) { - (*id_map)[def.def.id] = defs->size(); - defs->push_back(def); - } -} - -template -void ApplyUpdates(std::unordered_map* id_map, std::vector* defs, const std::vector& 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) { \