aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLW <git@llllvvuu.dev>2023-11-12 04:54:27 -0800
committerGitHub <noreply@github.com>2023-11-12 04:54:27 -0800
commit448907f65d6709fa234d8366053e33311a01bdb9 (patch)
tree17dcb47f3f7481f7ded11e0675309461c7a15973 /test
parentad3568a70167ceb870931650afb7dcaed88640ec (diff)
downloadrneovim-448907f65d6709fa234d8366053e33311a01bdb9.tar.gz
rneovim-448907f65d6709fa234d8366053e33311a01bdb9.tar.bz2
rneovim-448907f65d6709fa234d8366053e33311a01bdb9.zip
feat(lsp)!: vim.lsp.inlay_hint.get(), enable(), is_enabled() #25512
refactor!: `vim.lsp.inlay_hint()` -> `vim.lsp.inlay_hint.enable()` Problem: The LSP specification allows inlay hints to include tooltips, clickable label parts, and code actions; but Neovim provides no API to query for these. Solution: Add minimal viable extension point from which plugins can query for inlay hints in a range, in order to build functionality on top of. Possible Next Steps --- - Add `virt_text_idx` field to `vim.fn.getmousepos()` return value, for usage in mappings of `<LeftMouse>`, `<C-LeftMouse>`, etc
Diffstat (limited to 'test')
-rw-r--r--test/functional/helpers.lua7
-rw-r--r--test/functional/plugin/lsp/inlay_hint_spec.lua363
-rw-r--r--test/functional/plugin/lsp_spec.lua2
-rw-r--r--test/functional/ui/screen.lua1
4 files changed, 172 insertions, 201 deletions
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 6f5397a089..761e7dc522 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -18,8 +18,7 @@ local sleep = global_helpers.sleep
local tbl_contains = global_helpers.tbl_contains
local fail = global_helpers.fail
-local module = {
-}
+local module = {}
local start_dir = luv.cwd()
local runtime_set = 'set runtimepath^=./build/lib/nvim/'
@@ -834,6 +833,8 @@ function module.exec_capture(code)
return module.meths.exec2(code, { output = true }).output
end
+--- @param code string
+--- @return any
function module.exec_lua(code, ...)
return module.meths.exec_lua(code, {...})
end
@@ -948,8 +949,10 @@ function module.mkdir_p(path)
or 'mkdir -p '..path))
end
+--- @class test.functional.helpers: test.helpers
module = global_helpers.tbl_extend('error', module, global_helpers)
+--- @return test.functional.helpers
return function(after_each)
if after_each then
after_each(function()
diff --git a/test/functional/plugin/lsp/inlay_hint_spec.lua b/test/functional/plugin/lsp/inlay_hint_spec.lua
index eec86fdb8e..d0d55df72b 100644
--- a/test/functional/plugin/lsp/inlay_hint_spec.lua
+++ b/test/functional/plugin/lsp/inlay_hint_spec.lua
@@ -10,228 +10,195 @@ local insert = helpers.insert
local clear_notrace = lsp_helpers.clear_notrace
local create_server_definition = lsp_helpers.create_server_definition
+local text = dedent([[
+auto add(int a, int b) { return a + b; }
+
+int main() {
+ int x = 1;
+ int y = 2;
+ return add(x,y);
+}
+}]])
+
+local response = [==[
+[
+{"kind":1,"paddingLeft":false,"label":"-> int","position":{"character":22,"line":0},"paddingRight":false},
+{"kind":2,"paddingLeft":false,"label":"a:","position":{"character":15,"line":5},"paddingRight":true},
+{"kind":2,"paddingLeft":false,"label":"b:","position":{"character":17,"line":5},"paddingRight":true}
+]
+]==]
+
+local grid_without_inlay_hints = [[
+ auto add(int a, int b) { return a + b; } |
+ |
+ int main() { |
+ int x = 1; |
+ int y = 2; |
+ return add(x,y); |
+ } |
+ ^} |
+ |
+]]
+
+local grid_with_inlay_hints = [[
+ auto add(int a, int b)-> int { return a + b; } |
+ |
+ int main() { |
+ int x = 1; |
+ int y = 2; |
+ return add(a: x,b: y); |
+ } |
+ ^} |
+ |
+]]
+
+--- @type test.functional.ui.screen
+local screen
before_each(function()
clear_notrace()
+ screen = Screen.new(50, 9)
+ screen:attach()
+
+ exec_lua(create_server_definition)
+ exec_lua([[
+ local response = ...
+ server = _create_server({
+ capabilities = {
+ inlayHintProvider = true,
+ },
+ handlers = {
+ ['textDocument/inlayHint'] = function()
+ return vim.json.decode(response)
+ end,
+ }
+ })
+
+ bufnr = vim.api.nvim_get_current_buf()
+ vim.api.nvim_win_set_buf(0, bufnr)
+
+ client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ ]], response)
+
+ insert(text)
+ exec_lua([[vim.lsp.inlay_hint.enable(bufnr)]])
+ screen:expect({ grid = grid_with_inlay_hints })
end)
after_each(function()
exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
end)
-describe('inlay hints', function()
- local screen
- before_each(function()
- screen = Screen.new(50, 9)
- screen:attach()
+describe('vim.lsp.inlay_hint', function()
+ it('clears inlay hints when sole client detaches', function()
+ exec_lua([[vim.lsp.stop_client(client_id)]])
+ screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
+ end)
+
+ it('does not clear inlay hints when one of several clients detaches', function()
+ exec_lua([[
+ server2 = _create_server({
+ capabilities = {
+ inlayHintProvider = true,
+ },
+ handlers = {
+ ['textDocument/inlayHint'] = function()
+ return {}
+ end,
+ }
+ })
+ client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd })
+ vim.lsp.inlay_hint.enable(bufnr)
+ ]])
+
+ exec_lua([[ vim.lsp.stop_client(client2) ]])
+ screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
end)
- describe('general', function()
- local text = dedent([[
- auto add(int a, int b) { return a + b; }
+ describe('enable()', function()
+ it('clears/applies inlay hints when passed false/true/nil', function()
+ exec_lua([[vim.lsp.inlay_hint.enable(bufnr, false)]])
+ screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
- int main() {
- int x = 1;
- int y = 2;
- return add(x,y);
- }
- }]])
+ exec_lua([[vim.lsp.inlay_hint.enable(bufnr, true)]])
+ screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
+ exec_lua([[vim.lsp.inlay_hint.enable(bufnr, not vim.lsp.inlay_hint.is_enabled(bufnr))]])
+ screen:expect({ grid = grid_without_inlay_hints, unchanged = true })
- local response = [==[
- [
- {"kind":1,"paddingLeft":false,"label":"-> int","position":{"character":22,"line":0},"paddingRight":false},
- {"kind":2,"paddingLeft":false,"label":"a:","position":{"character":15,"line":5},"paddingRight":true},
- {"kind":2,"paddingLeft":false,"label":"b:","position":{"character":17,"line":5},"paddingRight":true}
- ]
- ]==]
+ exec_lua([[vim.lsp.inlay_hint.enable(bufnr)]])
+ screen:expect({ grid = grid_with_inlay_hints, unchanged = true })
+ end)
+ end)
+ describe('get()', function()
+ it('returns filtered inlay hints', function()
+ --- @type lsp.InlayHint[]
+ local expected = vim.json.decode(response)
+ local expected2 = {
+ kind = 1,
+ paddingLeft = false,
+ label = ': int',
+ position = {
+ character = 10,
+ line = 2,
+ },
+ paddingRight = false,
+ }
- before_each(function()
- exec_lua(create_server_definition)
exec_lua([[
- local response = ...
- server = _create_server({
+ local expected2 = ...
+ server2 = _create_server({
capabilities = {
inlayHintProvider = true,
},
handlers = {
['textDocument/inlayHint'] = function()
- return vim.json.decode(response)
+ return { expected2 }
end,
}
})
- ]], response)
+ client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd })
+ vim.lsp.inlay_hint.enable(bufnr)
+ ]], expected2)
+
+ --- @type vim.lsp.inlay_hint.get.ret
+ local res = exec_lua([[return vim.lsp.inlay_hint.get()]])
+ eq(res, {
+ { bufnr = 1, client_id = 1, inlay_hint = expected[1] },
+ { bufnr = 1, client_id = 1, inlay_hint = expected[2] },
+ { bufnr = 1, client_id = 1, inlay_hint = expected[3] },
+ { bufnr = 1, client_id = 2, inlay_hint = expected2 },
+ })
+
+ --- @type vim.lsp.inlay_hint.get.ret
+ res = exec_lua([[return vim.lsp.inlay_hint.get({
+ range = {
+ start = { line = 2, character = 10 },
+ ["end"] = { line = 2, character = 10 },
+ },
+ })]])
+ eq(res, {
+ { bufnr = 1, client_id = 2, inlay_hint = expected2 },
+ })
+
+ --- @type vim.lsp.inlay_hint.get.ret
+ res = exec_lua([[return vim.lsp.inlay_hint.get({
+ bufnr = vim.api.nvim_get_current_buf(),
+ range = {
+ start = { line = 4, character = 18 },
+ ["end"] = { line = 5, character = 17 },
+ },
+ })]])
+ eq(res, {
+ { bufnr = 1, client_id = 1, inlay_hint = expected[2] },
+ { bufnr = 1, client_id = 1, inlay_hint = expected[3] },
+ })
+
+ --- @type vim.lsp.inlay_hint.get.ret
+ res = exec_lua([[return vim.lsp.inlay_hint.get({
+ bufnr = vim.api.nvim_get_current_buf() + 1,
+ })]])
+ eq(res, {})
end)
-
- it(
- 'inlay hints are applied when vim.lsp.inlay_hint(true) is called',
- function()
- local res = exec_lua([[
- bufnr = vim.api.nvim_get_current_buf()
- vim.api.nvim_win_set_buf(0, bufnr)
- client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
- local client = vim.lsp.get_client_by_id(client_id)
- return {
- supports_method = client.supports_method("textDocument/inlayHint")
- }
- ]])
- eq(res, { supports_method = true })
-
-
- insert(text)
- exec_lua([[vim.lsp.inlay_hint(bufnr, true)]])
- screen:expect({
- grid = [[
- auto add(int a, int b)-> int { return a + b; } |
- |
- int main() { |
- int x = 1; |
- int y = 2; |
- return add(a: x,b: y); |
- } |
- ^} |
- |
-]]
- })
- end)
-
- it(
- 'inlay hints are cleared when vim.lsp.inlay_hint(false) is called',
- function()
- exec_lua([[
- bufnr = vim.api.nvim_get_current_buf()
- vim.api.nvim_win_set_buf(0, bufnr)
- client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
- ]])
-
- insert(text)
- exec_lua([[vim.lsp.inlay_hint(bufnr, true)]])
- screen:expect({
- grid = [[
- auto add(int a, int b)-> int { return a + b; } |
- |
- int main() { |
- int x = 1; |
- int y = 2; |
- return add(a: x,b: y); |
- } |
- ^} |
- |
-]]
- })
- exec_lua([[vim.lsp.inlay_hint(bufnr, false)]])
- screen:expect({
- grid = [[
- auto add(int a, int b) { return a + b; } |
- |
- int main() { |
- int x = 1; |
- int y = 2; |
- return add(x,y); |
- } |
- ^} |
- |
-]],
- unchanged = true
- })
- end)
-
- it(
- 'inlay hints are cleared when the client detaches',
- function()
- exec_lua([[
- bufnr = vim.api.nvim_get_current_buf()
- vim.api.nvim_win_set_buf(0, bufnr)
- client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
- ]])
-
- insert(text)
- exec_lua([[vim.lsp.inlay_hint(bufnr, true)]])
- screen:expect({
- grid = [[
- auto add(int a, int b)-> int { return a + b; } |
- |
- int main() { |
- int x = 1; |
- int y = 2; |
- return add(a: x,b: y); |
- } |
- ^} |
- |
-]]
- })
- exec_lua([[vim.lsp.stop_client(client_id)]])
- screen:expect({
- grid = [[
- auto add(int a, int b) { return a + b; } |
- |
- int main() { |
- int x = 1; |
- int y = 2; |
- return add(x,y); |
- } |
- ^} |
- |
-]],
- unchanged = true
- })
- end)
-
- it(
- 'inlay hints are not cleared when one of several clients detaches',
- function()
- -- Start two clients
- exec_lua([[
- bufnr = vim.api.nvim_get_current_buf()
- vim.api.nvim_win_set_buf(0, bufnr)
- server2 = _create_server({
- capabilities = {
- inlayHintProvider = true,
- },
- handlers = {
- ['textDocument/inlayHint'] = function()
- return {}
- end,
- }
- })
- client1 = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
- client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd })
- ]])
-
- insert(text)
- exec_lua([[vim.lsp.inlay_hint(bufnr, true)]])
- screen:expect({
- grid = [[
- auto add(int a, int b)-> int { return a + b; } |
- |
- int main() { |
- int x = 1; |
- int y = 2; |
- return add(a: x,b: y); |
- } |
- ^} |
- |
-]]
- })
-
- -- Now stop one client
- exec_lua([[ vim.lsp.stop_client(client2) ]])
-
- -- We should still see the hints
- screen:expect({
- grid = [[
- auto add(int a, int b)-> int { return a + b; } |
- |
- int main() { |
- int x = 1; |
- int y = 2; |
- return add(a: x,b: y); |
- } |
- ^} |
- |
-]],
- unchanged = true
- })
- end)
end)
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index d56e5b4afa..bb8d775838 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -1291,7 +1291,7 @@ describe('LSP', function()
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
- vim.lsp.inlay_hint(BUFFER, true)
+ vim.lsp.inlay_hint.enable(BUFFER)
]]
end
if ctx.method == 'textDocument/inlayHint' then
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index d3ffb07749..810a68d387 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -88,6 +88,7 @@ local function isempty(v)
return type(v) == 'table' and next(v) == nil
end
+--- @class test.functional.ui.screen
local Screen = {}
Screen.__index = Screen