Add semantic parent to textDocument/references

This commit is contained in:
Fangrui Song 2018-03-06 19:07:54 -08:00
parent a1210db985
commit 6815f1312f
3 changed files with 42 additions and 5 deletions

View File

@ -162,13 +162,16 @@ struct lsLocation {
MAKE_HASHABLE(lsLocation, t.uri, t.range);
MAKE_REFLECT_STRUCT(lsLocation, uri, range);
enum class lsSymbolKind : uint8_t;
// cquery extension
struct lsLocationEx : lsLocation {
optional<std::string_view> containerName;
optional<lsSymbolKind> parentKind;
// Avoid circular dependency on symbol.h
optional<uint16_t> role;
};
MAKE_REFLECT_STRUCT(lsLocationEx, uri, range, containerName, role);
MAKE_REFLECT_STRUCT(lsLocationEx, uri, range, containerName, parentKind, role);
template <typename T>
struct lsCommand {

View File

@ -53,16 +53,21 @@ struct TextDocumentReferencesHandler
Out_TextDocumentReferences out;
out.id = request->id;
bool container = config->xref.container;
for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references.
EachOccurrence(
db, sym, request->params.context.includeDeclaration, [&](Use use) {
EachOccurrenceWithParent(
db, sym, request->params.context.includeDeclaration,
[&](Use use, lsSymbolKind parent_kind) {
if (use.role & request->params.context.role)
if (optional<lsLocationEx> ls_loc = GetLsLocationEx(
db, working_files, use, config->xref.container))
if (optional<lsLocationEx> ls_loc =
GetLsLocationEx(db, working_files, use, container)) {
if (container)
ls_loc->parentKind = parent_kind;
out.result.push_back(*ls_loc);
}
});
break;
}

View File

@ -92,6 +92,35 @@ void EachOccurrence(QueryDatabase* db, SymbolIdx sym, bool include_decl, Fn&& fn
});
}
template <typename Fn>
void EachOccurrenceWithParent(QueryDatabase* db,
SymbolIdx sym,
bool include_decl,
Fn&& fn) {
WithEntity(db, sym, [&](const auto& entity) {
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
for (auto& def : entity.def)
if (def.spell) {
WithEntity(db, *def.spell, [&](const auto& entity) {
for (auto& def : entity.def) {
parent_kind = def.kind;
break;
}
});
break;
}
for (Use use : entity.uses)
fn(use, parent_kind);
if (include_decl) {
for (auto& def : entity.def)
if (def.spell)
fn(*def.spell, parent_kind);
for (Use use : entity.declarations)
fn(use, parent_kind);
}
});
}
template <typename Q, typename Fn>
void EachDefinedEntity(std::vector<Q>& collection,
const std::vector<Id<Q>>& ids,