diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 8c3435ef..f6233858 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -137,6 +137,8 @@ struct lsServerCapabilities { lsSignatureHelpOptions signatureHelpProvider; // The server provides goto definition support. bool definitionProvider = true; + // The server provides Goto Type Definition support. + bool typeDefinitionProvider = true; // The server provides find references support. bool referencesProvider = true; // The server provides document highlight support. diff --git a/src/messages/text_document_type_definition.cc b/src/messages/text_document_type_definition.cc index 7899394a..9745862b 100644 --- a/src/messages/text_document_type_definition.cc +++ b/src/messages/text_document_type_definition.cc @@ -22,6 +22,44 @@ MAKE_REFLECT_STRUCT(Out_TextDocumentTypeDefinition, jsonrpc, id, result); struct TextDocumentTypeDefinitionHandler : BaseMessageHandler { void Run(Ipc_TextDocumentTypeDefinition* request) override { + QueryFile* file; + if (!FindFileOrFail(db, project, request->id, + request->params.textDocument.uri.GetPath(), &file, + nullptr)) { + return; + } + WorkingFile* working_file = + working_files->GetFileByFilename(file->def->path); + + Out_TextDocumentTypeDefinition out; + out.id = request->id; + for (SymbolRef sym : + FindSymbolsAtLocation(working_file, file, request->params.position)) { + Id id = sym.id; + switch (sym.kind) { + case SymbolKind::Var: { + const QueryVar::Def* def = db->GetVar(sym).AnyDef(); + if (!def || !def->type) + continue; + id = *def->type; + } + // fallthrough + case SymbolKind::Type: { + QueryType& type = db->types[id.id]; + for (const auto& def : type.def) + if (def.spell) { + if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell, + config->xref.container)) + out.result.push_back(*ls_loc); + } + break; + } + default: + break; + } + } + + QueueManager::WriteStdout(IpcId::TextDocumentTypeDefinition, out); } }; REGISTER_MESSAGE_HANDLER(TextDocumentTypeDefinitionHandler);