summaryrefslogtreecommitdiff
path: root/script/core
diff options
context:
space:
mode:
Diffstat (limited to 'script/core')
-rw-r--r--script/core/diagnostics/assign-type-mismatch.lua2
-rw-r--r--script/core/diagnostics/cast-field-type.lua70
-rw-r--r--script/core/diagnostics/cast-local-type.lua2
-rw-r--r--script/core/diagnostics/init.lua13
-rw-r--r--script/core/find-source.lua2
5 files changed, 80 insertions, 9 deletions
diff --git a/script/core/diagnostics/assign-type-mismatch.lua b/script/core/diagnostics/assign-type-mismatch.lua
index aae4cccb..89ae0a61 100644
--- a/script/core/diagnostics/assign-type-mismatch.lua
+++ b/script/core/diagnostics/assign-type-mismatch.lua
@@ -16,7 +16,7 @@ local checkTypes = {
---@async
return function (uri, callback)
- if not PREVIEW then
+ if not PREVIEW and not TEST then
return
end
local state = files.getState(uri)
diff --git a/script/core/diagnostics/cast-field-type.lua b/script/core/diagnostics/cast-field-type.lua
new file mode 100644
index 00000000..24299649
--- /dev/null
+++ b/script/core/diagnostics/cast-field-type.lua
@@ -0,0 +1,70 @@
+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
+
+ local fieldNodeCache = {}
+
+ local function getParentField(parent, key)
+ if parent.type == 'getlocal' then
+ parent = parent.node
+ end
+ if not fieldNodeCache[parent] then
+ fieldNodeCache[parent] = {}
+ end
+ if fieldNodeCache[parent][key] then
+ return fieldNodeCache[parent][key]
+ end
+ local fieldNode = vm.createNode()
+ fieldNodeCache[parent][key] = fieldNode
+ for _, class in ipairs(vm.getDefs(parent)) do
+ if class.type == 'doc.class' then
+ vm.getClassFields(uri, vm.getGlobal('type', class.class[1]), key, false, function (def)
+ if def.type == 'doc.field' then
+ fieldNode:merge(vm.compileNode(def))
+ end
+ end)
+ end
+ end
+ return fieldNode
+ end
+
+ ---@async
+ guide.eachSourceTypes(state.ast, { 'setfield', 'setindex', 'setmethod', 'tablefield', 'tableindex' }, function (ref)
+ await.delay()
+ if not ref.value then
+ return
+ end
+ local key = guide.getKeyName(ref)
+ if not key then
+ return nil
+ end
+ local parent = ref.node
+ local fieldNode = getParentField(parent, key)
+ if not fieldNode or fieldNode:isEmpty() then
+ return
+ end
+ if vm.canCastType(uri, fieldNode, vm.compileNode(ref.value)) then
+ return
+ end
+ callback {
+ start = ref.start,
+ finish = ref.finish,
+ message = lang.script('DIAG_CAST_LOCAL_TYPE', {
+ def = vm.getInfer(fieldNode):view(uri),
+ ref = vm.getInfer(ref.value):view(uri),
+ }),
+ }
+ end)
+end
diff --git a/script/core/diagnostics/cast-local-type.lua b/script/core/diagnostics/cast-local-type.lua
index 0a236084..dd3a37e8 100644
--- a/script/core/diagnostics/cast-local-type.lua
+++ b/script/core/diagnostics/cast-local-type.lua
@@ -6,7 +6,7 @@ local await = require 'await'
---@async
return function (uri, callback)
- if not PREVIEW then
+ if not PREVIEW and not TEST then
return
end
local state = files.getState(uri)
diff --git a/script/core/diagnostics/init.lua b/script/core/diagnostics/init.lua
index 746052b0..efd23bf4 100644
--- a/script/core/diagnostics/init.lua
+++ b/script/core/diagnostics/init.lua
@@ -8,12 +8,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,
- ['assign-type-mismatch'] = 106,
+ ['not-yieldable'] = 100,
+ ['deprecated'] = 100,
+ ['undefined-field'] = 110,
+ ['redundant-parameter'] = 110,
+ ['cast-local-type'] = 120,
+ ['cast-field-type'] = 120,
+ ['assign-type-mismatch'] = 120,
}
local diagList = {}
diff --git a/script/core/find-source.lua b/script/core/find-source.lua
index 26a411e5..99013b31 100644
--- a/script/core/find-source.lua
+++ b/script/core/find-source.lua
@@ -21,7 +21,7 @@ return function (ast, position, accept)
end
end
local start, finish = guide.getStartFinish(source)
- if finish - start < len and accept[source.type] then
+ if finish - start <= len and accept[source.type] then
result = source
len = finish - start
end