- Show code lens for calls to parent and derived methods

- Don't show local variables in global symbol search
This commit is contained in:
Jacob Dufault 2017-04-11 00:29:36 -07:00
parent 91febd7343
commit 215a9a80fb
5 changed files with 138 additions and 55 deletions

View File

@ -15,6 +15,8 @@ std::string GetCachedFileName(std::string source_file) {
} }
std::unique_ptr<IndexedFile> LoadCachedFile(std::string filename) { std::unique_ptr<IndexedFile> LoadCachedFile(std::string filename) {
return nullptr;
std::string cache_file = GetCachedFileName(filename); std::string cache_file = GetCachedFileName(filename);
std::ifstream cache; std::ifstream cache;

View File

@ -25,8 +25,12 @@
#include <thread> #include <thread>
#include <vector> #include <vector>
// TODO: provide a feature like 'https://github.com/goldsborough/clang-expand', ie, a fully linear view of a function with // TODO: provide a feature like 'https://github.com/goldsborough/clang-expand',
// inline function calls expanded. We can probably use vscode decorators to achieve it. // ie, a fully linear view of a function with inline function calls expanded.
// We can probably use vscode decorators to achieve it.
// TODO: we are not marking calls when an implicit ctors gets run. See
// GetDefinitionExtentOfSymbol as a good example.
namespace { namespace {
@ -186,6 +190,42 @@ std::vector<QueryableLocation> GetDeclarationsOfSymbolForGotoDefinition(Queryabl
return {}; return {};
} }
optional<QueryableLocation> GetBaseDefinitionSpelling(QueryableDatabase* db, QueryableFuncDef& func) {
if (!func.def.base)
return nullopt;
return db->funcs[func.def.base->id].def.definition_spelling;
}
std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryableDatabase* db, QueryableFuncDef& root) {
std::vector<QueryFuncRef> callers;
optional<QueryFuncId> func_id = root.def.base;
while (func_id) {
QueryableFuncDef& def = db->funcs[func_id->id];
AddRange(&callers, def.callers);
func_id = def.def.base;
}
return callers;
}
std::vector<QueryFuncRef> GetCallersForAllDerivedFunctions(QueryableDatabase* db, QueryableFuncDef& root) {
std::vector<QueryFuncRef> callers;
std::queue<QueryFuncId> queue;
PushRange(&queue, root.derived);
while (!queue.empty()) {
QueryableFuncDef& def = db->funcs[queue.front().id];
queue.pop();
PushRange(&queue, def.derived);
AddRange(&callers, def.callers);
}
return callers;
}
optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) { optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
if (!working_file) { if (!working_file) {
return lsRange( return lsRange(
@ -265,26 +305,29 @@ lsSymbolInformation GetSymbolInfo(QueryableDatabase* db, WorkingFiles* working_f
return info; return info;
} }
struct CommonCodeLensParams {
std::vector<TCodeLens>* result;
QueryableDatabase* db;
WorkingFiles* working_files;
WorkingFile* working_file;
};
void AddCodeLens( void AddCodeLens(
QueryableDatabase* db, CommonCodeLensParams* common,
WorkingFiles* working_files,
std::vector<TCodeLens>* result,
QueryableLocation loc, QueryableLocation loc,
WorkingFile* working_file,
const std::vector<QueryableLocation>& uses, const std::vector<QueryableLocation>& uses,
bool exclude_loc,
bool only_interesting,
const char* singular, const char* singular,
const char* plural) { const char* plural,
bool exclude_loc = false,
bool only_interesting = false) {
TCodeLens code_lens; TCodeLens code_lens;
optional<lsRange> range = GetLsRange(working_file, loc.range); optional<lsRange> range = GetLsRange(common->working_file, loc.range);
if (!range) if (!range)
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 = "superindex.showReferences";
code_lens.command->arguments.uri = GetLsDocumentUri(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;
// Add unique uses. // Add unique uses.
@ -294,7 +337,7 @@ void AddCodeLens(
continue; continue;
if (only_interesting && !use.range.interesting) if (only_interesting && !use.range.interesting)
continue; continue;
optional<lsLocation> location = GetLsLocation(db, working_files, use); optional<lsLocation> location = GetLsLocation(common->db, common->working_files, use);
if (!location) if (!location)
continue; continue;
unique_uses.insert(*location); unique_uses.insert(*location);
@ -311,7 +354,7 @@ void AddCodeLens(
code_lens.command->title += plural; code_lens.command->title += plural;
if (exclude_loc || unique_uses.size() > 0) if (exclude_loc || unique_uses.size() > 0)
result->push_back(code_lens); common->result->push_back(code_lens);
} }
std::vector<QueryableLocation> ToQueryableLocation(QueryableDatabase* db, const std::vector<QueryFuncRef>& refs) { std::vector<QueryableLocation> ToQueryableLocation(QueryableDatabase* db, const std::vector<QueryFuncRef>& refs) {
@ -908,6 +951,8 @@ void QueryDbMainLoop(
} }
case IpcId::TextDocumentCodeLens: { case IpcId::TextDocumentCodeLens: {
// TODO: add code lens for
// - jump to parent method for functions
auto msg = static_cast<Ipc_TextDocumentCodeLens*>(message.get()); auto msg = static_cast<Ipc_TextDocumentCodeLens*>(message.get());
Out_TextDocumentCodeLens response; Out_TextDocumentCodeLens response;
@ -920,7 +965,11 @@ void QueryDbMainLoop(
std::cerr << "Unable to find file " << msg->params.textDocument.uri.GetPath() << std::endl; std::cerr << "Unable to find file " << msg->params.textDocument.uri.GetPath() << std::endl;
break; break;
} }
WorkingFile* working_file = working_files->GetFileByFilename(file->def.usr); CommonCodeLensParams common;
common.result = &response.result;
common.db = db;
common.working_files = working_files;
common.working_file = working_files->GetFileByFilename(file->def.usr);
for (SymbolRef ref : file->def.outline) { for (SymbolRef ref : file->def.outline) {
// NOTE: We OffsetColumn so that the code lens always show up in a // NOTE: We OffsetColumn so that the code lens always show up in a
@ -930,36 +979,59 @@ void QueryDbMainLoop(
switch (symbol.kind) { switch (symbol.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryableTypeDef& def = db->types[symbol.idx]; QueryableTypeDef& def = db->types[symbol.idx];
AddCodeLens(db, working_files, &response.result, ref.loc.OffsetStartColumn(0), working_file, def.uses, AddCodeLens(&common, ref.loc.OffsetStartColumn(0), def.uses, "ref", "refs");
false /*exclude_loc*/, false /*only_interesting*/, "ref", AddCodeLens(&common, ref.loc.OffsetStartColumn(1), def.uses, "iref", "irefs", false /*exclude_loc*/, true /*only_interesting*/);
"refs"); AddCodeLens(&common, ref.loc.OffsetStartColumn(2), ToQueryableLocation(db, def.derived), "derived", "derived");
AddCodeLens(db, working_files, &response.result, ref.loc.OffsetStartColumn(1), working_file, def.uses, AddCodeLens(&common, ref.loc.OffsetStartColumn(3), ToQueryableLocation(db, def.instantiations), "instantiation", "instantiations");
false /*exclude_loc*/, true /*only_interesting*/, "iref",
"irefs");
AddCodeLens(db, working_files, &response.result, ref.loc.OffsetStartColumn(2), working_file, ToQueryableLocation(db, def.derived),
false /*exclude_loc*/, false /*only_interesting*/, "derived", "derived");
AddCodeLens(db, working_files, &response.result, ref.loc.OffsetStartColumn(3), working_file, ToQueryableLocation(db, def.instantiations),
false /*exclude_loc*/, false /*only_interesting*/, "instantiation", "instantiations");
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryableFuncDef& def = db->funcs[symbol.idx]; QueryableFuncDef& func = db->funcs[symbol.idx];
//AddCodeLens(&response.result, ref.loc.OffsetStartColumn(0), def.uses,
// false /*exclude_loc*/, false /*only_interesting*/, "reference",
// "references"); int offset = 0;
AddCodeLens(db, working_files, &response.result, ref.loc.OffsetStartColumn(1), working_file, ToQueryableLocation(db, def.callers),
true /*exclude_loc*/, false /*only_interesting*/, "caller", "callers"); /*
//AddCodeLens(&response.result, ref.loc.OffsetColumn(2), def.def.callees, // TODO: See if we can get this working.
// false /*exclude_loc*/, false /*only_interesting*/, "callee", "callees"); optional<QueryableLocation> base_definition = GetBaseDefinitionSpelling(db, func);
AddCodeLens(db, working_files, &response.result, ref.loc.OffsetStartColumn(3), working_file, ToQueryableLocation(db, def.derived), if (base_definition) {
false /*exclude_loc*/, false /*only_interesting*/, "derived", "derived"); optional<lsLocation> ls_base = GetLsLocation(db, working_files, *base_definition);
if (ls_base) {
optional<lsRange> range = GetLsRange(common.working_file, ref.loc.range);
if (range) {
TCodeLens code_lens;
code_lens.range = *range;
code_lens.command = lsCommand<lsCodeLensCommandArguments>();
code_lens.command->command = "superindex.goto";
code_lens.command->arguments.uri = GetLsDocumentUri(db, ref.loc.path);
code_lens.command->arguments.position = code_lens.range.start;
code_lens.command->arguments.locations.push_back(*ls_base);
response.result.push_back(code_lens);
}
}
}
*/
std::vector<QueryFuncRef> base_callers = GetCallersForAllBaseFunctions(db, func);
std::vector<QueryFuncRef> derived_callers = GetCallersForAllDerivedFunctions(db, func);
if (base_callers.empty() && derived_callers.empty()) {
// set exclude_loc to true to force the code lens to show up
AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryableLocation(db, func.callers), "call", "calls", true /*exclude_loc*/);
}
else {
AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryableLocation(db, func.callers), "direct call", "direct calls");
if (!base_callers.empty())
AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryableLocation(db, base_callers), "base call", "base calls");
if (!derived_callers.empty())
AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryableLocation(db, derived_callers), "derived call", "derived calls");
}
AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryableLocation(db, func.derived), "derived", "derived");
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryableVarDef& def = db->vars[symbol.idx]; QueryableVarDef& def = db->vars[symbol.idx];
AddCodeLens(db, working_files, &response.result, ref.loc.OffsetStartColumn(0), working_file, def.uses, AddCodeLens(&common, ref.loc.OffsetStartColumn(0), def.uses, "reference", "references", true /*exclude_loc*/, false /*only_interesting*/);
true /*exclude_loc*/, false /*only_interesting*/, "reference",
"references");
break; break;
} }
case SymbolKind::File: case SymbolKind::File:
@ -1004,6 +1076,7 @@ void QueryDbMainLoop(
} }
} }
std::cerr << "- Found " << response.result.size() << " results" << std::endl;
SendOutMessageToClient(language_client, response); SendOutMessageToClient(language_client, response);
break; break;
} }

View File

@ -1394,7 +1394,7 @@ void indexEntityReference(CXClientData client_data,
std::vector<std::unique_ptr<IndexedFile>> Parse(FileConsumer* file_consumer, std::string filename, std::vector<std::string> args, bool dump_ast) { std::vector<std::unique_ptr<IndexedFile>> Parse(FileConsumer* file_consumer, std::string filename, std::vector<std::string> args, bool dump_ast) {
filename = NormalizePath(filename); filename = NormalizePath(filename);
return {}; //return {};
clang_enableStackTraces(); clang_enableStackTraces();
clang_toggleCrashRecovery(1); clang_toggleCrashRecovery(1);

View File

@ -151,21 +151,6 @@ QueryableVarDef::QueryableVarDef(const IdMap& id_map, const IndexedVarDef& index
template<typename T>
void AddRange(std::vector<T>* dest, const std::vector<T>& to_add) {
for (const T& e : to_add)
dest->push_back(e);
}
template<typename T>
void RemoveRange(std::vector<T>* dest, const std::vector<T>& to_remove) {
auto it = std::remove_if(dest->begin(), dest->end(), [&](const T& t) {
// TODO: make to_remove a set?
return std::find(to_remove.begin(), to_remove.end(), t) != to_remove.end();
});
if (it != dest->end())
dest->erase(it);
}
@ -643,7 +628,7 @@ void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableFile::DefUpdat
QueryableFile& existing = files[it->second.idx]; QueryableFile& existing = files[it->second.idx];
existing.def = def; existing.def = def;
UpdateQualifiedName(this, &existing.qualified_name_idx, SymbolKind::File, it->second.idx, def.usr); //UpdateQualifiedName(this, &existing.qualified_name_idx, SymbolKind::File, it->second.idx, def.usr);
} }
} }
@ -685,7 +670,8 @@ void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableVarDef::DefUpd
QueryableVarDef& existing = vars[it->second.idx]; QueryableVarDef& existing = vars[it->second.idx];
existing.def = def; existing.def = def;
UpdateQualifiedName(this, &existing.qualified_name_idx, SymbolKind::Var, it->second.idx, def.usr); if (def.declaring_type)
UpdateQualifiedName(this, &existing.qualified_name_idx, SymbolKind::Var, it->second.idx, def.usr);
} }
} }

View File

@ -2,6 +2,7 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <queue>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -27,6 +28,27 @@ std::unique_ptr<T> MakeUnique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
} }
template<typename T>
void AddRange(std::vector<T>* dest, const std::vector<T>& to_add) {
for (const T& e : to_add)
dest->push_back(e);
}
template<typename T>
void PushRange(std::queue<T>* dest, const std::vector<T>& to_add) {
for (const T& e : to_add)
dest->push(e);
}
template<typename T>
void RemoveRange(std::vector<T>* dest, const std::vector<T>& to_remove) {
auto it = std::remove_if(dest->begin(), dest->end(), [&](const T& t) {
// TODO: make to_remove a set?
return std::find(to_remove.begin(), to_remove.end(), t) != to_remove.end();
});
if (it != dest->end())
dest->erase(it);
}
// http://stackoverflow.com/a/38140932 // http://stackoverflow.com/a/38140932
// //