fix(providers): Ensure working on nvim-0.7

This commit removed the ability to receive symbols from all attached
clients in the current buffer. Everything works as before when only one
client is attached to a buffer.

This also fixes outline LSP finding clients on nvim-0.7
This commit is contained in:
hedy
2023-12-29 19:17:00 +08:00
parent 5669c8aa9e
commit 8b2f412b7b
7 changed files with 91 additions and 48 deletions

View File

@@ -140,7 +140,7 @@ function M.show_status(ctx)
if p.get_status then
table.insert(lines, 'Provider info:')
table.insert(lines, '')
for _, line in ipairs(p.get_status()) do
for _, line in ipairs(p.get_status(ctx.provider_info)) do
table.insert(lines, indent .. line)
end
end

View File

@@ -252,19 +252,20 @@ end
---Open a floating window displaying debug information about outline
function M.show_status()
local sidebar = M._get_sidebar(false)
local sidebar = M._get_sidebar()
local buf, win = 0, 0
local is_open, provider
local is_open, provider, provider_info
if sidebar then
buf = sidebar.code.buf
win = sidebar.code.win
is_open = sidebar.view:is_open()
provider = sidebar.provider
provider_info = sidebar.provider_info
end
if not is_open then
provider = providers.find_provider()
provider, provider_info = providers.find_provider()
end
---@type outline.StatusContext
@@ -272,9 +273,10 @@ function M.show_status()
priority = cfg.o.providers.priority,
outline_open = is_open,
provider = provider,
provider_info = provider_info,
}
if vim.api.nvim_buf_is_valid(buf) then
if buf and vim.api.nvim_buf_is_valid(buf) then
ctx.ft = vim.api.nvim_buf_get_option(buf, 'ft')
ctx.filter = cfg.o.symbols.user_config_filter[ctx.ft]
-- 'else' is handled in help.lua

View File

@@ -1,17 +1,19 @@
local M = {}
local import_prefix = 'outline/providers/'
---@return outline.Provider?
---@return outline.Provider?, table?
function M.find_provider()
if not M.providers then
M.providers = vim.tbl_map(function(p)
return import_prefix .. p
end, require('outline.config').get_providers())
end
for _, path in ipairs(M.providers) do
local provider = require(path)
if provider.supports_buffer(0) then
return provider
local ok, info = provider.supports_buffer(0)
if ok then
return provider, info
end
end
end

View File

@@ -6,52 +6,70 @@ local l = vim.lsp
local M = {
name = 'lsp',
---@type lsp.client
client = nil,
}
local request_timeout = 2000
function M.get_status()
if not M.client then
---@param info table? Must be the table received from `supports_buffer`
function M.get_status(info)
if not info then
return { 'No clients' }
end
return { 'client: ' .. M.client.name }
return { 'client: ' .. info.client.name }
end
local function get_appropriate_client(bufnr, capability)
local clients = l.get_active_clients({ bufnr = bufnr })
local use_client
for _, client in ipairs(clients) do
---@param client lsp.client
---@param capability string
---@return boolean
local function _check_client(client, capability)
if cfg.is_client_blacklisted(client) then
goto continue
else
if client.server_capabilities[capability] then
return false
end
return client.server_capabilities[capability]
end
---@param bufnr integer
---@param capability string
---@return lsp.client?
local function get_appropriate_client(bufnr, capability)
local clients, use_client
if _G._outline_nvim_has[8] then
clients = l.get_active_clients({ bufnr = bufnr })
for _, client in ipairs(clients) do
if _check_client(client, capability) then
use_client = client
M.client = client
break
end
end
::continue::
else
-- Returns client_id:client pairs
---@diagnostic disable-next-line
clients = l.buf_get_clients(bufnr)
for _, client in pairs(clients) do
if _check_client(client, capability) then
use_client = client
break
end
end
end
return use_client
end
---@return boolean
---@return boolean, table?
function M.supports_buffer(bufnr)
local client = get_appropriate_client(bufnr, 'documentSymbolProvider')
if not client then
return false
end
return true
return true, { client = client }
end
---@param response outline.ProviderSymbol[]
---Include JSX symbols if applicable, and merge it with existing symbols
---@param symbols outline.ProviderSymbol[]
---@return outline.ProviderSymbol[]
local function postprocess_symbols(response)
local symbols = lsp_utils.flatten_response(response)
local function postprocess_symbols(symbols)
local jsx_symbols = jsx.get_symbols()
if #jsx_symbols > 0 then
@@ -61,16 +79,31 @@ local function postprocess_symbols(response)
end
end
-- XXX: Only one LSP client is supported here, to prevent checking blacklisting
-- over again
---@param on_symbols fun(symbols?:outline.ProviderSymbol[], opts?:table)
---@param opts table
function M.request_symbols(on_symbols, opts)
---@param opts table?
---@param info table? Must be the table received from `supports_buffer`
function M.request_symbols(on_symbols, opts, info)
if not info then
return on_symbols(nil, opts)
end
local params = {
textDocument = l.util.make_text_document_params(),
}
l.buf_request_all(0, 'textDocument/documentSymbol', params, function(response)
-- XXX: Is bufnr=0 ok here?
local status = info.client.request('textDocument/documentSymbol', params, function(err, response)
if err or not response then
on_symbols(response, opts)
else
response = postprocess_symbols(response)
on_symbols(response, opts)
end)
end
end, 0)
if not status then
on_symbols(nil, opts)
end
end
-- No good way to update outline when LSP action complete for now
@@ -97,6 +130,7 @@ end
---@see rename_symbol
---@param sidebar outline.Sidebar
---@param client lsp.client
---@param node outline.FlatSymbol
---@return boolean success
local function legacy_rename(sidebar, client, node)
@@ -141,8 +175,8 @@ function M.rename_symbol(sidebar)
sidebar:wrap_goto_location(function()
-- Options table with filter key only added in nvim-0.8
-- Use vim.lsp's function because it has better support.
l.buf.rename(nil, { filter = function (client)
return not cfg.is_client_blacklisted(client)
l.buf.rename(nil, { filter = function (cl)
return not cfg.is_client_blacklisted(cl)
end })
end)
return true

View File

@@ -26,6 +26,7 @@ local Sidebar = {}
---@field code outline.SidebarCodeState
---@field augroup integer
---@field provider outline.Provider?
---@field provider_info table?
---@field preview outline.Preview|outline.LivePreview
function Sidebar:new(id)
@@ -92,6 +93,7 @@ end
---@param opts outline.OutlineOpts?
function Sidebar:initial_handler(response, opts)
if response == nil or type(response) ~= 'table' or self.view:is_open() then
utils.echo("No response from provider when requesting symbols!")
return
end
@@ -311,6 +313,7 @@ end
---@param response outline.ProviderSymbol[]
function Sidebar:refresh_handler(response)
if response == nil or type(response) ~= 'table' then
utils.echo("No response from provider when requesting symbols!")
return
end
@@ -340,11 +343,11 @@ function Sidebar:__refresh()
if ft == 'OutlineHelp' or not listed then
return
end
self.provider = providers.find_provider()
self.provider, self.provider_info = providers.find_provider()
if self.provider then
self.provider.request_symbols(function(res)
self:refresh_handler(res)
end)
end, nil, self.provider_info)
return
end
-- No provider
@@ -583,11 +586,11 @@ function Sidebar:open(opts)
if not self.view:is_open() then
self.preview.s = self
self.provider = providers.find_provider()
self.provider, self.provider_info = providers.find_provider()
if self.provider then
self.provider.request_symbols(function(...)
self:initial_handler(...)
end, opts)
end, opts, self.provider_info)
return
else
-- No provider

View File

@@ -63,9 +63,9 @@
---@class outline.Provider
---@field name string
---@field get_status? fun():string[]
---@field supports_buffer fun(bufnr:integer):boolean
---@field request_symbols fun(on_symbols:fun(symbols?:outline.ProviderSymbol[], opts:table?), opts:table?)
---@field get_status? fun(info:table?):string[]
---@field supports_buffer fun(bufnr:integer):boolean,table?
---@field request_symbols fun(on_symbols:fun(symbols?:outline.ProviderSymbol[], opts:table?, provider_info:table?), opts:table?)
---@field show_hover? fun(sidebar:outline.Sidebar):boolean
---@field rename_symbol? fun(sidebar:outline.Sidebar):boolean
---@field code_actions? fun(sidebar:outline.Sidebar):boolean
@@ -80,6 +80,7 @@
---@class outline.StatusContext
---@field provider outline.Provider?
---@field provider_info table?
---@field outline_open boolean?
---@field code_win_active boolean?
---@field ft string?

View File

@@ -12,13 +12,14 @@ function M.is_buf_markdown(bufnr)
end
--- Merge all client token lists in an LSP response
function M.flatten_response(response)
-- Currentlhy unused because we are only supporting receiving symbols
-- from 1 LSP client.
function M.merge_responses(responses)
local all_results = {}
-- flatten results to one giant table of symbols
for client_id, client_response in pairs(response) do
for client_id, client_response in pairs(responses) do
if config.is_client_blacklisted(client_id) then
print('skipping client ' .. client_id)
goto continue
end