diff options
-rw-r--r-- | script/core/diagnostics/assign-type-mismatch.lua | 47 | ||||
-rw-r--r-- | script/core/diagnostics/init.lua | 13 | ||||
-rw-r--r-- | script/core/diagnostics/type-check-assign.lua | 20 | ||||
-rw-r--r-- | script/proto/define.lua | 4 | ||||
-rw-r--r-- | script/vm/compiler.lua | 18 | ||||
-rw-r--r-- | script/vm/type.lua | 10 | ||||
-rw-r--r-- | test/diagnostics/common.lua | 59 |
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 +} +]] |