@@ -107,13 +107,15 @@ void MessageHandler::textDocument_documentLink(TextDocumentParam ¶m,
107107
108108namespace {
109109struct 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
118120struct 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