mirror of
https://github.com/MaskRay/ccls.git
synced 2025-04-16 05:42:17 +00:00
Add SymbolRole to SymbolRef and fix $cquery/{base,derived} by ordering definitions before uses
This commit is contained in:
parent
777193d02f
commit
16bf3158c5
@ -65,3 +65,23 @@ enum class StorageClass : uint8_t {
|
|||||||
};
|
};
|
||||||
MAKE_REFLECT_TYPE_PROXY(StorageClass,
|
MAKE_REFLECT_TYPE_PROXY(StorageClass,
|
||||||
std::underlying_type<StorageClass>::type);
|
std::underlying_type<StorageClass>::type);
|
||||||
|
|
||||||
|
enum class SymbolRole : uint8_t {
|
||||||
|
Declaration = 1 << 0,
|
||||||
|
Definition = 1 << 1,
|
||||||
|
Reference = 1 << 2,
|
||||||
|
Implicit = 1 << 3,
|
||||||
|
|
||||||
|
ChildOf = 1 << 4,
|
||||||
|
BaseOf = 1 << 5,
|
||||||
|
CalledBy = 1 << 6,
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_TYPE_PROXY(SymbolRole, std::underlying_type<SymbolRole>::type);
|
||||||
|
|
||||||
|
inline uint8_t operator&(SymbolRole lhs, SymbolRole rhs) {
|
||||||
|
return uint8_t(lhs) & uint8_t(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SymbolRole operator|(SymbolRole lhs, SymbolRole rhs) {
|
||||||
|
return SymbolRole(uint8_t(lhs) | uint8_t(rhs));
|
||||||
|
}
|
||||||
|
@ -23,8 +23,17 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
|
|||||||
|
|
||||||
Out_LocationList out;
|
Out_LocationList out;
|
||||||
out.id = request->id;
|
out.id = request->id;
|
||||||
for (const SymbolRef& ref :
|
std::vector<SymbolRef> refs =
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position);
|
||||||
|
// A template definition may be a use of its primary template.
|
||||||
|
// We want to get the definition instead of the use.
|
||||||
|
// Order by |Definition| DESC, range size ASC.
|
||||||
|
std::stable_sort(refs.begin(), refs.end(),
|
||||||
|
[](const SymbolRef& a, const SymbolRef& b) {
|
||||||
|
return (a.role & SymbolRole::Definition) >
|
||||||
|
(b.role & SymbolRole::Definition);
|
||||||
|
});
|
||||||
|
for (const SymbolRef& ref : refs) {
|
||||||
if (ref.idx.kind == SymbolKind::Type) {
|
if (ref.idx.kind == SymbolKind::Type) {
|
||||||
QueryType& type = db->types[ref.idx.idx];
|
QueryType& type = db->types[ref.idx.idx];
|
||||||
if (!type.def)
|
if (!type.def)
|
||||||
@ -32,11 +41,13 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
|
|||||||
std::vector<QueryLocation> locations =
|
std::vector<QueryLocation> locations =
|
||||||
ToQueryLocation(db, type.def->parents);
|
ToQueryLocation(db, type.def->parents);
|
||||||
out.result = GetLsLocations(db, working_files, locations);
|
out.result = GetLsLocations(db, working_files, locations);
|
||||||
|
break;
|
||||||
} else if (ref.idx.kind == SymbolKind::Func) {
|
} else if (ref.idx.kind == SymbolKind::Func) {
|
||||||
QueryFunc& func = db->funcs[ref.idx.idx];
|
QueryFunc& func = db->funcs[ref.idx.idx];
|
||||||
std::vector<QueryLocation> locations =
|
std::vector<QueryLocation> locations =
|
||||||
ToQueryLocation(db, func.def->base);
|
ToQueryLocation(db, func.def->base);
|
||||||
out.result = GetLsLocations(db, working_files, locations);
|
out.result = GetLsLocations(db, working_files, locations);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(IpcId::CqueryBase, out);
|
QueueManager::WriteStdout(IpcId::CqueryBase, out);
|
||||||
|
@ -23,18 +23,29 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
|
|||||||
|
|
||||||
Out_LocationList out;
|
Out_LocationList out;
|
||||||
out.id = request->id;
|
out.id = request->id;
|
||||||
for (const SymbolRef& ref :
|
std::vector<SymbolRef> refs =
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position);
|
||||||
|
// A template definition may be a use of its primary template.
|
||||||
|
// We want to get the definition instead of the use.
|
||||||
|
// Order by |Definition| DESC, range size ASC.
|
||||||
|
std::stable_sort(refs.begin(), refs.end(),
|
||||||
|
[](const SymbolRef& a, const SymbolRef& b) {
|
||||||
|
return (a.role & SymbolRole::Definition) >
|
||||||
|
(b.role & SymbolRole::Definition);
|
||||||
|
});
|
||||||
|
for (const SymbolRef& ref : refs) {
|
||||||
if (ref.idx.kind == SymbolKind::Type) {
|
if (ref.idx.kind == SymbolKind::Type) {
|
||||||
QueryType& type = db->types[ref.idx.idx];
|
QueryType& type = db->types[ref.idx.idx];
|
||||||
std::vector<QueryLocation> locations =
|
std::vector<QueryLocation> locations =
|
||||||
ToQueryLocation(db, type.derived);
|
ToQueryLocation(db, type.derived);
|
||||||
out.result = GetLsLocations(db, working_files, locations);
|
out.result = GetLsLocations(db, working_files, locations);
|
||||||
|
break;
|
||||||
} else if (ref.idx.kind == SymbolKind::Func) {
|
} else if (ref.idx.kind == SymbolKind::Func) {
|
||||||
QueryFunc& func = db->funcs[ref.idx.idx];
|
QueryFunc& func = db->funcs[ref.idx.idx];
|
||||||
std::vector<QueryLocation> locations =
|
std::vector<QueryLocation> locations =
|
||||||
ToQueryLocation(db, func.derived);
|
ToQueryLocation(db, func.derived);
|
||||||
out.result = GetLsLocations(db, working_files, locations);
|
out.result = GetLsLocations(db, working_files, locations);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueueManager::WriteStdout(IpcId::CqueryDerived, out);
|
QueueManager::WriteStdout(IpcId::CqueryDerived, out);
|
||||||
|
26
src/query.cc
26
src/query.cc
@ -219,30 +219,31 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) {
|
|||||||
}();
|
}();
|
||||||
|
|
||||||
auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) {
|
auto add_outline = [&def, &id_map](SymbolIdx idx, Range range) {
|
||||||
def.outline.push_back(SymbolRef(idx, id_map.ToQuery(range)));
|
def.outline.push_back(
|
||||||
|
SymbolRef(idx, SymbolRole::Declaration, id_map.ToQuery(range)));
|
||||||
};
|
};
|
||||||
auto add_all_symbols = [&def, &id_map](SymbolIdx idx, Range range) {
|
auto add_all_symbols = [&def, &id_map](SymbolIdx idx, SymbolRole role,
|
||||||
def.all_symbols.push_back(SymbolRef(idx, id_map.ToQuery(range)));
|
Range range) {
|
||||||
|
def.all_symbols.push_back(SymbolRef(idx, role, id_map.ToQuery(range)));
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const IndexType& type : indexed.types) {
|
for (const IndexType& type : indexed.types) {
|
||||||
if (type.def.definition_spelling.has_value())
|
if (type.def.definition_spelling.has_value())
|
||||||
add_all_symbols(id_map.ToSymbol(type.id),
|
add_all_symbols(id_map.ToSymbol(type.id), SymbolRole::Definition,
|
||||||
type.def.definition_spelling.value());
|
type.def.definition_spelling.value());
|
||||||
if (type.def.definition_extent.has_value())
|
if (type.def.definition_extent.has_value())
|
||||||
add_outline(id_map.ToSymbol(type.id), type.def.definition_extent.value());
|
add_outline(id_map.ToSymbol(type.id), type.def.definition_extent.value());
|
||||||
for (const Range& use : type.uses)
|
for (const Range& use : type.uses)
|
||||||
add_all_symbols(id_map.ToSymbol(type.id), use);
|
add_all_symbols(id_map.ToSymbol(type.id), SymbolRole::Reference, use);
|
||||||
}
|
}
|
||||||
for (const IndexFunc& func : indexed.funcs) {
|
for (const IndexFunc& func : indexed.funcs) {
|
||||||
if (func.def.definition_spelling.has_value())
|
if (func.def.definition_spelling.has_value())
|
||||||
add_all_symbols(id_map.ToSymbol(func.id),
|
add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Definition,
|
||||||
func.def.definition_spelling.value());
|
func.def.definition_spelling.value());
|
||||||
if (func.def.definition_extent.has_value())
|
if (func.def.definition_extent.has_value())
|
||||||
add_outline(id_map.ToSymbol(func.id), func.def.definition_extent.value());
|
add_outline(id_map.ToSymbol(func.id), func.def.definition_extent.value());
|
||||||
for (const IndexFunc::Declaration& decl : func.declarations) {
|
for (const IndexFunc::Declaration& decl : func.declarations) {
|
||||||
// TODO: add more outline info?
|
add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Declaration, decl.spelling);
|
||||||
add_all_symbols(id_map.ToSymbol(func.id), decl.spelling);
|
|
||||||
add_outline(id_map.ToSymbol(func.id), decl.spelling);
|
add_outline(id_map.ToSymbol(func.id), decl.spelling);
|
||||||
}
|
}
|
||||||
for (const IndexFuncRef& caller : func.callers) {
|
for (const IndexFuncRef& caller : func.callers) {
|
||||||
@ -256,21 +257,22 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) {
|
|||||||
range.start.column--;
|
range.start.column--;
|
||||||
range.end.column++;
|
range.end.column++;
|
||||||
}
|
}
|
||||||
add_all_symbols(id_map.ToSymbol(func.id), range);
|
add_all_symbols(id_map.ToSymbol(func.id),
|
||||||
|
SymbolRole::Implicit | SymbolRole::CalledBy, range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const IndexVar& var : indexed.vars) {
|
for (const IndexVar& var : indexed.vars) {
|
||||||
if (var.def.definition_spelling.has_value())
|
if (var.def.definition_spelling.has_value())
|
||||||
add_all_symbols(id_map.ToSymbol(var.id),
|
add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Definition,
|
||||||
var.def.definition_spelling.value());
|
var.def.definition_spelling.value());
|
||||||
if (var.def.definition_extent.has_value())
|
if (var.def.definition_extent.has_value())
|
||||||
add_outline(id_map.ToSymbol(var.id), var.def.definition_extent.value());
|
add_outline(id_map.ToSymbol(var.id), var.def.definition_extent.value());
|
||||||
for (const Range& decl : var.declarations) {
|
for (const Range& decl : var.declarations) {
|
||||||
add_all_symbols(id_map.ToSymbol(var.id), decl);
|
add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Declaration, decl);
|
||||||
add_outline(id_map.ToSymbol(var.id), decl);
|
add_outline(id_map.ToSymbol(var.id), decl);
|
||||||
}
|
}
|
||||||
for (const Range& use : var.uses)
|
for (const Range& use : var.uses)
|
||||||
add_all_symbols(id_map.ToSymbol(var.id), use);
|
add_all_symbols(id_map.ToSymbol(var.id), SymbolRole::Reference, use);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(def.outline.begin(), def.outline.end(),
|
std::sort(def.outline.begin(), def.outline.end(),
|
||||||
|
@ -81,10 +81,12 @@ MAKE_HASHABLE(SymbolIdx, t.kind, t.idx);
|
|||||||
|
|
||||||
struct SymbolRef {
|
struct SymbolRef {
|
||||||
SymbolIdx idx;
|
SymbolIdx idx;
|
||||||
|
SymbolRole role;
|
||||||
QueryLocation loc;
|
QueryLocation loc;
|
||||||
|
|
||||||
SymbolRef() {} // Do not use, needed for reflect.
|
SymbolRef() {} // Do not use, needed for reflect.
|
||||||
SymbolRef(SymbolIdx idx, QueryLocation loc) : idx(idx), loc(loc) {}
|
SymbolRef(SymbolIdx idx, SymbolRole role, QueryLocation loc)
|
||||||
|
: idx(idx), role(role), loc(loc) {}
|
||||||
|
|
||||||
bool operator==(const SymbolRef& that) const {
|
bool operator==(const SymbolRef& that) const {
|
||||||
return idx == that.idx && loc == that.loc;
|
return idx == that.idx && loc == that.loc;
|
||||||
|
@ -488,6 +488,7 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
|||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Sort only by range length, not |kind| or |idx|
|
||||||
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
|
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
|
||||||
QueryFile* file,
|
QueryFile* file,
|
||||||
lsPosition position) {
|
lsPosition position) {
|
||||||
|
Loading…
Reference in New Issue
Block a user