mirror of
https://github.com/neovim/neovim.git
synced 2026-03-28 19:32:01 +00:00
Problem The logic that clears codelenses beyond the buffer also removes the codelenses on the last line. Solution Do not clear the codelens on the last line.
423 lines
14 KiB
Lua
423 lines
14 KiB
Lua
local t = require('test.testutil')
|
|
local n = require('test.functional.testnvim')()
|
|
local t_lsp = require('test.functional.plugin.lsp.testutil')
|
|
local Screen = require('test.functional.ui.screen')
|
|
|
|
local dedent = t.dedent
|
|
local eq = t.eq
|
|
|
|
local api = n.api
|
|
local exec_lua = n.exec_lua
|
|
local insert = n.insert
|
|
local feed = n.feed
|
|
|
|
local clear_notrace = t_lsp.clear_notrace
|
|
local create_server_definition = t_lsp.create_server_definition
|
|
|
|
describe('vim.lsp.codelens', function()
|
|
local text = dedent([[
|
|
struct S {
|
|
a: i32,
|
|
b: String,
|
|
}
|
|
|
|
impl S {
|
|
fn new(a: i32, b: String) -> Self {
|
|
S { a, b }
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let s = S::new(42, String::from("Hello, world!"));
|
|
println!("S.a: {}, S.b: {}", s.a, s.b);
|
|
}
|
|
]])
|
|
|
|
local grid_with_lenses = dedent([[
|
|
{1: 1 implementation} |
|
|
struct S { |
|
|
a: i32, |
|
|
b: String, |
|
|
} |
|
|
|
|
|
impl S { |
|
|
fn new(a: i32, b: String) -> Self { |
|
|
S { a, b } |
|
|
} |
|
|
} |
|
|
|
|
|
{1: ▶︎ Run } |
|
|
fn main() { |
|
|
let s = S::new(42, String::from("Hello, world!"))|
|
|
; |
|
|
println!("S.a: {}, S.b: {}", s.a, s.b); |
|
|
} |
|
|
^ |
|
|
|
|
|
]])
|
|
|
|
local grid_without_lenses = dedent([[
|
|
struct S { |
|
|
a: i32, |
|
|
b: String, |
|
|
} |
|
|
|
|
|
impl S { |
|
|
fn new(a: i32, b: String) -> Self { |
|
|
S { a, b } |
|
|
} |
|
|
} |
|
|
|
|
|
fn main() { |
|
|
let s = S::new(42, String::from("Hello, world!"))|
|
|
; |
|
|
println!("S.a: {}, S.b: {}", s.a, s.b); |
|
|
} |
|
|
^ |
|
|
{1:~ }|*2
|
|
|
|
|
]])
|
|
|
|
--- @type test.functional.ui.screen
|
|
local screen
|
|
|
|
--- @type integer
|
|
local client_id
|
|
|
|
before_each(function()
|
|
clear_notrace()
|
|
exec_lua(create_server_definition)
|
|
|
|
screen = Screen.new(nil, 20)
|
|
|
|
client_id = exec_lua(function()
|
|
_G.server = _G._create_server({
|
|
capabilities = {
|
|
codeLensProvider = {
|
|
resolveProvider = true,
|
|
},
|
|
},
|
|
handlers = {
|
|
['textDocument/codeLens'] = function(_, _, callback)
|
|
callback(nil, {
|
|
{
|
|
data = {
|
|
kind = {
|
|
impls = {
|
|
position = {
|
|
character = 7,
|
|
line = 0,
|
|
},
|
|
},
|
|
},
|
|
version = 0,
|
|
},
|
|
range = {
|
|
['end'] = {
|
|
character = 8,
|
|
line = 0,
|
|
},
|
|
start = {
|
|
character = 7,
|
|
line = 0,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
command = {
|
|
arguments = {},
|
|
command = 'rust-analyzer.runSingle',
|
|
title = '▶︎ Run ',
|
|
},
|
|
range = {
|
|
['end'] = {
|
|
character = 7,
|
|
line = 11,
|
|
},
|
|
start = {
|
|
character = 3,
|
|
line = 11,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
end,
|
|
['codeLens/resolve'] = function(_, _, callback)
|
|
vim.schedule(function()
|
|
callback(nil, {
|
|
command = {
|
|
arguments = {},
|
|
command = 'rust-analyzer.showReferences',
|
|
title = '1 implementation',
|
|
},
|
|
range = {
|
|
['end'] = {
|
|
character = 8,
|
|
line = 0,
|
|
},
|
|
start = {
|
|
character = 7,
|
|
line = 0,
|
|
},
|
|
},
|
|
})
|
|
end)
|
|
end,
|
|
},
|
|
})
|
|
|
|
return vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd })
|
|
end)
|
|
|
|
insert(text)
|
|
|
|
exec_lua(function()
|
|
vim.lsp.codelens.enable()
|
|
end)
|
|
|
|
screen:expect({ grid = grid_with_lenses })
|
|
end)
|
|
|
|
it('clears code lenses when disabled', function()
|
|
exec_lua(function()
|
|
vim.lsp.codelens.enable(false)
|
|
end)
|
|
|
|
screen:expect({ grid = grid_without_lenses })
|
|
end)
|
|
|
|
it('clears code lenses when sole client detaches', function()
|
|
exec_lua(function()
|
|
vim.lsp.get_client_by_id(client_id):stop()
|
|
end)
|
|
|
|
screen:expect({ grid = grid_without_lenses })
|
|
end)
|
|
|
|
it('get code lenses in the current buffer', function()
|
|
local result = exec_lua(function()
|
|
vim.api.nvim_win_set_cursor(0, { 12, 3 })
|
|
return vim.lsp.codelens.get()
|
|
end)
|
|
|
|
eq({
|
|
{
|
|
client_id = 1,
|
|
lens = {
|
|
command = {
|
|
arguments = {},
|
|
command = 'rust-analyzer.showReferences',
|
|
title = '1 implementation',
|
|
},
|
|
range = {
|
|
['end'] = {
|
|
character = 8,
|
|
line = 0,
|
|
},
|
|
start = {
|
|
character = 7,
|
|
line = 0,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
client_id = 1,
|
|
lens = {
|
|
command = {
|
|
arguments = {},
|
|
command = 'rust-analyzer.runSingle',
|
|
title = '▶︎ Run ',
|
|
},
|
|
range = {
|
|
['end'] = {
|
|
character = 7,
|
|
line = 11,
|
|
},
|
|
start = {
|
|
character = 3,
|
|
line = 11,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}, result)
|
|
end)
|
|
|
|
it('refreshes code lenses on request', function()
|
|
feed('ggdd')
|
|
|
|
screen:expect([[
|
|
{1: 1 implementation} |
|
|
^a: i32, |
|
|
b: String, |
|
|
} |
|
|
|
|
|
impl S { |
|
|
fn new(a: i32, b: String) -> Self { |
|
|
S { a, b } |
|
|
} |
|
|
} |
|
|
|
|
|
{1: ▶︎ Run } |
|
|
fn main() { |
|
|
let s = S::new(42, String::from("Hello, world!"))|
|
|
; |
|
|
println!("S.a: {}, S.b: {}", s.a, s.b); |
|
|
} |
|
|
|
|
|
{1:~ }|
|
|
|
|
|
]])
|
|
exec_lua(function()
|
|
vim.lsp.codelens.on_refresh(
|
|
nil,
|
|
nil,
|
|
{ method = 'workspace/codeLens/refresh', client_id = client_id }
|
|
)
|
|
end)
|
|
screen:expect([[
|
|
{1: 1 implementation} |
|
|
^a: i32, |
|
|
b: String, |
|
|
} |
|
|
|
|
|
impl S { |
|
|
fn new(a: i32, b: String) -> Self { |
|
|
S { a, b } |
|
|
} |
|
|
} |
|
|
|
|
|
fn main() { |
|
|
{1: ▶︎ Run } |
|
|
let s = S::new(42, String::from("Hello, world!"))|
|
|
; |
|
|
println!("S.a: {}, S.b: {}", s.a, s.b); |
|
|
} |
|
|
|
|
|
{1:~ }|
|
|
|
|
|
]])
|
|
end)
|
|
|
|
it('ignores stale codeLens/resolve responses', function()
|
|
clear_notrace()
|
|
exec_lua(create_server_definition)
|
|
|
|
insert('line1\nline2\n')
|
|
|
|
exec_lua(function()
|
|
local codelens_request_count = 0
|
|
_G.stale_resolve_sent = false
|
|
_G.server = _G._create_server({
|
|
capabilities = {
|
|
codeLensProvider = {
|
|
resolveProvider = true,
|
|
},
|
|
},
|
|
handlers = {
|
|
['textDocument/codeLens'] = function(_, _, callback)
|
|
codelens_request_count = codelens_request_count + 1
|
|
if codelens_request_count == 1 then
|
|
callback(nil, {
|
|
{
|
|
range = {
|
|
['end'] = {
|
|
character = 1,
|
|
line = 0,
|
|
},
|
|
start = {
|
|
character = 0,
|
|
line = 0,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
else
|
|
callback(nil, {})
|
|
end
|
|
end,
|
|
['codeLens/resolve'] = function(_, lens, callback)
|
|
vim.defer_fn(function()
|
|
_G.stale_resolve_sent = true
|
|
callback(nil, {
|
|
command = {
|
|
arguments = {},
|
|
command = 'dummy.command',
|
|
title = 'resolved',
|
|
},
|
|
range = lens.range,
|
|
})
|
|
end, 100)
|
|
end,
|
|
},
|
|
})
|
|
|
|
local stale_client_id = vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd })
|
|
vim.lsp.codelens.enable()
|
|
vim.wait(1000, function()
|
|
return #vim.lsp.codelens.get() > 0
|
|
end)
|
|
|
|
vim.api.nvim__redraw({ flush = true })
|
|
|
|
vim.lsp.codelens.on_refresh(nil, nil, {
|
|
method = 'workspace/codeLens/refresh',
|
|
client_id = stale_client_id,
|
|
})
|
|
|
|
assert(
|
|
vim.wait(1000, function()
|
|
return _G.stale_resolve_sent
|
|
end),
|
|
'timed out waiting for stale resolve response'
|
|
)
|
|
end)
|
|
|
|
eq('', api.nvim_get_vvar('errmsg'))
|
|
end)
|
|
|
|
it('clears extmarks beyond the bottom of the buffer', function()
|
|
feed('12G4dd')
|
|
screen:expect([[
|
|
{1: 1 implementation} |
|
|
struct S { |
|
|
a: i32, |
|
|
b: String, |
|
|
} |
|
|
|
|
|
impl S { |
|
|
fn new(a: i32, b: String) -> Self { |
|
|
S { a, b } |
|
|
} |
|
|
} |
|
|
|
|
|
{1: ▶︎ Run } |
|
|
^ |
|
|
{1:~ }|*5
|
|
4 fewer lines |
|
|
]])
|
|
feed('dd')
|
|
screen:expect([[
|
|
{1: 1 implementation} |
|
|
struct S { |
|
|
a: i32, |
|
|
b: String, |
|
|
} |
|
|
|
|
|
impl S { |
|
|
fn new(a: i32, b: String) -> Self { |
|
|
S { a, b } |
|
|
} |
|
|
} |
|
|
^ |
|
|
{1:~ }|*7
|
|
4 fewer lines |
|
|
]])
|
|
end)
|
|
|
|
after_each(function()
|
|
api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
|
|
end)
|
|
end)
|