mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-27 10:02:03 +00:00
Add ExtentRef; merge symbol2refcnt and outline2refcnt
Fix hierarchical document symbol for namespaces when there are multiple declarations.
This commit is contained in:
parent
6deadc5f24
commit
556e611573
@ -51,6 +51,15 @@ struct SymbolRef {
|
|||||||
};
|
};
|
||||||
MAKE_HASHABLE(SymbolRef, t.range, t.usr, t.kind, t.role);
|
MAKE_HASHABLE(SymbolRef, t.range, t.usr, t.kind, t.role);
|
||||||
|
|
||||||
|
struct ExtentRef : SymbolRef {
|
||||||
|
Range extent;
|
||||||
|
std::tuple<Range, Usr, SymbolKind, Role, Range> ToTuple() const {
|
||||||
|
return std::make_tuple(range, usr, kind, role, extent);
|
||||||
|
}
|
||||||
|
bool operator==(const ExtentRef &o) const { return ToTuple() == o.ToTuple(); }
|
||||||
|
};
|
||||||
|
MAKE_HASHABLE(ExtentRef, t.range, t.usr, t.kind, t.role, t.extent);
|
||||||
|
|
||||||
struct Ref {
|
struct Ref {
|
||||||
Range range;
|
Range range;
|
||||||
Role role;
|
Role role;
|
||||||
|
@ -102,15 +102,16 @@ bool Expand(MessageHandler *m, Out_cclsCall *entry, bool callee,
|
|||||||
} else {
|
} else {
|
||||||
for (Use use : func.uses) {
|
for (Use use : func.uses) {
|
||||||
const QueryFile &file1 = m->db->files[use.file_id];
|
const QueryFile &file1 = m->db->files[use.file_id];
|
||||||
Maybe<SymbolRef> best_sym;
|
Maybe<ExtentRef> best;
|
||||||
for (auto [sym, refcnt] : file1.outline2refcnt)
|
for (auto [sym, refcnt] : file1.symbol2refcnt)
|
||||||
if (refcnt > 0 && sym.kind == SymbolKind::Func &&
|
if (refcnt > 0 && sym.extent.Valid() &&
|
||||||
sym.range.start <= use.range.start &&
|
sym.kind == SymbolKind::Func &&
|
||||||
use.range.end <= sym.range.end &&
|
sym.extent.start <= use.range.start &&
|
||||||
(!best_sym || best_sym->range.start < sym.range.start))
|
use.range.end <= sym.extent.end &&
|
||||||
best_sym = sym;
|
(!best || best->extent.start < sym.extent.start))
|
||||||
if (best_sym)
|
best = sym;
|
||||||
handle(*best_sym, use.file_id, call_type);
|
if (best)
|
||||||
|
handle(*best, use.file_id, call_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -55,49 +55,49 @@ struct Handler_CclsNavigate : BaseMessageHandler<In_CclsNavigate> {
|
|||||||
switch (params.direction[0]) {
|
switch (params.direction[0]) {
|
||||||
case 'D': {
|
case 'D': {
|
||||||
Maybe<Range> parent;
|
Maybe<Range> parent;
|
||||||
for (auto [sym, refcnt] : file->outline2refcnt)
|
for (auto [sym, refcnt] : file->symbol2refcnt)
|
||||||
if (refcnt > 0 && sym.range.start <= pos && pos < sym.range.end &&
|
if (refcnt > 0 && sym.extent.Valid() && sym.extent.start <= pos &&
|
||||||
(!parent || parent->start < sym.range.start))
|
pos < sym.extent.end && (!parent || parent->start < sym.extent.start))
|
||||||
parent = sym.range;
|
parent = sym.extent;
|
||||||
for (auto [sym, refcnt] : file->outline2refcnt)
|
for (auto [sym, refcnt] : file->symbol2refcnt)
|
||||||
if (refcnt > 0 && pos < sym.range.start &&
|
if (refcnt > 0 && pos < sym.extent.start &&
|
||||||
(!parent || sym.range.end <= parent->end) &&
|
(!parent || sym.extent.end <= parent->end) &&
|
||||||
(!res || sym.range.start < res->start))
|
(!res || sym.extent.start < res->start))
|
||||||
res = sym.range;
|
res = sym.extent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'L':
|
case 'L':
|
||||||
for (auto [sym, refcnt] : file->outline2refcnt)
|
for (auto [sym, refcnt] : file->symbol2refcnt)
|
||||||
if (refcnt > 0 && sym.range.end <= pos &&
|
if (refcnt > 0 && sym.extent.Valid() && sym.extent.end <= pos &&
|
||||||
(!res || (res->end == sym.range.end ? sym.range.start < res->start
|
(!res || (res->end == sym.extent.end ? sym.extent.start < res->start
|
||||||
: res->end < sym.range.end)))
|
: res->end < sym.extent.end)))
|
||||||
res = sym.range;
|
res = sym.extent;
|
||||||
break;
|
break;
|
||||||
case 'R': {
|
case 'R': {
|
||||||
Maybe<Range> parent;
|
Maybe<Range> parent;
|
||||||
for (auto [sym, refcnt] : file->outline2refcnt)
|
for (auto [sym, refcnt] : file->symbol2refcnt)
|
||||||
if (refcnt > 0 && sym.range.start <= pos && pos < sym.range.end &&
|
if (refcnt > 0 && sym.extent.Valid() && sym.extent.start <= pos &&
|
||||||
(!parent || parent->start < sym.range.start))
|
pos < sym.extent.end && (!parent || parent->start < sym.extent.start))
|
||||||
parent = sym.range;
|
parent = sym.extent;
|
||||||
if (parent && parent->start.line == pos.line && pos < parent->end) {
|
if (parent && parent->start.line == pos.line && pos < parent->end) {
|
||||||
pos = parent->end;
|
pos = parent->end;
|
||||||
if (pos.column)
|
if (pos.column)
|
||||||
pos.column--;
|
pos.column--;
|
||||||
}
|
}
|
||||||
for (auto [sym, refcnt] : file->outline2refcnt)
|
for (auto [sym, refcnt] : file->symbol2refcnt)
|
||||||
if (refcnt > 0 && pos < sym.range.start &&
|
if (refcnt > 0 && sym.extent.Valid() && pos < sym.extent.start &&
|
||||||
(!res ||
|
(!res ||
|
||||||
(sym.range.start == res->start ? res->end < sym.range.end
|
(sym.extent.start == res->start ? res->end < sym.extent.end
|
||||||
: sym.range.start < res->start)))
|
: sym.extent.start < res->start)))
|
||||||
res = sym.range;
|
res = sym.extent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'U':
|
case 'U':
|
||||||
default:
|
default:
|
||||||
for (auto [sym, refcnt] : file->outline2refcnt)
|
for (auto [sym, refcnt] : file->symbol2refcnt)
|
||||||
if (refcnt > 0 && sym.range.start < pos && pos < sym.range.end &&
|
if (refcnt > 0 && sym.extent.Valid() && sym.extent.start < pos &&
|
||||||
(!res || res->start < sym.range.start))
|
pos < sym.extent.end && (!res || res->start < sym.extent.start))
|
||||||
res = sym.range;
|
res = sym.extent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::vector<lsLocation> result;
|
std::vector<lsLocation> result;
|
||||||
|
@ -74,15 +74,15 @@ struct Handler_TextDocumentCodeLens
|
|||||||
return;
|
return;
|
||||||
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
|
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
|
||||||
|
|
||||||
auto Add = [&](const char *singular, Cmd_xref show, Use use, int num,
|
auto Add = [&](const char *singular, Cmd_xref show, Range range, int num,
|
||||||
bool force_display = false) {
|
bool force_display = false) {
|
||||||
if (!num && !force_display)
|
if (!num && !force_display)
|
||||||
return;
|
return;
|
||||||
std::optional<lsRange> range = GetLsRange(wfile, use.range);
|
std::optional<lsRange> ls_range = GetLsRange(wfile, range);
|
||||||
if (!range)
|
if (!ls_range)
|
||||||
return;
|
return;
|
||||||
lsCodeLens &code_lens = result.emplace_back();
|
lsCodeLens &code_lens = result.emplace_back();
|
||||||
code_lens.range = *range;
|
code_lens.range = *ls_range;
|
||||||
code_lens.command = lsCommand();
|
code_lens.command = lsCommand();
|
||||||
code_lens.command->command = std::string(ccls_xref);
|
code_lens.command->command = std::string(ccls_xref);
|
||||||
bool plural = num > 1 && singular[strlen(singular) - 1] != 'd';
|
bool plural = num > 1 && singular[strlen(singular) - 1] != 'd';
|
||||||
@ -91,19 +91,10 @@ struct Handler_TextDocumentCodeLens
|
|||||||
code_lens.command->arguments.push_back(ToString(show));
|
code_lens.command->arguments.push_back(ToString(show));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ToSpell = [&](SymbolRef sym, int file_id) -> Use {
|
|
||||||
Maybe<DeclRef> def = GetDefinitionSpell(db, sym);
|
|
||||||
if (def && def->file_id == file_id &&
|
|
||||||
def->range.start.line == sym.range.start.line)
|
|
||||||
return *def;
|
|
||||||
return {{sym.range, sym.role}, file_id};
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unordered_set<Range> seen;
|
std::unordered_set<Range> seen;
|
||||||
for (auto [sym, refcnt] : file->outline2refcnt) {
|
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
||||||
if (refcnt <= 0 || !seen.insert(sym.range).second)
|
if (refcnt <= 0 || !sym.extent.Valid() || !seen.insert(sym.range).second)
|
||||||
continue;
|
continue;
|
||||||
Use use = ToSpell(sym, file->id);
|
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func: {
|
case SymbolKind::Func: {
|
||||||
QueryFunc &func = db->GetFunc(sym);
|
QueryFunc &func = db->GetFunc(sym);
|
||||||
@ -112,28 +103,28 @@ struct Handler_TextDocumentCodeLens
|
|||||||
continue;
|
continue;
|
||||||
std::vector<Use> base_uses = GetUsesForAllBases(db, func);
|
std::vector<Use> base_uses = GetUsesForAllBases(db, func);
|
||||||
std::vector<Use> derived_uses = GetUsesForAllDerived(db, func);
|
std::vector<Use> derived_uses = GetUsesForAllDerived(db, func);
|
||||||
Add("ref", {sym.usr, SymbolKind::Func, "uses"}, use, func.uses.size(),
|
Add("ref", {sym.usr, SymbolKind::Func, "uses"}, sym.range,
|
||||||
base_uses.empty());
|
func.uses.size(), base_uses.empty());
|
||||||
if (base_uses.size())
|
if (base_uses.size())
|
||||||
Add("b.ref", {sym.usr, SymbolKind::Func, "bases uses"}, use,
|
Add("b.ref", {sym.usr, SymbolKind::Func, "bases uses"}, sym.range,
|
||||||
base_uses.size());
|
base_uses.size());
|
||||||
if (derived_uses.size())
|
if (derived_uses.size())
|
||||||
Add("d.ref", {sym.usr, SymbolKind::Func, "derived uses"}, use,
|
Add("d.ref", {sym.usr, SymbolKind::Func, "derived uses"}, sym.range,
|
||||||
derived_uses.size());
|
derived_uses.size());
|
||||||
if (base_uses.empty())
|
if (base_uses.empty())
|
||||||
Add("base", {sym.usr, SymbolKind::Func, "bases"}, use,
|
Add("base", {sym.usr, SymbolKind::Func, "bases"}, sym.range,
|
||||||
def->bases.size());
|
def->bases.size());
|
||||||
Add("derived", {sym.usr, SymbolKind::Func, "derived"}, use,
|
Add("derived", {sym.usr, SymbolKind::Func, "derived"}, sym.range,
|
||||||
func.derived.size());
|
func.derived.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
case SymbolKind::Type: {
|
||||||
QueryType &type = db->GetType(sym);
|
QueryType &type = db->GetType(sym);
|
||||||
Add("ref", {sym.usr, SymbolKind::Type, "uses"}, use, type.uses.size(),
|
Add("ref", {sym.usr, SymbolKind::Type, "uses"}, sym.range, type.uses.size(),
|
||||||
true);
|
true);
|
||||||
Add("derived", {sym.usr, SymbolKind::Type, "derived"}, use,
|
Add("derived", {sym.usr, SymbolKind::Type, "derived"}, sym.range,
|
||||||
type.derived.size());
|
type.derived.size());
|
||||||
Add("var", {sym.usr, SymbolKind::Type, "instances"}, use,
|
Add("var", {sym.usr, SymbolKind::Type, "instances"}, sym.range,
|
||||||
type.instances.size());
|
type.instances.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -142,7 +133,7 @@ struct Handler_TextDocumentCodeLens
|
|||||||
const QueryVar::Def *def = var.AnyDef();
|
const QueryVar::Def *def = var.AnyDef();
|
||||||
if (!def || (def->is_local() && !g_config->codeLens.localVariables))
|
if (!def || (def->is_local() && !g_config->codeLens.localVariables))
|
||||||
continue;
|
continue;
|
||||||
Add("ref", {sym.usr, SymbolKind::Var, "uses"}, use, var.uses.size(),
|
Add("ref", {sym.usr, SymbolKind::Var, "uses"}, sym.range, var.uses.size(),
|
||||||
def->kind != lsSymbolKind::Macro);
|
def->kind != lsSymbolKind::Macro);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -71,12 +71,11 @@ struct Handler_TextDocumentDocumentSymbol
|
|||||||
if (!wfile)
|
if (!wfile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto &symbol2refcnt =
|
|
||||||
params.all ? file->symbol2refcnt : file->outline2refcnt;
|
|
||||||
if (params.startLine >= 0) {
|
if (params.startLine >= 0) {
|
||||||
std::vector<lsRange> result;
|
std::vector<lsRange> result;
|
||||||
for (auto [sym, refcnt] : symbol2refcnt)
|
for (auto [sym, refcnt] : file->symbol2refcnt)
|
||||||
if (refcnt > 0 && params.startLine <= sym.range.start.line &&
|
if (refcnt > 0 && (params.all || sym.extent.Valid()) &&
|
||||||
|
params.startLine <= sym.range.start.line &&
|
||||||
sym.range.start.line <= params.endLine)
|
sym.range.start.line <= params.endLine)
|
||||||
if (auto loc = GetLsLocation(db, working_files, sym, file_id))
|
if (auto loc = GetLsLocation(db, working_files, sym, file_id))
|
||||||
result.push_back(loc->range);
|
result.push_back(loc->range);
|
||||||
@ -84,79 +83,59 @@ struct Handler_TextDocumentDocumentSymbol
|
|||||||
pipeline::Reply(request->id, result);
|
pipeline::Reply(request->id, result);
|
||||||
} else if (g_config->client.hierarchicalDocumentSymbolSupport) {
|
} else if (g_config->client.hierarchicalDocumentSymbolSupport) {
|
||||||
std::unordered_map<SymbolIdx, std::unique_ptr<lsDocumentSymbol>> sym2ds;
|
std::unordered_map<SymbolIdx, std::unique_ptr<lsDocumentSymbol>> sym2ds;
|
||||||
std::vector<std::pair<const QueryFunc::Def *, lsDocumentSymbol *>> funcs;
|
std::vector<std::pair<std::vector<const void *>, lsDocumentSymbol *>>
|
||||||
std::vector<std::pair<const QueryType::Def *, lsDocumentSymbol *>> types;
|
funcs, types;
|
||||||
for (auto [sym, refcnt] : symbol2refcnt) {
|
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
||||||
if (refcnt <= 0)
|
if (refcnt <= 0 || !sym.extent.Valid())
|
||||||
continue;
|
continue;
|
||||||
auto r = sym2ds.try_emplace(SymbolIdx{sym.usr, sym.kind});
|
auto r = sym2ds.try_emplace(SymbolIdx{sym.usr, sym.kind});
|
||||||
if (!r.second)
|
if (!r.second)
|
||||||
continue;
|
continue;
|
||||||
auto &ds = r.first->second;
|
auto &ds = r.first->second;
|
||||||
ds = std::make_unique<lsDocumentSymbol>();
|
ds = std::make_unique<lsDocumentSymbol>();
|
||||||
const void *def_ptr = nullptr;
|
std::vector<const void *> def_ptrs;
|
||||||
WithEntity(db, sym, [&](const auto &entity) {
|
WithEntity(db, sym, [&, sym = sym](const auto &entity) {
|
||||||
auto *def = entity.AnyDef();
|
auto *def = entity.AnyDef();
|
||||||
if (!def)
|
if (!def)
|
||||||
return;
|
return;
|
||||||
ds->name = def->Name(false);
|
ds->name = def->Name(false);
|
||||||
ds->detail = def->Name(true);
|
ds->detail = def->Name(true);
|
||||||
|
if (auto ls_range = GetLsRange(wfile, sym.range)) {
|
||||||
|
ds->selectionRange = *ls_range;
|
||||||
|
ds->range = ds->selectionRange;
|
||||||
|
if (sym.extent.Valid())
|
||||||
|
if (auto ls_range1 = GetLsRange(wfile, sym.extent))
|
||||||
|
ds->range = *ls_range1;
|
||||||
|
}
|
||||||
|
|
||||||
// Try to find a definition with spell first.
|
|
||||||
const void *candidate_def_ptr = nullptr;
|
|
||||||
for (auto &def : entity.def)
|
for (auto &def : entity.def)
|
||||||
if (def.file_id == file_id && !Ignore(&def)) {
|
if (def.file_id == file_id && !Ignore(&def)) {
|
||||||
ds->kind = def.kind;
|
ds->kind = def.kind;
|
||||||
if (def.kind == lsSymbolKind::Namespace)
|
if (def.spell || def.kind == lsSymbolKind::Namespace)
|
||||||
candidate_def_ptr = &def;
|
def_ptrs.push_back(&def);
|
||||||
|
|
||||||
if (!def.spell)
|
|
||||||
continue;
|
|
||||||
if (auto ls_range = GetLsRange(wfile, def.spell->extent))
|
|
||||||
ds->range = *ls_range;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
if (auto ls_range = GetLsRange(wfile, def.spell->range))
|
|
||||||
ds->selectionRange = *ls_range;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
def_ptr = &def;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find a declaration.
|
|
||||||
if (!def_ptr && candidate_def_ptr)
|
|
||||||
for (auto &decl : entity.declarations)
|
|
||||||
if (decl.file_id == file_id) {
|
|
||||||
if (auto ls_range = GetLsRange(wfile, decl.extent))
|
|
||||||
ds->range = *ls_range;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
if (auto ls_range = GetLsRange(wfile, decl.range))
|
|
||||||
ds->selectionRange = *ls_range;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
def_ptr = candidate_def_ptr;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!def_ptr) {
|
if (def_ptrs.empty() || !(params.all || sym.role & Role::Definition ||
|
||||||
|
ds->kind == lsSymbolKind::Namespace)) {
|
||||||
ds.reset();
|
ds.reset();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (sym.kind == SymbolKind::Func)
|
if (sym.kind == SymbolKind::Func)
|
||||||
funcs.emplace_back((const QueryFunc::Def *)def_ptr, ds.get());
|
funcs.emplace_back(std::move(def_ptrs), ds.get());
|
||||||
else if (sym.kind == SymbolKind::Type)
|
else if (sym.kind == SymbolKind::Type)
|
||||||
types.emplace_back((const QueryType::Def *)def_ptr, ds.get());
|
types.emplace_back(std::move(def_ptrs), ds.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &[def, ds] : funcs)
|
for (auto &[def_ptrs, ds] : funcs)
|
||||||
for (Usr usr1 : def->vars) {
|
for (const void *def_ptr : def_ptrs)
|
||||||
|
for (Usr usr1 : ((const QueryFunc::Def *)def_ptr)->vars) {
|
||||||
auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Var});
|
auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Var});
|
||||||
if (it != sym2ds.end() && it->second)
|
if (it != sym2ds.end() && it->second)
|
||||||
ds->children.push_back(std::move(it->second));
|
ds->children.push_back(std::move(it->second));
|
||||||
}
|
}
|
||||||
for (auto &[def, ds] : types) {
|
for (auto &[def_ptrs, ds] : types)
|
||||||
|
for (const void *def_ptr : def_ptrs) {
|
||||||
|
auto *def = (const QueryType::Def *)def_ptr;
|
||||||
for (Usr usr1 : def->funcs) {
|
for (Usr usr1 : def->funcs) {
|
||||||
auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Func});
|
auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Func});
|
||||||
if (it != sym2ds.end() && it->second)
|
if (it != sym2ds.end() && it->second)
|
||||||
@ -180,8 +159,10 @@ struct Handler_TextDocumentDocumentSymbol
|
|||||||
pipeline::Reply(request->id, result);
|
pipeline::Reply(request->id, result);
|
||||||
} else {
|
} else {
|
||||||
std::vector<lsSymbolInformation> result;
|
std::vector<lsSymbolInformation> result;
|
||||||
for (auto [sym, refcnt] : symbol2refcnt) {
|
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
||||||
if (refcnt <= 0) continue;
|
if (refcnt <= 0 || !sym.extent.Valid() ||
|
||||||
|
!(params.all || sym.role & Role::Definition))
|
||||||
|
continue;
|
||||||
if (std::optional<lsSymbolInformation> info =
|
if (std::optional<lsSymbolInformation> info =
|
||||||
GetSymbolInfo(db, sym, false)) {
|
GetSymbolInfo(db, sym, false)) {
|
||||||
if ((sym.kind == SymbolKind::Type &&
|
if ((sym.kind == SymbolKind::Type &&
|
||||||
|
28
src/query.cc
28
src/query.cc
@ -224,7 +224,7 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
|||||||
SymbolKind kind, Use &use, int delta) {
|
SymbolKind kind, Use &use, int delta) {
|
||||||
use.file_id =
|
use.file_id =
|
||||||
use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second;
|
use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second;
|
||||||
SymbolRef sym{use.range, usr, kind, use.role};
|
ExtentRef sym{{use.range, usr, kind, use.role}};
|
||||||
int &v = files[use.file_id].symbol2refcnt[sym];
|
int &v = files[use.file_id].symbol2refcnt[sym];
|
||||||
v += delta;
|
v += delta;
|
||||||
assert(v >= 0);
|
assert(v >= 0);
|
||||||
@ -233,9 +233,14 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
|||||||
};
|
};
|
||||||
auto RefDecl = [&](std::unordered_map<int, int> &lid2fid, Usr usr,
|
auto RefDecl = [&](std::unordered_map<int, int> &lid2fid, Usr usr,
|
||||||
SymbolKind kind, DeclRef &dr, int delta) {
|
SymbolKind kind, DeclRef &dr, int delta) {
|
||||||
Ref(lid2fid, usr, kind, dr, delta);
|
dr.file_id =
|
||||||
files[dr.file_id]
|
dr.file_id == -1 ? u->file_id : lid2fid.find(dr.file_id)->second;
|
||||||
.outline2refcnt[SymbolRef{dr.extent, usr, kind, dr.role}] += delta;
|
ExtentRef sym{{dr.range, usr, kind, dr.role}, dr.extent};
|
||||||
|
int &v = files[dr.file_id].symbol2refcnt[sym];
|
||||||
|
v += delta;
|
||||||
|
assert(v >= 0);
|
||||||
|
if (!v)
|
||||||
|
files[dr.file_id].symbol2refcnt.erase(sym);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto UpdateUses =
|
auto UpdateUses =
|
||||||
@ -369,9 +374,8 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
|
|||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
AssignFileId(lid2file_id, file_id, *def.spell);
|
AssignFileId(lid2file_id, file_id, *def.spell);
|
||||||
files[def.spell->file_id].symbol2refcnt[{
|
files[def.spell->file_id].symbol2refcnt[{
|
||||||
def.spell->range, u.first, SymbolKind::Func, def.spell->role}]++;
|
{def.spell->range, u.first, SymbolKind::Func, def.spell->role},
|
||||||
files[def.spell->file_id].outline2refcnt[{
|
def.spell->extent}]++;
|
||||||
def.spell->extent, u.first, SymbolKind::Func, def.spell->role}]++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto R = func_usr.try_emplace({u.first}, func_usr.size());
|
auto R = func_usr.try_emplace({u.first}, func_usr.size());
|
||||||
@ -393,9 +397,8 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
|
|||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
AssignFileId(lid2file_id, file_id, *def.spell);
|
AssignFileId(lid2file_id, file_id, *def.spell);
|
||||||
files[def.spell->file_id].symbol2refcnt[{
|
files[def.spell->file_id].symbol2refcnt[{
|
||||||
def.spell->range, u.first, SymbolKind::Type, def.spell->role}]++;
|
{def.spell->range, u.first, SymbolKind::Type, def.spell->role},
|
||||||
files[def.spell->file_id].outline2refcnt[{
|
def.spell->extent}]++;
|
||||||
def.spell->extent, u.first, SymbolKind::Type, def.spell->role}]++;
|
|
||||||
}
|
}
|
||||||
auto R = type_usr.try_emplace({u.first}, type_usr.size());
|
auto R = type_usr.try_emplace({u.first}, type_usr.size());
|
||||||
if (R.second)
|
if (R.second)
|
||||||
@ -416,9 +419,8 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
|
|||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
AssignFileId(lid2file_id, file_id, *def.spell);
|
AssignFileId(lid2file_id, file_id, *def.spell);
|
||||||
files[def.spell->file_id].symbol2refcnt[{
|
files[def.spell->file_id].symbol2refcnt[{
|
||||||
def.spell->range, u.first, SymbolKind::Var, def.spell->role}]++;
|
{def.spell->range, u.first, SymbolKind::Var, def.spell->role},
|
||||||
files[def.spell->file_id].outline2refcnt[{
|
def.spell->extent}]++;
|
||||||
def.spell->extent, u.first, SymbolKind::Var, def.spell->role}]++;
|
|
||||||
}
|
}
|
||||||
auto R = var_usr.try_emplace({u.first}, var_usr.size());
|
auto R = var_usr.try_emplace({u.first}, var_usr.size());
|
||||||
if (R.second)
|
if (R.second)
|
||||||
|
20
src/query.h
20
src/query.h
@ -11,17 +11,13 @@
|
|||||||
#include <llvm/ADT/StringMap.h>
|
#include <llvm/ADT/StringMap.h>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
template <> struct DenseMapInfo<SymbolRef> {
|
template <> struct DenseMapInfo<ExtentRef> {
|
||||||
static inline SymbolRef getEmptyKey() { return {}; }
|
static inline ExtentRef getEmptyKey() { return {}; }
|
||||||
static inline SymbolRef getTombstoneKey() {
|
static inline ExtentRef getTombstoneKey() { return {{Range(), Usr(-1)}}; }
|
||||||
SymbolRef ret{};
|
static unsigned getHashValue(ExtentRef sym) {
|
||||||
ret.usr = -1;
|
return std::hash<ExtentRef>()(sym);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
static unsigned getHashValue(SymbolRef sym) {
|
static bool isEqual(ExtentRef l, ExtentRef r) { return l == r; }
|
||||||
return std::hash<SymbolRef>()(sym);
|
|
||||||
}
|
|
||||||
static bool isEqual(SymbolRef l, SymbolRef r) { return l == r; }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,8 +38,8 @@ struct QueryFile {
|
|||||||
|
|
||||||
int id = -1;
|
int id = -1;
|
||||||
std::optional<Def> def;
|
std::optional<Def> def;
|
||||||
llvm::DenseMap<SymbolRef, int> symbol2refcnt;
|
// `extent` is valid => declaration; invalid => regular reference
|
||||||
llvm::DenseMap<SymbolRef, int> outline2refcnt;
|
llvm::DenseMap<ExtentRef, int> symbol2refcnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Q, typename QDef> struct QueryEntity {
|
template <typename Q, typename QDef> struct QueryEntity {
|
||||||
|
Loading…
Reference in New Issue
Block a user