Skip to content

Commit

Permalink
feat(config): health check reports for .vscode/settings.json
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcjkb committed Oct 15, 2024
1 parent d1f5667 commit b07daf7
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 3 deletions.
49 changes: 46 additions & 3 deletions lua/rustaceanvim/config/json.lua
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
local M = {}

local function tbl_set(tbl, keys, value)
local warnings = {}
local errors = {}
local is_json_config_loaded = false

---@param warning string
local function add_warning(warning)
table.insert(warnings, warning)
end

---@param err string
local function add_error(err)
table.insert(errors, err)
end

---@param field_name string | nil
---@param tbl unknown
---@param keys string[]
---@param value unknown
local function tbl_set(field_name, tbl, keys, value)
local next = table.remove(keys, 1)
if type(tbl) ~= 'table' then
add_warning(([[
Ignored field '%s' of invalid type '%s': %s
Please refer to the rust-analyzer documentation at
https://rust-analyzer.github.io/manual.html#%s
]]):format(field_name, type(value), vim.inspect(value), field_name))
return
end
if #keys > 0 then
tbl[next] = tbl[next] or {}
tbl_set(tbl[next], keys, value)
field_name = (field_name and field_name .. '.' or '') .. next
tbl_set(field_name, tbl[next], keys, value)
else
tbl[next] = value
end
Expand All @@ -15,14 +42,17 @@ end
---@param json_value unknown
local function override_tbl_values(tbl, json_key, json_value)
local keys = vim.split(json_key, '%.')
tbl_set(tbl, keys, json_value)
tbl_set(nil, tbl, keys, json_value)
end

---@param json_content string
---@return table
function M.silent_decode(json_content)
warnings = {}
errors = {}
local ok, json_tbl = pcall(vim.json.decode, json_content)
if not ok or type(json_tbl) ~= 'table' then
add_error(('Failed to decode json: %s'):format(json_tbl or 'unknown error'))
return {}
end
return json_tbl
Expand All @@ -32,6 +62,7 @@ end
---@param json_tbl { [string]: unknown }
---@param key_predicate? fun(string): boolean
function M.override_with_json_keys(tbl, json_tbl, key_predicate)
is_json_config_loaded = true
for json_key, value in pairs(json_tbl) do
if not key_predicate or key_predicate(json_key) then
override_tbl_values(tbl, json_key, value)
Expand All @@ -47,4 +78,16 @@ function M.override_with_rust_analyzer_json_keys(tbl, json_tbl)
end)
end

function M.is_json_config_loaded()
return is_json_config_loaded
end

function M.get_warnings()
return warnings
end

function M.get_errors()
return errors
end

return M
20 changes: 20 additions & 0 deletions lua/rustaceanvim/health.lua
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,25 @@ local function check_tree_sitter()
end
end

local function check_json_config()
local json = require('rustaceanvim.config.json')
if json.is_json_config_loaded() then
local errors = json.get_errors()
if #errors > 0 then
h.warn('.vscode/settings.json failed to load.')
vim.iter(errors):each(h.error)
return
end
local warnings = json.get_warnings()
if #warnings == 0 then
h.ok('.vscode/settings.json loaded without errors.')
else
h.warn('.vscode/settings.json loaded with warnings.')
vim.iter(warnings):each(h.warn)
end
end
end

function health.check()
local types = require('rustaceanvim.types.internal')
local config = require('rustaceanvim.config.internal')
Expand Down Expand Up @@ -281,6 +300,7 @@ function health.check()
check_config(config)
check_for_conflicts()
check_tree_sitter()
check_json_config()
end

return health
43 changes: 43 additions & 0 deletions spec/json_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,47 @@ describe('Decode rust-analyzer settings from json', function()
},
}, tbl)
end)
it('persists warnings on invalid config', function()
local invalid_json_content = [[
{
"rust-analyzer.checkOnSave.overrideCommand": [
"cargo",
"check",
"-p",
"service_b",
"--message-format=json"
],
"rust-analyzer.foo.enable": true,
"rust-analyzer.foo.bar.enable": true,
"rust-analyzer.foo.bar.baz.bat": "something deeply nested",
"some-other-key.foo.bar.baz.bat": "should not be included"
}
]]
local tbl = {
['rust-analyzer'] = {
checkOnSave = true,
},
}
local json_tbl = json.silent_decode(invalid_json_content)
json.override_with_rust_analyzer_json_keys(tbl, json_tbl)
assert.same({
[[
Ignored field 'rust-analyzer.checkOnSave' of invalid type 'table': { "cargo", "check", "-p", "service_b", "--message-format=json" }
Please refer to the rust-analyzer documentation at
https://rust-analyzer.github.io/manual.html#rust-analyzer.checkOnSave
]],
}, json.get_warnings())
end)
it('persists warnings about config parse errors', function()
local unsupported_json_content = [[
{
// This is a json5 comment
"rust-analyzer.foo.enable": true,
}
]]
json.silent_decode(unsupported_json_content)
assert.same({
'Failed to decode json: Expected object key string but found invalid token at character 5',
}, json.get_errors())
end)
end)

0 comments on commit b07daf7

Please sign in to comment.