summaryrefslogtreecommitdiff
path: root/script/vm
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2024-08-16 16:55:57 +0800
committer最萌小汐 <sumneko@hotmail.com>2024-08-16 16:55:57 +0800
commit080d672ee4bbc082a24aef95821860afa78a7d9f (patch)
tree687c6229d6a904d1e31ee240254d83f93d83508d /script/vm
parent18ae29cd86dd7e6caa45eba9ac05c44170970df3 (diff)
downloadlua-language-server-080d672ee4bbc082a24aef95821860afa78a7d9f.zip
Add setting: `Lua.type.checkTableShape`
Diffstat (limited to 'script/vm')
-rw-r--r--script/vm/type.lua130
1 files changed, 69 insertions, 61 deletions
diff --git a/script/vm/type.lua b/script/vm/type.lua
index 4835065a..3bc51cd8 100644
--- a/script/vm/type.lua
+++ b/script/vm/type.lua
@@ -284,6 +284,71 @@ local function isAlias(name, suri)
return false
end
+local function checkTableShape(parent, child, uri, mark, errs)
+ local set = parent:getSets(uri)
+ local missedKeys = {}
+ local failedCheck
+ local myKeys
+ for _, def in ipairs(set) do
+ if not def.fields or #def.fields == 0 then
+ goto continue
+ end
+ if not myKeys then
+ myKeys = {}
+ for _, field in ipairs(child) do
+ local key = vm.getKeyName(field) or field.tindex
+ if key then
+ myKeys[key] = vm.compileNode(field)
+ end
+ end
+ end
+
+ for _, field in ipairs(def.fields) do
+ local key = vm.getKeyName(field)
+ if not key then
+ local fieldnode = vm.compileNode(field.field)[1]
+ if fieldnode and fieldnode.type == 'doc.type.integer' then
+ ---@cast fieldnode parser.object
+ key = vm.getKeyName(fieldnode)
+ end
+ end
+ if not key then
+ goto continue
+ end
+
+ local ok
+ local nodeField = vm.compileNode(field)
+ if myKeys[key] then
+ ok = vm.isSubType(uri, myKeys[key], nodeField, mark, errs)
+ if ok == false then
+ errs[#errs+1] = 'TYPE_ERROR_PARENT_ALL_DISMATCH' -- error display can be greatly improved
+ errs[#errs+1] = myKeys[key]
+ errs[#errs+1] = nodeField
+ failedCheck = true
+ end
+ elseif not nodeField:isNullable() then
+ if type(key) == "number" then
+ missedKeys[#missedKeys+1] = ('`[%s]`'):format(key)
+ else
+ missedKeys[#missedKeys+1] = ('`%s`'):format(key)
+ end
+ failedCheck = true
+ end
+ end
+ ::continue::
+ end
+ if #missedKeys > 0 then
+ errs[#errs+1] = 'DIAG_MISSING_FIELDS'
+ errs[#errs+1] = parent
+ errs[#errs+1] = table.concat(missedKeys, ', ')
+ end
+ if failedCheck then
+ return false
+ end
+
+ return true
+end
+
---@param uri uri
---@param child vm.node|string|vm.node.object
---@param parent vm.node|string|vm.node.object
@@ -483,68 +548,11 @@ function vm.isSubType(uri, child, parent, mark, errs)
return true
end
if childName == 'table' and not guide.isBasicType(parentName) then
- local set = parent:getSets(uri)
- local missedKeys = {}
- local failedCheck
- local myKeys
- for _, def in ipairs(set) do
- if not def.fields or #def.fields == 0 then
- goto continue
- end
- if not myKeys then
- myKeys = {}
- for _, field in ipairs(child) do
- local key = vm.getKeyName(field) or field.tindex
- if key then
- myKeys[key] = vm.compileNode(field)
- end
- end
- end
-
- for _, field in ipairs(def.fields) do
- local key = vm.getKeyName(field)
- if not key then
- local fieldnode = vm.compileNode(field.field)[1]
- if fieldnode and fieldnode.type == 'doc.type.integer' then
- ---@cast fieldnode parser.object
- key = vm.getKeyName(fieldnode)
- end
- end
- if not key then
- goto continue
- end
-
- local ok
- local nodeField = vm.compileNode(field)
- if myKeys[key] then
- ok = vm.isSubType(uri, myKeys[key], nodeField, mark, errs)
- if ok == false then
- errs[#errs+1] = 'TYPE_ERROR_PARENT_ALL_DISMATCH' -- error display can be greatly improved
- errs[#errs+1] = myKeys[key]
- errs[#errs+1] = nodeField
- failedCheck = true
- end
- elseif not nodeField:isNullable() then
- if type(key) == "number" then
- missedKeys[#missedKeys+1] = ('`[%s]`'):format(key)
- else
- missedKeys[#missedKeys+1] = ('`%s`'):format(key)
- end
- failedCheck = true
- end
- end
- ::continue::
- end
- if #missedKeys > 0 then
- errs[#errs+1] = 'DIAG_MISSING_FIELDS'
- errs[#errs+1] = parent
- errs[#errs+1] = table.concat(missedKeys, ', ')
- end
- if failedCheck then
- return false
+ if config.get(uri, 'Lua.type.checkTableShape') then
+ return checkTableShape(parent, child, uri, mark, errs)
+ else
+ return true
end
-
- return true
end
-- check class parent