Skip to content

Commit 202898f

Browse files
committed
ui,tree: use workspace symbol if possible
after researching #10 a bit more I found that certain LSPs (gopls here) provides more accurate symbol information via a workspace symbol query. it would be nice to receieve the same symbol info regardless of the lsp method being used. see: golang/go#49690 this pr now resolves the workspace symbol for all call hierarchy items placed into the tree. this is a bit slower (with gopls anyway) on start, however I've found that after some caching the results are snappy. Signed-off-by: ldelossa <louis.delos@gmail.com>
1 parent 08f311e commit 202898f

File tree

4 files changed

+72
-6
lines changed

4 files changed

+72
-6
lines changed

lua/calltree/lsp/handlers.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local tree = require('calltree.tree')
22
local ui = require('calltree.ui')
3+
local lsp_util = require('calltree.lsp.util')
34

45
local M = {}
56

@@ -35,6 +36,9 @@ M.ch_lsp_handler = function(direction)
3536
ctx.params.item,
3637
ctx.params.item.kind)
3738

39+
-- try to resolve the workspace symbol for root.
40+
root.symbol = lsp_util.symbol_from_node(ui.active_lsp_clients, root, ui.invoking_win_handle)
41+
3842
-- create the root's children nodes via the response array.
3943
local children = {}
4044
for _, call_hierarchy_call in pairs(result) do
@@ -45,6 +49,8 @@ M.ch_lsp_handler = function(direction)
4549
call_hierarchy_call[direction].kind,
4650
call_hierarchy_call.fromRanges
4751
)
52+
-- try to resolve the workspace symbol for child
53+
child.symbol = lsp_util.symbol_from_node(ui.active_lsp_clients, child, ui.invoking_win_handle)
4854
table.insert(children, child)
4955
end
5056

lua/calltree/lsp/util.lua

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ M.multi_client_request = function(clients, method, params, handler, bufnr)
1010
end
1111
end
1212

13-
function M.relative_path_from_uri(uri)
13+
function M.relative_path_from_uri(uri)
1414
local cwd = vim.fn.getcwd()
1515
local uri_path = vim.fn.substitute(uri, "file://", "", "")
1616
local idx = vim.fn.stridx(uri_path, cwd)
@@ -22,4 +22,48 @@ function M.relative_path_from_uri(uri)
2222
return vim.fn.substitute(uri_path, cwd .. "/", "", ""), true
2323
end
2424

25+
-- symbol_from_node attempts to extract the workspace
26+
-- symbol the node represents.
27+
--
28+
-- clients : table - all active lsp clients
29+
--
30+
-- node : tree.Node - the node which we are resolving
31+
-- a symbol for.
32+
--
33+
-- bufnr : buffer_handle - the calltree buffer handle
34+
--
35+
-- returns:
36+
-- table - the SymbolInformation LSP structure
37+
-- https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#symbolInformation
38+
function M.symbol_from_node(clients, node, bufnr)
39+
local params = {
40+
query = node.name,
41+
}
42+
for _, client in ipairs(clients) do
43+
if not client.supports_method("workspace/symbol") then
44+
goto continue
45+
end
46+
-- not all LSPs are optimized, specially ones in early development, set
47+
-- this timeout high.
48+
local out = client.request_sync("workspace/symbol", params, 5000, bufnr)
49+
if out == nil then
50+
goto continue
51+
end
52+
if out.err ~= nil or (out.result == nil or #out.result <= 0) then
53+
goto continue
54+
end
55+
for _, res in ipairs(out.result) do
56+
if
57+
res.uri == node.uri and
58+
res.location.range.start.line ==
59+
node.call_hierarchy_obj.range.start.line
60+
then
61+
return res
62+
end
63+
end
64+
::continue::
65+
end
66+
return nil
67+
end
68+
2569
return M

lua/calltree/ui.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ local function ch_expand_handler(node, linenr, direction)
139139
call_hierarchy_call[direction].kind,
140140
call_hierarchy_call.fromRanges
141141
)
142+
-- try to resolve the workspace symbol for child
143+
child.symbol = lsp_util.symbol_from_node(M.active_lsp_clients, child, M.buffer_handle)
142144
table.insert(children, child)
143145
end
144146

@@ -201,6 +203,8 @@ local function ch_switch_handler(direction)
201203
0,
202204
ctx.params.item,
203205
ctx.params.item.kind)
206+
-- try to resolve the workspace symbol for root
207+
root.symbol = lsp_util.symbol_from_node(M.active_lsp_clients, child, M.buffer_handle)
204208

205209
-- create the root's children nodes via the response array.
206210
local children = {}
@@ -212,6 +216,8 @@ local function ch_switch_handler(direction)
212216
call_hierarchy_call[direction].kind,
213217
call_hierarchy_call.fromRanges
214218
)
219+
-- try to resolve the workspace symbol for child
220+
child.symbol = lsp_util.symbol_from_node(M.active_lsp_clients, child, M.buffer_handle)
215221
table.insert(children, child)
216222
end
217223

lua/calltree/ui/marshal.lua

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,28 @@ function M.marshal_node(node)
3131
glyph = M.glyphs["collapsed"]
3232
end
3333

34-
local kind = vim.lsp.protocol.SymbolKind[node.kind]
34+
-- prefer using workspace symbol details if available.
35+
-- fallback to callhierarchy object details.
36+
local name = ""
37+
local kind = ""
38+
if node.symbol ~= nil then
39+
name = node.symbol.name
40+
kind = vim.lsp.protocol.SymbolKind[node.symbol.kind]
41+
else
42+
name = node.name
43+
kind = vim.lsp.protocol.SymbolKind[node.kind]
44+
end
3545

3646
-- add spacing up to node's depth
3747
for _=1, node.depth do
3848
str = str .. " "
3949
end
4050

4151
-- ▶ Func1
42-
str = str .. glyph .. " " .. node.name
52+
str = str .. glyph .. " " .. name
4353
if ct.config.icons ~= "none" then
44-
-- ▶ Func1[]
45-
str = str .. "[" .. ct.active_icon_set[kind] .. "]" .. " "
54+
-- ▶ Func1 []
55+
str = str .. " " .. "[" .. ct.active_icon_set[kind] .. "]" .. " "
4656
else
4757
-- ▶ Func1 • [Function]
4858
str = str .. M.glyphs.separator .. " " .. "[" .. kind .. "]" .. " "
@@ -52,7 +62,7 @@ function M.marshal_node(node)
5262
ct.config.layout == "top" then
5363
-- now we got all the room in the world, add detail
5464
path = lsp_util.relative_path_from_uri(node.call_hierarchy_obj.uri)
55-
-- ▶ Func1[] • relative/path/to/file
65+
-- ▶ Func1 [] • relative/path/to/file
5666
-- or
5767
-- ▶ Func1 • [Function] • relative/path/to/file
5868
str = str .. M.glyphs.separator .. " " .. path

0 commit comments

Comments
 (0)