Support keyboard shortcuts for vars, callers, base, and derived.

This commit is contained in:
Jacob Dufault 2017-05-06 23:56:04 -07:00
parent fc55589ed3
commit 5524abdaa7
4 changed files with 195 additions and 6 deletions

View File

@ -526,6 +526,21 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db, WorkingFiles* working_file
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.
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, WorkingFiles* working_files, SymbolIdx symbol) {
switch (symbol.kind) {
@ -606,7 +621,7 @@ void AddCodeLens(
return;
code_lens.range = *range;
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.position = code_lens.range.start;
@ -806,6 +821,10 @@ void RegisterMessageTypes() {
MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
MessageRegistry::instance()->Register<Ipc_WorkspaceSymbol>();
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;
}
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: {
// 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.
@ -1708,7 +1847,7 @@ bool QueryDbMainLoop(
code_lens.range.start.character += offset++;
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
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.position = ls_base->range.start;
response.result.push_back(code_lens);
@ -1992,7 +2131,11 @@ void LanguageServerStdinLoop(IndexerConfig* config, std::unordered_map<IpcId, Ti
case IpcId::TextDocumentDocumentSymbol:
case IpcId::TextDocumentCodeLens:
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));
break;
}

View File

@ -41,9 +41,17 @@ const char* IpcIdToString(IpcId id) {
case IpcId::WorkspaceSymbol:
return "workspace/symbol";
case IpcId::CqueryFreshenIndex: {
case IpcId::CqueryFreshenIndex:
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:
return "$cout";

View File

@ -29,6 +29,12 @@ enum class IpcId : int {
// Custom messages
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.
Cout
};

View File

@ -1399,4 +1399,36 @@ struct Ipc_CqueryFreshenIndex : public IpcMessage<Ipc_CqueryFreshenIndex> {
const static IpcId kIpcId = IpcId::CqueryFreshenIndex;
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);