Skip to content

Commit cb31013

Browse files
authored
feat(config): health check reports for .vscode/settings.json (#539)
1 parent 1c47bdd commit cb31013

File tree

3 files changed

+109
-3
lines changed

3 files changed

+109
-3
lines changed

lua/rustaceanvim/config/json.lua

+46-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,37 @@
11
local M = {}
22

3-
local function tbl_set(tbl, keys, value)
3+
local warnings = {}
4+
local errors = {}
5+
local is_json_config_loaded = false
6+
7+
---@param warning string
8+
local function add_warning(warning)
9+
table.insert(warnings, warning)
10+
end
11+
12+
---@param err string
13+
local function add_error(err)
14+
table.insert(errors, err)
15+
end
16+
17+
---@param field_name string | nil
18+
---@param tbl unknown
19+
---@param keys string[]
20+
---@param value unknown
21+
local function tbl_set(field_name, tbl, keys, value)
422
local next = table.remove(keys, 1)
23+
if type(tbl) ~= 'table' then
24+
add_warning(([[
25+
Ignored field '%s' of invalid type '%s': %s
26+
Please refer to the rust-analyzer documentation at
27+
https://rust-analyzer.github.io/manual.html#%s
28+
]]):format(field_name, type(value), vim.inspect(value), field_name))
29+
return
30+
end
531
if #keys > 0 then
632
tbl[next] = tbl[next] or {}
7-
tbl_set(tbl[next], keys, value)
33+
field_name = (field_name and field_name .. '.' or '') .. next
34+
tbl_set(field_name, tbl[next], keys, value)
835
else
936
tbl[next] = value
1037
end
@@ -15,14 +42,17 @@ end
1542
---@param json_value unknown
1643
local function override_tbl_values(tbl, json_key, json_value)
1744
local keys = vim.split(json_key, '%.')
18-
tbl_set(tbl, keys, json_value)
45+
tbl_set(nil, tbl, keys, json_value)
1946
end
2047

2148
---@param json_content string
2249
---@return table
2350
function M.silent_decode(json_content)
51+
warnings = {}
52+
errors = {}
2453
local ok, json_tbl = pcall(vim.json.decode, json_content)
2554
if not ok or type(json_tbl) ~= 'table' then
55+
add_error(('Failed to decode json: %s'):format(json_tbl or 'unknown error'))
2656
return {}
2757
end
2858
return json_tbl
@@ -32,6 +62,7 @@ end
3262
---@param json_tbl { [string]: unknown }
3363
---@param key_predicate? fun(string): boolean
3464
function M.override_with_json_keys(tbl, json_tbl, key_predicate)
65+
is_json_config_loaded = true
3566
for json_key, value in pairs(json_tbl) do
3667
if not key_predicate or key_predicate(json_key) then
3768
override_tbl_values(tbl, json_key, value)
@@ -47,4 +78,16 @@ function M.override_with_rust_analyzer_json_keys(tbl, json_tbl)
4778
end)
4879
end
4980

81+
function M.is_json_config_loaded()
82+
return is_json_config_loaded
83+
end
84+
85+
function M.get_warnings()
86+
return warnings
87+
end
88+
89+
function M.get_errors()
90+
return errors
91+
end
92+
5093
return M

lua/rustaceanvim/health.lua

+20
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,25 @@ local function check_tree_sitter()
148148
end
149149
end
150150

151+
local function check_json_config()
152+
local json = require('rustaceanvim.config.json')
153+
if json.is_json_config_loaded() then
154+
local errors = json.get_errors()
155+
if #errors > 0 then
156+
h.warn('.vscode/settings.json failed to load.')
157+
vim.iter(errors):each(h.error)
158+
return
159+
end
160+
local warnings = json.get_warnings()
161+
if #warnings == 0 then
162+
h.ok('.vscode/settings.json loaded without errors.')
163+
else
164+
h.warn('.vscode/settings.json loaded with warnings.')
165+
vim.iter(warnings):each(h.warn)
166+
end
167+
end
168+
end
169+
151170
function health.check()
152171
local types = require('rustaceanvim.types.internal')
153172
local config = require('rustaceanvim.config.internal')
@@ -281,6 +300,7 @@ function health.check()
281300
check_config(config)
282301
check_for_conflicts()
283302
check_tree_sitter()
303+
check_json_config()
284304
end
285305

286306
return health

spec/json_spec.lua

+43
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,47 @@ describe('Decode rust-analyzer settings from json', function()
4242
},
4343
}, tbl)
4444
end)
45+
it('persists warnings on invalid config', function()
46+
local invalid_json_content = [[
47+
{
48+
"rust-analyzer.checkOnSave.overrideCommand": [
49+
"cargo",
50+
"check",
51+
"-p",
52+
"service_b",
53+
"--message-format=json"
54+
],
55+
"rust-analyzer.foo.enable": true,
56+
"rust-analyzer.foo.bar.enable": true,
57+
"rust-analyzer.foo.bar.baz.bat": "something deeply nested",
58+
"some-other-key.foo.bar.baz.bat": "should not be included"
59+
}
60+
]]
61+
local tbl = {
62+
['rust-analyzer'] = {
63+
checkOnSave = true,
64+
},
65+
}
66+
local json_tbl = json.silent_decode(invalid_json_content)
67+
json.override_with_rust_analyzer_json_keys(tbl, json_tbl)
68+
assert.same({
69+
[[
70+
Ignored field 'rust-analyzer.checkOnSave' of invalid type 'table': { "cargo", "check", "-p", "service_b", "--message-format=json" }
71+
Please refer to the rust-analyzer documentation at
72+
https://rust-analyzer.github.io/manual.html#rust-analyzer.checkOnSave
73+
]],
74+
}, json.get_warnings())
75+
end)
76+
it('persists warnings about config parse errors', function()
77+
local unsupported_json_content = [[
78+
{
79+
// This is a json5 comment
80+
"rust-analyzer.foo.enable": true,
81+
}
82+
]]
83+
json.silent_decode(unsupported_json_content)
84+
assert.same({
85+
'Failed to decode json: Expected object key string but found invalid token at character 5',
86+
}, json.get_errors())
87+
end)
4588
end)

0 commit comments

Comments
 (0)