Skip to content

Commit

Permalink
fix(LSP): Apply changes from the language server that touches the mos…
Browse files Browse the repository at this point in the history
…t files
  • Loading branch information
peterfication authored Dec 18, 2023
1 parent fea6fd4 commit 1f981c3
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 5 deletions.
24 changes: 19 additions & 5 deletions lua/textcase/plugin/conversion.lua
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,31 @@ function M.do_lsp_rename(method)

lsp.buf_request_all(0, "textDocument/rename", params, function(results)
local total_files = 0
local results_to_be_applied = nil
local offset_encoding_to_be_applied = nil

-- Loop through the results and find the one that touches the most files
-- and save its results to be applied.
for client_id, response in pairs(results) do
if not response.error then
local client = vim.lsp.get_client_by_id(client_id)
vim.lsp.util.apply_workspace_edit(response.result, client.offset_encoding)
local files_count_by_current_response = vim.tbl_count(response.result.changes)

-- after the edits are applied, the files are not saved automatically.
-- let's remind ourselves to save those...
-- TODO: This will be modified to include only one of the clients count
total_files = vim.tbl_count(response.result.changes)
if files_count_by_current_response > total_files then
total_files = files_count_by_current_response
results_to_be_applied = response.result
offset_encoding_to_be_applied = client.offset_encoding
end
end
end

if total_files > 0 and offset_encoding_to_be_applied ~= nil then
-- If there are results to be applied, apply them.
vim.lsp.util.apply_workspace_edit(results_to_be_applied, offset_encoding_to_be_applied)
end

-- After the edits are applied, the files are not saved automatically.
-- Let's remind ourselves to save those...
print(string.format("Changed %s file%s. To save them run ':wa'", total_files, total_files > 1 and "s" or ""))
end)
end
Expand Down
142 changes: 142 additions & 0 deletions tests/textcase/lsp/error_handling_no_lsp_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ local get_active_clients_fn = vim.lsp.get_active_clients
local buf_request_all_fn = vim.lsp.buf_request_all
local buf_request_all_results = {}
local make_position_params_fn = vim.lsp.util.make_position_params
local get_client_by_id_fn = vim.lsp.get_client_by_id
local apply_workspace_edit_fn = vim.lsp.util.apply_workspace_edit

-- The spies override the default behavior of nvim.
-- If the tests are run in parallel there will be unexpected behaviors.
Expand Down Expand Up @@ -119,4 +121,144 @@ describe("LSP renaming", function()
assert.spy(err_spy).was.not_called()
end)
end)

describe("LS textDocument/rename with multiple language server results", function()
local err_spy = nil
local buf_request_all_spy = nil
local make_position_params_spy = nil
local get_client_by_id_spy = nil
local apply_workspace_edit_spy = nil
local get_clients = nil

before_each(function()
textcase.setup({})

local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_command("buffer " .. buf)

err_spy = spy.new(function() end)
get_client_by_id_spy = spy.new(function(id)
local clients = {}
clients["1"] = {
id = 1,
offset_encoding = "utf-8",
}
clients["2"] = {
id = 2,
offset_encoding = "utf-8",
}
return clients[id]
end)
buf_request_all_spy = spy.new(function(buffer, method, params, callback)
callback(buf_request_all_results)
end)
make_position_params_spy = spy.new(function()
return {}
end)
apply_workspace_edit_spy = spy.new(function()
return {}
end)
get_clients = function()
return {
{
supports_method = function()
return true
end,
},
{
supports_method = function()
return true
end,
},
}
end

vim.api.nvim_err_writeln = err_spy
vim.lsp.get_active_clients = get_clients
vim.lsp.get_client_by_id = get_client_by_id_spy
vim.lsp.buf_request_all = buf_request_all_spy
vim.lsp.util.make_position_params = make_position_params_spy
vim.lsp.util.apply_workspace_edit = apply_workspace_edit_spy
end)

after_each(function()
vim.lsp.get_active_clients = get_active_clients_fn
vim.lsp.buf_request_all = buf_request_all_fn
vim.lsp.get_client_by_id = get_client_by_id_fn
vim.lsp.util.make_position_params = make_position_params_fn
vim.lsp.util.apply_workspace_edit = apply_workspace_edit_fn
vim.api.nvim_err_writeln = err_fn
end)

describe("with different amount of changes", function()
before_each(function()
buf_request_all_results["1"] = {
result = {
changes = {
["file1"] = {},
},
},
}
buf_request_all_results["2"] = {
result = {
changes = {
["file1"] = {},
["file2"] = {},
},
},
}
end)

it("should use the results from the language server that touches the most files", function()
vim.api.nvim_buf_set_lines(0, 0, -1, true, { "plain text" })

test_helpers.execute_keys("<CMD>lua require('textcase').lsp_rename('to_upper_case')<CR>")

assert.spy(buf_request_all_spy).was.called_with(0, "textDocument/rename", match._, match._)
assert.spy(apply_workspace_edit_spy).was.called_with({
changes = {
["file1"] = {},
["file2"] = {},
},
}, "utf-8")
assert.spy(err_spy).was.not_called()
end)
end)

describe("with the same amount of changes", function()
before_each(function()
buf_request_all_results["1"] = {
result = {
changes = {
["file1"] = {},
["file2"] = {},
},
},
}
buf_request_all_results["2"] = {
result = {
changes = {
["file1"] = {},
["file2"] = {},
},
},
}
end)

it("should use the results from the language server that touches the most files", function()
vim.api.nvim_buf_set_lines(0, 0, -1, true, { "plain text" })

test_helpers.execute_keys("<CMD>lua require('textcase').lsp_rename('to_upper_case')<CR>")

assert.spy(buf_request_all_spy).was.called_with(0, "textDocument/rename", match._, match._)
assert.spy(apply_workspace_edit_spy).was.called_with({
changes = {
["file1"] = {},
["file2"] = {},
},
}, "utf-8")
assert.spy(err_spy).was.not_called()
end)
end)
end)
end)

0 comments on commit 1f981c3

Please sign in to comment.