@@ -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,58 @@ 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
+ // Global variables `int i, j, k;` have the same extent.start. Sort them by
164
+ // range.start instead. In case of a tie, prioritize the widest ExtentRef.
165
+ std::sort (syms.begin (), syms.end (),
166
+ [](const ExtentRef &lhs, const ExtentRef &rhs) {
167
+ return std::tie (lhs.range .start , rhs.extent .end ) <
168
+ std::tie (rhs.range .start , lhs.extent .end );
169
+ });
170
+
171
+ std::vector<std::unique_ptr<DocumentSymbol>> res;
172
+ std::vector<DocumentSymbol *> scopes;
173
+ for (ExtentRef sym : syms) {
174
+ auto ds = std::make_unique<DocumentSymbol>();
175
+ if (auto range = getLsRange (wf, sym.range )) {
176
+ ds->selectionRange = *range;
177
+ ds->range = ds->selectionRange ;
178
+ // For a macro expansion, M(name), we may use `M` for extent and
179
+ // `name` for spell, do the check as selectionRange must be a subrange
180
+ // of range.
181
+ if (sym.extent .valid ())
182
+ if (auto range1 = getLsRange (wf, sym.extent );
183
+ range1 && range1->includes (*range))
184
+ ds->range = *range1;
190
185
}
191
- if (!r.second )
192
- continue ;
193
- std::vector<const void *> def_ptrs;
194
- SymbolKind kind = SymbolKind::Unknown;
195
186
withEntity (db, sym, [&](const auto &entity) {
196
- auto *def = entity.anyDef ();
187
+ const auto *def = entity.anyDef ();
197
188
if (!def)
198
189
return ;
199
190
ds->name = def->name (false );
200
191
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
- }
192
+ ds->kind = def->kind ;
193
+
194
+ if (!ignore (def) && (ds->kind == SymbolKind::Namespace || allows (sym))) {
195
+ // Drop scopes which are before selectionRange.start. In
196
+ // `int i, j, k;`, the scope of i will be ended by j.
197
+ while (!scopes.empty () &&
198
+ scopes.back ()->range .end <= ds->selectionRange .start )
199
+ scopes.pop_back ();
200
+ auto *ds1 = ds.get ();
201
+ if (scopes.empty ())
202
+ res.push_back (std::move (ds));
203
+ else
204
+ scopes.back ()->children .push_back (std::move (ds));
205
+ scopes.push_back (ds1);
206
+ }
206
207
});
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
208
}
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);
209
+ reply (res);
251
210
} else {
252
211
std::vector<SymbolInformation> result;
253
212
for (auto [sym, refcnt] : file->symbol2refcnt ) {
0 commit comments