Skip to content

Commit e8eef7f

Browse files
authored
fix: make hierarchical docsyms right (#115)
* fix: make hierarchical docsyms right * fix: installation output * fix: compatibility with legacy LSPs who return SymbolInformation * fix: java wont need nested symbols * fix: simply keep behavior of golang same as before * fix: ignore ToolVersion and skip Java
1 parent 0c97a4d commit e8eef7f

File tree

6 files changed

+63
-11
lines changed

6 files changed

+63
-11
lines changed

.github/workflows/go-test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ jobs:
2121
# test tries to retrieve non-existent node
2222
# TestParser_NodeFieldsConsistency:
2323
# Vars.Content only includes name, not whole body
24+
# TestCollector_CollectByTreeSitter_Java
25+
# JDTLS download was rate-limited on github actions
2426
SKIPPED_TESTS: >-
25-
TestPatcher|TestCases|Test_goParser_ParseNode|TestParser_NodeFieldsConsistency|TestRustLSP
27+
TestPatcher|TestCases|Test_goParser_ParseNode|TestParser_NodeFieldsConsistency|TestRustLSP|TestCollector_CollectByTreeSitter_Java
2628
2729
steps:
2830
- name: Checkout code

.github/workflows/regression.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ jobs:
1818
DIFFJSON_IGNORE: >
1919
['id']
2020
['Path']
21+
['ToolVersion']
2122
['Modules']['a.b/c']['Dependencies']['a.b/c']
2223
['Modules']['a.b/c/cmdx']['Dependencies']['a.b/c/cmdx']
2324
steps:

lang/lsp/client.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func NewLSPClient(repo string, openfile string, wait time.Duration, opts ClientO
5656
return nil, err
5757
}
5858

59-
cli, err := initLSPClient(context.Background(), svr, NewURI(repo), opts.Verbose, opts.InitializationOptions)
59+
cli, err := initLSPClient(context.Background(), svr, NewURI(repo), opts.Verbose, opts.Language, opts.InitializationOptions)
6060
if err != nil {
6161
return nil, err
6262
}
@@ -122,7 +122,7 @@ func (c *LSPClient) InitFiles() {
122122
}
123123
}
124124

125-
func initLSPClient(ctx context.Context, svr io.ReadWriteCloser, dir DocumentURI, verbose bool, InitializationOptions interface{}) (*LSPClient, error) {
125+
func initLSPClient(ctx context.Context, svr io.ReadWriteCloser, dir DocumentURI, verbose bool, language uniast.Language, InitializationOptions interface{}) (*LSPClient, error) {
126126
h := newLSPHandler()
127127
stream := jsonrpc2.NewBufferedStream(svr, jsonrpc2.VSCodeObjectCodec{})
128128
conn := jsonrpc2.NewConn(ctx, stream, h)
@@ -141,8 +141,12 @@ func initLSPClient(ctx context.Context, svr io.ReadWriteCloser, dir DocumentURI,
141141
"dynamicRegistration": true,
142142
},
143143
},
144-
"documentSymbol": map[string]interface{}{
145-
"hierarchicalDocumentSymbolSupport": true,
144+
"textDocument": map[string]interface{}{
145+
"documentSymbol": map[string]interface{}{
146+
// Java uses tree-sitter instead of hierarchical symbols
147+
// Golang stays the same as older versions. ABCoder do not use gopls, so don't play with it.
148+
"hierarchicalDocumentSymbolSupport": (language != uniast.Java && language != uniast.Golang),
149+
},
146150
},
147151
}
148152

lang/lsp/lsp.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,18 @@ type DocumentSymbol struct {
184184
Name string `json:"name"`
185185
Kind SymbolKind `json:"kind"`
186186
Tags []json.RawMessage `json:"tags"`
187-
Location Location `json:"location"`
188187
Children []*DocumentSymbol `json:"children"`
189188
Text string `json:"text"`
190189
Tokens []Token `json:"tokens"`
191190
Node *sitter.Node `json:"-"`
192191
Role SymbolRole `json:"-"`
192+
193+
// Older LSPs might return SymbolInformation[] which have `Location`.
194+
// Newer LSPs return DocumentSymbol[] which have `Range` and `SelectionRange`.
195+
// ABCoder uses `Location`, and converts `Range` to `Location` when needed.
196+
Location Location `json:"location"`
197+
Range *Range `json:"range"`
198+
SelectionRange *Range `json:"selectionRange"`
193199
}
194200

195201
type TextDocumentPositionParams struct {

lang/lsp/lsp_methods.go

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,44 @@ func (cli *LSPClient) DidOpen(ctx context.Context, file DocumentURI) (*TextDocum
6363
return f, nil
6464
}
6565

66+
func flattenDocumentSymbols(symbols []*DocumentSymbol, uri DocumentURI) []*DocumentSymbol {
67+
var result []*DocumentSymbol
68+
for _, sym := range symbols {
69+
var location Location
70+
if sym.Range != nil {
71+
location = Location{
72+
URI: uri,
73+
Range: *sym.Range,
74+
}
75+
} else {
76+
location = sym.Location
77+
}
78+
flatSymbol := DocumentSymbol{
79+
// copy
80+
Name: sym.Name,
81+
Kind: sym.Kind,
82+
Tags: sym.Tags,
83+
Text: sym.Text,
84+
Tokens: sym.Tokens,
85+
Node: sym.Node,
86+
Children: sym.Children,
87+
// new
88+
Location: location,
89+
// empty
90+
Role: 0,
91+
Range: nil,
92+
SelectionRange: nil,
93+
}
94+
result = append(result, &flatSymbol)
95+
96+
if len(sym.Children) > 0 {
97+
childSymbols := flattenDocumentSymbols(sym.Children, uri)
98+
result = append(result, childSymbols...)
99+
}
100+
}
101+
return result
102+
}
103+
66104
func (cli *LSPClient) DocumentSymbols(ctx context.Context, file DocumentURI) (map[Range]*DocumentSymbol, error) {
67105
// open file first
68106
f, err := cli.DidOpen(ctx, file)
@@ -78,14 +116,15 @@ func (cli *LSPClient) DocumentSymbols(ctx context.Context, file DocumentURI) (ma
78116
URI: uri,
79117
},
80118
}
81-
var resp []DocumentSymbol
119+
var resp []*DocumentSymbol
82120
if err := cli.Call(ctx, "textDocument/documentSymbol", req, &resp); err != nil {
83121
return nil, err
84122
}
123+
respFlatten := flattenDocumentSymbols(resp, file)
85124
// cache symbols
86-
f.Symbols = make(map[Range]*DocumentSymbol, len(resp))
87-
for i := range resp {
88-
s := &resp[i]
125+
f.Symbols = make(map[Range]*DocumentSymbol, len(respFlatten))
126+
for i := range respFlatten {
127+
s := respFlatten[i]
89128
f.Symbols[s.Location.Range] = s
90129
}
91130
return f.Symbols, nil

lang/python/lib.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func CheckPythonVersion() error {
5959

6060
func InstallLanguageServer() (string, error) {
6161
if out, err := exec.Command("pylsp", "--version").CombinedOutput(); err == nil {
62-
log.Info("pylsp already installed: %v", out)
62+
log.Info("pylsp already installed: %v", string(out))
6363
return lspName, nil
6464
}
6565
if err := CheckPythonVersion(); err != nil {

0 commit comments

Comments
 (0)