@@ -128,16 +128,6 @@ template <> bool ignore(const QueryType::Def *def) {
128128template <> bool ignore (const QueryVar::Def *def) {
129129 return !def || def->is_local ();
130130}
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- }
141131} // namespace
142132
143133void MessageHandler::textDocument_documentSymbol (JsonReader &reader,
@@ -165,89 +155,55 @@ void MessageHandler::textDocument_documentSymbol(JsonReader &reader,
165155 std::sort (result.begin (), result.end ());
166156 reply (result);
167157 } 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;
190184 }
191- if (!r.second )
192- continue ;
193- std::vector<const void *> def_ptrs;
194- SymbolKind kind = SymbolKind::Unknown;
195185 withEntity (db, sym, [&](const auto &entity) {
196- auto *def = entity.anyDef ();
186+ const auto *def = entity.anyDef ();
197187 if (!def)
198188 return ;
199189 ds->name = def->name (false );
200190 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+ }
206204 });
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 ());
215205 }
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);
251207 } else {
252208 std::vector<SymbolInformation> result;
253209 for (auto [sym, refcnt] : file->symbol2refcnt ) {
0 commit comments