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); 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) { bool IsScopeSemanticContainer(CXCursorKind kind) {
switch (kind) { switch (kind) {
case CXCursor_Namespace: case CXCursor_Namespace:
@ -1820,7 +1837,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
} }
} }
} else } else
UniqueAddUse(db, type->uses, spell, fromContainer(decl->lexicalContainer)); UniqueAddUse(db, type->declarations, spell,
fromContainer(decl->lexicalContainer));
switch (decl->entityInfo->templateKind) { switch (decl->entityInfo->templateKind) {
default: default:
@ -2152,6 +2170,9 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
// Foo f; // Foo f;
// } // }
// //
if (!ref->parentEntity || IsDeclContext(ref->parentEntity->kind))
UniqueAddUseSpell(db, ref_type->declarations, ref->cursor);
else
UniqueAddUseSpell(db, ref_type->uses, ref->cursor); UniqueAddUseSpell(db, ref_type->uses, ref->cursor);
break; break;
} }

View File

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

View File

@ -37,11 +37,15 @@ std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db,
case SymbolKind::Var: { case SymbolKind::Var: {
std::vector<Use> ret = std::vector<Use> ret =
GetDeclarationsOfSymbolForGotoDefinition(db, sym); GetDeclarationsOfSymbolForGotoDefinition(db, sym);
QueryVar::Def* def = db->GetVar(sym).AnyDef(); if (ret.empty()) {
if (def && def->type) { for (auto& def : db->GetVar(sym).def)
std::vector<Use> types = GetDeclarationsOfSymbolForGotoDefinition( if (def.type) {
db, SymbolIdx{*def->type, SymbolKind::Type}); if (Maybe<Use> use = GetDefinitionSpellingOfSymbol(
ret.insert(ret.end(), types.begin(), types.end()); db, SymbolIdx{*def.type, SymbolKind::Type})) {
ret.push_back(*use);
break;
}
}
} }
return ret; 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); add_all_symbols(*type.def.spell, id, SymbolKind::Type);
if (type.def.extent) if (type.def.extent)
add_outline(*type.def.extent, id, SymbolKind::Type); 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) for (Use use : type.uses)
add_all_symbols(use, id, SymbolKind::Type); add_all_symbols(use, id, SymbolKind::Type);
} }
@ -523,6 +527,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
[this, &previous_id_map](IndexType* type) { [this, &previous_id_map](IndexType* type) {
if (type->def.spell) if (type->def.spell)
types_removed.push_back(type->usr); 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()) if (!type->derived.empty())
types_derived.push_back(QueryType::DerivedUpdate( types_derived.push_back(QueryType::DerivedUpdate(
previous_id_map.ToQuery(type->id), {}, previous_id_map.ToQuery(type->id), {},
@ -543,6 +551,10 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
if (def_update) if (def_update)
types_def_update.push_back( types_def_update.push_back(
QueryType::DefUpdate(type->usr, std::move(*def_update))); 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()) if (!type->derived.empty())
types_derived.push_back( types_derived.push_back(
QueryType::DerivedUpdate(current_id_map.ToQuery(type->id), 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))); 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_derived, derived, QueryTypeId);
PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances, PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances,
QueryVarId); QueryVarId);
@ -820,6 +833,7 @@ void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) {
RemoveUsrs(SymbolKind::Type, update->types_removed); RemoveUsrs(SymbolKind::Type, update->types_removed);
ImportOrUpdate(std::move(update->types_def_update)); ImportOrUpdate(std::move(update->types_def_update));
HANDLE_MERGEABLE(types_declarations, declarations, types);
HANDLE_MERGEABLE(types_derived, derived, types); HANDLE_MERGEABLE(types_derived, derived, types);
HANDLE_MERGEABLE(types_instances, instances, types); HANDLE_MERGEABLE(types_instances, instances, types);
HANDLE_MERGEABLE(types_uses, uses, types); HANDLE_MERGEABLE(types_uses, uses, types);

View File

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

View File

@ -16,6 +16,26 @@ int ComputeRangeSize(const Range& range) {
return range.end.column - range.start.column; 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 } // namespace
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db, Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
@ -112,54 +132,16 @@ Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
std::vector<Use> ToUses(QueryDatabase* db, std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryFuncId>& ids) { const std::vector<QueryFuncId>& ids) {
std::vector<Use> ret; return ToUsesHelper(db->funcs, ids);
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;
} }
std::vector<Use> ToUses(QueryDatabase* db, std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryTypeId>& ids) { const std::vector<QueryTypeId>& ids) {
std::vector<Use> ret; return ToUsesHelper(db->types, ids);
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;
} }
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) { std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) {
std::vector<Use> ret; return ToUsesHelper(db->vars, ids);
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;
} }
std::vector<Use> GetUsesOfSymbol(QueryDatabase* db, std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
@ -173,6 +155,7 @@ std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
for (auto& def : type.def) for (auto& def : type.def)
if (def.spell) if (def.spell)
ret.push_back(*def.spell); ret.push_back(*def.spell);
AddRange(&ret, type.declarations);
} }
return ret; return ret;
} }
@ -210,27 +193,15 @@ std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db, QueryDatabase* db,
SymbolIdx sym) { SymbolIdx sym) {
switch (sym.kind) { 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: case SymbolKind::Func:
return db->GetFunc(sym).declarations; return db->GetFunc(sym).declarations;
case SymbolKind::Type:
return db->GetType(sym).declarations;
case SymbolKind::Var: case SymbolKind::Var:
return db->GetVar(sym).declarations; return db->GetVar(sym).declarations;
default: default:
break;
}
return {}; return {};
}
} }
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) { bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {

View File

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