fix(lsp): adjust codelens position based on the server-provided range

This commit is contained in:
Yi Ming
2026-03-08 10:42:38 +08:00
parent e8e694d837
commit 378435968f
2 changed files with 40 additions and 50 deletions

View File

@@ -227,35 +227,34 @@ function Provider:on_win(toprow, botrow)
return a.range.start.character < b.range.start.character
end)
---@type integer
local indent = api.nvim_buf_call(bufnr, function()
return vim.fn.indent(row + 1)
end)
local client = assert(vim.lsp.get_client_by_id(client_id))
local range = vim.range.lsp(bufnr, lenses[1].range, client.offset_encoding)
---@type [string, string][]
local virt_text = {
{ string.rep(' ', range.start.col), 'LspCodeLensSeparator' },
}
---@type [string, string|integer][][]
local virt_lines = { { { string.rep(' ', indent), 'LspCodeLensSeparator' } } }
local virt_text = virt_lines[1]
for _, lens in ipairs(lenses) do
-- A code lens is unresolved when no command is associated to it.
if not lens.command then
local client = assert(vim.lsp.get_client_by_id(client_id)) ---@type vim.lsp.Client
self:resolve(client, lens)
else
virt_text[#virt_text + 1] = { lens.command.title, 'LspCodeLens' }
virt_text[#virt_text + 1] = { ' | ', 'LspCodeLensSeparator' }
vim.list_extend(virt_text, {
{ lens.command.title, 'LspCodeLens' },
{ ' | ', 'LspCodeLensSeparator' },
})
end
end
-- Remove trailing separator.
table.remove(virt_text)
if #virt_text > 1 then
-- Remove trailing separator.
virt_text[#virt_text] = nil
else
-- Use a placeholder to prevent flickering caused by layout shifts.
virt_text[#virt_text + 1] = { '...', 'LspCodeLens' }
-- Use a placeholder to prevent flickering caused by layout shifts.
if #virt_text == 1 then
table.insert(virt_text, { '', 'LspCodeLens' })
end
api.nvim_buf_set_extmark(bufnr, namespace, row, 0, {
virt_lines = virt_lines,
virt_lines = { virt_text },
virt_lines_above = true,
virt_lines_overflow = 'scroll',
hl_mode = 'combine',

View File

@@ -16,7 +16,6 @@ local create_server_definition = t_lsp.create_server_definition
describe('vim.lsp.codelens', function()
local text = dedent([[
https://github.com/neovim/neovim/issues/16166
struct S {
a: i32,
b: String,
@@ -35,8 +34,6 @@ describe('vim.lsp.codelens', function()
]])
local grid_with_lenses = dedent([[
^https://github.com/neovim/neovim/issues/16166 |
{1:1 implementation} |
struct S { |
a: i32, |
b: String, |
@@ -48,17 +45,18 @@ describe('vim.lsp.codelens', function()
} |
} |
|
{1:▶︎ Run } |
{1: ▶︎ Run } |
fn main() { |
let s = S::new(42, String::from("Hello, world!"))|
; |
println!("S.a: {}, S.b: {}", s.a, s.b); |
} |
|*2
^ |
{1:~ }|
|
]])
local grid_without_lenses = dedent([[
^https://github.com/neovim/neovim/issues/16166 |
struct S { |
a: i32, |
b: String, |
@@ -75,7 +73,7 @@ describe('vim.lsp.codelens', function()
; |
println!("S.a: {}, S.b: {}", s.a, s.b); |
} |
|
^ |
{1:~ }|*2
|
]])
@@ -90,7 +88,7 @@ describe('vim.lsp.codelens', function()
clear_notrace()
exec_lua(create_server_definition)
screen = Screen.new(nil, 21)
screen = Screen.new(nil, 20)
client_id = exec_lua(function()
_G.server = _G._create_server({
@@ -108,7 +106,7 @@ describe('vim.lsp.codelens', function()
impls = {
position = {
character = 7,
line = 1,
line = 0,
},
},
},
@@ -117,11 +115,11 @@ describe('vim.lsp.codelens', function()
range = {
['end'] = {
character = 8,
line = 1,
line = 0,
},
start = {
character = 7,
line = 1,
line = 0,
},
},
},
@@ -134,11 +132,11 @@ describe('vim.lsp.codelens', function()
range = {
['end'] = {
character = 7,
line = 12,
line = 11,
},
start = {
character = 3,
line = 12,
line = 11,
},
},
},
@@ -155,11 +153,11 @@ describe('vim.lsp.codelens', function()
range = {
['end'] = {
character = 8,
line = 1,
line = 0,
},
start = {
character = 7,
line = 1,
line = 0,
},
},
})
@@ -177,7 +175,6 @@ describe('vim.lsp.codelens', function()
vim.lsp.codelens.enable()
end)
feed('gg')
screen:expect({ grid = grid_with_lenses })
end)
@@ -215,11 +212,11 @@ describe('vim.lsp.codelens', function()
range = {
['end'] = {
character = 8,
line = 1,
line = 0,
},
start = {
character = 7,
line = 1,
line = 0,
},
},
},
@@ -235,11 +232,11 @@ describe('vim.lsp.codelens', function()
range = {
['end'] = {
character = 7,
line = 12,
line = 11,
},
start = {
character = 3,
line = 12,
line = 11,
},
},
},
@@ -248,11 +245,9 @@ describe('vim.lsp.codelens', function()
end)
it('refreshes code lenses on request', function()
feed('2Gdd')
feed('ggdd')
screen:expect([[
https://github.com/neovim/neovim/issues/16166 |
{1:1 implementation} |
^a: i32, |
b: String, |
} |
@@ -263,14 +258,14 @@ describe('vim.lsp.codelens', function()
} |
} |
|
{1:▶︎ Run } |
{1: ▶︎ Run } |
fn main() { |
let s = S::new(42, String::from("Hello, world!"))|
; |
println!("S.a: {}, S.b: {}", s.a, s.b); |
} |
|
{1:~ }|*1
{1:~ }|*2
|
]])
exec_lua(function()
@@ -281,8 +276,6 @@ describe('vim.lsp.codelens', function()
)
end)
screen:expect([[
https://github.com/neovim/neovim/issues/16166 |
{1: 1 implementation} |
^a: i32, |
b: String, |
} |
@@ -294,13 +287,13 @@ describe('vim.lsp.codelens', function()
} |
|
fn main() { |
{1: ▶︎ Run } |
{1: ▶︎ Run } |
let s = S::new(42, String::from("Hello, world!"))|
; |
println!("S.a: {}, S.b: {}", s.a, s.b); |
} |
|
{1:~ }|*1
{1:~ }|*2
|
]])
end)
@@ -383,10 +376,8 @@ describe('vim.lsp.codelens', function()
end)
it('clears extmarks beyond the bottom of the buffer', function()
feed('13G4dd')
feed('12G4dd')
screen:expect([[
https://github.com/neovim/neovim/issues/16166 |
{1:1 implementation} |
struct S { |
a: i32, |
b: String, |
@@ -399,7 +390,7 @@ describe('vim.lsp.codelens', function()
} |
|
^ |
{1:~ }|*6
{1:~ }|*7
4 fewer lines |
]])
end)