mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-29 11:01:57 +00:00
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:
parent
9f3e0ce0dc
commit
40ab5900de
@ -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;
|
||||
}
|
||||
|
@ -231,6 +231,7 @@ struct IndexType {
|
||||
IndexTypeId id;
|
||||
|
||||
Def def;
|
||||
std::vector<Use> declarations;
|
||||
|
||||
// Immediate derived types.
|
||||
std::vector<IndexTypeId> derived;
|
||||
|
@ -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;
|
||||
}
|
||||
|
14
src/query.cc
14
src/query.cc
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user