Skip to content

Commit 83104f3

Browse files
committed
fix gopls without setting ale_go_gopls_init_options
1 parent b9d7f56 commit 83104f3

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

lua/ale/lsp.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ module.start = function(config)
88
config.init_options[true] = nil
99
end
1010

11+
-- ensure init_options uses empty_dict if empty
12+
if type(config.init_options) == "table"
13+
and next(config.init_options) == nil
14+
and getmetatable(config.init_options) == nil
15+
then
16+
config.init_options = vim.empty_dict()
17+
end
18+
1119
-- If configuring LSP via a socket connection, then generate the cmd
1220
-- using vim.lsp.rpc.connect(), as defined in Neovim documentation.
1321
if config.host then

test/linter/test_gopls.vader

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,25 @@ Execute('go.mod' should be ignored if modules are off):
9494
call delete(b:git_dir, 'd')
9595
unlet! b:parent_dir
9696
unlet! b:git_dir
97+
98+
Execute(Init options should handle empty and non-empty values correctly):
99+
" Regression test for: Invalid settings: invalid options type []interface {}
100+
" This ensures empty init_options {} is passed as an object, not array
101+
call ale#test#SetFilename('../test-files/go/go1/prj1/file.go')
102+
103+
" Test 1: Default empty dict
104+
AssertLSPOptions {}
105+
106+
" Test 2: Explicitly set to empty
107+
let b:ale_go_gopls_init_options = {}
108+
AssertLSPOptions {}
109+
110+
" Test 3: Non-empty options should be preserved
111+
let b:ale_go_gopls_init_options = {
112+
\ 'ui.diagnostic.analyses': {'composites': v:false},
113+
\ 'completeUnimported': v:true
114+
\}
115+
AssertLSPOptions {
116+
\ 'ui.diagnostic.analyses': {'composites': v:false},
117+
\ 'completeUnimported': v:true
118+
\}

test/lua/ale_lsp_spec.lua

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ describe("ale.lsp.start", function()
1313
defer_fn = function(func, delay)
1414
table.insert(defer_calls, {func, delay})
1515
end,
16+
empty_dict = function()
17+
-- Returns a table with a metatable to distinguish it from arrays
18+
return setmetatable({}, {__empty_dict = true})
19+
end,
1620
fn = setmetatable({}, {
1721
__index = function(_, key)
1822
return function(...)
@@ -105,6 +109,50 @@ describe("ale.lsp.start", function()
105109
eq({}, vim_fn_calls)
106110
end)
107111

112+
it("should convert empty init_options to vim.empty_dict", function()
113+
-- Mock vim.empty_dict
114+
local empty_dict_called = false
115+
_G.vim.empty_dict = function()
116+
empty_dict_called = true
117+
return setmetatable({}, {__empty_dict = true})
118+
end
119+
120+
lsp.start({
121+
name = "gopls:/code",
122+
cmd = "gopls",
123+
root_dir = "/code",
124+
-- Empty table without metatable (like from VimScript {})
125+
init_options = {},
126+
})
127+
128+
-- Verify that empty_dict was called
129+
eq(true, empty_dict_called)
130+
131+
-- Verify init_options has metatable now
132+
eq(1, #start_calls)
133+
local init_opts = start_calls[1][1].init_options
134+
eq(true, getmetatable(init_opts) ~= nil)
135+
end)
136+
137+
it("should preserve non-empty init_options", function()
138+
lsp.start({
139+
name = "gopls:/code",
140+
cmd = "gopls",
141+
root_dir = "/code",
142+
init_options = {foo = "bar", nested = {baz = 123}},
143+
})
144+
145+
-- Remove functions we can't compare
146+
for _, args in pairs(start_calls) do
147+
args[1].handlers = nil
148+
args[1].on_init = nil
149+
args[1].get_language_id = nil
150+
end
151+
152+
eq(1, #start_calls)
153+
eq({foo = "bar", nested = {baz = 123}}, start_calls[1][1].init_options)
154+
end)
155+
108156
it("should start lsp socket connections with the correct arguments", function()
109157
lsp.start({
110158
name = "localhost:1234:/code",

0 commit comments

Comments
 (0)