@@ -128,16 +128,6 @@ template <> bool ignore(const QueryType::Def *def) {
128
128
template <> bool ignore (const QueryVar::Def *def) {
129
129
return !def || def->is_local ();
130
130
}
131
-
132
- void uniquify (std::vector<std::unique_ptr<DocumentSymbol>> &cs) {
133
- std::sort (cs.begin (), cs.end (),
134
- [](auto &l, auto &r) { return l->range < r->range ; });
135
- cs.erase (std::unique (cs.begin (), cs.end (),
136
- [](auto &l, auto &r) { return l->range == r->range ; }),
137
- cs.end ());
138
- for (auto &c : cs)
139
- uniquify (c->children );
140
- }
141
131
} // namespace
142
132
143
133
void MessageHandler::textDocument_documentSymbol (JsonReader &reader,
@@ -165,89 +155,55 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
165
155
std::sort (result.begin (), result.end ());
166
156
reply (result);
167
157
} else if (g_config->client .hierarchicalDocumentSymbolSupport ) {
168
- std::unordered_map<SymbolIdx, std::unique_ptr<DocumentSymbol>> sym2ds;
169
- std::vector<std::pair<std::vector<const void *>, DocumentSymbol *>> funcs,
170
- types;
171
- for (auto [sym, refcnt] : file->symbol2refcnt ) {
172
- if (refcnt <= 0 || !sym.extent .valid ())
173
- continue ;
174
- auto r = sym2ds.try_emplace (SymbolIdx{sym.usr , sym.kind });
175
- auto &ds = r.first ->second ;
176
- if (!ds || sym.role & Role::Definition) {
177
- if (!ds)
178
- ds = std::make_unique<DocumentSymbol>();
179
- if (auto range = getLsRange (wf, sym.range )) {
180
- ds->selectionRange = *range;
181
- ds->range = ds->selectionRange ;
182
- // For a macro expansion, M(name), we may use `M` for extent and
183
- // `name` for spell, do the check as selectionRange must be a subrange
184
- // of range.
185
- if (sym.extent .valid ())
186
- if (auto range1 = getLsRange (wf, sym.extent );
187
- range1 && range1->includes (*range))
188
- ds->range = *range1;
189
- }
158
+ std::vector<ExtentRef> syms;
159
+ syms.reserve (file->symbol2refcnt .size ());
160
+ for (auto [sym, refcnt] : file->symbol2refcnt )
161
+ if (refcnt > 0 && sym.extent .valid ())
162
+ syms.push_back (sym);
163
+ // If multiple ranges start at the same Position, prioritize the widest one.
164
+ std::sort (syms.begin (), syms.end (),
165
+ [](const ExtentRef &lhs, const ExtentRef &rhs) {
166
+ return std::tie (lhs.extent .start , rhs.extent .end ) <
167
+ std::tie (rhs.extent .start , lhs.extent .end );
168
+ });
169
+
170
+ std::vector<std::unique_ptr<DocumentSymbol>> res;
171
+ std::vector<DocumentSymbol *> scopes;
172
+ for (ExtentRef sym : syms) {
173
+ auto ds = std::make_unique<DocumentSymbol>();
174
+ if (auto range = getLsRange (wf, sym.range )) {
175
+ ds->selectionRange = *range;
176
+ ds->range = ds->selectionRange ;
177
+ // For a macro expansion, M(name), we may use `M` for extent and
178
+ // `name` for spell, do the check as selectionRange must be a subrange
179
+ // of range.
180
+ if (sym.extent .valid ())
181
+ if (auto range1 = getLsRange (wf, sym.extent );
182
+ range1 && range1->includes (*range))
183
+ ds->range = *range1;
190
184
}
191
- if (!r.second )
192
- continue ;
193
- std::vector<const void *> def_ptrs;
194
- SymbolKind kind = SymbolKind::Unknown;
195
185
withEntity (db, sym, [&](const auto &entity) {
196
- auto *def = entity.anyDef ();
186
+ const auto *def = entity.anyDef ();
197
187
if (!def)
198
188
return ;
199
189
ds->name = def->name (false );
200
190
ds->detail = def->detailed_name ;
201
- for (auto &def : entity.def )
202
- if (def.file_id == file_id && !ignore (&def)) {
203
- kind = ds->kind = def.kind ;
204
- def_ptrs.push_back (&def);
205
- }
191
+ ds->kind = def->kind ;
192
+
193
+ if (!ignore (def) && (ds->kind == SymbolKind::Namespace || allows (sym))) {
194
+ // Drop symbols that are behind the current one.
195
+ while (!scopes.empty () && scopes.back ()->range .end <= ds->range .start )
196
+ scopes.pop_back ();
197
+ auto *ds1 = ds.get ();
198
+ if (scopes.empty ())
199
+ res.push_back (std::move (ds));
200
+ else
201
+ scopes.back ()->children .push_back (std::move (ds));
202
+ scopes.push_back (ds1);
203
+ }
206
204
});
207
- if (def_ptrs.empty () || !(kind == SymbolKind::Namespace || allows (sym))) {
208
- ds.reset ();
209
- continue ;
210
- }
211
- if (sym.kind == Kind::Func)
212
- funcs.emplace_back (std::move (def_ptrs), ds.get ());
213
- else if (sym.kind == Kind::Type)
214
- types.emplace_back (std::move (def_ptrs), ds.get ());
215
205
}
216
-
217
- for (auto &[def_ptrs, ds] : funcs)
218
- for (const void *def_ptr : def_ptrs)
219
- for (Usr usr1 : ((const QueryFunc::Def *)def_ptr)->vars ) {
220
- auto it = sym2ds.find (SymbolIdx{usr1, Kind::Var});
221
- if (it != sym2ds.end () && it->second )
222
- ds->children .push_back (std::move (it->second ));
223
- }
224
- for (auto &[def_ptrs, ds] : types)
225
- for (const void *def_ptr : def_ptrs) {
226
- auto *def = (const QueryType::Def *)def_ptr;
227
- for (Usr usr1 : def->funcs ) {
228
- auto it = sym2ds.find (SymbolIdx{usr1, Kind::Func});
229
- if (it != sym2ds.end () && it->second )
230
- ds->children .push_back (std::move (it->second ));
231
- }
232
- for (Usr usr1 : def->types ) {
233
- auto it = sym2ds.find (SymbolIdx{usr1, Kind::Type});
234
- if (it != sym2ds.end () && it->second )
235
- ds->children .push_back (std::move (it->second ));
236
- }
237
- for (auto [usr1, _] : def->vars ) {
238
- auto it = sym2ds.find (SymbolIdx{usr1, Kind::Var});
239
- if (it != sym2ds.end () && it->second )
240
- ds->children .push_back (std::move (it->second ));
241
- }
242
- }
243
- std::vector<std::unique_ptr<DocumentSymbol>> result;
244
- for (auto &[_, ds] : sym2ds)
245
- if (ds) {
246
- uniquify (ds->children );
247
- result.push_back (std::move (ds));
248
- }
249
- uniquify (result);
250
- reply (result);
206
+ reply (res);
251
207
} else {
252
208
std::vector<SymbolInformation> result;
253
209
for (auto [sym, refcnt] : file->symbol2refcnt ) {
0 commit comments