summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-06-22 16:13:50 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-06-22 16:13:50 +0800
commite5d692cb0845e5de7988904017440bd4db551bb7 (patch)
treedcfad1a5b739f3f7987d2baf5c4d6979b754b78f
parent82c3b68c6b80f754aa9fc12a4f029eba237e2807 (diff)
downloadlua-language-server-e5d692cb0845e5de7988904017440bd4db551bb7.zip
`param-type-mismatch`
-rw-r--r--locale/zh-cn/script.lua4
-rw-r--r--script/core/diagnostics/init.lua1
-rw-r--r--script/core/diagnostics/param-type-mismatch.lua61
-rw-r--r--script/proto/define.lua2
-rw-r--r--script/vm/type.lua3
-rw-r--r--test/diagnostics/common.lua6
-rw-r--r--test/diagnostics/type-check.lua7
7 files changed, 80 insertions, 4 deletions
diff --git a/locale/zh-cn/script.lua b/locale/zh-cn/script.lua
index 9cbe43d2..2738d51a 100644
--- a/locale/zh-cn/script.lua
+++ b/locale/zh-cn/script.lua
@@ -121,7 +121,9 @@ DIAG_CAST_LOCAL_TYPE =
DIAG_CAST_FIELD_TYPE =
'已显式定义字段的类型为 `{def}` ,不能再将其类型转换为 `{ref}`。'
DIAG_ASSIGN_TYPE_MISMATCH =
-'不能将类型 `{ref}` 赋值给类型 `{def}`。'
+'类型不匹配,不能将 `{ref}` 赋值给 `{def}`。'
+DIAG_PARAM_TYPE_MISMATCH =
+'参数类型不匹配,不能将 `{ref}` 赋值给 `{def}`。'
MWS_NOT_SUPPORT =
'{} 目前还不支持多工作目录,我可能需要重启才能支持新的工作目录...'
diff --git a/script/core/diagnostics/init.lua b/script/core/diagnostics/init.lua
index fe551bc8..c5cb90ca 100644
--- a/script/core/diagnostics/init.lua
+++ b/script/core/diagnostics/init.lua
@@ -14,6 +14,7 @@ local diagSort = {
['redundant-parameter'] = 110,
['cast-local-type'] = 120,
['assign-type-mismatch'] = 120,
+ ['param-type-mismatch'] = 120,
}
local diagList = {}
diff --git a/script/core/diagnostics/param-type-mismatch.lua b/script/core/diagnostics/param-type-mismatch.lua
new file mode 100644
index 00000000..a05b03e4
--- /dev/null
+++ b/script/core/diagnostics/param-type-mismatch.lua
@@ -0,0 +1,61 @@
+local files = require 'files'
+local lang = require 'language'
+local guide = require 'parser.guide'
+local vm = require 'vm'
+local await = require 'await'
+
+---@async
+return function (uri, callback)
+ if not PREVIEW and not TEST then
+ return
+ end
+ local state = files.getState(uri)
+ if not state then
+ return
+ end
+
+ ---@param funcNode vm.node
+ ---@param i integer
+ ---@return vm.node?
+ local function getDefNode(funcNode, i)
+ local defNode = vm.createNode()
+ for f in funcNode:eachObject() do
+ if f.type == 'function'
+ or f.type == 'doc.type.function' then
+ local param = f.args and f.args[i]
+ if param then
+ defNode:merge(vm.compileNode(param))
+ end
+ end
+ end
+ if defNode:isEmpty() then
+ return nil
+ end
+ return defNode
+ end
+
+ ---@async
+ guide.eachSourceType(state.ast, 'call', function (source)
+ if not source.args then
+ return
+ end
+ await.delay()
+ local funcNode = vm.compileNode(source.node)
+ for i, arg in ipairs(source.args) do
+ local refNode = vm.compileNode(arg)
+ local defNode = getDefNode(funcNode, i)
+ if defNode then
+ if not vm.canCastType(uri, defNode, refNode) then
+ callback {
+ start = arg.start,
+ finish = arg.finish,
+ message = lang.script('DIAG_PARAM_TYPE_MISMATCH', {
+ def = vm.getInfer(defNode):view(uri),
+ ref = vm.getInfer(refNode):view(uri),
+ })
+ }
+ end
+ end
+ end
+ end)
+end
diff --git a/script/proto/define.lua b/script/proto/define.lua
index 8c7c7a0f..45fbba9e 100644
--- a/script/proto/define.lua
+++ b/script/proto/define.lua
@@ -51,6 +51,7 @@ m.DiagnosticDefaultSeverity = {
['need-check-nil'] = 'Warning',
['cast-local-type'] = 'Warning',
['assign-type-mismatch'] = 'Warning',
+ ['param-type-mismatch'] = 'Warning',
['duplicate-doc-alias'] = 'Warning',
['undefined-doc-class'] = 'Warning',
@@ -114,6 +115,7 @@ m.DiagnosticDefaultNeededFileStatus = {
['need-check-nil'] = 'Opened',
['cast-local-type'] = 'Any',
['assign-type-mismatch'] = 'Any',
+ ['param-type-mismatch'] = 'Any',
['duplicate-doc-alias'] = 'Any',
['undefined-doc-class'] = 'Any',
diff --git a/script/vm/type.lua b/script/vm/type.lua
index e6541f1b..ecca4382 100644
--- a/script/vm/type.lua
+++ b/script/vm/type.lua
@@ -72,6 +72,9 @@ function vm.isSubType(uri, child, parent, mark)
and vm.isSubType(uri, child, n, mark) then
return true
end
+ if n.type == 'doc.generic.name' then
+ return true
+ end
end
if parent:isOptional() then
if vm.isSubType(uri, child, 'nil', mark) then
diff --git a/test/diagnostics/common.lua b/test/diagnostics/common.lua
index 7d745039..5de7d5db 100644
--- a/test/diagnostics/common.lua
+++ b/test/diagnostics/common.lua
@@ -239,7 +239,7 @@ local m = {}
function m:x(a, b)
return a, b
end
-m.x(1, 2, 3, <!4!>)
+m.x(m, 2, 3, <!4!>)
]]
TEST [[
@@ -469,7 +469,7 @@ local mt = {}
function mt:f(a, b)
return a, b
end
-mt.f(1, 2, 3, <!4!>)
+mt.f(mt, 2, 3, <!4!>)
]]
@@ -569,7 +569,7 @@ local m = {}
function m:open()
end
-m.open('ok')
+m.open(m)
]]
TEST [[
diff --git a/test/diagnostics/type-check.lua b/test/diagnostics/type-check.lua
index 20c611ab..3e4584c0 100644
--- a/test/diagnostics/type-check.lua
+++ b/test/diagnostics/type-check.lua
@@ -310,5 +310,12 @@ m.x = 1
<!m.x!> = {}
]]
+TEST [[
+---@param x number
+local function f(x) end
+
+f(<!true!>)
+]]
+
config.remove(nil, 'Lua.diagnostics.disable', 'unused-local')
config.remove(nil, 'Lua.diagnostics.disable', 'undefined-global')