mirror of
https://github.com/MaskRay/ccls.git
synced 2024-12-01 20:07:08 +00:00
Support keyboard shortcuts for vars, callers, base, and derived.
This commit is contained in:
parent
fc55589ed3
commit
5524abdaa7
@ -526,6 +526,21 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db, WorkingFiles* working_file
|
|||||||
return lsLocation(uri, *range);
|
return lsLocation(uri, *range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NonElidedVector<lsLocation> GetLsLocations(QueryDatabase* db, WorkingFiles* working_files, const std::vector<QueryLocation>& locations) {
|
||||||
|
std::unordered_set<lsLocation> unique_locations;
|
||||||
|
for (const QueryLocation& query_location : locations) {
|
||||||
|
optional<lsLocation> location = GetLsLocation(db, working_files, query_location);
|
||||||
|
if (!location)
|
||||||
|
continue;
|
||||||
|
unique_locations.insert(*location);
|
||||||
|
}
|
||||||
|
|
||||||
|
NonElidedVector<lsLocation> result;
|
||||||
|
result.reserve(unique_locations.size());
|
||||||
|
result.assign(unique_locations.begin(), unique_locations.end());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a symbol. The symbol will have *NOT* have a location assigned.
|
// Returns a symbol. The symbol will have *NOT* have a location assigned.
|
||||||
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, WorkingFiles* working_files, SymbolIdx symbol) {
|
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, WorkingFiles* working_files, SymbolIdx symbol) {
|
||||||
switch (symbol.kind) {
|
switch (symbol.kind) {
|
||||||
@ -606,7 +621,7 @@ void AddCodeLens(
|
|||||||
return;
|
return;
|
||||||
code_lens.range = *range;
|
code_lens.range = *range;
|
||||||
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
|
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
|
||||||
code_lens.command->command = "superindex.showReferences";
|
code_lens.command->command = "cquery.showReferences";
|
||||||
code_lens.command->arguments.uri = GetLsDocumentUri(common->db, loc.path);
|
code_lens.command->arguments.uri = GetLsDocumentUri(common->db, loc.path);
|
||||||
code_lens.command->arguments.position = code_lens.range.start;
|
code_lens.command->arguments.position = code_lens.range.start;
|
||||||
|
|
||||||
@ -806,6 +821,10 @@ void RegisterMessageTypes() {
|
|||||||
MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
|
MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
|
||||||
MessageRegistry::instance()->Register<Ipc_WorkspaceSymbol>();
|
MessageRegistry::instance()->Register<Ipc_WorkspaceSymbol>();
|
||||||
MessageRegistry::instance()->Register<Ipc_CqueryFreshenIndex>();
|
MessageRegistry::instance()->Register<Ipc_CqueryFreshenIndex>();
|
||||||
|
MessageRegistry::instance()->Register<Ipc_CqueryVars>();
|
||||||
|
MessageRegistry::instance()->Register<Ipc_CqueryCallers>();
|
||||||
|
MessageRegistry::instance()->Register<Ipc_CqueryBase>();
|
||||||
|
MessageRegistry::instance()->Register<Ipc_CqueryDerived>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1344,6 +1363,126 @@ bool QueryDbMainLoop(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case IpcId::CqueryVars: {
|
||||||
|
auto msg = static_cast<Ipc_CqueryVars*>(message.get());
|
||||||
|
|
||||||
|
QueryFile* file = FindFile(db, msg->params.textDocument.uri.GetPath());
|
||||||
|
if (!file) {
|
||||||
|
std::cerr << "Unable to find file " << msg->params.textDocument.uri.GetPath() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WorkingFile* working_file = working_files->GetFileByFilename(file->def.path);
|
||||||
|
|
||||||
|
Out_LocationList response;
|
||||||
|
response.id = msg->id;
|
||||||
|
for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) {
|
||||||
|
if (ref.idx.kind == SymbolKind::Type) {
|
||||||
|
optional<QueryType>& type = db->types[ref.idx.idx];
|
||||||
|
if (!type) continue;
|
||||||
|
std::vector<QueryLocation> locations = ToQueryLocation(db, type->instances);
|
||||||
|
response.result = GetLsLocations(db, working_files, locations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipc->SendOutMessageToClient(IpcId::TextDocumentReferences, response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IpcId::CqueryCallers: {
|
||||||
|
auto msg = static_cast<Ipc_CqueryCallers*>(message.get());
|
||||||
|
|
||||||
|
QueryFile* file = FindFile(db, msg->params.textDocument.uri.GetPath());
|
||||||
|
if (!file) {
|
||||||
|
std::cerr << "Unable to find file " << msg->params.textDocument.uri.GetPath() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WorkingFile* working_file = working_files->GetFileByFilename(file->def.path);
|
||||||
|
|
||||||
|
Out_LocationList response;
|
||||||
|
response.id = msg->id;
|
||||||
|
for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) {
|
||||||
|
if (ref.idx.kind == SymbolKind::Func) {
|
||||||
|
optional<QueryFunc>& func = db->funcs[ref.idx.idx];
|
||||||
|
if (!func) continue;
|
||||||
|
std::vector<QueryLocation> locations = ToQueryLocation(db, func->callers);
|
||||||
|
response.result = GetLsLocations(db, working_files, locations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipc->SendOutMessageToClient(IpcId::TextDocumentReferences, response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IpcId::CqueryBase: {
|
||||||
|
auto msg = static_cast<Ipc_CqueryBase*>(message.get());
|
||||||
|
|
||||||
|
QueryFile* file = FindFile(db, msg->params.textDocument.uri.GetPath());
|
||||||
|
if (!file) {
|
||||||
|
std::cerr << "Unable to find file " << msg->params.textDocument.uri.GetPath() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WorkingFile* working_file = working_files->GetFileByFilename(file->def.path);
|
||||||
|
|
||||||
|
Out_LocationList response;
|
||||||
|
response.id = msg->id;
|
||||||
|
for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) {
|
||||||
|
if (ref.idx.kind == SymbolKind::Type) {
|
||||||
|
optional<QueryType>& type = db->types[ref.idx.idx];
|
||||||
|
if (!type) continue;
|
||||||
|
std::vector<QueryLocation> locations = ToQueryLocation(db, type->def.parents);
|
||||||
|
response.result = GetLsLocations(db, working_files, locations);
|
||||||
|
}
|
||||||
|
else if (ref.idx.kind == SymbolKind::Func) {
|
||||||
|
optional<QueryFunc>& func = db->funcs[ref.idx.idx];
|
||||||
|
if (!func) continue;
|
||||||
|
optional<QueryLocation> location = GetBaseDefinitionOrDeclarationSpelling(db, *func);
|
||||||
|
if (!location) continue;
|
||||||
|
optional<lsLocation> ls_loc = GetLsLocation(db, working_files, *location);
|
||||||
|
if (!ls_loc) continue;
|
||||||
|
response.result.push_back(*ls_loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipc->SendOutMessageToClient(IpcId::TextDocumentReferences, response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IpcId::CqueryDerived: {
|
||||||
|
auto msg = static_cast<Ipc_CqueryDerived*>(message.get());
|
||||||
|
|
||||||
|
QueryFile* file = FindFile(db, msg->params.textDocument.uri.GetPath());
|
||||||
|
if (!file) {
|
||||||
|
std::cerr << "Unable to find file " << msg->params.textDocument.uri.GetPath() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WorkingFile* working_file = working_files->GetFileByFilename(file->def.path);
|
||||||
|
|
||||||
|
Out_LocationList response;
|
||||||
|
response.id = msg->id;
|
||||||
|
for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) {
|
||||||
|
if (ref.idx.kind == SymbolKind::Type) {
|
||||||
|
optional<QueryType>& type = db->types[ref.idx.idx];
|
||||||
|
if (!type) continue;
|
||||||
|
std::vector<QueryLocation> locations = ToQueryLocation(db, type->derived);
|
||||||
|
response.result = GetLsLocations(db, working_files, locations);
|
||||||
|
}
|
||||||
|
else if (ref.idx.kind == SymbolKind::Func) {
|
||||||
|
optional<QueryFunc>& func = db->funcs[ref.idx.idx];
|
||||||
|
if (!func) continue;
|
||||||
|
std::vector<QueryLocation> locations = ToQueryLocation(db, func->derived);
|
||||||
|
response.result = GetLsLocations(db, working_files, locations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipc->SendOutMessageToClient(IpcId::TextDocumentReferences, response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case IpcId::TextDocumentDidOpen: {
|
case IpcId::TextDocumentDidOpen: {
|
||||||
// NOTE: This function blocks code lens. If it starts taking a long time
|
// NOTE: This function blocks code lens. If it starts taking a long time
|
||||||
// we will need to find a way to unblock the code lens request.
|
// we will need to find a way to unblock the code lens request.
|
||||||
@ -1708,7 +1847,7 @@ bool QueryDbMainLoop(
|
|||||||
code_lens.range.start.character += offset++;
|
code_lens.range.start.character += offset++;
|
||||||
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
|
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
|
||||||
code_lens.command->title = "Base";
|
code_lens.command->title = "Base";
|
||||||
code_lens.command->command = "superindex.goto";
|
code_lens.command->command = "cquery.goto";
|
||||||
code_lens.command->arguments.uri = ls_base->uri;
|
code_lens.command->arguments.uri = ls_base->uri;
|
||||||
code_lens.command->arguments.position = ls_base->range.start;
|
code_lens.command->arguments.position = ls_base->range.start;
|
||||||
response.result.push_back(code_lens);
|
response.result.push_back(code_lens);
|
||||||
@ -1992,7 +2131,11 @@ void LanguageServerStdinLoop(IndexerConfig* config, std::unordered_map<IpcId, Ti
|
|||||||
case IpcId::TextDocumentDocumentSymbol:
|
case IpcId::TextDocumentDocumentSymbol:
|
||||||
case IpcId::TextDocumentCodeLens:
|
case IpcId::TextDocumentCodeLens:
|
||||||
case IpcId::WorkspaceSymbol:
|
case IpcId::WorkspaceSymbol:
|
||||||
case IpcId::CqueryFreshenIndex: {
|
case IpcId::CqueryFreshenIndex:
|
||||||
|
case IpcId::CqueryVars:
|
||||||
|
case IpcId::CqueryCallers:
|
||||||
|
case IpcId::CqueryBase:
|
||||||
|
case IpcId::CqueryDerived: {
|
||||||
ipc->SendMessage(IpcManager::Destination::Server, std::move(message));
|
ipc->SendMessage(IpcManager::Destination::Server, std::move(message));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
12
src/ipc.cc
12
src/ipc.cc
@ -41,9 +41,17 @@ const char* IpcIdToString(IpcId id) {
|
|||||||
case IpcId::WorkspaceSymbol:
|
case IpcId::WorkspaceSymbol:
|
||||||
return "workspace/symbol";
|
return "workspace/symbol";
|
||||||
|
|
||||||
case IpcId::CqueryFreshenIndex: {
|
case IpcId::CqueryFreshenIndex:
|
||||||
return "$cquery/freshenIndex";
|
return "$cquery/freshenIndex";
|
||||||
}
|
|
||||||
|
case IpcId::CqueryVars:
|
||||||
|
return "$cquery/vars";
|
||||||
|
case IpcId::CqueryCallers:
|
||||||
|
return "$cquery/callers";
|
||||||
|
case IpcId::CqueryBase:
|
||||||
|
return "$cquery/base";
|
||||||
|
case IpcId::CqueryDerived:
|
||||||
|
return "$cquery/derived";
|
||||||
|
|
||||||
case IpcId::Cout:
|
case IpcId::Cout:
|
||||||
return "$cout";
|
return "$cout";
|
||||||
|
@ -29,6 +29,12 @@ enum class IpcId : int {
|
|||||||
// Custom messages
|
// Custom messages
|
||||||
CqueryFreshenIndex,
|
CqueryFreshenIndex,
|
||||||
|
|
||||||
|
// These are like DocumentReferences but show different types of data.
|
||||||
|
CqueryVars, // Show all variables of a type.
|
||||||
|
CqueryCallers, // Show all callers of a function.
|
||||||
|
CqueryBase, // Show base types/method.
|
||||||
|
CqueryDerived, // Show all derived types/methods.
|
||||||
|
|
||||||
// Internal implementation detail.
|
// Internal implementation detail.
|
||||||
Cout
|
Cout
|
||||||
};
|
};
|
||||||
|
@ -1400,3 +1400,35 @@ struct Ipc_CqueryFreshenIndex : public IpcMessage<Ipc_CqueryFreshenIndex> {
|
|||||||
lsRequestId id;
|
lsRequestId id;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex, id);
|
MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex, id);
|
||||||
|
|
||||||
|
|
||||||
|
// Vars, Callers, Derived, GotoParent
|
||||||
|
struct Ipc_CqueryVars : public IpcMessage<Ipc_CqueryVars> {
|
||||||
|
const static IpcId kIpcId = IpcId::CqueryVars;
|
||||||
|
lsRequestId id;
|
||||||
|
lsTextDocumentPositionParams params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Ipc_CqueryVars, id, params);
|
||||||
|
struct Ipc_CqueryCallers : public IpcMessage<Ipc_CqueryCallers> {
|
||||||
|
const static IpcId kIpcId = IpcId::CqueryCallers;
|
||||||
|
lsRequestId id;
|
||||||
|
lsTextDocumentPositionParams params;
|
||||||
|
};
|
||||||
|
struct Ipc_CqueryBase : public IpcMessage<Ipc_CqueryBase> {
|
||||||
|
const static IpcId kIpcId = IpcId::CqueryBase;
|
||||||
|
lsRequestId id;
|
||||||
|
lsTextDocumentPositionParams params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Ipc_CqueryBase, id, params);
|
||||||
|
MAKE_REFLECT_STRUCT(Ipc_CqueryCallers, id, params);
|
||||||
|
struct Ipc_CqueryDerived : public IpcMessage<Ipc_CqueryDerived> {
|
||||||
|
const static IpcId kIpcId = IpcId::CqueryDerived;
|
||||||
|
lsRequestId id;
|
||||||
|
lsTextDocumentPositionParams params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Ipc_CqueryDerived, id, params);
|
||||||
|
struct Out_LocationList : public lsOutMessage<Out_LocationList> {
|
||||||
|
lsRequestId id;
|
||||||
|
NonElidedVector<lsLocation> result;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, result);
|
Loading…
Reference in New Issue
Block a user