diff --git a/CHANGELOG.md b/CHANGELOG.md index 17df23e0b1..09b954d412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] - Add LSP completion for `buf.gen.yaml`, `buf.yaml`, and `buf.policy.yaml` files. +- Fix LSP `textDocument/documentSymbol` marking every symbol as deprecated. ## [v1.69.0] - 2026-04-29 diff --git a/private/buf/buflsp/document_symbol_test.go b/private/buf/buflsp/document_symbol_test.go index 26087a0585..7fced93eeb 100644 --- a/private/buf/buflsp/document_symbol_test.go +++ b/private/buf/buflsp/document_symbol_test.go @@ -72,6 +72,8 @@ func TestDocumentSymbol(t *testing.T) { {name: "symbols.v1.CreateDocumentResponse.document", kind: protocol.SymbolKindField, line: 39}, // Document document {name: "symbols.v1.LegacyDocument", kind: protocol.SymbolKindClass, line: 42, deprecated: true}, // message LegacyDocument (deprecated) {name: "symbols.v1.LegacyDocument.id", kind: protocol.SymbolKindField, line: 44}, // string id + {name: "symbols.v1.ExplicitlyNotDeprecated", kind: protocol.SymbolKindClass, line: 47}, // message ExplicitlyNotDeprecated (option deprecated = false) + {name: "symbols.v1.ExplicitlyNotDeprecated.id", kind: protocol.SymbolKindField, line: 49}, // string id }, }, } @@ -100,6 +102,15 @@ func TestDocumentSymbol(t *testing.T) { assert.Equal(t, testURI, found.Location.URI, "symbol %s has wrong URI", expectedSymbol.name) assert.Equal(t, expectedSymbol.line, found.Location.Range.Start.Line, "symbol %s has wrong line number", expectedSymbol.name) assert.Equal(t, expectedSymbol.deprecated, found.Deprecated, "symbol %s has wrong deprecated status", expectedSymbol.name) + // Tags must only carry SymbolTagDeprecated for symbols that are + // actually deprecated. Clients prefer Tags over the legacy + // Deprecated field, so an unconditional tag would render every + // symbol with a strikethrough. + var expectedTags []protocol.SymbolTag + if expectedSymbol.deprecated { + expectedTags = []protocol.SymbolTag{protocol.SymbolTagDeprecated} + } + assert.Equal(t, expectedTags, found.Tags, "symbol %s has wrong tags", expectedSymbol.name) } }) } diff --git a/private/buf/buflsp/symbol.go b/private/buf/buflsp/symbol.go index 61c9ba744e..018942ebab 100644 --- a/private/buf/buflsp/symbol.go +++ b/private/buf/buflsp/symbol.go @@ -377,9 +377,10 @@ func (s *symbol) GetSymbolInformation() protocol.SymbolInformation { default: kind = protocol.SymbolKindVariable } - var isDeprecated bool - if _, ok := s.ir.Deprecated().AsBool(); ok { - isDeprecated = true + isDeprecated, _ := s.ir.Deprecated().AsBool() + var tags []protocol.SymbolTag + if isDeprecated { + tags = []protocol.SymbolTag{protocol.SymbolTagDeprecated} } return protocol.SymbolInformation{ Name: string(name), @@ -387,9 +388,7 @@ func (s *symbol) GetSymbolInformation() protocol.SymbolInformation { Location: location, ContainerName: containerName, Deprecated: isDeprecated, - Tags: []protocol.SymbolTag{ - protocol.SymbolTagDeprecated, - }, + Tags: tags, } } diff --git a/private/buf/buflsp/testdata/symbols/symbols.proto b/private/buf/buflsp/testdata/symbols/symbols.proto index 1af9a100ea..11cbde4eed 100644 --- a/private/buf/buflsp/testdata/symbols/symbols.proto +++ b/private/buf/buflsp/testdata/symbols/symbols.proto @@ -44,3 +44,8 @@ message LegacyDocument { option deprecated = true; string id = 1; } + +message ExplicitlyNotDeprecated { + option deprecated = false; + string id = 1; +}