mirror of
https://github.com/dense-analysis/ale.git
synced 2025-12-07 05:04:28 +08:00
Some checks failed
CI / build_image (push) Has been cancelled
CI / test_ale (--linters-only) (push) Has been cancelled
CI / test_ale (--lua-only) (push) Has been cancelled
CI / test_ale (--neovim-07-only) (push) Has been cancelled
CI / test_ale (--neovim-08-only) (push) Has been cancelled
CI / test_ale (--vim-80-only) (push) Has been cancelled
CI / test_ale (--vim-90-only) (push) Has been cancelled
Implement the diagnostics pull model with the LSP Neovim client. We must handle messages a little different and tweak client capabilities for pull diagnostics to work through the Neovim client.
363 lines
10 KiB
Lua
363 lines
10 KiB
Lua
local eq = assert.are.same
|
|
local lsp = require("ale.lsp")
|
|
|
|
describe("ale.lsp.start", function()
|
|
local start_calls
|
|
local rpc_connect_calls
|
|
local vim_fn_calls
|
|
local defer_calls
|
|
local nvim_default_capabilities
|
|
|
|
setup(function()
|
|
_G.vim = {
|
|
defer_fn = function(func, delay)
|
|
table.insert(defer_calls, {func, delay})
|
|
end,
|
|
fn = setmetatable({}, {
|
|
__index = function(_, key)
|
|
return function(...)
|
|
table.insert(vim_fn_calls, {key, ...})
|
|
|
|
if key == "ale#lsp#GetLanguage" then
|
|
return "python"
|
|
end
|
|
|
|
if key ~= "ale#lsp_linter#HandleLSPDiagnostics"
|
|
and key ~= "ale#lsp#UpdateCapabilities"
|
|
and key ~= "ale#lsp#CallInitCallbacks"
|
|
then
|
|
assert(false, "Invalid ALE function: " .. key)
|
|
end
|
|
|
|
return nil
|
|
end
|
|
end,
|
|
}),
|
|
lsp = {
|
|
rpc = {
|
|
connect = function(host, port)
|
|
return function(dispatch)
|
|
table.insert(rpc_connect_calls, {
|
|
host = host,
|
|
port = port,
|
|
dispatch = dispatch,
|
|
})
|
|
end
|
|
end,
|
|
},
|
|
start = function(...)
|
|
table.insert(start_calls, {...})
|
|
|
|
return 42
|
|
end,
|
|
protocol = {
|
|
make_client_capabilities = function()
|
|
return nvim_default_capabilities
|
|
end,
|
|
},
|
|
},
|
|
}
|
|
end)
|
|
|
|
teardown(function()
|
|
_G.vim = nil
|
|
end)
|
|
|
|
before_each(function()
|
|
start_calls = {}
|
|
rpc_connect_calls = {}
|
|
vim_fn_calls = {}
|
|
defer_calls = {}
|
|
nvim_default_capabilities = {
|
|
textDocument = {},
|
|
}
|
|
end)
|
|
|
|
it("should start lsp programs with the correct arguments", function()
|
|
lsp.start({
|
|
name = "server:/code",
|
|
cmd = "server",
|
|
root_dir = "/code",
|
|
-- This Boolean value somehow ends up in Dictionaries from
|
|
-- Vim for init_options, and we need to remove it.
|
|
init_options = {[true] = 123},
|
|
})
|
|
|
|
-- Remove arguments with functions we can't apply equality checks
|
|
-- for easily.
|
|
for _, args in pairs(start_calls) do
|
|
args[1].handlers = nil
|
|
args[1].on_init = nil
|
|
args[1].get_language_id = nil
|
|
end
|
|
|
|
eq({
|
|
{
|
|
{
|
|
cmd = "server",
|
|
name = "server:/code",
|
|
root_dir = "/code",
|
|
init_options = {},
|
|
},
|
|
{attach = false, silent = true}
|
|
}
|
|
}, start_calls)
|
|
eq({}, vim_fn_calls)
|
|
end)
|
|
|
|
it("should start lsp socket connections with the correct arguments", function()
|
|
lsp.start({
|
|
name = "localhost:1234:/code",
|
|
host = "localhost",
|
|
port = 1234,
|
|
root_dir = "/code",
|
|
init_options = {foo = "bar"},
|
|
})
|
|
|
|
local cmd
|
|
|
|
-- Remove arguments with functions we can't apply equality checks
|
|
-- for easily.
|
|
for _, args in pairs(start_calls) do
|
|
cmd = args[1].cmd
|
|
args[1].cmd = nil
|
|
args[1].handlers = nil
|
|
args[1].on_init = nil
|
|
args[1].get_language_id = nil
|
|
end
|
|
|
|
eq({
|
|
{
|
|
{
|
|
name = "localhost:1234:/code",
|
|
root_dir = "/code",
|
|
init_options = {foo = "bar"},
|
|
},
|
|
{attach = false, silent = true}
|
|
}
|
|
}, start_calls)
|
|
|
|
cmd("dispatch_value")
|
|
|
|
eq({
|
|
{dispatch = "dispatch_value", host = "localhost", port = 1234},
|
|
}, rpc_connect_calls)
|
|
eq({}, vim_fn_calls)
|
|
end)
|
|
|
|
it("should return the client_id value from vim.lsp.start", function()
|
|
eq(42, lsp.start({}))
|
|
end)
|
|
|
|
it("should implement get_language_id correctly", function()
|
|
lsp.start({name = "server:/code"})
|
|
|
|
eq(1, #start_calls)
|
|
eq("python", start_calls[1][1].get_language_id(347, "ftype"))
|
|
eq({{"ale#lsp#GetLanguage", "server:/code", 347}}, vim_fn_calls)
|
|
end)
|
|
|
|
it("should enable dynamicRegistration for the pull model", function()
|
|
nvim_default_capabilities = {textDocument = {diagnostic = {}}}
|
|
|
|
lsp.start({name = "server:/code"})
|
|
eq(1, #start_calls)
|
|
|
|
eq(
|
|
{
|
|
textDocument = {
|
|
diagnostic = {
|
|
dynamicRegistration = true,
|
|
},
|
|
},
|
|
},
|
|
start_calls[1][1].capabilities
|
|
)
|
|
end)
|
|
|
|
it("should initialize clients with ALE correctly", function()
|
|
lsp.start({name = "server:/code"})
|
|
|
|
eq(1, #start_calls)
|
|
|
|
start_calls[1][1].on_init({server_capabilities = {cap = 1}})
|
|
|
|
eq({
|
|
{"ale#lsp#UpdateCapabilities", "server:/code", {cap = 1}},
|
|
}, vim_fn_calls)
|
|
eq(1, #defer_calls)
|
|
eq(2, #defer_calls[1])
|
|
eq("function", type(defer_calls[1][1]))
|
|
eq(0, defer_calls[1][2])
|
|
|
|
defer_calls[1][1]()
|
|
|
|
eq({
|
|
{"ale#lsp#UpdateCapabilities", "server:/code", {cap = 1}},
|
|
{"ale#lsp#CallInitCallbacks", "server:/code"},
|
|
}, vim_fn_calls)
|
|
end)
|
|
|
|
it("should configure handlers correctly", function()
|
|
lsp.start({name = "server:/code"})
|
|
|
|
eq(1, #start_calls)
|
|
|
|
local handlers = start_calls[1][1].handlers
|
|
local handler_names = {}
|
|
|
|
-- get keys from handlers
|
|
for key, _ in pairs(handlers) do
|
|
-- add key to handler_names mapping
|
|
handler_names[key] = true
|
|
end
|
|
|
|
eq({
|
|
["textDocument/publishDiagnostics"] = true,
|
|
["textDocument/diagnostic"] = true,
|
|
["workspace/diagnostic/refresh"] = true,
|
|
}, handler_names)
|
|
end)
|
|
|
|
it("should handle push model published diagnostics", function()
|
|
lsp.start({name = "server:/code"})
|
|
|
|
eq(1, #start_calls)
|
|
|
|
local handlers = start_calls[1][1].handlers
|
|
|
|
eq("function", type(handlers["textDocument/publishDiagnostics"]))
|
|
|
|
handlers["textDocument/publishDiagnostics"](nil, {
|
|
uri = "file://code/foo.py",
|
|
diagnostics = {
|
|
{
|
|
lnum = 1,
|
|
end_lnum = 2,
|
|
col = 3,
|
|
end_col = 5,
|
|
severity = 1,
|
|
code = "123",
|
|
message = "Warning message",
|
|
}
|
|
},
|
|
})
|
|
|
|
eq({
|
|
{
|
|
"ale#lsp_linter#HandleLSPDiagnostics",
|
|
"server:/code",
|
|
"file://code/foo.py",
|
|
{
|
|
{
|
|
lnum = 1,
|
|
end_lnum = 2,
|
|
col = 3,
|
|
end_col = 5,
|
|
severity = 1,
|
|
code = "123",
|
|
message = "Warning message",
|
|
},
|
|
},
|
|
},
|
|
}, vim_fn_calls)
|
|
end)
|
|
|
|
it("should respond to workspace diagnostic refresh requests", function()
|
|
lsp.start({name = "server:/code"})
|
|
|
|
eq(1, #start_calls)
|
|
|
|
local handlers = start_calls[1][1].handlers
|
|
|
|
eq("function", type(handlers["workspace/diagnostic/refresh"]))
|
|
|
|
eq({}, handlers["workspace/diagnostic/refresh"]())
|
|
end)
|
|
|
|
it("should handle pull model diagnostics", function()
|
|
lsp.start({name = "server:/code"})
|
|
|
|
eq(1, #start_calls)
|
|
|
|
local handlers = start_calls[1][1].handlers
|
|
|
|
eq("function", type(handlers["textDocument/diagnostic"]))
|
|
|
|
handlers["textDocument/diagnostic"](
|
|
nil,
|
|
{
|
|
kind = "full",
|
|
items = {
|
|
{
|
|
lnum = 1,
|
|
end_lnum = 2,
|
|
col = 3,
|
|
end_col = 5,
|
|
severity = 1,
|
|
code = "123",
|
|
message = "Warning message",
|
|
}
|
|
},
|
|
},
|
|
{
|
|
params = {
|
|
textDocument = {
|
|
uri = "file://code/foo.py",
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
eq({
|
|
{
|
|
"ale#lsp_linter#HandleLSPDiagnostics",
|
|
"server:/code",
|
|
"file://code/foo.py",
|
|
{
|
|
{
|
|
lnum = 1,
|
|
end_lnum = 2,
|
|
col = 3,
|
|
end_col = 5,
|
|
severity = 1,
|
|
code = "123",
|
|
message = "Warning message",
|
|
},
|
|
},
|
|
},
|
|
}, vim_fn_calls)
|
|
end)
|
|
|
|
it("should handle unchanged pull model diagnostics", function()
|
|
lsp.start({name = "server:/code"})
|
|
|
|
eq(1, #start_calls)
|
|
|
|
local handlers = start_calls[1][1].handlers
|
|
|
|
eq("function", type(handlers["textDocument/diagnostic"]))
|
|
|
|
handlers["textDocument/diagnostic"](
|
|
nil,
|
|
{kind = "unchanged"},
|
|
{
|
|
params = {
|
|
textDocument = {
|
|
uri = "file://code/foo.py",
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
eq({
|
|
{
|
|
"ale#lsp_linter#HandleLSPDiagnostics",
|
|
"server:/code",
|
|
"file://code/foo.py",
|
|
"unchanged",
|
|
},
|
|
}, vim_fn_calls)
|
|
end)
|
|
end)
|