diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 4198cfcc97..9e8f661ac7 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -922,9 +922,19 @@ function M.make_floating_popup_options(width, height, opts) local anchor = '' - local lines_above = opts.relative == 'mouse' and vim.fn.getmousepos().line - 1 - or vim.fn.winline() - 1 - local lines_below = vim.fn.winheight(0) - lines_above + local lines_above --- @type integer + local lines_below --- @type integer + if opts.relative == 'mouse' then + lines_above = vim.fn.getmousepos().line - 1 + lines_below = vim.fn.winheight(0) - lines_above + elseif opts.relative == 'editor' then + -- No cursor to anchor against; treat the whole editor as space below. + lines_above = 0 + lines_below = vim.o.lines + else + lines_above = vim.fn.winline() - 1 + lines_below = vim.fn.winheight(0) - lines_above + end local anchor_bias = opts.anchor_bias or 'auto' @@ -951,7 +961,14 @@ function M.make_floating_popup_options(width, height, opts) row = 0 end - local wincol = opts.relative == 'mouse' and vim.fn.getmousepos().column or vim.fn.wincol() + local wincol --- @type integer + if opts.relative == 'mouse' then + wincol = vim.fn.getmousepos().column + elseif opts.relative == 'editor' then + wincol = 0 + else + wincol = vim.fn.wincol() + end if wincol + width + (opts.offset_x or 0) <= vim.o.columns then anchor = anchor .. 'W' diff --git a/test/functional/plugin/lsp/util_spec.lua b/test/functional/plugin/lsp/util_spec.lua index 8aa78602c5..db7c56495f 100644 --- a/test/functional/plugin/lsp/util_spec.lua +++ b/test/functional/plugin/lsp/util_spec.lua @@ -1393,6 +1393,14 @@ describe('vim.lsp.util', function() eq('Title', opts.title) end) end) + + it('anchor is NW for relative = "editor" regardless of cursor #39306', function() + feed('G') -- without the fix, cursor on the last line picks an 'S*' anchor + local opts = exec_lua(function() + return vim.lsp.util.make_floating_popup_options(30, 10, { relative = 'editor' }) + end) + eq('NW', opts.anchor) + end) end) describe('open_floating_preview', function()