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, 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));
}

View File

@ -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);

View File

@ -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);

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) { 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(),

View File

@ -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;

View File

@ -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) {