summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--script/core/diagnostics/assign-type-mismatch.lua47
-rw-r--r--script/core/diagnostics/init.lua13
-rw-r--r--script/core/diagnostics/type-check-assign.lua20
-rw-r--r--script/proto/define.lua4
-rw-r--r--script/vm/compiler.lua18
-rw-r--r--script/vm/type.lua10
-rw-r--r--test/diagnostics/common.lua59
7 files changed, 132 insertions, 39 deletions
diff --git a/script/core/diagnostics/assign-type-mismatch.lua b/script/core/diagnostics/assign-type-mismatch.lua
new file mode 100644
index 00000000..38cfc674
--- /dev/null
+++ b/script/core/diagnostics/assign-type-mismatch.lua
@@ -0,0 +1,47 @@
+local files = require 'files'
+local lang = require 'language'
+local guide = require 'parser.guide'
+local vm = require 'vm'
+local await = require 'await'
+
+local checkTypes = {
+ 'setlocal',
+ 'setglobal',
+ 'setfield',
+ 'setindex',
+ 'setmethod',
+ 'tablefield',
+ 'tableindex'
+}
+
+---@async
+return function (uri, callback)
+ local state = files.getState(uri)
+ if not state then
+ return
+ end
+
+ ---@async
+ guide.eachSourceTypes(state.ast, checkTypes, function (source)
+ local value = source.value
+ if not value then
+ return
+ end
+ await.delay()
+ local varNode = vm.compileNode(source)
+ local valueNode = vm.compileNode(value)
+ if vm.getInfer(varNode):hasUnknown(uri) then
+ return
+ end
+ if not vm.isSubType(uri, valueNode, varNode) then
+ callback {
+ start = source.start,
+ finish = source.finish,
+ message = lang.script('DIAG_ASSIGN_TYPE_MISMATCH', {
+ loc = vm.getInfer(varNode):view(uri),
+ ref = vm.getInfer(valueNode):view(uri),
+ }),
+ }
+ end
+ end)
+end
diff --git a/script/core/diagnostics/init.lua b/script/core/diagnostics/init.lua
index e9af8ea3..746052b0 100644
--- a/script/core/diagnostics/init.lua
+++ b/script/core/diagnostics/init.lua
@@ -7,12 +7,13 @@ local util = require 'utility'
-- 把耗时最长的诊断放到最后面
local diagSort = {
- ['redundant-value'] = 100,
- ['not-yieldable'] = 101,
- ['deprecated'] = 102,
- ['undefined-field'] = 103,
- ['redundant-parameter'] = 104,
- ['cast-local-type'] = 105,
+ ['redundant-value'] = 100,
+ ['not-yieldable'] = 101,
+ ['deprecated'] = 102,
+ ['undefined-field'] = 103,
+ ['redundant-parameter'] = 104,
+ ['cast-local-type'] = 105,
+ ['assign-type-mismatch'] = 106,
}
local diagList = {}
diff --git a/script/core/diagnostics/type-check-assign.lua b/script/core/diagnostics/type-check-assign.lua
deleted file mode 100644
index 6b3c73b3..00000000
--- a/script/core/diagnostics/type-check-assign.lua
+++ /dev/null
@@ -1,20 +0,0 @@
-local files = require 'files'
-local lang = require 'language'
-local guide = require 'parser.guide'
-local vm = require 'vm'
-
-return function (uri, callback)
- local state = files.getState(uri)
- if not state then
- return
- end
-
- guide.eachSourceType(state.ast, 'setlocal', function (source)
- local value = source.value
- if not value then
- return
- end
- local locNode = vm.compileNode(source)
- local valueNode = vm.compileNode(value)
- end)
-end
diff --git a/script/proto/define.lua b/script/proto/define.lua
index 2ea1fd90..8c7c7a0f 100644
--- a/script/proto/define.lua
+++ b/script/proto/define.lua
@@ -50,7 +50,7 @@ m.DiagnosticDefaultSeverity = {
['discard-returns'] = 'Warning',
['need-check-nil'] = 'Warning',
['cast-local-type'] = 'Warning',
- ['type-check-assign'] = 'Warning',
+ ['assign-type-mismatch'] = 'Warning',
['duplicate-doc-alias'] = 'Warning',
['undefined-doc-class'] = 'Warning',
@@ -113,7 +113,7 @@ m.DiagnosticDefaultNeededFileStatus = {
['discard-returns'] = 'Opened',
['need-check-nil'] = 'Opened',
['cast-local-type'] = 'Any',
- ['type-check-assign'] = 'Any',
+ ['assign-type-mismatch'] = 'Any',
['duplicate-doc-alias'] = 'Any',
['undefined-doc-class'] = 'Any',
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index dd41d7b6..bc85407d 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -637,16 +637,14 @@ local function compileByLocalID(source)
end
end
end
- for _, src in ipairs(sources) do
- if src.value then
- if not hasMarkDoc or guide.isLiteral(src.value) then
- if src.value.type ~= 'nil' then
- local valueNode = vm.compileNode(src.value)
- if valueNode:hasType 'unknown' then
- vm.setNode(source, valueNode:copy():remove 'unknown')
- else
- vm.setNode(source, valueNode)
- end
+ if not hasMarkDoc then
+ for _, src in ipairs(sources) do
+ if src.value and src.value.type ~= 'nil' then
+ local valueNode = vm.compileNode(src.value)
+ if valueNode:hasType 'unknown' then
+ vm.setNode(source, valueNode:copy():remove 'unknown')
+ else
+ vm.setNode(source, valueNode)
end
end
end
diff --git a/script/vm/type.lua b/script/vm/type.lua
index 3ad60dae..db378878 100644
--- a/script/vm/type.lua
+++ b/script/vm/type.lua
@@ -50,6 +50,11 @@ function vm.isSubType(uri, child, parent, mark)
return false
end
end
+ if child:isOptional() then
+ if not vm.isSubType(uri, 'nil', parent, mark) then
+ return false
+ end
+ end
return true
end
@@ -64,6 +69,11 @@ function vm.isSubType(uri, child, parent, mark)
return true
end
end
+ if parent:isOptional() then
+ if vm.isSubType(uri, child, 'nil', mark) then
+ return true
+ end
+ end
return false
end
diff --git a/test/diagnostics/common.lua b/test/diagnostics/common.lua
index f9e28941..704ac9e5 100644
--- a/test/diagnostics/common.lua
+++ b/test/diagnostics/common.lua
@@ -1007,7 +1007,7 @@ function mt2:method2() end
local v
---@type Bar
local v2
-v2 = v -- TODO 这里应该给警告
+<!v2!> = v
v2:<!method1!>()
v2:method2()
]]
@@ -1677,6 +1677,15 @@ x = nil
]]
TEST [[
+---@diagnostic disable: unused-local
+
+---@type string?
+local x
+
+x = nil
+]]
+
+TEST [[
---@diagnostic disable: unused-local, undefined-global
---@type integer
@@ -1738,3 +1747,51 @@ end
x = f()
]]
+
+
+TEST [[
+---@diagnostic disable: unused-local
+
+---@type boolean
+local x
+
+---@type integer
+local y
+
+<!x!> = y
+]]
+
+TEST [[
+---@diagnostic disable: unused-local
+
+---@class A
+---@field x integer
+local t
+
+<!t.x!> = true
+]]
+
+TEST [[
+---@diagnostic disable: unused-local
+
+---@class A
+---@field x integer
+local t
+
+---@type boolean
+local y
+
+<!t.x!> = y
+]]
+
+TEST [[
+---@diagnostic disable: unused-local
+
+---@class A
+---@field x integer
+local t
+
+t = {
+ <!x!> = true
+}
+]]