Add SymbolRole to SymbolRef and fix $cquery/{base,derived} by ordering definitions before uses

This commit is contained in:
Fangrui Song 2018-01-28 20:39:41 -08:00
parent 777193d02f
commit 16bf3158c5
6 changed files with 64 additions and 17 deletions

View File

@ -65,3 +65,23 @@ enum class StorageClass : uint8_t {
};
MAKE_REFLECT_TYPE_PROXY(StorageClass,
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));
}

View File

@ -23,8 +23,17 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
Out_LocationList out;
out.id = request->id;
for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
std::vector<SymbolRef> refs =
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) {
QueryType& type = db->types[ref.idx.idx];
if (!type.def)
@ -32,11 +41,13 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
std::vector<QueryLocation> locations =
ToQueryLocation(db, type.def->parents);
out.result = GetLsLocations(db, working_files, locations);
break;
} else if (ref.idx.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx];
std::vector<QueryLocation> locations =
ToQueryLocation(db, func.def->base);
out.result = GetLsLocations(db, working_files, locations);
break;
}
}
QueueManager::WriteStdout(IpcId::CqueryBase, out);

View File

@ -23,18 +23,29 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
Out_LocationList out;
out.id = request->id;
for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
std::vector<SymbolRef> refs =
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) {
QueryType& type = db->types[ref.idx.idx];
std::vector<QueryLocation> locations =
ToQueryLocation(db, type.derived);
out.result = GetLsLocations(db, working_files, locations);
break;
} else if (ref.idx.kind == SymbolKind::Func) {
QueryFunc& func = db->funcs[ref.idx.idx];
std::vector<QueryLocation> locations =
ToQueryLocation(db, func.derived);
out.result = GetLsLocations(db, working_files, locations);
break;
}
}
QueueManager::WriteStdout(IpcId::CqueryDerived, out);

View File

@ -219,30 +219,31 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) {
}();
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) {
def.all_symbols.push_back(SymbolRef(idx, id_map.ToQuery(range)));
auto add_all_symbols = [&def, &id_map](SymbolIdx idx, SymbolRole role,
Range range) {
def.all_symbols.push_back(SymbolRef(idx, role, id_map.ToQuery(range)));
};
for (const IndexType& type : indexed.types) {
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());
if (type.def.definition_extent.has_value())
add_outline(id_map.ToSymbol(type.id), type.def.definition_extent.value());
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) {
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());
if (func.def.definition_extent.has_value())
add_outline(id_map.ToSymbol(func.id), func.def.definition_extent.value());
for (const IndexFunc::Declaration& decl : func.declarations) {
// TODO: add more outline info?
add_all_symbols(id_map.ToSymbol(func.id), decl.spelling);
add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Declaration, decl.spelling);
add_outline(id_map.ToSymbol(func.id), decl.spelling);
}
for (const IndexFuncRef& caller : func.callers) {
@ -256,21 +257,22 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) {
range.start.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) {
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());
if (var.def.definition_extent.has_value())
add_outline(id_map.ToSymbol(var.id), var.def.definition_extent.value());
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);
}
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(),

View File

@ -81,10 +81,12 @@ MAKE_HASHABLE(SymbolIdx, t.kind, t.idx);
struct SymbolRef {
SymbolIdx idx;
SymbolRole role;
QueryLocation loc;
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 {
return idx == that.idx && loc == that.loc;

View File

@ -488,6 +488,7 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
return nullopt;
}
// TODO Sort only by range length, not |kind| or |idx|
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
QueryFile* file,
lsPosition position) {