summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--script/core/diagnostics/inject-field.lua54
-rw-r--r--script/core/diagnostics/undefined-field.lua8
-rw-r--r--script/proto/diagnostic.lua1
-rw-r--r--test/diagnostics/init.lua1
-rw-r--r--test/diagnostics/inject-field.lua25
5 files changed, 81 insertions, 8 deletions
diff --git a/script/core/diagnostics/inject-field.lua b/script/core/diagnostics/inject-field.lua
new file mode 100644
index 00000000..62e1d1ca
--- /dev/null
+++ b/script/core/diagnostics/inject-field.lua
@@ -0,0 +1,54 @@
+local files = require 'files'
+local vm = require 'vm'
+local lang = require 'language'
+local guide = require 'parser.guide'
+local await = require 'await'
+
+local skipCheckClass = {
+ ['unknown'] = true,
+ ['any'] = true,
+ ['table'] = true,
+}
+
+---@async
+return function (uri, callback)
+ local ast = files.getState(uri)
+ if not ast then
+ return
+ end
+
+ ---@async
+ local function checkInjectField(src)
+ await.delay()
+
+ local node = src.node
+ if node then
+ local ok
+ for view in vm.getInfer(node):eachView(uri) do
+ if skipCheckClass[view] then
+ return
+ end
+ ok = true
+ end
+ if not ok then
+ return
+ end
+ end
+ local message = lang.script('DIAG_INJECT_FIELD', guide.getKeyName(src))
+ if src.type == 'setfield' and src.field then
+ callback {
+ start = src.field.start,
+ finish = src.field.finish,
+ message = message,
+ }
+ elseif src.type == 'setfield' and src.method then
+ callback {
+ start = src.method.start,
+ finish = src.method.finish,
+ message = message,
+ }
+ end
+ end
+ guide.eachSourceType(ast.ast, 'setfield', checkInjectField)
+ guide.eachSourceType(ast.ast, 'setmethod', checkInjectField)
+end
diff --git a/script/core/diagnostics/undefined-field.lua b/script/core/diagnostics/undefined-field.lua
index a83241f5..4fd55966 100644
--- a/script/core/diagnostics/undefined-field.lua
+++ b/script/core/diagnostics/undefined-field.lua
@@ -8,13 +8,6 @@ local skipCheckClass = {
['unknown'] = true,
['any'] = true,
['table'] = true,
- ['nil'] = true,
- ['number'] = true,
- ['integer'] = true,
- ['boolean'] = true,
- ['function'] = true,
- ['userdata'] = true,
- ['lightuserdata'] = true,
}
---@async
@@ -61,5 +54,4 @@ return function (uri, callback)
end
guide.eachSourceType(ast.ast, 'getfield', checkUndefinedField)
guide.eachSourceType(ast.ast, 'getmethod', checkUndefinedField)
- guide.eachSourceType(ast.ast, 'getindex', checkUndefinedField)
end
diff --git a/script/proto/diagnostic.lua b/script/proto/diagnostic.lua
index 9c095531..61b8ff4b 100644
--- a/script/proto/diagnostic.lua
+++ b/script/proto/diagnostic.lua
@@ -77,6 +77,7 @@ m.register {
'param-type-mismatch',
'cast-type-mismatch',
'return-type-mismatch',
+ 'inject-field',
} {
group = 'type-check',
severity = 'Warning',
diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua
index cd6a5c03..99a5dc24 100644
--- a/test/diagnostics/init.lua
+++ b/test/diagnostics/init.lua
@@ -90,6 +90,7 @@ check 'empty-block'
check 'global-element'
check 'global-in-nil-env'
check 'incomplete-signature-doc'
+check 'inject-field'
check 'invisible'
check 'lowercase-global'
check 'missing-fields'
diff --git a/test/diagnostics/inject-field.lua b/test/diagnostics/inject-field.lua
new file mode 100644
index 00000000..8e2273b5
--- /dev/null
+++ b/test/diagnostics/inject-field.lua
@@ -0,0 +1,25 @@
+TEST [[
+---@class Class
+local m = {}
+
+m.xx = 1 -- OK
+
+---@type Class
+local m
+
+m.xx = 1 -- OK
+m.<!yy!> = 1 -- Warning
+]]
+
+TEST [[
+---@class Class
+local m = {}
+
+m.xx = 1 -- OK
+
+---@class Class
+local m
+
+m.xx = 1 -- OK
+m.yy = 1 -- OK
+]]