Skip to content

Commit c87151a

Browse files
committed
Add excludeRole to documentSymbol and override declaration's range/selectionRange with definition's
1 parent 62cbf58 commit c87151a

1 file changed

Lines changed: 39 additions & 36 deletions

File tree

src/messages/textDocument_document.cc

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,15 @@ void MessageHandler::textDocument_documentLink(TextDocumentParam &param,
107107

108108
namespace {
109109
struct DocumentSymbolParam : TextDocumentParam {
110-
// false: outline; true: all symbols
111-
bool all = false;
110+
// Include sym if `!(sym.role & excludeRole)`.
111+
Role excludeRole =
112+
Role((int)Role::All - (int)Role::Definition - (int)Role::Declaration);
112113
// If >= 0, return Range[] instead of SymbolInformation[] to reduce output.
113114
int startLine = -1;
114115
int endLine = -1;
115116
};
116-
REFLECT_STRUCT(DocumentSymbolParam, textDocument, all, startLine, endLine);
117+
REFLECT_STRUCT(DocumentSymbolParam, textDocument, excludeRole, startLine,
118+
endLine);
117119

118120
struct DocumentSymbol {
119121
std::string name;
@@ -161,44 +163,52 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
161163

162164
int file_id;
163165
auto [file, wf] = FindOrFail(param.textDocument.uri.GetPath(), reply, &file_id);
164-
if (!wf) {
166+
if (!wf)
165167
return;
166-
}
168+
auto Allows = [&](SymbolRef sym) {
169+
return !(sym.role & param.excludeRole);
170+
};
167171

168172
if (param.startLine >= 0) {
169173
std::vector<lsRange> result;
170-
for (auto [sym, refcnt] : file->symbol2refcnt)
171-
if (refcnt > 0 && (param.all || sym.extent.Valid()) &&
172-
param.startLine <= sym.range.start.line &&
173-
sym.range.start.line <= param.endLine)
174-
if (auto loc = GetLsLocation(db, wfiles, sym, file_id))
175-
result.push_back(loc->range);
174+
for (auto [sym, refcnt] : file->symbol2refcnt) {
175+
if (refcnt <= 0 || !Allows(sym) ||
176+
!(param.startLine <= sym.range.start.line &&
177+
sym.range.start.line <= param.endLine))
178+
continue;
179+
if (auto loc = GetLsLocation(db, wfiles, sym, file_id))
180+
result.push_back(loc->range);
181+
}
176182
std::sort(result.begin(), result.end());
177183
reply(result);
178184
} else if (g_config->client.hierarchicalDocumentSymbolSupport) {
179185
std::unordered_map<SymbolIdx, std::unique_ptr<DocumentSymbol>> sym2ds;
180186
std::vector<std::pair<std::vector<const void *>, DocumentSymbol *>> funcs,
181187
types;
182188
for (auto [sym, refcnt] : file->symbol2refcnt) {
183-
if (refcnt <= 0 || !sym.extent.Valid())
189+
if (refcnt <= 0)
184190
continue;
185191
auto r = sym2ds.try_emplace(SymbolIdx{sym.usr, sym.kind});
186-
if (!r.second)
187-
continue;
188192
auto &ds = r.first->second;
189-
ds = std::make_unique<DocumentSymbol>();
190-
if (auto range = GetLsRange(wf, sym.range)) {
191-
ds->selectionRange = *range;
192-
ds->range = ds->selectionRange;
193-
// For a macro expansion, M(name), we may use `M` for extent and `name`
194-
// for spell, do the check as selectionRange must be a subrange of
195-
// range.
196-
if (sym.extent.Valid())
197-
if (auto range1 = GetLsRange(wf, sym.extent);
198-
range1 && range1->Includes(*range))
199-
ds->range = *range1;
193+
if (!ds || sym.role & Role::Definition) {
194+
if (!ds)
195+
ds = std::make_unique<DocumentSymbol>();
196+
if (auto range = GetLsRange(wf, sym.range)) {
197+
ds->selectionRange = *range;
198+
ds->range = ds->selectionRange;
199+
// For a macro expansion, M(name), we may use `M` for extent and
200+
// `name` for spell, do the check as selectionRange must be a subrange
201+
// of range.
202+
if (sym.extent.Valid())
203+
if (auto range1 = GetLsRange(wf, sym.extent);
204+
range1 && range1->Includes(*range))
205+
ds->range = *range1;
206+
}
200207
}
208+
if (!r.second)
209+
continue;
201210
std::vector<const void *> def_ptrs;
211+
SymbolKind kind = SymbolKind::Unknown;
202212
WithEntity(db, sym, [&](const auto &entity) {
203213
auto *def = entity.AnyDef();
204214
if (!def)
@@ -207,20 +217,14 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
207217
ds->detail = def->detailed_name;
208218
for (auto &def : entity.def)
209219
if (def.file_id == file_id && !Ignore(&def)) {
210-
ds->kind = def.kind;
211-
if (def.spell || def.kind == SymbolKind::Namespace)
212-
def_ptrs.push_back(&def);
220+
kind = ds->kind = def.kind;
221+
def_ptrs.push_back(&def);
213222
}
214223
});
215-
if (!(param.all || sym.role & Role::Definition ||
216-
ds->kind == SymbolKind::Function ||
217-
ds->kind == SymbolKind::Method ||
218-
ds->kind == SymbolKind::Namespace)) {
224+
if (def_ptrs.empty() || !(kind == SymbolKind::Namespace || Allows(sym))) {
219225
ds.reset();
220226
continue;
221227
}
222-
if (def_ptrs.empty())
223-
continue;
224228
if (sym.kind == Kind::Func)
225229
funcs.emplace_back(std::move(def_ptrs), ds.get());
226230
else if (sym.kind == Kind::Type)
@@ -264,8 +268,7 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
264268
} else {
265269
std::vector<SymbolInformation> result;
266270
for (auto [sym, refcnt] : file->symbol2refcnt) {
267-
if (refcnt <= 0 || !sym.extent.Valid() ||
268-
!(param.all || sym.role & Role::Definition))
271+
if (refcnt <= 0 || !Allows(sym))
269272
continue;
270273
if (std::optional<SymbolInformation> info =
271274
GetSymbolInfo(db, sym, false)) {

0 commit comments

Comments
 (0)