Skip to content

Commit eaf7773

Browse files
committed
Improve exception go-to-definition
Allow going to definition from the standalone render_exception UI, and improve the reliability of the package/namespace/symbol discoverability.
1 parent 3b3da5b commit eaf7773

File tree

2 files changed

+63
-37
lines changed

2 files changed

+63
-37
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,75 @@
11
local ui_exceptions = require("clojure-test.ui.exceptions")
22
local config = require("clojure-test.config")
3+
local utils = require("clojure-test.utils")
4+
local nio = require("nio")
35

46
local M = {}
57

8+
function M.go_to_exception(target_window, exception)
9+
local stack = exception["stack-trace"]
10+
if not stack or stack == vim.NIL then
11+
return
12+
end
13+
14+
-- This will iterate over all the frames in a stack trace until a frame points to
15+
-- a line/file/symbol that is within the project classpath and cwd.
16+
--
17+
-- This is a bit hacky as it involves many sequential evals, but it's quick and
18+
-- dirty and it works.
19+
--
20+
-- Future implementation should probably do all this work in clojure land over a
21+
-- single eval
22+
for _, frame in ipairs(stack) do
23+
local line = frame.line
24+
if line == vim.NIL then
25+
line = nil
26+
end
27+
28+
local symbols = {}
29+
if frame.package then
30+
table.insert(symbols, frame.package)
31+
end
32+
if frame.names[1] then
33+
table.insert(symbols, frame.names[1])
34+
end
35+
36+
for _, symbol in ipairs(symbols) do
37+
local meta = config.backend:resolve_metadata_for_symbol(symbol)
38+
if meta and meta ~= vim.NIL then
39+
vim.api.nvim_set_current_win(target_window)
40+
vim.cmd("edit " .. meta.file)
41+
vim.schedule(function()
42+
vim.api.nvim_win_set_cursor(0, { line or meta.line or 1, meta.column or 0 })
43+
end)
44+
return
45+
end
46+
end
47+
end
48+
end
49+
650
function M.render_exception(sym)
751
local exceptions = config.backend:analyze_exception(sym)
852
if not exceptions or exceptions == vim.NIL then
953
return
1054
end
1155

56+
local last_active_window = vim.api.nvim_get_current_win()
57+
1258
local popup = ui_exceptions.open_exception_popup()
1359
ui_exceptions.render_exceptions_to_buf(popup.bufnr, exceptions)
60+
61+
local event = require("nui.utils.autocmd").event
62+
popup:on({ event.WinLeave }, function()
63+
popup:unmount()
64+
end, {})
65+
66+
for _, chord in ipairs(utils.into_table(config.keys.ui.go_to)) do
67+
popup:map("n", chord, function()
68+
nio.run(function()
69+
M.go_to_exception(last_active_window, exceptions[1])
70+
end)
71+
end)
72+
end
1473
end
1574

1675
return M

lua/clojure-test/api/run.lua

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
local exceptions_api = require("clojure-test.api.exceptions")
12
local interface_api = require("clojure-test.ui")
23
local config = require("clojure-test.config")
34
local nio = require("nio")
@@ -15,41 +16,6 @@ local function go_to_test(target_window, test)
1516
end)
1617
end
1718

18-
local function go_to_exception(target_window, exception)
19-
local stack = exception["stack-trace"]
20-
if not stack or stack == vim.NIL then
21-
return
22-
end
23-
24-
-- This will iterate over all the frames in a stack trace until a frame points to
25-
-- a line/file/symbol that is within the project classpath and cwd.
26-
--
27-
-- This is a bit hacky as it involves many sequential evals, but it's quick and
28-
-- dirty and it works.
29-
--
30-
-- Future implementation should probably do all this work in clojure land over a
31-
-- single eval
32-
for _, frame in ipairs(stack) do
33-
local symbol = frame.names[1]
34-
local line = frame.line
35-
if line == vim.NIL then
36-
line = nil
37-
end
38-
39-
if symbol then
40-
local meta = config.backend:resolve_metadata_for_symbol(symbol)
41-
if meta and meta ~= vim.NIL then
42-
vim.api.nvim_set_current_win(target_window)
43-
vim.cmd("edit " .. meta.file)
44-
vim.schedule(function()
45-
vim.api.nvim_win_set_cursor(0, { line or meta.line or 1, meta.column or 0 })
46-
end)
47-
return
48-
end
49-
end
50-
end
51-
end
52-
5319
-- This function is called when <Cr> is pressed while on a node in the report
5420
-- tree.
5521
--
@@ -64,14 +30,15 @@ local function handle_go_to_event(target_window, event)
6430

6531
if node.assertion then
6632
if node.assertion.exceptions then
67-
return go_to_exception(target_window, node.assertion.exceptions[#node.assertion.exceptions])
33+
local exception = node.assertion.exceptions[#node.assertion.exceptions]
34+
return exceptions_api.go_to_exception(target_window, exception)
6835
end
6936

7037
return go_to_test(target_window, node.test)
7138
end
7239

7340
if node.exception then
74-
return go_to_exception(target_window, node.exception)
41+
return exceptions_api.go_to_exception(target_window, node.exception)
7542
end
7643
end)
7744
end

0 commit comments

Comments
 (0)