Add TypeDefDefinitionData::declarations

Constructors and destructors are also included in declarations. But this is not necessarily bad, as textDocument/definition on class spelling names can jump to constructors as well as declarations.
This commit is contained in:
Fangrui Song 2018-02-20 13:56:56 -08:00
parent 9f3e0ce0dc
commit 40ab5900de
7 changed files with 78 additions and 63 deletions

View File

@ -39,6 +39,23 @@ void AddFuncUse(std::vector<Use>* result, Use ref) {
result->push_back(ref);
}
// TODO How to check if a reference to type is a declaration?
// This currently also includes constructors/destructors.
// It seems declarations in functions are not indexed.
bool IsDeclContext(CXIdxEntityKind kind) {
switch (kind) {
case CXIdxEntity_CXXClass:
case CXIdxEntity_CXXNamespace:
case CXIdxEntity_ObjCCategory:
case CXIdxEntity_ObjCClass:
case CXIdxEntity_ObjCProtocol:
case CXIdxEntity_Struct:
return true;
default:
return false;
}
}
bool IsScopeSemanticContainer(CXCursorKind kind) {
switch (kind) {
case CXCursor_Namespace:
@ -1820,7 +1837,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
}
}
} else
UniqueAddUse(db, type->uses, spell, fromContainer(decl->lexicalContainer));
UniqueAddUse(db, type->declarations, spell,
fromContainer(decl->lexicalContainer));
switch (decl->entityInfo->templateKind) {
default:
@ -2152,6 +2170,9 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
// Foo f;
// }
//
if (!ref->parentEntity || IsDeclContext(ref->parentEntity->kind))
UniqueAddUseSpell(db, ref_type->declarations, ref->cursor);
else
UniqueAddUseSpell(db, ref_type->uses, ref->cursor);
break;
}

View File

@ -231,6 +231,7 @@ struct IndexType {
IndexTypeId id;
Def def;
std::vector<Use> declarations;
// Immediate derived types.
std::vector<IndexTypeId> derived;

View File

@ -37,11 +37,15 @@ std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db,
case SymbolKind::Var: {
std::vector<Use> ret =
GetDeclarationsOfSymbolForGotoDefinition(db, sym);
QueryVar::Def* def = db->GetVar(sym).AnyDef();
if (def && def->type) {
std::vector<Use> types = GetDeclarationsOfSymbolForGotoDefinition(
db, SymbolIdx{*def->type, SymbolKind::Type});
ret.insert(ret.end(), types.begin(), types.end());
if (ret.empty()) {
for (auto& def : db->GetVar(sym).def)
if (def.type) {
if (Maybe<Use> use = GetDefinitionSpellingOfSymbol(
db, SymbolIdx{*def.type, SymbolKind::Type})) {
ret.push_back(*use);
break;
}
}
}
return ret;
}

View File

@ -247,6 +247,10 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IdMap& id_map, const IndexFile& in
add_all_symbols(*type.def.spell, id, SymbolKind::Type);
if (type.def.extent)
add_outline(*type.def.extent, id, SymbolKind::Type);
for (Use decl : type.declarations) {
add_all_symbols(decl, id, SymbolKind::Type);
add_outline(decl, id, SymbolKind::Type);
}
for (Use use : type.uses)
add_all_symbols(use, id, SymbolKind::Type);
}
@ -523,6 +527,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
[this, &previous_id_map](IndexType* type) {
if (type->def.spell)
types_removed.push_back(type->usr);
if (!type->declarations.empty())
types_declarations.push_back(QueryType::DeclarationsUpdate(
previous_id_map.ToQuery(type->id), {},
previous_id_map.ToQuery(type->declarations)));
if (!type->derived.empty())
types_derived.push_back(QueryType::DerivedUpdate(
previous_id_map.ToQuery(type->id), {},
@ -543,6 +551,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
if (def_update)
types_def_update.push_back(
QueryType::DefUpdate(type->usr, std::move(*def_update)));
if (!type->declarations.empty())
types_declarations.push_back(QueryType::DeclarationsUpdate(
current_id_map.ToQuery(type->id),
current_id_map.ToQuery(type->declarations)));
if (!type->derived.empty())
types_derived.push_back(
QueryType::DerivedUpdate(current_id_map.ToQuery(type->id),
@ -570,6 +582,7 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
current->usr, std::move(*current_remapped_def)));
}
PROCESS_UPDATE_DIFF(QueryTypeId, types_declarations, declarations, Use);
PROCESS_UPDATE_DIFF(QueryTypeId, types_derived, derived, QueryTypeId);
PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances,
QueryVarId);
@ -820,6 +833,7 @@ void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) {
RemoveUsrs(SymbolKind::Type, update->types_removed);
ImportOrUpdate(std::move(update->types_def_update));
HANDLE_MERGEABLE(types_declarations, declarations, types);
HANDLE_MERGEABLE(types_derived, derived, types);
HANDLE_MERGEABLE(types_instances, instances, types);
HANDLE_MERGEABLE(types_uses, uses, types);

View File

@ -136,6 +136,7 @@ MAKE_REFLECT_STRUCT(QueryFile::Def,
struct QueryType {
using Def = TypeDefDefinitionData<QueryFamily>;
using DefUpdate = WithUsr<Def>;
using DeclarationsUpdate = MergeableUpdate<QueryTypeId, Use>;
using DerivedUpdate = MergeableUpdate<QueryTypeId, QueryTypeId>;
using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>;
using UsesUpdate = MergeableUpdate<QueryTypeId, Use>;
@ -143,6 +144,7 @@ struct QueryType {
Usr usr;
Maybe<Id<void>> symbol_idx;
std::forward_list<Def> def;
std::vector<Use> declarations;
std::vector<QueryTypeId> derived;
std::vector<QueryVarId> instances;
std::vector<Use> uses;
@ -228,6 +230,7 @@ struct IndexUpdate {
// Type updates.
std::vector<Usr> types_removed;
std::vector<QueryType::DefUpdate> types_def_update;
std::vector<QueryType::DeclarationsUpdate> types_declarations;
std::vector<QueryType::DerivedUpdate> types_derived;
std::vector<QueryType::InstancesUpdate> types_instances;
std::vector<QueryType::UsesUpdate> types_uses;

View File

@ -16,6 +16,26 @@ int ComputeRangeSize(const Range& range) {
return range.end.column - range.start.column;
}
template <typename Q>
std::vector<Use> ToUsesHelper(std::vector<Q>& entities,
const std::vector<Id<Q>>& ids) {
std::vector<Use> ret;
ret.reserve(ids.size());
for (auto id : ids) {
Q& entity = entities[id.id];
bool has_def = false;
for (auto& def : entity.def)
if (def.spell) {
ret.push_back(*def.spell);
has_def = true;
break;
}
if (!has_def && entity.declarations.size())
ret.push_back(entity.declarations[0]);
}
return ret;
}
} // namespace
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
@ -112,54 +132,16 @@ Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryFuncId>& ids) {
std::vector<Use> ret;
ret.reserve(ids.size());
for (auto id : ids) {
QueryFunc& func = db->funcs[id.id];
bool has_def = false;
for (auto& def : func.def)
if (def.spell) {
ret.push_back(*def.spell);
has_def = true;
break;
}
if (!has_def && func.declarations.size())
ret.push_back(func.declarations[0]);
}
return ret;
return ToUsesHelper(db->funcs, ids);
}
std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryTypeId>& ids) {
std::vector<Use> ret;
ret.reserve(ids.size());
for (auto id : ids) {
QueryType& type = db->types[id.id];
for (auto& def : type.def)
if (def.spell) {
ret.push_back(*def.spell);
break;
}
}
return ret;
return ToUsesHelper(db->types, ids);
}
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) {
std::vector<Use> ret;
ret.reserve(ids.size());
for (auto id : ids) {
QueryVar& var = db->vars[id.id];
bool has_def = false;
for (auto& def : var.def)
if (def.spell) {
ret.push_back(*def.spell);
has_def = true;
break;
}
if (!has_def && var.declarations.size())
ret.push_back(var.declarations[0]);
}
return ret;
return ToUsesHelper(db->vars, ids);
}
std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
@ -173,6 +155,7 @@ std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
for (auto& def : type.def)
if (def.spell)
ret.push_back(*def.spell);
AddRange(&ret, type.declarations);
}
return ret;
}
@ -210,27 +193,15 @@ std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db,
SymbolIdx sym) {
switch (sym.kind) {
case SymbolKind::Type: {
// Returning the definition spelling of a type is a hack (and is why the
// function has the postfix `ForGotoDefintion`, but it lets the user
// jump to the start of a type if clicking goto-definition on the same
// type from within the type definition.
if (const auto* def = db->GetType(sym).AnyDef()) {
Maybe<Use> spell = def->spell;
if (spell)
return {*spell};
}
break;
}
case SymbolKind::Func:
return db->GetFunc(sym).declarations;
case SymbolKind::Type:
return db->GetType(sym).declarations;
case SymbolKind::Var:
return db->GetVar(sym).declarations;
default:
break;
}
return {};
}
}
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {

View File

@ -215,6 +215,7 @@ void Reflect(TVisitor& visitor, IndexType& value) {
ReflectShortName(visitor, value.def);
REFLECT_MEMBER2("kind", value.def.kind);
ReflectHoverAndComments(visitor, value.def);
REFLECT_MEMBER2("declarations", value.declarations);
REFLECT_MEMBER2("spell", value.def.spell);
REFLECT_MEMBER2("extent", value.def.extent);
REFLECT_MEMBER2("alias_of", value.def.alias_of);