summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--locale/en-us/script.lua2
-rw-r--r--locale/pt-br/script.lua2
-rw-r--r--locale/zh-cn/script.lua2
-rw-r--r--locale/zh-tw/script.lua2
-rw-r--r--script/client.lua80
-rw-r--r--test/tclient/tests/modify-luarc.lua150
7 files changed, 226 insertions, 14 deletions
diff --git a/changelog.md b/changelog.md
index d3c78de9..50685423 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,8 +1,10 @@
# changelog
## 3.6.5
+* `FIX` [#831]
* `FIX` [#1729]
+[#831]: https://github.com/sumneko/lua-language-server/issues/831
[#1729]: https://github.com/sumneko/lua-language-server/issues/1729
`2022-11-29`
diff --git a/locale/en-us/script.lua b/locale/en-us/script.lua
index a75f2301..fb203d7e 100644
--- a/locale/en-us/script.lua
+++ b/locale/en-us/script.lua
@@ -562,6 +562,8 @@ CONFIG_LOAD_ERROR =
'Setting file loading error: {}'
CONFIG_TYPE_ERROR =
'The setting file must be in lua or json format: {}'
+CONFIG_MODIFY_FAIL_SYNTAX_ERROR =
+'Failed to modify settings, there are syntax errors in the settings file: {}'
PLUGIN_RUNTIME_ERROR =
[[
diff --git a/locale/pt-br/script.lua b/locale/pt-br/script.lua
index 5ae052d2..aabb3a19 100644
--- a/locale/pt-br/script.lua
+++ b/locale/pt-br/script.lua
@@ -562,6 +562,8 @@ CONFIG_LOAD_ERROR =
'Configurando o erro de carregamento do arquivo: {}'
CONFIG_TYPE_ERROR =
'O arquivo de configuração deve estar no formato LUA ou JSON: {}'
+CONFIG_MODIFY_FAIL_SYNTAX_ERROR = -- TODO: need translate!
+'Failed to modify settings, there are syntax errors in the settings file: {}'
PLUGIN_RUNTIME_ERROR =
[[
diff --git a/locale/zh-cn/script.lua b/locale/zh-cn/script.lua
index a9905e35..6adaa17d 100644
--- a/locale/zh-cn/script.lua
+++ b/locale/zh-cn/script.lua
@@ -562,6 +562,8 @@ CONFIG_LOAD_ERROR =
'设置文件加载错误:{}'
CONFIG_TYPE_ERROR =
'设置文件必须是lua或json格式:{}'
+CONFIG_MODIFY_FAIL_SYNTAX_ERROR =
+'修改设置失败,设置文件中有语法错误:{}'
PLUGIN_RUNTIME_ERROR =
[[
diff --git a/locale/zh-tw/script.lua b/locale/zh-tw/script.lua
index f9315057..ec69bea8 100644
--- a/locale/zh-tw/script.lua
+++ b/locale/zh-tw/script.lua
@@ -562,6 +562,8 @@ CONFIG_LOAD_ERROR =
'設定檔案載入錯誤:{}'
CONFIG_TYPE_ERROR =
'設定檔案必須是lua或json格式:{}'
+CONFIG_MODIFY_FAIL_SYNTAX_ERROR = -- TODO: need translate!
+'Failed to modify settings, there are syntax errors in the settings file: {}'
PLUGIN_RUNTIME_ERROR =
[[
diff --git a/script/client.lua b/script/client.lua
index ea80ee53..473c748b 100644
--- a/script/client.lua
+++ b/script/client.lua
@@ -223,20 +223,68 @@ local function getValidChanges(uri, changes)
end
---@class json.patch
----@field op 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test'
+---@field op 'add' | 'remove' | 'replace'
---@field path string
---@field value any
+---@class json.patchInfo
+---@field key string
+---@field value any
+
+---@param cfg table
+---@param rawKey string
+---@return json.patchInfo
+local function searchPatchInfo(cfg, rawKey)
+
+ ---@param key string
+ ---@param parentKey string
+ ---@param parentValue table
+ ---@return json.patchInfo?
+ local function searchOnce(key, parentKey, parentValue)
+ if parentValue == nil then
+ return nil
+ end
+ if type(parentValue) ~= 'table' then
+ return {
+ key = parentKey,
+ value = parentValue,
+ }
+ end
+ if parentValue[key] then
+ return {
+ key = parentKey .. '/' .. key,
+ value = parentValue[key],
+ }
+ end
+ for pos in key:gmatch '()%.' do
+ local k = key:sub(1, pos - 1)
+ local v = parentValue[k]
+ local info = searchOnce(key:sub(pos + 1), parentKey .. '/' .. k, v)
+ if info then
+ return info
+ end
+ end
+ return nil
+ end
+
+ return searchOnce(rawKey, '', cfg)
+ or searchOnce(rawKey:gsub('^Lua%.', ''), '', cfg)
+ or {
+ key = '/' .. rawKey,
+ value = nil,
+ }
+end
+
---@param cfg table
---@param change config.change
---@return json.patch?
local function makeConfigPatch(cfg, change)
- local value = cfg[change.key]
+ local info = searchPatchInfo(cfg, change.key)
if change.action == 'add' then
- if type(value) == 'table' and #cfg[change.key] > 0 then
+ if type(info.value) == 'table' and #info.value > 0 then
return {
op = 'add',
- path = '/' .. change.key .. '/-',
+ path = info.key .. '/-',
value = change.value,
}
else
@@ -247,24 +295,24 @@ local function makeConfigPatch(cfg, change)
})
end
elseif change.action == 'set' then
- if value ~= nil then
+ if info.value ~= nil then
return {
op = 'replace',
- path = '/' .. change.key,
+ path = info.key,
value = change.value,
}
else
return {
op = 'add',
- path = '/' .. change.key,
+ path = info.key,
value = change.value,
}
end
elseif change.action == 'prop' then
- if type(value) == 'table' and #value == 0 then
+ if type(info.value) == 'table' and #info.value == 0 then
return {
op = 'add',
- path = '/' .. change.key .. '/' .. change.prop,
+ path = info.key .. '/' .. change.prop,
value = change.value,
}
else
@@ -286,13 +334,17 @@ local function editConfigJson(path, changes)
if not text then
return nil
end
- local cfg = jsonc.decode_jsonc(text)
- if type(cfg) ~= 'table' then
- cfg = {}
+ local suc, res = pcall(jsonc.decode_jsonc, text)
+ if not suc then
+ m.showMessage('Error', lang.script('CONFIG_MODIFY_FAIL_SYNTAX_ERROR', path .. res:match 'ERROR(.+)$'))
+ return text
+ end
+ if type(res) ~= 'table' then
+ res = {}
end
- ---@cast cfg table
+ ---@cast res table
for _, change in ipairs(changes) do
- local patch = makeConfigPatch(cfg, change)
+ local patch = makeConfigPatch(res, change)
if patch then
text = jsone.edit(text, patch, { indent = ' ' })
end
diff --git a/test/tclient/tests/modify-luarc.lua b/test/tclient/tests/modify-luarc.lua
index 94756847..11de446b 100644
--- a/test/tclient/tests/modify-luarc.lua
+++ b/test/tclient/tests/modify-luarc.lua
@@ -39,6 +39,26 @@ lclient():start(function (languageClient)
-------------------------------
+ util.saveFile(configPath, jsonb.beautify {
+ ['Lua.runtime.version'] = json.null,
+ })
+
+ provider.updateConfig()
+
+ client.setConfig({
+ {
+ action = 'set',
+ key = 'Lua.runtime.version',
+ value = 'LuaJIT',
+ }
+ })
+
+ assert(util.equal(jsonc.decode_jsonc(util.loadFile(configPath)), {
+ ['Lua.runtime.version'] = 'LuaJIT',
+ }))
+
+ -------------------------------
+
util.saveFile(configPath, jsonb.beautify(json.createEmptyObject()))
provider.updateConfig()
@@ -174,4 +194,134 @@ lclient():start(function (languageClient)
}
}))
+ -------------------------------
+
+ util.saveFile(configPath, jsonb.beautify {
+ ['runtime.version'] = json.null,
+ })
+
+ provider.updateConfig()
+
+ client.setConfig({
+ {
+ action = 'set',
+ key = 'Lua.runtime.version',
+ value = 'LuaJIT',
+ }
+ })
+
+ assert(util.equal(jsonc.decode_jsonc(util.loadFile(configPath)), {
+ ['runtime.version'] = 'LuaJIT',
+ }))
+
+ -------------------------------
+
+ util.saveFile(configPath, jsonb.beautify {
+ Lua = {
+ runtime = {
+ version = json.null,
+ }
+ }
+ })
+
+ provider.updateConfig()
+
+ client.setConfig({
+ {
+ action = 'set',
+ key = 'Lua.runtime.version',
+ value = 'LuaJIT',
+ }
+ })
+
+ assert(util.equal(jsonc.decode_jsonc(util.loadFile(configPath)), {
+ Lua = {
+ runtime = {
+ version = 'LuaJIT',
+ }
+ }
+ }))
+
+ -------------------------------
+
+ util.saveFile(configPath, jsonb.beautify {
+ runtime = {
+ version = json.null,
+ }
+ })
+
+ provider.updateConfig()
+
+ client.setConfig({
+ {
+ action = 'set',
+ key = 'Lua.runtime.version',
+ value = 'LuaJIT',
+ }
+ })
+
+ assert(util.equal(jsonc.decode_jsonc(util.loadFile(configPath)), {
+ runtime = {
+ version = 'LuaJIT',
+ }
+ }))
+
+ -------------------------------
+
+ util.saveFile(configPath, jsonb.beautify {
+ diagnostics = {
+ disable = {
+ 'unused-local',
+ }
+ }
+ })
+
+ provider.updateConfig()
+
+ client.setConfig({
+ {
+ action = 'add',
+ key = 'Lua.diagnostics.disable',
+ value = 'undefined-global',
+ }
+ })
+
+ assert(util.equal(jsonc.decode_jsonc(util.loadFile(configPath)), {
+ diagnostics = {
+ disable = {
+ 'unused-local',
+ 'undefined-global',
+ }
+ }
+ }))
+
+ -------------------------------
+
+ util.saveFile(configPath, jsonb.beautify {
+ runtime = {
+ special = {
+ import = 'require',
+ }
+ }
+ })
+
+ provider.updateConfig()
+
+ client.setConfig({
+ {
+ action = 'prop',
+ key = 'Lua.runtime.special',
+ prop = 'include',
+ value = 'require',
+ }
+ })
+
+ assert(util.equal(jsonc.decode_jsonc(util.loadFile(configPath)), {
+ runtime = {
+ special = {
+ import = 'require',
+ include = 'require',
+ }
+ }
+ }))
end)