summaryrefslogtreecommitdiff
path: root/test/diagnostics
diff options
context:
space:
mode:
Diffstat (limited to 'test/diagnostics')
-rw-r--r--test/diagnostics/await-in-sync.lua181
-rw-r--r--test/diagnostics/circle-doc-class.lua14
-rw-r--r--test/diagnostics/common.lua977
-rw-r--r--test/diagnostics/count-down-loop.lua29
-rw-r--r--test/diagnostics/deprecated.lua18
-rw-r--r--test/diagnostics/discard-returns.lua17
-rw-r--r--test/diagnostics/doc-field-no-class.lua16
-rw-r--r--test/diagnostics/duplicate-doc-alias.lua10
-rw-r--r--test/diagnostics/duplicate-doc-field.lua22
-rw-r--r--test/diagnostics/duplicate-doc-param.lua12
-rw-r--r--test/diagnostics/duplicate-index.lua7
-rw-r--r--test/diagnostics/duplicate-set-field.lua43
-rw-r--r--test/diagnostics/init.lua12
-rw-r--r--test/diagnostics/lowercase-global.lua33
-rw-r--r--test/diagnostics/need-check-nil.lua62
-rw-r--r--test/diagnostics/redundant-parameter.lua66
-rw-r--r--test/diagnostics/redundant-return.lua34
-rw-r--r--test/diagnostics/unbalanced-assignments.lua34
-rw-r--r--test/diagnostics/undefined-doc-class.lua23
-rw-r--r--test/diagnostics/undefined-doc-param.lua21
-rw-r--r--test/diagnostics/undefined-field.lua132
-rw-r--r--test/diagnostics/undefined-global.lua5
-rw-r--r--test/diagnostics/unknown-diag-code.lua3
23 files changed, 793 insertions, 978 deletions
diff --git a/test/diagnostics/await-in-sync.lua b/test/diagnostics/await-in-sync.lua
new file mode 100644
index 00000000..277101dd
--- /dev/null
+++ b/test/diagnostics/await-in-sync.lua
@@ -0,0 +1,181 @@
+TEST [[
+function F()
+ <!coroutine.yield!>()
+end
+]]
+
+TEST [[
+---@async
+function F()
+ coroutine.yield()
+end
+]]
+
+TEST [[
+---@type async fun()
+local f
+
+function F()
+ <!f!>()
+end
+]]
+
+TEST [[
+---@type async fun()
+local f
+
+---@async
+function F()
+ f()
+end
+]]
+
+TEST [[
+local function f(cb)
+ cb()
+end
+
+return function()
+ <!f>(function () ---@async
+ return nil
+ end)
+end
+]]
+
+TEST [[
+local function f(cb)
+ pcall(cb)
+end
+
+return function()
+ <!f!>(function () ---@async
+ return nil
+ end)
+end
+]]
+
+TEST [[
+---@param c any
+local function f(c)
+ return c
+end
+
+return function ()
+ f(function () ---@async
+ return nil
+ end)
+end
+]]
+
+TEST [[
+---@param ... any
+local function f(...)
+ return ...
+end
+
+return function ()
+ f(function () ---@async
+ return nil
+ end)
+end
+]]
+
+TEST [[
+---@vararg any
+local function f(...)
+ return ...
+end
+
+return function ()
+ f(function () ---@async
+ return nil
+ end)
+end
+]]
+
+TEST [[
+local function f(...)
+ return ...
+end
+
+return function ()
+ f(function () ---@async
+ return nil
+ end)
+end
+]]
+
+TEST [[
+local function f(...)
+ return ...
+end
+
+return function ()
+ f(function () ---@async
+ return nil
+ end)
+end
+]]
+
+TEST [[
+---@param cb fun()
+local function f(cb)
+ return cb
+end
+
+---@async
+local function af()
+ return nil
+end
+
+f(<!af!>)
+]]
+
+TEST [[
+---@param cb async fun()
+local function f(cb)
+ return cb
+end
+
+---@async
+local function af()
+ return nil
+end
+
+f(af)
+]]
+
+TEST [[
+local function f(cb)
+ cb()
+end
+
+local function af()
+ <!f!>(function () ---@async
+ return nil
+ end)
+end
+
+return af
+]]
+
+TEST [[
+local function f(cb)
+ cb()
+end
+
+---@async
+local function af()
+ f(function () ---@async
+ return nil
+ end)
+end
+
+return af
+]]
+
+TEST [[
+local _ = type(function () ---@async
+ return nil
+end)
+]]
diff --git a/test/diagnostics/circle-doc-class.lua b/test/diagnostics/circle-doc-class.lua
new file mode 100644
index 00000000..089b0c9b
--- /dev/null
+++ b/test/diagnostics/circle-doc-class.lua
@@ -0,0 +1,14 @@
+TEST [[
+---@class <!A : B!>
+---@class <!B : C!>
+---@class <!C : D!>
+---@class <!D : A!>
+]]
+
+TEST [[
+---@class A : B
+---@class B : C
+---@class C : D
+---@class D
+]]
+
diff --git a/test/diagnostics/common.lua b/test/diagnostics/common.lua
index 24ec4c8c..9352765f 100644
--- a/test/diagnostics/common.lua
+++ b/test/diagnostics/common.lua
@@ -1,982 +1,5 @@
-local config = require 'config'
-local util = require 'utility'
-
-
-
-
-
-
-TEST [[
-local x, <!y!>, <!z!> = 1
-print(x, y, z)
-]]
-
-TEST [[
-local x, y, <!z!> = 1, 2
-print(x, y, z)
-]]
-
-TEST [[
-local x, y, z = print()
-print(x, y, z)
-]]
-
-TEST [[
-local x, y, z
-print(x, y, z)
-]]
-
-TEST [[
-local x, y, z
-x, <!y!>, <!z!> = 1
-print(x, y, z)
-]]
-
-TEST [[
-X, <!Y!>, <!Z!> = 1
-]]
-
-TEST [[
-T = {}
-T.x, <!T.y!>, <!T.z!> = 1
-]]
-
-TEST [[
-T = {}
-T['x'], <!T['y']!>, <!T['z']!> = 1
-]]
-
---TEST [[
------@class <!Class!>
------@class <!Class!>
---]]
-
-TEST [[
----@alias <!A!> integer
----@alias <!A!> integer
-]]
-
-TEST [[
----@class A : <!B!>
-]]
-
-TEST [[
----@class <!A : B!>
----@class <!B : C!>
----@class <!C : D!>
----@class <!D : A!>
-]]
-
-TEST [[
----@class A : B
----@class B : C
----@class C : D
----@class D
-]]
-
-TEST [[
----@type <!A!>
-]]
-
-TEST [[
----@class A
----@type A|<!B!>|<!C!>
-]]
-
-TEST [[
----@class AAA
----@alias B AAA
-
----@type B
-]]
-
-TEST [[
----@alias B <!AAA!>
-]]
-
-TEST [[
----@class A
----@class B
----@alias <!A!> B
-]]
-
-TEST [[
----@param <!x!> <!Class!>
-]]
-
-TEST [[
----@class Class
----@param <!y!> Class
-local function f(x)
- return x
-end
-f()
-]]
-
-TEST [[
----@class Class
----@param <!y!> Class
-function F(x)
- return x
-end
-F()
-]]
-
-TEST [[
----@class Class
----@param <!x!> Class
----@param y Class
----@param <!x!> Class
-local function f(x, y)
- return x, y
-end
-
-local _
-f(_, _)
-]]
-
-TEST [[
----@field <!x Class!>
----@class Class
-]]
-
-TEST [[
----@class Class
-
----@field <!x Class!>
-]]
-
-TEST [[
----@class Class
----
----@field x Class
-]]
-
-TEST [[
----@class Class
----@field <!x!> Class
----@field <!x!> Class
-]]
-
-TEST [[
----@class Class : any
-]]
-
-TEST [[
----@type fun(a: integer)
-local f
-f(1)
-]]
-
-TEST [[
----@class c
-c = {}
-]]
-
-TEST [[
----@generic T: any
----@param v T
----@param message any
----@return T
----@return any message
-function assert(v, message)
- return v, message
-end
-]]
-
-TEST [[
----@type string
----|
-]]
-
-TEST [[
----@type
----| 'xx'
-]]
-
-TEST [[
----@class class
-local t
-]]
----[==[
--- checkUndefinedField 通用
-TEST [[
----@class Foo
----@field field1 integer
-local mt = {}
-function mt:Constructor()
- self.field2 = 1
-end
-function mt:method1() return 1 end
-function mt.method2() return 2 end
-
----@class Bar: Foo
----@field field4 integer
-local mt2 = {}
-
----@type Foo
-local v
-print(v.field1 + 1)
-print(v.field2 + 1)
-print(v.<!field3!> + 1)
-print(v:method1())
-print(v.method2())
-print(v:<!method3!>())
-
----@type Bar
-local v2
-print(v2.field1 + 1)
-print(v2.field2 + 1)
-print(v2.<!field3!> + 1)
-print(v2.field4 + 1)
-print(v2:method1())
-print(v2.method2())
-print(v2:<!method3!>())
-
-local v3 = {}
-print(v3.abc)
-
----@class Bar2
-local mt3
-function mt3:method() return 1 end
-print(mt3:method())
-]]
-
--- checkUndefinedField 通过type找到class
-TEST [[
----@class Foo
-local Foo
-function Foo:method1() end
-
----@type Foo
-local v
-v:method1()
-v:<!method2!>() -- doc.class.name
-]]
-
--- checkUndefinedField 通过type找到class,涉及到 class 继承版
-TEST [[
----@class Foo
-local Foo
-function Foo:method1() end
----@class Bar: Foo
-local Bar
-function Bar:method3() end
-
----@type Bar
-local v
-v:method1()
-v:<!method2!>() -- doc.class.name
-v:method3()
-]]
-
--- checkUndefinedField 类名和类变量同名,类变量被直接使用
-TEST [[
----@class Foo
-local Foo
-function Foo:method1() end
-Foo:<!method2!>() -- doc.class
-Foo:<!method2!>() -- doc.class
-]]
-
--- checkUndefinedField 没有@class的不检测
-TEST [[
-local Foo
-function Foo:method1()
- return Foo:method2() -- table
-end
-]]
-
--- checkUndefinedField 类名和类变量不同名,类变量被直接使用、使用self
-TEST [[
----@class Foo
-local mt
-function mt:method1()
- mt.<!method2!>() -- doc.class
- self:method1()
- return self.<!method2!>() -- doc.class.name
-end
-]]
-
--- checkUndefinedField 当会推导成多个class类型时
-TEST [[
----@class Foo
-local mt
-function mt:method1() end
-
----@class Bar
-local mt2
-function mt2:method2() end
-
----@type Foo
-local v
----@type Bar
-local v2
-<!v2!> = v
-v2:method1()
-v2:<!method2!>()
-]]
-
-TEST [[
----@type table
-T1 = {}
-print(T1.f1)
----@type tablelib
-T2 = {}
-print(T2.<!f2!>)
-]]
---]==]
-TEST [[
----@overload fun(...)
-local function f() end
-
-f(1)
-]]
-
-TEST [[
-for i = <!10, 1!> do
- print(i)
-end
-]]
-
-TEST [[
-for i = <!10, 1, 5!> do
- print(i)
-end
-]]
-
-TEST [[
-for i = <!100, 10, 1!> do
- print(i)
-end
-]]
-
-TEST [[
-for i = <!1, -10!> do
- print(i)
-end
-]]
-
-TEST [[
-for i = 1, 1 do
- print(i)
-end
-]]
-
-TEST [[
-local m = {}
-
-function <!m:fff!>()
-end
-
-function <!m:fff!>()
-end
-
-return m
-]]
-
-TEST [[
-local m = {}
-
-function <!m:fff!>()
-end
-
-do
- function <!m:fff!>()
- end
-end
-
-return m
-]]
-
-TEST [[
-local m = {}
-
-m.x = true
-m.x = false
-
-return m
-]]
-
-TEST [[
-local m = {}
-
-m.x = io.open('')
-m.x = nil
-
-return m
-]]
-
-TEST [[
----@meta
-
----@class A
----@field a boolean
-
----@return A
-local function f() end
-
-local r = f()
-r.x = 1
-
-return r.x
-]]
-
-TEST [[
----@diagnostic disable-next-line
-x = 1
-]]
-
-TEST [[
----@diagnostic disable-next-line: lowercase-global
-x = 1
-]]
-
-TEST [[
----@diagnostic disable-next-line: unused-local
-<!x!> = 1
-]]
-
-TEST [[
----@diagnostic disable
-x = 1
-]]
-
-TEST [[
----@diagnostic disable
----@diagnostic enable
-<!x!> = 1
-]]
-
-TEST [[
----@diagnostic disable
----@diagnostic disable
----@diagnostic enable
-x = 1
-]]
-
-TEST [[
----@diagnostic disable-next-line: <!xxx!>
-]]
-
-TEST [[
-local mt = {}
-
-function mt:a(x)
- return self, x
-end
-
-function mt:b(y)
- self:a(1):b(2)
- return y
-end
-
-return mt
-]]
-
-TEST [[
-local function each()
- return function ()
- end
-end
-
-for x in each() do
- print(x)
-end
-]]
-
-TEST [[
----@type string
-local s
-
-print(s:upper())
-]]
-
-TEST [[
-local t = ().
-return t
-]]
-
-TEST [[
-return {
- [1] = 1,
- ['1'] = 1,
-}
-]]
-
-TEST [[
-return {
- [print()] = 1,
- [print()] = 1,
-}
-]]
-
-TEST [[
----@type { x: number, y: number}
----| "'resume'"
-]]
-
-TEST [[
-return {
- 1, <!2!>, 3,
- [<!2!>] = 4,
-}
-]]
-
-TEST [[
---- @class Emit
---- @field on fun(eventName: string, cb: function)
---- @field on fun(eventName: '"died"', cb: fun(i: integer))
---- @field on fun(eventName: '"won"', cb: fun(s: string))
-local emit = {}
-]]
-
-TEST [[
---- @class Emit
---- @field on fun(eventName: string, cb: function)
---- @field <!on!> fun(eventName: '"died"', cb: fun(i: integer))
---- @field on fun(eventName: '"won"', cb: fun(s: string))
---- @field <!on!> fun(eventName: '"died"', cb: fun(i: integer))
-local emit = {}
-]]
-
--- redundant-return
-TEST [[
-local function f()
- <!return!>
-end
-f()
-]]
-
-TEST [[
-local function f()
- return nil
-end
-f()
-]]
-
-TEST [[
-local function f()
- local function x()
- <!return!>
- end
- x()
- return true
-end
-f()
-]]
-
-TEST [[
-local function f()
- local function x()
- return true
- end
- return x()
-end
-f()
-]]
-
-TEST [[
----@type file*
-local f
-local _ = f:read '*a'
-local _ = f:read('*a')
-]]
-
-TEST [[
-function F()
- <!coroutine.yield!>()
-end
-]]
-
-TEST [[
----@async
-function F()
- coroutine.yield()
-end
-]]
-
-TEST [[
----@type async fun()
-local f
-
-function F()
- <!f!>()
-end
-]]
-
-TEST [[
----@type async fun()
-local f
-
----@async
-function F()
- f()
-end
-]]
-
-TEST [[
-local function f(cb)
- cb()
-end
-
-return function()
- <!f>(function () ---@async
- return nil
- end)
-end
-]]
-
-TEST [[
-local function f(cb)
- pcall(cb)
-end
-
-return function()
- <!f!>(function () ---@async
- return nil
- end)
-end
-]]
-
-TEST [[
----@param c any
-local function f(c)
- return c
-end
-
-return function ()
- f(function () ---@async
- return nil
- end)
-end
-]]
-
-TEST [[
----@param ... any
-local function f(...)
- return ...
-end
-
-return function ()
- f(function () ---@async
- return nil
- end)
-end
-]]
-
-TEST [[
----@vararg any
-local function f(...)
- return ...
-end
-
-return function ()
- f(function () ---@async
- return nil
- end)
-end
-]]
-
-TEST [[
-local function f(...)
- return ...
-end
-
-return function ()
- f(function () ---@async
- return nil
- end)
-end
-]]
-
-TEST [[
-local function f(...)
- return ...
-end
-
-return function ()
- f(function () ---@async
- return nil
- end)
-end
-]]
-
-TEST [[
----@nodiscard
-local function f()
- return 1
-end
-
-<!f()!>
-]]
-
-TEST [[
----@nodiscard
-local function f()
- return 1
-end
-
-X = f()
-]]
-
-config.get(nil, 'Lua.diagnostics.neededFileStatus')['not-yieldable'] = 'Any'
-TEST [[
----@param cb fun()
-local function f(cb)
- return cb
-end
-
----@async
-local function af()
- return nil
-end
-
-f(<!af!>)
-]]
-
-TEST [[
----@param cb async fun()
-local function f(cb)
- return cb
-end
-
----@async
-local function af()
- return nil
-end
-
-f(af)
-]]
-
-TEST [[
-local function f(cb)
- cb()
-end
-
-local function af()
- <!f!>(function () ---@async
- return nil
- end)
-end
-
-return af
-]]
-
-TEST [[
-local function f(cb)
- cb()
-end
-
----@async
-local function af()
- f(function () ---@async
- return nil
- end)
-end
-
-return af
-]]
-
-TEST [[
-local _ = type(function () ---@async
- return nil
-end)
-]]
-
-TEST [[
----@param ... number
-local function f(...)
- return ...
-end
-
-return f
-]]
-
-TEST [[
----@type fun(...: string)
-]]
-
-TEST [[
----@type fun(xxx, yyy, ...): boolean
-]]
-
-TEST [[
-local <!x!>
-
-return {
- x = 1,
-}
-]]
-
-TEST [[
----@class A #1
-]]
-
-TEST [[
----@class A 1
-]]
-
-TEST [[
-return ('1'):upper()
-]]
-
-TEST [[
-local value
-value = '1'
-value = value:upper()
-]]
-
-TEST [[
-T = {}
----@deprecated # comment
-T.x = 1
-
-print(<!T.x!>)
-]]
-
-TEST [[
-T = {}
-
----@deprecated
-function T:ff()
-end
-
-<!T:ff!>()
-]]
-
-TEST [[
----@type string?
-local x
-
-S = <!x!>:upper()
-]]
-
-TEST [[
----@type string?
-local x
-
-if x then
- S = x:upper()
-end
-]]
-
-TEST [[
----@type string?
-local x
-
-if not x then
- x = ''
-end
-
-S = x:upper()
-]]
-
-TEST [[
----@type fun()?
-local x
-
-S = <!x!>()
-]]
-
-TEST [[
----@type integer?
-local x
-
-T = {}
-T[<!x!>] = 1
-]]
-
-TEST [[
-local x, y
-local z = x and y
-
-print(z.y)
-]]
-
-TEST [[
-local x, y
-function x()
- y()
-end
-
-function y()
- x()
-end
-
-x()
-]]
-
-TEST [[
----@meta
-
----@param x fun()
-local function f1(x)
-end
-
----@return fun()
-local function f2()
-end
-
-f1(f2())
-]]
-
-TEST [[
----@meta
-
----@type fun():integer
-local f
-
----@param x integer
-local function foo(x) end
-
-foo(f())
-]]
-
-TEST [[
----@type string|table
-local n
-
-print(n.x)
-]]
-
-TEST [[
----@diagnostic disable: unused-local, unused-function, undefined-global
-
-function F() end
-
----@param x boolean
-function F(x) end
-
-F(k())
-]]
-
-TEST [[
-local function f()
- return 1, 2, 3
-end
-
-local function k()
-end
-
-k(<!f()!>)
-]]
-
-TEST [[
----@diagnostic disable: unused-local
-local function f()
- return 1, 2, 3
-end
-
----@param x integer
-local function k(x)
-end
-
-k(f())
-]]
-
TEST [[
---@cast <!x!> integer
]]
diff --git a/test/diagnostics/count-down-loop.lua b/test/diagnostics/count-down-loop.lua
new file mode 100644
index 00000000..f4e385f5
--- /dev/null
+++ b/test/diagnostics/count-down-loop.lua
@@ -0,0 +1,29 @@
+TEST [[
+for i = <!10, 1!> do
+ print(i)
+end
+]]
+
+TEST [[
+for i = <!10, 1, 5!> do
+ print(i)
+end
+]]
+
+TEST [[
+for i = <!100, 10, 1!> do
+ print(i)
+end
+]]
+
+TEST [[
+for i = <!1, -10!> do
+ print(i)
+end
+]]
+
+TEST [[
+for i = 1, 1 do
+ print(i)
+end
+]]
diff --git a/test/diagnostics/deprecated.lua b/test/diagnostics/deprecated.lua
index 1086ecb2..c5486752 100644
--- a/test/diagnostics/deprecated.lua
+++ b/test/diagnostics/deprecated.lua
@@ -1,3 +1,21 @@
TEST [[
local _ = <!unpack!>
]]
+
+TEST [[
+T = {}
+---@deprecated # comment
+T.x = 1
+
+print(<!T.x!>)
+]]
+
+TEST [[
+T = {}
+
+---@deprecated
+function T:ff()
+end
+
+<!T:ff!>()
+]]
diff --git a/test/diagnostics/discard-returns.lua b/test/diagnostics/discard-returns.lua
new file mode 100644
index 00000000..2e348390
--- /dev/null
+++ b/test/diagnostics/discard-returns.lua
@@ -0,0 +1,17 @@
+TEST [[
+---@nodiscard
+local function f()
+ return 1
+end
+
+<!f()!>
+]]
+
+TEST [[
+---@nodiscard
+local function f()
+ return 1
+end
+
+X = f()
+]]
diff --git a/test/diagnostics/doc-field-no-class.lua b/test/diagnostics/doc-field-no-class.lua
new file mode 100644
index 00000000..87db518c
--- /dev/null
+++ b/test/diagnostics/doc-field-no-class.lua
@@ -0,0 +1,16 @@
+TEST [[
+---@field <!x Class!>
+---@class Class
+]]
+
+TEST [[
+---@class Class
+
+---@field <!x Class!>
+]]
+
+TEST [[
+---@class Class
+---
+---@field x Class
+]]
diff --git a/test/diagnostics/duplicate-doc-alias.lua b/test/diagnostics/duplicate-doc-alias.lua
new file mode 100644
index 00000000..0373fee9
--- /dev/null
+++ b/test/diagnostics/duplicate-doc-alias.lua
@@ -0,0 +1,10 @@
+TEST [[
+---@alias <!A!> integer
+---@alias <!A!> integer
+]]
+
+TEST [[
+---@class A
+---@class B
+---@alias <!A!> B
+]]
diff --git a/test/diagnostics/duplicate-doc-field.lua b/test/diagnostics/duplicate-doc-field.lua
index e69de29b..937e2ea4 100644
--- a/test/diagnostics/duplicate-doc-field.lua
+++ b/test/diagnostics/duplicate-doc-field.lua
@@ -0,0 +1,22 @@
+TEST [[
+---@class Class
+---@field <!x!> Class
+---@field <!x!> Class
+]]
+
+TEST [[
+--- @class Emit
+--- @field on fun(eventName: string, cb: function)
+--- @field on fun(eventName: '"died"', cb: fun(i: integer))
+--- @field on fun(eventName: '"won"', cb: fun(s: string))
+local emit = {}
+]]
+
+TEST [[
+--- @class Emit
+--- @field on fun(eventName: string, cb: function)
+--- @field <!on!> fun(eventName: '"died"', cb: fun(i: integer))
+--- @field on fun(eventName: '"won"', cb: fun(s: string))
+--- @field <!on!> fun(eventName: '"died"', cb: fun(i: integer))
+local emit = {}
+]]
diff --git a/test/diagnostics/duplicate-doc-param.lua b/test/diagnostics/duplicate-doc-param.lua
new file mode 100644
index 00000000..42eb73d3
--- /dev/null
+++ b/test/diagnostics/duplicate-doc-param.lua
@@ -0,0 +1,12 @@
+TEST [[
+---@class Class
+---@param <!x!> Class
+---@param y Class
+---@param <!x!> Class
+local function f(x, y)
+ return x, y
+end
+
+local _
+f(_, _)
+]]
diff --git a/test/diagnostics/duplicate-index.lua b/test/diagnostics/duplicate-index.lua
index feb5381d..3289c736 100644
--- a/test/diagnostics/duplicate-index.lua
+++ b/test/diagnostics/duplicate-index.lua
@@ -15,3 +15,10 @@ return {
y = 2,
}
]]
+
+TEST [[
+return {
+ 1, <!2!>, 3,
+ [<!2!>] = 4,
+}
+]]
diff --git a/test/diagnostics/duplicate-set-field.lua b/test/diagnostics/duplicate-set-field.lua
new file mode 100644
index 00000000..52f70c9d
--- /dev/null
+++ b/test/diagnostics/duplicate-set-field.lua
@@ -0,0 +1,43 @@
+TEST [[
+local m = {}
+
+function <!m:fff!>()
+end
+
+function <!m:fff!>()
+end
+
+return m
+]]
+
+TEST [[
+local m = {}
+
+function <!m:fff!>()
+end
+
+do
+ function <!m:fff!>()
+ end
+end
+
+return m
+]]
+
+TEST [[
+local m = {}
+
+m.x = true
+m.x = false
+
+return m
+]]
+
+TEST [[
+local m = {}
+
+m.x = io.open('')
+m.x = nil
+
+return m
+]]
diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua
index 3fb90f39..d1acd31e 100644
--- a/test/diagnostics/init.lua
+++ b/test/diagnostics/init.lua
@@ -100,6 +100,16 @@ check 'deprecated'
check 'duplicate-index'
check 'empty-block'
check 'redundant-value'
-check 'code-after-block'
+check 'code-after-break'
+check 'duplicate-doc-alias'
+check 'circle-doc-class'
+check 'undefined-doc-param'
+check 'duplicate-doc-param'
+check 'doc-field-no-class'
+check 'undefined-field'
+check 'count-down-loop'
+check 'duplicate-set-field'
+check 'redundant-return'
+check 'discard-returns'
require 'diagnostics.common'
diff --git a/test/diagnostics/lowercase-global.lua b/test/diagnostics/lowercase-global.lua
index 5e1d70a9..bf73b8c8 100644
--- a/test/diagnostics/lowercase-global.lua
+++ b/test/diagnostics/lowercase-global.lua
@@ -4,3 +4,36 @@ tostring = 1
ROOT = 1
_G.bb = 1
]]
+
+TEST [[
+---@diagnostic disable-next-line
+x = 1
+]]
+
+TEST [[
+---@diagnostic disable-next-line: lowercase-global
+x = 1
+]]
+
+TEST [[
+---@diagnostic disable-next-line: unused-local
+<!x!> = 1
+]]
+
+TEST [[
+---@diagnostic disable
+x = 1
+]]
+
+TEST [[
+---@diagnostic disable
+---@diagnostic enable
+<!x!> = 1
+]]
+
+TEST [[
+---@diagnostic disable
+---@diagnostic disable
+---@diagnostic enable
+x = 1
+]]
diff --git a/test/diagnostics/need-check-nil.lua b/test/diagnostics/need-check-nil.lua
index 246fc655..c4e3bba6 100644
--- a/test/diagnostics/need-check-nil.lua
+++ b/test/diagnostics/need-check-nil.lua
@@ -4,3 +4,65 @@ local x
local s = <!x!>:upper()
]]
+
+TEST [[
+---@type string?
+local x
+
+S = <!x!>:upper()
+]]
+
+TEST [[
+---@type string?
+local x
+
+if x then
+ S = x:upper()
+end
+]]
+
+TEST [[
+---@type string?
+local x
+
+if not x then
+ x = ''
+end
+
+S = x:upper()
+]]
+
+TEST [[
+---@type fun()?
+local x
+
+S = <!x!>()
+]]
+
+TEST [[
+---@type integer?
+local x
+
+T = {}
+T[<!x!>] = 1
+]]
+
+TEST [[
+local x, y
+local z = x and y
+
+print(z.y)
+]]
+
+TEST [[
+local x, y
+function x()
+ y()
+end
+
+function y()
+ x()
+end
+
+x()
+]]
diff --git a/test/diagnostics/redundant-parameter.lua b/test/diagnostics/redundant-parameter.lua
index cd9d7a43..3bbb50f6 100644
--- a/test/diagnostics/redundant-parameter.lua
+++ b/test/diagnostics/redundant-parameter.lua
@@ -133,3 +133,69 @@ m.open(m)
TEST [[
table.insert({}, 1, 2, <!3!>)
]]
+
+TEST [[
+---@overload fun(...)
+local function f() end
+
+f(1)
+]]
+
+TEST [[
+function F() end
+
+---@param x boolean
+function F(x) end
+
+F(k())
+]]
+
+TEST [[
+local function f()
+ return 1, 2, 3
+end
+
+local function k()
+end
+
+k(<!f()!>)
+]]
+
+TEST [[
+---@diagnostic disable: unused-local
+local function f()
+ return 1, 2, 3
+end
+
+---@param x integer
+local function k(x)
+end
+
+k(f())
+]]
+
+TEST [[
+---@meta
+
+---@param x fun()
+local function f1(x)
+end
+
+---@return fun()
+local function f2()
+end
+
+f1(f2())
+]]
+
+TEST [[
+---@meta
+
+---@type fun():integer
+local f
+
+---@param x integer
+local function foo(x) end
+
+foo(f())
+]]
diff --git a/test/diagnostics/redundant-return.lua b/test/diagnostics/redundant-return.lua
new file mode 100644
index 00000000..11214aab
--- /dev/null
+++ b/test/diagnostics/redundant-return.lua
@@ -0,0 +1,34 @@
+TEST [[
+local function f()
+ <!return!>
+end
+f()
+]]
+
+TEST [[
+local function f()
+ return nil
+end
+f()
+]]
+
+TEST [[
+local function f()
+ local function x()
+ <!return!>
+ end
+ x()
+ return true
+end
+f()
+]]
+
+TEST [[
+local function f()
+ local function x()
+ return true
+ end
+ return x()
+end
+f()
+]]
diff --git a/test/diagnostics/unbalanced-assignments.lua b/test/diagnostics/unbalanced-assignments.lua
new file mode 100644
index 00000000..a0d47f56
--- /dev/null
+++ b/test/diagnostics/unbalanced-assignments.lua
@@ -0,0 +1,34 @@
+TEST [[
+local x, <!y!>, <!z!> = 1
+]]
+
+TEST [[
+local x, y, <!z!> = 1, 2
+]]
+
+TEST [[
+local x, y, z = print()
+]]
+
+TEST [[
+local x, y, z
+]]
+
+TEST [[
+local x, y, z
+x, <!y!>, <!z!> = 1
+]]
+
+TEST [[
+X, <!Y!>, <!Z!> = 1
+]]
+
+TEST [[
+T = {}
+T.x, <!T.y!>, <!T.z!> = 1
+]]
+
+TEST [[
+T = {}
+T['x'], <!T['y']!>, <!T['z']!> = 1
+]]
diff --git a/test/diagnostics/undefined-doc-class.lua b/test/diagnostics/undefined-doc-class.lua
new file mode 100644
index 00000000..6b7acfd1
--- /dev/null
+++ b/test/diagnostics/undefined-doc-class.lua
@@ -0,0 +1,23 @@
+TEST [[
+---@class A : <!B!>
+]]
+
+TEST [[
+---@type <!A!>
+]]
+
+TEST [[
+---@class A
+---@type A|<!B!>|<!C!>
+]]
+
+TEST [[
+---@class AAA
+---@alias B AAA
+
+---@type B
+]]
+
+TEST [[
+---@alias B <!AAA!>
+]]
diff --git a/test/diagnostics/undefined-doc-param.lua b/test/diagnostics/undefined-doc-param.lua
new file mode 100644
index 00000000..7bfbafa5
--- /dev/null
+++ b/test/diagnostics/undefined-doc-param.lua
@@ -0,0 +1,21 @@
+TEST [[
+---@param <!x!> Class
+]]
+
+TEST [[
+---@class Class
+---@param <!y!> Class
+local function f(x)
+ return x
+end
+f()
+]]
+
+TEST [[
+---@class Class
+---@param <!y!> Class
+function F(x)
+ return x
+end
+F()
+]]
diff --git a/test/diagnostics/undefined-field.lua b/test/diagnostics/undefined-field.lua
new file mode 100644
index 00000000..4bca5195
--- /dev/null
+++ b/test/diagnostics/undefined-field.lua
@@ -0,0 +1,132 @@
+TEST [[
+---@class Foo
+---@field field1 integer
+local mt = {}
+function mt:Constructor()
+ self.field2 = 1
+end
+function mt:method1() return 1 end
+function mt.method2() return 2 end
+
+---@class Bar: Foo
+---@field field4 integer
+local mt2 = {}
+
+---@type Foo
+local v
+print(v.field1 + 1)
+print(v.field2 + 1)
+print(v.<!field3!> + 1)
+print(v:method1())
+print(v.method2())
+print(v:<!method3!>())
+
+---@type Bar
+local v2
+print(v2.field1 + 1)
+print(v2.field2 + 1)
+print(v2.<!field3!> + 1)
+print(v2.field4 + 1)
+print(v2:method1())
+print(v2.method2())
+print(v2:<!method3!>())
+
+local v3 = {}
+print(v3.abc)
+
+---@class Bar2
+local mt3
+function mt3:method() return 1 end
+print(mt3:method())
+]]
+
+-- checkUndefinedField 通过type找到class
+TEST [[
+---@class Foo
+local Foo
+function Foo:method1() end
+
+---@type Foo
+local v
+v:method1()
+v:<!method2!>() -- doc.class.name
+]]
+
+-- checkUndefinedField 通过type找到class,涉及到 class 继承版
+TEST [[
+---@class Foo
+local Foo
+function Foo:method1() end
+---@class Bar: Foo
+local Bar
+function Bar:method3() end
+
+---@type Bar
+local v
+v:method1()
+v:<!method2!>() -- doc.class.name
+v:method3()
+]]
+
+-- checkUndefinedField 类名和类变量同名,类变量被直接使用
+TEST [[
+---@class Foo
+local Foo
+function Foo:method1() end
+Foo:<!method2!>() -- doc.class
+Foo:<!method2!>() -- doc.class
+]]
+
+-- checkUndefinedField 没有@class的不检测
+TEST [[
+local Foo
+function Foo:method1()
+ return Foo:method2() -- table
+end
+]]
+
+-- checkUndefinedField 类名和类变量不同名,类变量被直接使用、使用self
+TEST [[
+---@class Foo
+local mt
+function mt:method1()
+ mt.<!method2!>() -- doc.class
+ self:method1()
+ return self.<!method2!>() -- doc.class.name
+end
+]]
+
+-- checkUndefinedField 当会推导成多个class类型时
+TEST [[
+---@class Foo
+local mt
+function mt:method1() end
+
+---@class Bar
+local mt2
+function mt2:method2() end
+
+---@type Foo
+local v
+---@type Bar
+local v2
+v2 = v
+v2:method1()
+v2:<!method2!>()
+]]
+
+TEST [[
+---@type table
+T1 = {}
+print(T1.f1)
+---@type tablelib
+T2 = {}
+print(T2.<!f2!>)
+]]
+
+TEST [[
+---@type string|table
+local n
+
+print(n.x)
+]]
diff --git a/test/diagnostics/undefined-global.lua b/test/diagnostics/undefined-global.lua
index 55ef5a00..f5a6396c 100644
--- a/test/diagnostics/undefined-global.lua
+++ b/test/diagnostics/undefined-global.lua
@@ -29,3 +29,8 @@ print(T5)
print(T6)
print(T7)
]]
+
+TEST [[
+---@class c
+c = {}
+]]
diff --git a/test/diagnostics/unknown-diag-code.lua b/test/diagnostics/unknown-diag-code.lua
new file mode 100644
index 00000000..33b41886
--- /dev/null
+++ b/test/diagnostics/unknown-diag-code.lua
@@ -0,0 +1,3 @@
+TEST [[
+---@diagnostic disable-next-line: <!xxx!>
+]]