QueryLocation -> Reference

This commit is contained in:
Fangrui Song 2018-02-08 21:11:35 -08:00
parent 2d255da07b
commit 82b429bfbc
12 changed files with 126 additions and 109 deletions

View File

@ -452,7 +452,7 @@ struct IndexVar {
std::vector<Range> declarations;
// Usages.
std::vector<Range> uses;
std::vector<Reference> uses;
IndexVar() {} // For serialization.
IndexVar(IndexVarId id, Usr usr) : usr(usr), id(id) {

View File

@ -148,8 +148,8 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
QueryFileId impl_file_id,
QueryFunc& func) {
assert(func.def);
for (const QueryLocation& decl : func.declarations) {
if (decl.FileId() != decl_file_id)
for (const Reference& decl : func.declarations) {
if (GetFileId(db, decl) != decl_file_id)
continue;
optional<lsRange> ls_decl = GetLsRange(working_file, decl.range);
@ -202,8 +202,8 @@ optional<lsTextEdit> BuildAutoImplementForFunction(QueryDatabase* db,
if (!sym_func.def || !sym_func.def->definition_extent)
break;
for (QueryLocation& func_decl : sym_func.declarations) {
if (func_decl.FileId() == decl_file_id) {
for (const Reference& func_decl : sym_func.declarations) {
if (GetFileId(db, func_decl) == decl_file_id) {
int dist = func_decl.range.start.line - decl.range.start.line;
if (abs(dist) < abs(best_dist)) {
optional<lsLocation> def_loc = GetLsLocation(

View File

@ -76,6 +76,7 @@ struct CommonCodeLensParams {
WorkingFile* working_file;
};
// FIXME Reference
void AddCodeLens(const char* singular,
const char* plural,
CommonCodeLensParams* common,
@ -270,8 +271,13 @@ struct TextDocumentCodeLensHandler
if (var.def->is_macro())
force_display = false;
// FIXME Reference
std::vector<QueryLocation> uses;
for (auto x: var.uses)
uses.push_back(QueryLocation{x.range, GetFileId(db, x), x.role});
AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0),
var.uses, var.def->definition_spelling, force_display);
uses, var.def->definition_spelling, force_display);
break;
}
case SymbolKind::File:

View File

@ -23,20 +23,18 @@ struct Out_TextDocumentDefinition
};
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
std::vector<QueryLocation> GetGotoDefinitionTargets(QueryDatabase* db,
const SymbolIdx& symbol) {
std::vector<Reference> GetGotoDefinitionTargets(QueryDatabase* db,
const SymbolIdx& symbol) {
switch (symbol.kind) {
// Returns GetDeclarationsOfSymbolForGotoDefinition and
// variable type definition.
case SymbolKind::Var: {
std::vector<QueryLocation> ret =
std::vector<Reference> ret =
GetDeclarationsOfSymbolForGotoDefinition(db, symbol);
QueryVar& var = db->vars[symbol.idx];
// FIXME WithGen
if (var.def && var.def->variable_type) {
std::vector<QueryLocation> types =
GetDeclarationsOfSymbolForGotoDefinition(
db, SymbolIdx(SymbolKind::Type, var.def->variable_type->id));
std::vector<Reference> types = GetDeclarationsOfSymbolForGotoDefinition(
db, SymbolIdx(SymbolKind::Type, var.def->variable_type->id));
ret.insert(ret.end(), types.begin(), types.end());
}
return ret;
@ -94,9 +92,8 @@ struct TextDocumentDefinitionHandler
def_loc->range.Contains(target_line, target_column))) {
// Goto declaration.
std::vector<QueryLocation> targets =
GetGotoDefinitionTargets(db, ref.idx);
for (QueryLocation target : targets) {
std::vector<Reference> targets = GetGotoDefinitionTargets(db, ref.idx);
for (Reference target : targets) {
optional<lsLocation> ls_target =
GetLsLocation(db, working_files, target);
if (ls_target)

View File

@ -38,10 +38,10 @@ struct TextDocumentDocumentHighlightHandler
for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references to highlight.
std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx, true);
std::vector<Reference> uses = GetUsesOfSymbol(db, ref.idx, true);
out.result.reserve(uses.size());
for (const QueryLocation& use : uses) {
if (use.FileId() != file_id)
for (const Reference& use : uses) {
if (GetFileId(db, use) != file_id)
continue;
optional<lsLocation> ls_location =

View File

@ -54,10 +54,10 @@ struct TextDocumentReferencesHandler
for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references.
std::vector<QueryLocation> uses = GetUsesOfSymbol(
std::vector<Reference> uses = GetUsesOfSymbol(
db, ref.idx, request->params.context.includeDeclaration);
out.result.reserve(uses.size());
for (const QueryLocation& use : uses) {
for (const Reference& use : uses) {
optional<lsLocation> ls_location =
GetLsLocation(db, working_files, use);
if (ls_location)

View File

@ -6,17 +6,17 @@ namespace {
lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<QueryLocation>& locations,
const std::vector<Reference>& refs,
const std::string& new_text) {
std::unordered_map<QueryFileId, lsTextDocumentEdit> path_to_edit;
for (auto& location : locations) {
for (auto& ref : refs) {
optional<lsLocation> ls_location =
GetLsLocation(db, working_files, location);
GetLsLocation(db, working_files, ref);
if (!ls_location)
continue;
QueryFileId file_id = location.FileId();
QueryFileId file_id = GetFileId(db, ref);
if (path_to_edit.find(file_id) == path_to_edit.end()) {
path_to_edit[file_id] = lsTextDocumentEdit();
@ -98,9 +98,9 @@ struct TextDocumentRenameHandler : BaseMessageHandler<Ipc_TextDocumentRename> {
for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references to rename.
std::vector<QueryLocation> uses = GetUsesOfSymbol(db, ref.idx, true);
out.result =
BuildWorkspaceEdit(db, working_files, uses, request->params.newName);
out.result = BuildWorkspaceEdit(db, working_files,
GetUsesOfSymbol(db, ref.idx, true),
request->params.newName);
break;
}

View File

@ -23,15 +23,17 @@ bool InsertSymbolIntoResult(QueryDatabase* db,
return false;
optional<QueryLocation> location = GetDefinitionExtentOfSymbol(db, symbol);
if (!location) {
Reference loc;
if (location)
loc = *location;
else {
auto decls = GetDeclarationsOfSymbolForGotoDefinition(db, symbol);
if (decls.empty())
return false;
location = decls[0];
loc = decls[0];
}
optional<lsLocation> ls_location =
GetLsLocation(db, working_files, *location);
optional<lsLocation> ls_location = GetLsLocation(db, working_files, loc);
if (!ls_location)
return false;
info->location = *ls_location;

View File

@ -293,8 +293,8 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Declaration, decl);
add_outline(id_map.ToSymbol(var.id), decl);
}
for (const Range& use : var.uses)
add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Reference, use);
for (auto& use : var.uses)
add_all_symbols(id_map.ToSymbol(var.id), use.role, use.range);
}
std::sort(def.outline.begin(), def.outline.end(),
@ -453,12 +453,12 @@ QueryVarId IdMap::ToQuery(IndexVarId id) const {
QueryFuncRef IdMap::ToQuery(IndexFuncRef ref) const {
return QueryFuncRef{ToQuery(ref.id), ToQuery(ref.loc, ref.role)};
}
QueryLocation IdMap::ToQuery(IndexFunc::Declaration decl) const {
Reference IdMap::ToQuery(IndexFunc::Declaration decl) const {
// TODO: expose more than just QueryLocation.
return QueryLocation{decl.spelling, primary_file, SymbolRole::Declaration};
return Reference{decl.spelling, Id<void>(primary_file), SymbolKind::File, SymbolRole::Declaration};
}
std::vector<QueryLocation> IdMap::ToQuery(const std::vector<Range>& a) const {
std::vector<QueryLocation> ret;
std::vector<Reference> IdMap::ToQuery(const std::vector<Range>& a) const {
std::vector<Reference> ret;
ret.reserve(a.size());
for (auto& x : a)
ret.push_back(ToQuery(x, SymbolRole::Reference));
@ -645,7 +645,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
}
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations,
QueryLocation);
Reference);
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_derived, derived, QueryFuncId);
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_callers, callers, QueryFuncRef);
});
@ -697,8 +697,8 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
current->usr, std::move(*current_remapped_def)));
PROCESS_UPDATE_DIFF(QueryVarId, vars_declarations, declarations,
QueryLocation);
PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, QueryLocation);
Reference);
PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, Reference);
});
#undef PROCESS_UPDATE_DIFF
@ -1031,7 +1031,7 @@ TEST_SUITE("query") {
->callers.push_back(IndexFuncRef{Range(Position(2, 0)), IndexFuncId(0),
SymbolRole::None});
previous.Resolve(previous.ToVarId(HashUsr("usr3")))
->uses.push_back(Range(Position(3, 0)));
->uses.push_back(Reference{Range(Position(3, 0))});
IndexUpdate update = GetDelta(previous, current);

View File

@ -34,6 +34,10 @@ struct QueryLocation {
bool HasValue() const { return range.HasValue(); }
QueryFileId FileId() const { return path; }
operator Reference() const {
return Reference{range, Id<void>(path), SymbolKind::File, role};
}
std::tuple<Range, QueryFileId, SymbolRole> ToTuple() const {
return std::make_tuple(range, path, role);
}
@ -246,14 +250,14 @@ struct QueryFunc {
QueryFuncRef,
QueryLocation>;
using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryFuncId, QueryLocation>;
using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Reference>;
using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>;
using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>;
Usr usr;
Maybe<Id<void>> symbol_idx;
optional<Def> def;
std::vector<QueryLocation> declarations;
std::vector<Reference> declarations;
std::vector<QueryFuncId> derived;
std::vector<QueryFuncRef> callers;
@ -267,14 +271,14 @@ struct QueryVar {
QueryVarId,
QueryLocation>;
using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryVarId, QueryLocation>;
using UsesUpdate = MergeableUpdate<QueryVarId, QueryLocation>;
using DeclarationsUpdate = MergeableUpdate<QueryVarId, Reference>;
using UsesUpdate = MergeableUpdate<QueryVarId, Reference>;
Usr usr;
Maybe<Id<void>> symbol_idx;
optional<Def> def;
std::vector<QueryLocation> declarations;
std::vector<QueryLocation> uses;
std::vector<Reference> declarations;
std::vector<Reference> uses;
explicit QueryVar(const Usr& usr) : usr(usr) {}
};
@ -400,9 +404,9 @@ template <> struct IndexToQuery<IndexFuncId> { using type = QueryFuncId; };
template <> struct IndexToQuery<IndexTypeId> { using type = QueryTypeId; };
template <> struct IndexToQuery<IndexVarId> { using type = QueryVarId; };
template <> struct IndexToQuery<IndexFuncRef> { using type = QueryFuncRef; };
template <> struct IndexToQuery<Range> { using type = QueryLocation; };
template <> struct IndexToQuery<Range> { using type = Reference; };
template <> struct IndexToQuery<Reference> { using type = Reference; };
template <> struct IndexToQuery<IndexFunc::Declaration> { using type = QueryLocation; };
template <> struct IndexToQuery<IndexFunc::Declaration> { using type = Reference; };
template <typename I> struct IndexToQuery<optional<I>> {
using type = optional<typename IndexToQuery<I>::type>;
};
@ -425,7 +429,7 @@ struct IdMap {
QueryFuncId ToQuery(IndexFuncId id) const;
QueryVarId ToQuery(IndexVarId id) const;
QueryFuncRef ToQuery(IndexFuncRef ref) const;
QueryLocation ToQuery(IndexFunc::Declaration decl) const;
Reference ToQuery(IndexFunc::Declaration decl) const;
template <typename I>
Maybe<typename IndexToQuery<I>::type> ToQuery(Maybe<I> id) const {
if (!id)
@ -440,7 +444,7 @@ struct IdMap {
ret.push_back(ToQuery(x));
return ret;
}
std::vector<QueryLocation> ToQuery(const std::vector<Range>& a) const;
std::vector<Reference> ToQuery(const std::vector<Range>& a) const;
// clang-format on
SymbolIdx ToSymbol(IndexTypeId id) const;

View File

@ -28,36 +28,36 @@ std::vector<QueryLocation> ToQueryLocationHelper(
return locs;
}
} // namespace
QueryFileId GetFileId(QueryDatabase* db, Reference ref) {
switch (ref.lex_parent_kind) {
case SymbolKind::Invalid:
break;
case SymbolKind::File:
return QueryFileId(ref.lex_parent_id);
case SymbolKind::Func: {
QueryFunc& file = db->funcs[ref.lex_parent_id.id];
if (file.def)
return file.def->file;
break;
}
case SymbolKind::Type: {
QueryType& type = db->types[ref.lex_parent_id.id];
if (type.def)
return type.def->file;
break;
}
case SymbolKind::Var: {
QueryVar& var = db->vars[ref.lex_parent_id.id];
if (var.def)
return var.def->file;
break;
}
case SymbolKind::Invalid:
break;
case SymbolKind::File:
return QueryFileId(ref.lex_parent_id);
case SymbolKind::Func: {
QueryFunc& file = db->funcs[ref.lex_parent_id.id];
if (file.def)
return file.def->file;
break;
}
case SymbolKind::Type: {
QueryType& type = db->types[ref.lex_parent_id.id];
if (type.def)
return type.def->file;
break;
}
case SymbolKind::Var: {
QueryVar& var = db->vars[ref.lex_parent_id.id];
if (var.def)
return var.def->file;
break;
}
}
return QueryFileId();
}
} // namespace
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryTypeId& id) {
QueryType& type = db->types[id.id];
@ -157,7 +157,7 @@ optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx];
if (!func.declarations.empty())
return func.declarations[0].FileId();
return GetFileId(db, func.declarations[0]);
if (func.def && func.def->definition_spelling)
return func.def->definition_spelling->FileId();
break;
@ -183,6 +183,16 @@ QueryLocation ToQueryLocation(QueryDatabase* db, Reference ref) {
return QueryLocation{ref.range, GetFileId(db, ref), ref.role};
}
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryFuncRef>& refs) {
std::vector<Reference> ret;
ret.reserve(refs.size());
for (auto& ref : refs)
ret.push_back(Reference{ref.loc.range, Id<void>(ref.id_), SymbolKind::Func,
ref.loc.role});
return ret;
}
std::vector<QueryLocation> ToQueryLocation(
QueryDatabase* db,
const std::vector<QueryFuncRef>& refs) {
@ -208,16 +218,13 @@ std::vector<QueryLocation> ToQueryLocation(
return ToQueryLocationHelper(db, ids);
}
std::vector<QueryLocation> GetUsesOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol,
bool include_decl) {
std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol,
bool include_decl) {
switch (symbol.kind) {
case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx];
std::vector<QueryLocation> ret;
ret.reserve(type.uses.size());
for (auto& x : type.uses)
ret.push_back(ToQueryLocation(db, x));
std::vector<Reference> ret = type.uses;
if (include_decl && type.def && type.def->definition_spelling)
ret.push_back(*type.def->definition_spelling);
return ret;
@ -225,17 +232,17 @@ std::vector<QueryLocation> GetUsesOfSymbol(QueryDatabase* db,
case SymbolKind::Func: {
// TODO: the vector allocation could be avoided.
QueryFunc& func = db->funcs[symbol.idx];
std::vector<QueryLocation> result = ToQueryLocation(db, func.callers);
std::vector<Reference> ret = ToReference(db, func.callers);
if (include_decl) {
AddRange(&result, func.declarations);
AddRange(&ret, func.declarations);
if (func.def && func.def->definition_spelling)
result.push_back(*func.def->definition_spelling);
ret.push_back(*func.def->definition_spelling);
}
return result;
return ret;
}
case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx];
std::vector<QueryLocation> ret = var.uses;
std::vector<Reference> ret = var.uses;
if (include_decl) {
if (var.def && var.def->definition_spelling)
ret.push_back(*var.def->definition_spelling);
@ -246,15 +253,14 @@ std::vector<QueryLocation> GetUsesOfSymbol(QueryDatabase* db,
case SymbolKind::File:
case SymbolKind::Invalid: {
assert(false && "unexpected");
break;
return {};
}
}
return {};
}
std::vector<QueryLocation> GetDeclarationsOfSymbolForGotoDefinition(
std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db,
const SymbolIdx& symbol) {
SymbolIdx symbol) {
switch (symbol.kind) {
case SymbolKind::Type: {
// Returning the definition spelling of a type is a hack (and is why the
@ -265,17 +271,14 @@ std::vector<QueryLocation> GetDeclarationsOfSymbolForGotoDefinition(
if (type.def) {
optional<QueryLocation> declaration = type.def->definition_spelling;
if (declaration)
return {*declaration};
return {Reference(*declaration)};
}
break;
}
case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx];
return func.declarations;
}
case SymbolKind::Var: {
case SymbolKind::Func:
return db->funcs[symbol.idx].declarations;
case SymbolKind::Var:
return db->vars[symbol.idx].declarations;
}
default:
break;
}
@ -434,11 +437,11 @@ lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id) {
optional<lsLocation> GetLsLocation(QueryDatabase* db,
WorkingFiles* working_files,
const QueryLocation& location) {
Reference ref) {
std::string path;
lsDocumentUri uri = GetLsDocumentUri(db, location.FileId(), &path);
lsDocumentUri uri = GetLsDocumentUri(db, GetFileId(db, ref), &path);
optional<lsRange> range =
GetLsRange(working_files->GetFileByFilename(path), location.range);
GetLsRange(working_files->GetFileByFilename(path), ref.range);
if (!range)
return nullopt;
return lsLocation(uri, *range);

View File

@ -21,6 +21,10 @@ optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
const SymbolIdx& symbol);
QueryLocation ToQueryLocation(QueryDatabase* db, Reference ref);
QueryFileId GetFileId(QueryDatabase* db, Reference ref);
std::vector<Reference> ToReference(QueryDatabase* db,
const std::vector<QueryFuncRef>& refs);
std::vector<QueryLocation> ToQueryLocation(
QueryDatabase* db,
const std::vector<QueryFuncRef>& refs);
@ -32,12 +36,12 @@ std::vector<QueryLocation> ToQueryLocation(
const std::vector<QueryVarId>& refs);
std::vector<QueryLocation> ToQueryLocation(QueryDatabase* db,
const std::vector<QueryFuncId>& ids);
std::vector<QueryLocation> GetUsesOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol,
bool include_decl);
std::vector<QueryLocation> GetDeclarationsOfSymbolForGotoDefinition(
std::vector<Reference> GetUsesOfSymbol(QueryDatabase* db,
const SymbolIdx& symbol,
bool include_decl);
std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db,
const SymbolIdx& symbol);
SymbolIdx symbol);
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root);
std::vector<QueryFuncRef> GetCallersForAllBaseFunctions(QueryDatabase* db,
@ -51,9 +55,10 @@ lsDocumentUri GetLsDocumentUri(QueryDatabase* db,
QueryFileId file_id,
std::string* path);
lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id);
optional<lsLocation> GetLsLocation(QueryDatabase* db,
WorkingFiles* working_files,
const QueryLocation& location);
Reference location);
std::vector<lsLocation> GetLsLocations(
QueryDatabase* db,
WorkingFiles* working_files,