Query* structs: QueryLocation -> Reference

This commit is contained in:
Fangrui Song 2018-02-09 17:30:22 -08:00
parent aa125e34f3
commit 50cf05763b
8 changed files with 114 additions and 108 deletions

View File

@ -72,9 +72,10 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
QueryFunc& func = sym.Func(db); QueryFunc& func = sym.Func(db);
// Note: we ignore the definition if it is in the same file (ie, // Note: we ignore the definition if it is in the same file (ie,
// possibly a header). // possibly a header).
if (func.def && func.def->definition_extent && if (func.def && func.def->definition_extent) {
func.def->definition_extent->FileId() != file_id) { QueryFileId t = GetFileId(db, *func.def->definition_extent);
return func.def->definition_extent->FileId(); if (t != file_id)
return t;
} }
break; break;
} }
@ -82,9 +83,10 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
QueryVar& var = sym.Var(db); QueryVar& var = sym.Var(db);
// Note: we ignore the definition if it is in the same file (ie, // Note: we ignore the definition if it is in the same file (ie,
// possibly a header). // possibly a header).
if (var.def && var.def->definition_extent && if (var.def && var.def->definition_extent) {
var.def->definition_extent->FileId() != file_id) { QueryFileId t = GetFileId(db, *var.def->definition_extent);
return var.def->definition_extent->FileId(); if (t != file_id)
return t;
} }
break; break;
} }

View File

@ -82,7 +82,6 @@ void AddCodeLens(const char* singular,
CommonCodeLensParams* common, CommonCodeLensParams* common,
QueryLocation loc, QueryLocation loc,
const std::vector<Reference>& uses, const std::vector<Reference>& uses,
optional<QueryLocation> excluded,
bool force_display) { bool force_display) {
TCodeLens code_lens; TCodeLens code_lens;
optional<lsRange> range = GetLsRange(common->working_file, loc.range); optional<lsRange> range = GetLsRange(common->working_file, loc.range);
@ -97,8 +96,6 @@ void AddCodeLens(const char* singular,
// Add unique uses. // Add unique uses.
std::unordered_set<lsLocation> unique_uses; std::unordered_set<lsLocation> unique_uses;
for (const Reference& use : uses) { for (const Reference& use : uses) {
if (excluded && Reference(*excluded) == use)
continue;
optional<lsLocation> location = optional<lsLocation> location =
GetLsLocation(common->db, common->working_files, use); GetLsLocation(common->db, common->working_files, use);
if (!location) if (!location)
@ -155,14 +152,12 @@ struct TextDocumentCodeLensHandler
if (type.def->kind == ClangSymbolKind::Namespace) if (type.def->kind == ClangSymbolKind::Namespace)
continue; continue;
AddCodeLens("ref", "refs", &common, sym.OffsetStartColumn(db, 0), AddCodeLens("ref", "refs", &common, sym.OffsetStartColumn(db, 0),
type.uses, type.def->definition_spelling, type.uses, true /*force_display*/);
true /*force_display*/); AddCodeLens("derived", "derived", &common,
AddCodeLens( sym.OffsetStartColumn(db, 1),
"derived", "derived", &common, sym.OffsetStartColumn(db, 1), ToReference(db, type.derived), false /*force_display*/);
ToReference(db, type.derived), nullopt, false /*force_display*/);
AddCodeLens("var", "vars", &common, sym.OffsetStartColumn(db, 2), AddCodeLens("var", "vars", &common, sym.OffsetStartColumn(db, 2),
ToReference(db, type.instances), nullopt, ToReference(db, type.instances), false /*force_display*/);
false /*force_display*/);
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
@ -176,14 +171,13 @@ struct TextDocumentCodeLensHandler
// extent since that is better for outline. This tries to convert the // extent since that is better for outline. This tries to convert the
// extent location to the spelling location. // extent location to the spelling location.
auto try_ensure_spelling = [&](SymbolRef sym) { auto try_ensure_spelling = [&](SymbolRef sym) {
optional<QueryLocation> def = optional<Reference> def =
GetDefinitionSpellingOfSymbol(db, sym); GetDefinitionSpellingOfSymbol(db, sym);
if (!def || def->FileId() != GetFileId(db, sym) || if (!def || db->GetFileId(*def) != db->GetFileId(sym) ||
def->range.start.line != sym.range.start.line) { def->range.start.line != sym.range.start.line) {
return sym; return sym;
} }
return SymbolRef(def->range, Id<void>(def->FileId()), return SymbolRef(*def);
SymbolKind::File, SymbolRole::None);
}; };
std::vector<QueryFuncRef> base_callers = std::vector<QueryFuncRef> base_callers =
@ -194,35 +188,31 @@ struct TextDocumentCodeLensHandler
SymbolRef loc = try_ensure_spelling(sym); SymbolRef loc = try_ensure_spelling(sym);
AddCodeLens("call", "calls", &common, AddCodeLens("call", "calls", &common,
loc.OffsetStartColumn(db, offset++), loc.OffsetStartColumn(db, offset++),
ToReference(db, func.callers), nullopt, ToReference(db, func.callers), true /*force_display*/);
true /*force_display*/);
} else { } else {
SymbolRef loc = try_ensure_spelling(sym); SymbolRef loc = try_ensure_spelling(sym);
AddCodeLens("direct call", "direct calls", &common, AddCodeLens("direct call", "direct calls", &common,
loc.OffsetStartColumn(db, offset++), loc.OffsetStartColumn(db, offset++),
ToReference(db, func.callers), nullopt, ToReference(db, func.callers), false /*force_display*/);
false /*force_display*/);
if (!base_callers.empty()) if (!base_callers.empty())
AddCodeLens("base call", "base calls", &common, AddCodeLens("base call", "base calls", &common,
loc.OffsetStartColumn(db, offset++), loc.OffsetStartColumn(db, offset++),
ToReference(db, base_callers), nullopt, ToReference(db, base_callers),
false /*force_display*/); false /*force_display*/);
if (!derived_callers.empty()) if (!derived_callers.empty())
AddCodeLens("derived call", "derived calls", &common, AddCodeLens("derived call", "derived calls", &common,
loc.OffsetStartColumn(db, offset++), loc.OffsetStartColumn(db, offset++),
ToReference(db, derived_callers), nullopt, ToReference(db, derived_callers),
false /*force_display*/); false /*force_display*/);
} }
AddCodeLens("derived", "derived", &common, AddCodeLens("derived", "derived", &common,
sym.OffsetStartColumn(db, offset++), sym.OffsetStartColumn(db, offset++),
ToReference(db, func.derived), nullopt, ToReference(db, func.derived), false /*force_display*/);
false /*force_display*/);
// "Base" // "Base"
if (func.def->base.size() == 1) { if (func.def->base.size() == 1) {
// FIXME WithGen optional<Reference> base_loc =
optional<QueryLocation> base_loc =
GetDefinitionSpellingOfSymbol(db, func.def->base[0]); GetDefinitionSpellingOfSymbol(db, func.def->base[0]);
if (base_loc) { if (base_loc) {
optional<lsLocation> ls_base = optional<lsLocation> ls_base =
@ -245,7 +235,7 @@ struct TextDocumentCodeLensHandler
} }
} else { } else {
AddCodeLens("base", "base", &common, sym.OffsetStartColumn(db, 1), AddCodeLens("base", "base", &common, sym.OffsetStartColumn(db, 1),
ToReference(db, func.def->base), nullopt, ToReference(db, func.def->base),
false /*force_display*/); false /*force_display*/);
} }
@ -266,7 +256,7 @@ struct TextDocumentCodeLensHandler
force_display = false; force_display = false;
AddCodeLens("ref", "refs", &common, sym.OffsetStartColumn(db, 0), AddCodeLens("ref", "refs", &common, sym.OffsetStartColumn(db, 0),
var.uses, var.def->definition_spelling, force_display); var.uses, force_display);
break; break;
} }
case SymbolKind::File: case SymbolKind::File:

View File

@ -74,12 +74,12 @@ struct TextDocumentDefinitionHandler
// - start at spelling but end at extent for better mouse tooltip // - start at spelling but end at extent for better mouse tooltip
// - goto declaration while in definition of recursive type // - goto declaration while in definition of recursive type
optional<QueryLocation> def_loc = GetDefinitionSpellingOfSymbol(db, sym); optional<Reference> def_loc = GetDefinitionSpellingOfSymbol(db, sym);
// We use spelling start and extent end because this causes vscode to // We use spelling start and extent end because this causes vscode to
// highlight the entire definition when previewing / hoving with the // highlight the entire definition when previewing / hoving with the
// mouse. // mouse.
optional<QueryLocation> def_extent = GetDefinitionExtentOfSymbol(db, sym); optional<Reference> def_extent = GetDefinitionExtentOfSymbol(db, sym);
if (def_loc && def_extent) if (def_loc && def_extent)
def_loc->range.end = def_extent->range.end; def_loc->range.end = def_extent->range.end;
@ -87,7 +87,7 @@ struct TextDocumentDefinitionHandler
// the declaration if possible. We also want to use declarations if // the declaration if possible. We also want to use declarations if
// we're pointing to, ie, a pure virtual function which has no // we're pointing to, ie, a pure virtual function which has no
// definition. // definition.
if (!def_loc || (def_loc->FileId() == file_id && if (!def_loc || (db->GetFileId(*def_loc) == file_id &&
def_loc->range.Contains(target_line, target_column))) { def_loc->range.Contains(target_line, target_column))) {
// Goto declaration. // Goto declaration.

View File

@ -22,7 +22,7 @@ bool InsertSymbolIntoResult(QueryDatabase* db,
if (!info) if (!info)
return false; return false;
optional<QueryLocation> location = GetDefinitionExtentOfSymbol(db, symbol); optional<Reference> location = GetDefinitionExtentOfSymbol(db, symbol);
Reference loc; Reference loc;
if (location) if (location)
loc = *location; loc = *location;

View File

@ -97,11 +97,10 @@ optional<QueryVar::Def> ToQuery(const IdMap& id_map, const IndexVar::Def& var) {
result.file = id_map.primary_file; result.file = id_map.primary_file;
if (var.definition_spelling) if (var.definition_spelling)
result.definition_spelling = result.definition_spelling =
QueryLocation{*var.definition_spelling, id_map.primary_file, id_map.ToQuery(*var.definition_spelling, SymbolRole::Definition);
SymbolRole::Definition};
if (var.definition_extent) if (var.definition_extent)
result.definition_extent = QueryLocation{ result.definition_extent =
*var.definition_extent, id_map.primary_file, SymbolRole::None}; id_map.ToQuery(*var.definition_extent, SymbolRole::None);
result.variable_type = id_map.ToQuery(var.variable_type); result.variable_type = id_map.ToQuery(var.variable_type);
if (result.parent_id) if (result.parent_id)
switch (var.parent_kind) { switch (var.parent_kind) {
@ -394,32 +393,9 @@ Maybe<QueryVarId> GetQueryVarIdFromUsr(QueryDatabase* query_db,
} // namespace } // namespace
// FIXME Reference Remove
QueryFileId GetFileId(QueryDatabase* db, Reference ref) { QueryFileId GetFileId(QueryDatabase* db, Reference ref) {
switch (ref.kind) { return db->GetFileId(ref);
case SymbolKind::Invalid:
break;
case SymbolKind::File:
return QueryFileId(ref.id);
case SymbolKind::Func: {
QueryFunc& file = db->funcs[ref.id.id];
if (file.def)
return file.def->file;
break;
}
case SymbolKind::Type: {
QueryType& type = db->types[ref.id.id];
if (type.def)
return type.def->file;
break;
}
case SymbolKind::Var: {
QueryVar& var = db->vars[ref.id.id];
if (var.def)
return var.def->file;
break;
}
}
return QueryFileId();
} }
QueryFunc& SymbolRef::Func(QueryDatabase* db) const { QueryFunc& SymbolRef::Func(QueryDatabase* db) const {
@ -471,8 +447,8 @@ IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids)
*GetQueryVarIdFromUsr(query_db, entry.second, true); *GetQueryVarIdFromUsr(query_db, entry.second, true);
} }
QueryLocation IdMap::ToQuery(Range range, SymbolRole role) const { Reference IdMap::ToQuery(Range range, SymbolRole role) const {
return QueryLocation{range, primary_file, role}; return Reference{range, Id<void>(primary_file), SymbolKind:: File, role};
} }
Reference IdMap::ToQuery(Reference ref) const { Reference IdMap::ToQuery(Reference ref) const {
switch (ref.kind) { switch (ref.kind) {

View File

@ -69,6 +69,7 @@ struct SymbolRef : Reference {
SymbolRef() = default; SymbolRef() = default;
SymbolRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role) SymbolRef(Range range, Id<void> id, SymbolKind kind, SymbolRole role)
: Reference{range, id, kind, role} {} : Reference{range, id, kind, role} {}
SymbolRef(Reference ref) : Reference{ref} {}
SymbolRef(SymbolIdx si) SymbolRef(SymbolIdx si)
: Reference{Range(), Id<void>(si.idx), si.kind, SymbolRole::None} {} : Reference{Range(), Id<void>(si.idx), si.kind, SymbolRole::None} {}
@ -202,7 +203,7 @@ struct QueryType {
QueryTypeId, QueryTypeId,
QueryFuncId, QueryFuncId,
QueryVarId, QueryVarId,
QueryLocation>; Reference>;
using DefUpdate = WithUsr<Def>; using DefUpdate = WithUsr<Def>;
using DerivedUpdate = MergeableUpdate<QueryTypeId, QueryTypeId>; using DerivedUpdate = MergeableUpdate<QueryTypeId, QueryTypeId>;
using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>; using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>;
@ -224,7 +225,7 @@ struct QueryFunc {
QueryFuncId, QueryFuncId,
QueryVarId, QueryVarId,
QueryFuncRef, QueryFuncRef,
QueryLocation>; Reference>;
using DefUpdate = WithUsr<Def>; using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Reference>; using DeclarationsUpdate = MergeableUpdate<QueryFuncId, Reference>;
using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>; using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>;
@ -245,7 +246,7 @@ struct QueryVar {
QueryTypeId, QueryTypeId,
QueryFuncId, QueryFuncId,
QueryVarId, QueryVarId,
QueryLocation>; Reference>;
using DefUpdate = WithUsr<Def>; using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryVarId, Reference>; using DeclarationsUpdate = MergeableUpdate<QueryVarId, Reference>;
using UsesUpdate = MergeableUpdate<QueryVarId, Reference>; using UsesUpdate = MergeableUpdate<QueryVarId, Reference>;
@ -369,6 +370,46 @@ struct QueryDatabase {
Maybe<QueryTypeId> GetQueryTypeIdFromUsr(Usr usr); Maybe<QueryTypeId> GetQueryTypeIdFromUsr(Usr usr);
Maybe<QueryFuncId> GetQueryFuncIdFromUsr(Usr usr); Maybe<QueryFuncId> GetQueryFuncIdFromUsr(Usr usr);
Maybe<QueryVarId> GetQueryVarIdFromUsr(Usr usr); Maybe<QueryVarId> GetQueryVarIdFromUsr(Usr usr);
QueryFileId GetFileId(Reference ref) {
switch (ref.kind) {
case SymbolKind::Invalid:
break;
case SymbolKind::File:
return QueryFileId(ref.id);
case SymbolKind::Func: {
QueryFunc& file = funcs[ref.id.id];
if (file.def)
return file.def->file;
break;
}
case SymbolKind::Type: {
QueryType& type = types[ref.id.id];
if (type.def)
return type.def->file;
break;
}
case SymbolKind::Var: {
QueryVar& var = vars[ref.id.id];
if (var.def)
return var.def->file;
break;
}
}
return QueryFileId();
}
QueryFile& GetFile(Reference ref) {
return files[ref.id.id];
}
QueryFunc& GetFunc(Reference ref) {
return funcs[ref.id.id];
}
QueryType& GetType(Reference ref) {
return types[ref.id.id];
}
QueryVar& GetVar(Reference ref) {
return vars[ref.id.id];
}
}; };
template <typename I> template <typename I>
@ -399,7 +440,7 @@ struct IdMap {
// FIXME Too verbose // FIXME Too verbose
// clang-format off // clang-format off
QueryLocation ToQuery(Range range, SymbolRole role) const; Reference ToQuery(Range range, SymbolRole role) const;
Reference ToQuery(Reference ref) const; Reference ToQuery(Reference ref) const;
QueryTypeId ToQuery(IndexTypeId id) const; QueryTypeId ToQuery(IndexTypeId id) const;
QueryFuncId ToQuery(IndexFuncId id) const; QueryFuncId ToQuery(IndexFuncId id) const;

View File

@ -18,7 +18,7 @@ int ComputeRangeSize(const Range& range) {
} // namespace } // namespace
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryTypeId& id) { const QueryTypeId& id) {
QueryType& type = db->types[id.id]; QueryType& type = db->types[id.id];
if (type.def) if (type.def)
@ -26,7 +26,7 @@ optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
return nullopt; return nullopt;
} }
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryFuncId& id) { const QueryFuncId& id) {
QueryFunc& func = db->funcs[id.id]; QueryFunc& func = db->funcs[id.id];
if (func.def) if (func.def)
@ -34,7 +34,7 @@ optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
return nullopt; return nullopt;
} }
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryVarId& id) { const QueryVarId& id) {
QueryVar& var = db->vars[id.id]; QueryVar& var = db->vars[id.id];
if (var.def) if (var.def)
@ -42,7 +42,7 @@ optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
return nullopt; return nullopt;
} }
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
SymbolRef sym) { SymbolRef sym) {
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
@ -72,7 +72,7 @@ optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
return nullopt; return nullopt;
} }
optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionExtentOfSymbol(QueryDatabase* db,
SymbolRef sym) { SymbolRef sym) {
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
@ -93,10 +93,8 @@ optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db,
return var.def->definition_extent; return var.def->definition_extent;
break; break;
} }
case SymbolKind::File: { case SymbolKind::File:
return QueryLocation{Range(Position(0, 0), Position(0, 0)), return sym;
QueryFileId(sym.Idx()), SymbolRole::None};
}
case SymbolKind::Invalid: { case SymbolKind::Invalid: {
assert(false && "unexpected"); assert(false && "unexpected");
break; break;
@ -111,26 +109,25 @@ optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = sym.Type(db); QueryType& type = sym.Type(db);
if (type.def && type.def->definition_spelling) if (type.def && type.def->definition_spelling)
return type.def->definition_spelling->FileId(); return db->GetFileId(*type.def->definition_spelling);
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = sym.Func(db); QueryFunc& func = sym.Func(db);
if (!func.declarations.empty()) if (!func.declarations.empty())
return GetFileId(db, func.declarations[0]); return db->GetFileId(func.declarations[0]);
if (func.def && func.def->definition_spelling) if (func.def && func.def->definition_spelling)
return func.def->definition_spelling->FileId(); return db->GetFileId(*func.def->definition_spelling);
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = sym.Var(db); QueryVar& var = sym.Var(db);
if (var.def && var.def->definition_spelling) if (var.def && var.def->definition_spelling)
return var.def->definition_spelling->FileId(); return db->GetFileId(*var.def->definition_spelling);
break; break;
} }
case SymbolKind::File: { case SymbolKind::File:
return QueryFileId(sym.Idx()); return QueryFileId(sym.Idx());
}
case SymbolKind::Invalid: { case SymbolKind::Invalid: {
assert(false && "unexpected"); assert(false && "unexpected");
break; break;
@ -197,18 +194,18 @@ std::vector<Reference> GetDeclarationsOfSymbolForGotoDefinition(
// function has the postfix `ForGotoDefintion`, but it lets the user // function has the postfix `ForGotoDefintion`, but it lets the user
// jump to the start of a type if clicking goto-definition on the same // jump to the start of a type if clicking goto-definition on the same
// type from within the type definition. // type from within the type definition.
QueryType& type = sym.Type(db); QueryType& type = db->GetType(sym);
if (type.def) { if (type.def) {
optional<QueryLocation> declaration = type.def->definition_spelling; Maybe<Reference> def = type.def->definition_spelling;
if (declaration) if (def)
return {Reference(*declaration)}; return {*def};
} }
break; break;
} }
case SymbolKind::Func: case SymbolKind::Func:
return sym.Func(db).declarations; return db->GetFunc(sym).declarations;
case SymbolKind::Var: case SymbolKind::Var:
return sym.Var(db).declarations; return db->GetVar(sym).declarations;
default: default:
break; break;
} }

View File

@ -7,15 +7,15 @@
#include <optional.h> #include <optional.h>
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryTypeId& id); const QueryTypeId& id);
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryFuncId& id); const QueryFuncId& id);
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
const QueryVarId& id); const QueryVarId& id);
optional<QueryLocation> GetDefinitionSpellingOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
SymbolRef sym); SymbolRef sym);
optional<QueryLocation> GetDefinitionExtentOfSymbol(QueryDatabase* db, optional<Reference> GetDefinitionExtentOfSymbol(QueryDatabase* db,
SymbolRef sym); SymbolRef sym);
optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db, optional<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
SymbolRef sym); SymbolRef sym);
@ -29,7 +29,7 @@ std::vector<Reference> ToReference(QueryDatabase* db,
std::vector<Reference> ret; std::vector<Reference> ret;
ret.reserve(ids.size()); ret.reserve(ids.size());
for (auto id : ids) { for (auto id : ids) {
optional<QueryLocation> loc = GetDefinitionSpellingOfSymbol(db, id); optional<Reference> loc = GetDefinitionSpellingOfSymbol(db, id);
if (loc) if (loc)
ret.push_back(*loc); ret.push_back(*loc);
} }