Skip to content

Commit

Permalink
feat: errors do not stop formatting early
Browse files Browse the repository at this point in the history
  • Loading branch information
stevearc committed Oct 8, 2023
1 parent e758196 commit a94f686
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 111 deletions.
63 changes: 63 additions & 0 deletions lua/conform/errors.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
local M = {}

---@class conform.Error
---@field code conform.ERROR_CODE
---@field message string
---@field debounce_message? boolean

---@enum conform.ERROR_CODE
M.ERROR_CODE = {
-- Command was passed invalid arguments
INVALID_ARGS = 1,
-- Command was not executable
NOT_EXECUTABLE = 2,
-- Command timed out during execution
TIMEOUT = 3,
-- Command was pre-empted by another call to format
INTERRUPTED = 4,
-- Command produced an error during execution
RUNTIME = 5,
-- Asynchronous formatter results were discarded due to a concurrent modification
CONCURRENT_MODIFICATION = 6,
}

---@param code conform.ERROR_CODE
---@return integer
M.level_for_code = function(code)
if code == M.ERROR_CODE.CONCURRENT_MODIFICATION then
return vim.log.levels.INFO
elseif code == M.ERROR_CODE.TIMEOUT or code == M.ERROR_CODE.INTERRUPTED then
return vim.log.levels.WARN
else
return vim.log.levels.ERROR
end
end

---Returns true if the error occurred while attempting to run the formatter
---@param code conform.ERROR_CODE
---@return boolean
M.is_execution_error = function(code)
return code == M.ERROR_CODE.RUNTIME
or code == M.ERROR_CODE.NOT_EXECUTABLE
or code == M.ERROR_CODE.INVALID_ARGS
end

---@param err1? conform.Error
---@param err2? conform.Error
---@return nil|conform.Error
M.coalesce = function(err1, err2)
if not err1 then
return err2
elseif not err2 then
return err1
end
local level1 = M.level_for_code(err1.code)
local level2 = M.level_for_code(err2.code)
if level2 > level1 then
return err2
else
return err1
end
end

return M
27 changes: 13 additions & 14 deletions lua/conform/formatters/injected.lua
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ return {
end,
format = function(self, ctx, lines, callback)
local conform = require("conform")
local errors = require("conform.errors")
local log = require("conform.log")
local util = require("conform.util")
local text = table.concat(lines, "\n")
Expand Down Expand Up @@ -124,19 +125,17 @@ return {

local function apply_format_results()
if format_error then
if self.options.ignore_errors then
-- Find all of the conform errors in the replacements table and remove them
local i = 1
while i <= #replacements do
if replacements[i].code then
table.remove(replacements, i)
else
i = i + 1
end
-- Find all of the conform errors in the replacements table and remove them
local i = 1
while i <= #replacements do
if replacements[i].code then
table.remove(replacements, i)
else
i = i + 1
end
else
callback(format_error)
return
end
if self.options.ignore_errors then
format_error = nil
end
end

Expand All @@ -150,13 +149,13 @@ return {
table.insert(formatted_lines, start_lnum, new_lines[i])
end
end
callback(nil, formatted_lines)
callback(format_error, formatted_lines)
end

local num_format = 0
local formatter_cb = function(err, idx, start_lnum, end_lnum, new_lines)
if err then
format_error = err
format_error = errors.coalesce(format_error, err)
replacements[idx] = err
else
replacements[idx] = { start_lnum, end_lnum, new_lines }
Expand Down
8 changes: 5 additions & 3 deletions lua/conform/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ M.format = function(opts, callback)
opts.range = range_from_selection(opts.bufnr, mode)
end
callback = callback or function(_err) end
local errors = require("conform.errors")
local log = require("conform.log")
local lsp_format = require("conform.lsp_format")
local runner = require("conform.runner")
Expand All @@ -377,12 +378,12 @@ M.format = function(opts, callback)
---@param err? conform.Error
local function handle_err(err)
if err then
local level = runner.level_for_code(err.code)
local level = errors.level_for_code(err.code)
log.log(level, err.message)
local should_notify = not opts.quiet and level >= vim.log.levels.WARN
-- Execution errors have special handling. Maybe should reconsider this.
local notify_msg = err.message
if runner.is_execution_error(err.code) then
if errors.is_execution_error(err.code) then
should_notify = should_notify and M.notify_on_error and not err.debounce_message
notify_msg = "Formatter failed. See :ConformInfo for details"
end
Expand Down Expand Up @@ -449,6 +450,7 @@ M.format_lines = function(formatter_names, lines, opts, callback)
quiet = false,
})
callback = callback or function(_err, _lines) end
local errors = require("conform.errors")
local log = require("conform.log")
local runner = require("conform.runner")
local formatters = resolve_formatters(formatter_names, opts.bufnr, not opts.quiet)
Expand All @@ -461,7 +463,7 @@ M.format_lines = function(formatter_names, lines, opts, callback)
---@param new_lines? string[]
local function handle_err(err, new_lines)
if err then
local level = runner.level_for_code(err.code)
local level = errors.level_for_code(err.code)
log.log(level, err.message)
end
callback(err, new_lines)
Expand Down
Loading

0 comments on commit a94f686

Please sign in to comment.