summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/basic/init.lua1
-rw-r--r--test/basic/linker.txt141
-rw-r--r--test/basic/noder.lua143
-rw-r--r--test/catch.lua7
-rw-r--r--test/completion/common.lua151
-rw-r--r--test/crossfile/allreferences.lua218
-rw-r--r--test/crossfile/completion.lua2
-rw-r--r--test/crossfile/definition.lua55
-rw-r--r--test/crossfile/hover.lua74
-rw-r--r--test/crossfile/init.lua1
-rw-r--r--test/crossfile/references.lua223
-rw-r--r--test/definition/bug.lua119
-rw-r--r--test/definition/call.lua8
-rw-r--r--test/definition/field.lua23
-rw-r--r--test/definition/function.lua2
-rw-r--r--test/definition/init.lua6
-rw-r--r--test/definition/luadoc.lua358
-rw-r--r--test/definition/special.lua36
-rw-r--r--test/definition/table.lua52
-rw-r--r--test/diagnostics/common.lua1389
-rw-r--r--test/diagnostics/init.lua1538
-rw-r--r--test/diagnostics/type-check.lua164
-rw-r--r--test/example/guide.txt2
-rw-r--r--test/full/example.lua1
-rw-r--r--test/highlight/init.lua1
-rw-r--r--test/hover/init.lua161
-rw-r--r--test/references/all.lua145
-rw-r--r--test/references/common.lua165
-rw-r--r--test/references/init.lua3
-rw-r--r--test/rename/init.lua2
-rw-r--r--test/type_inference/init.lua473
31 files changed, 2873 insertions, 2791 deletions
diff --git a/test/basic/init.lua b/test/basic/init.lua
index 1b698493..8490d51c 100644
--- a/test/basic/init.lua
+++ b/test/basic/init.lua
@@ -1,2 +1 @@
require 'basic.textmerger'
-require 'basic.noder'
diff --git a/test/basic/linker.txt b/test/basic/linker.txt
deleted file mode 100644
index ea3ba180..00000000
--- a/test/basic/linker.txt
+++ /dev/null
@@ -1,141 +0,0 @@
-ast -> linkers = {
- ['g|"X"|"Y"|"Z"'] = {src1, src2, src3},
- ['g|"X"|"Y"'] = {src4, src5, src6},
- ['g|"X"'] = {src7, src8, src9},
- ['l|7'] = {src10},
- ['l|7|"x"'] = {src11},
- ['l|11|"k"'] = {src12},
-}
-
-```lua
-x.y.<?z?> = <!f!>
-
-<?g?> = x.y.z
-
-t.<!z!> = 1
-x.y = t
-
-x = {
- y = {
- <!z!> = 1
- }
-}
-```
-
-expect: 'l|x|y|z'
-forward: 'l|x|y|z' -> f
-backward: 'l|x|y|z' -> g
-last: 'l|x|y' + 'z'
-
-expect: 'l|x|y' + '|z'
-forward: 'l|t' + '|z' -> 'l|t|z' -> t.z
-backward: nil
-last: 'l|x' + '|y|z'
-
-expect: 'l|x' + '|y|z'
-forward: 'l|0' + '|y|z' -> 'l|0|y|z'
-backward: nil
-last: nil
-
-expect: 'l|0|y|z'
-forward: nil
-backward: nil
-last: 'l|0|y' + '|z'
-
-expect: 'l|0|y' + '|z'
-forward: 'l|1'+ '|z' -> 'l|1|z' -> field z
-backward: nil
-last: 'l|0' + '|y|z'
-
-
-```lua
-a = {
- b = {
- <?c?> = 1,
- }
-}
-
-print(a.b.<!c!>)
-```
-
-expect: 't|3|c'
-forward: nil
-backward: nil
-last: 't|3' + '|c'
-
-expect: 't|3' + '|c'
-forward: nil
-backward: 't|2|b' + '|c'
-last: nil
-
-expect: 't|2|b|c'
-forward: nil
-backward: 't|2|b' + '|c'
-last: nil
-
-```lua
----@return <?A?>
-local function f()
-end
-
-local <!x!> = f()
-```
-
-'d|A'
-'f|1|#1'
-'f|1' + '|#1'
-'l|1' + '|#1'
-'s|1' + '|#1'
-
-```lua
----@generic T
----@param a T
----@return T
-local function f(a) end
-
-local <?c?>
-
-local <!v!> = f(c)
-```
-
-'l1'
-'l2|@1'
-'f|1|@1'
-'f|1|#1'
-
-```
----@generic T
----@param p T
----@return T
-local function f(p) end
-
-local <?r?> = f(<!k!>)
-```
-
-l:r
-s:1#1 call
-l:f#1 call
-f:1#1 call -> f:1&T = l:k
-l:f@1 --> 从保存的call信息里找到 f:1&T = l:k
-l:k
-
-
-
-```
----@generic T, V
----@param p T
----@return fun(V):T, V
-local function f(p) end
-
-local f2 = f(<!k!>)
-local <?r?> = f2()
-```
-
-l:r
-s:2|#1 call1
-l:f2|#1 call1
-f:2|#1 call1
-s:1#1|#1 call2
-f:1#1|#1 call2 -> f:1&T = l:k
-dfun:1|#1
-dn:V -> f:1&T = l:k
diff --git a/test/basic/noder.lua b/test/basic/noder.lua
deleted file mode 100644
index 49585ee8..00000000
--- a/test/basic/noder.lua
+++ /dev/null
@@ -1,143 +0,0 @@
-local noder = require 'core.noder'
-local files = require 'files'
-local util = require 'utility'
-local guide = require 'parser.guide'
-local catch = require 'catch'
-
-local function getSource(pos)
- local ast = files.getState('')
- return guide.eachSourceContain(ast.ast, pos, function (source)
- if source.type == 'local'
- or source.type == 'getlocal'
- or source.type == 'setlocal'
- or source.type == 'setglobal'
- or source.type == 'getglobal'
- or source.type == 'setfield'
- or source.type == 'getfield'
- or source.type == 'setmethod'
- or source.type == 'getmethod'
- or source.type == 'tablefield'
- or source.type == 'setindex'
- or source.type == 'getindex'
- or source.type == 'tableindex'
- or source.type == 'label'
- or source.type == 'goto' then
- return source
- end
- end)
-end
-
-local CARE = {}
-local function TEST(script)
- return function (expect)
- local newScript, catched = catch(script, '?')
- files.setText('', newScript)
- local source = getSource(catched['?'][1][1])
- assert(source)
- local result = {
- id = noder.getID(source),
- }
-
- expect['id'] = expect['id']:gsub('|', '\x1F')
-
- for key in pairs(CARE) do
- assert(result[key] == expect[key])
- end
- files.remove('')
- end
-end
-
-CARE['id'] = true
-TEST [[
-local <?x?>
-]] {
- id = 'l:6',
-}
-
-TEST [[
-local x
-print(<?x?>)
-]] {
- id = 'l:6',
-}
-
-TEST [[
-local x
-<?x?> = 1
-]] {
- id = 'l:6',
-}
-
-TEST [[
-print(<?X?>)
-]] {
- id = 'g:.X',
-}
-
-TEST [[
-print(<?X?>)
-]] {
- id = 'g:.X',
-}
-
-TEST [[
-local x
-print(x.y.<?z?>)
-]] {
- id = 'l:6|.y|.z',
-}
-
-TEST [[
-local x
-function x:<?f?>() end
-]] {
- id = 'l:6|.f',
-}
-
-TEST [[
-print(X.Y.<?Z?>)
-]] {
- id = 'g:.X|.Y|.Z',
-}
-
-TEST [[
-function x:<?f?>() end
-]] {
- id = 'g:.x|.f',
-}
-
-TEST [[
-{
- <?x?> = 1,
-}
-]] {
- id = 't:0|.x',
-}
-
-TEST [[
-return <?X?>
-]] {
- id = 'g:.X',
-}
-
-TEST [[
-function f()
- return <?X?>
-end
-]] {
- id = 'g:.X',
-}
-
-TEST [[
-::<?label?>::
-goto label
-]] {
- id = 'l:2',
-}
-
-TEST [[
-::label::
-goto <?label?>
-]] {
- id = 'l:2',
-}
diff --git a/test/catch.lua b/test/catch.lua
index 849be09d..01aac665 100644
--- a/test/catch.lua
+++ b/test/catch.lua
@@ -41,6 +41,10 @@ return function (script, seps)
local result = {}
local marks = {}
+ for s in seps:gmatch '.' do
+ result[s] = catchedTable()
+ end
+
local lineOffset = 1
local line = 0
local skipOffset = 0
@@ -68,9 +72,6 @@ return function (script, seps)
local mark = marks[j]
if mark.char == text then
local position = line * 10000 + offset - skipOffset - lineOffset
- if not result[text] then
- result[text] = catchedTable()
- end
result[text][#result[text]+1] = { mark.position, position }
table.remove(marks, j)
break
diff --git a/test/completion/common.lua b/test/completion/common.lua
index 8128d2ab..292a2dca 100644
--- a/test/completion/common.lua
+++ b/test/completion/common.lua
@@ -630,7 +630,7 @@ self.results.list[#self.re<??>]
},
{
label = 'results',
- kind = define.CompletionItemKind.Field,
+ kind = define.CompletionItemKind.Text,
},
}
@@ -1192,10 +1192,51 @@ TEST [[
}
TEST [[
+---@class ZBBC
+---@class ZBBC : Z<??>
+]]
+(nil)
+
+TEST [[
---@class ZABC
---@class ZBBC : <??>
]]
-(EXISTS)
+(function (results)
+ local ok
+ for _, res in ipairs(results) do
+ if res.label == 'ZABC' then
+ ok = true
+ end
+ if res.label == 'ZBBC' then
+ error('ZBBC should not be here')
+ end
+ end
+ assert(ok, 'ZABC should be here')
+end)
+
+TEST [[
+---@class ZBBC
+---@class ZBBC : <??>
+]]
+(function (results)
+ for _, res in ipairs(results) do
+ if res.label == 'ZBBC' then
+ error('ZBBC should not be here')
+ end
+ end
+end)
+
+TEST [[
+---@class ZABC
+---@class ZABC
+---@class ZBBC : Z<??>
+]]
+{
+ {
+ label = 'ZABC',
+ kind = define.CompletionItemKind.Class,
+ },
+}
TEST [[
---@class zabc
@@ -1485,7 +1526,7 @@ mt.<??>
}
TEST [[
----@param x string | "'AAA'" | "'BBB'" | "'CCC'"
+---@param x string | "AAA" | "BBB" | "CCC"
function f(y, x)
end
@@ -1493,21 +1534,21 @@ f(1, <??>)
]]
{
{
- label = "'AAA'",
+ label = '"AAA"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'BBB'",
+ label = '"BBB"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'CCC'",
+ label = '"CCC"',
kind = define.CompletionItemKind.EnumMember,
}
}
TEST [[
----@param x string | "'AAA'" | "'BBB'" | "'CCC'"
+---@param x string | "AAA" | "BBB" | "CCC"
function f(y, x)
end
@@ -1515,21 +1556,21 @@ f(1,<??>)
]]
{
{
- label = "'AAA'",
+ label = '"AAA"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'BBB'",
+ label = '"BBB"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'CCC'",
+ label = '"CCC"',
kind = define.CompletionItemKind.EnumMember,
}
}
TEST [[
----@param x string | "'AAA'" | "'BBB'" | "'CCC'"
+---@param x string | "AAA" | "BBB" | "CCC"
function f(x)
end
@@ -1537,21 +1578,21 @@ f(<??>)
]]
{
{
- label = "'AAA'",
+ label = '"AAA"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'BBB'",
+ label = '"BBB"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'CCC'",
+ label = '"CCC"',
kind = define.CompletionItemKind.EnumMember,
}
}
TEST [[
----@alias Option string | "'AAA'" | "'BBB'" | "'CCC'"
+---@alias Option string | "AAA" | "BBB" | "CCC"
---@param x Option
function f(x)
end
@@ -1560,21 +1601,21 @@ f(<??>)
]]
{
{
- label = "'AAA'",
+ label = '"AAA"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'BBB'",
+ label = '"BBB"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'CCC'",
+ label = '"CCC"',
kind = define.CompletionItemKind.EnumMember,
}
}
TEST [[
----@param x string | "'AAA'" | "'BBB'" | "'CCC'"
+---@param x string | "AAA" | "BBB" | "CCC"
function f(x)
end
@@ -1605,10 +1646,10 @@ TEST [[
---@alias XXXX
---comment 1
---comment 1
----| '1'
+---| 1
---comment 2
---comment 2
----| '2'
+---| 2
---@param x XXXX
local function f(x)
@@ -1634,10 +1675,10 @@ TEST [[
---@alias XXXX
---comment 1
---comment 1
----| '1'
+---| 1
---comment 2
---comment 2
----| '2'
+---| 2
---@param x XXXX
local function f(x)
end
@@ -1645,7 +1686,7 @@ end
---comment 3
---comment 3
----| '3'
+---| 3
f(<??>)
]]
@@ -1719,20 +1760,20 @@ global zzz: integer = 1
TEST [[
---@param x string
----| "'选项1'" # 注释1
----| "'选项2'" # 注释2
+---| "选项1" # 注释1
+---| "选项2" # 注释2
function f(x) end
f(<??>)
]]
{
{
- label = "'选项1'",
+ label = '"选项1"',
kind = define.CompletionItemKind.EnumMember,
description = '注释1',
},
{
- label = "'选项2'",
+ label = '"选项2"',
kind = define.CompletionItemKind.EnumMember,
description = '注释2',
},
@@ -1751,49 +1792,49 @@ utf8.charpatter<??>
}
TEST [[
----@type "'a'"|"'b'"|"'c'"
+---@type "a"|"b"|"c"
local x
print(x == <??>)
]]
{
{
- label = "'a'",
+ label = '"a"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'b'",
+ label = '"b"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'c'",
+ label = '"c"',
kind = define.CompletionItemKind.EnumMember,
},
}
TEST [[
----@type "'a'"|"'b'"|"'c'"
+---@type "a"|"b"|"c"
local x
x = <??>
]]
{
{
- label = "'a'",
+ label = '"a"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'b'",
+ label = '"b"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'c'",
+ label = '"c"',
kind = define.CompletionItemKind.EnumMember,
},
}
TEST [[
----@type "'a'"|"'b'"|"'c'"
+---@type "a"|"b"|"c"
local x
print(x == '<??>')
@@ -1817,7 +1858,7 @@ print(x == '<??>')
}
TEST [[
----@type "'a'"|"'b'"|"'c'"
+---@type "a"|"b"|"c"
local x
x = '<??>'
@@ -1880,6 +1921,7 @@ vvv<??>
},
}
+--[=[
Cared['insertText'] = true
TEST [[
---@param callback fun(x: number, y: number):string
@@ -1903,6 +1945,7 @@ end\
```"
},
}
+]=]
Cared['insertText'] = nil
@@ -2060,85 +2103,85 @@ field cc.aaa: number
Cared['description'] = nil
TEST [[
----@type table<string, "'a'"|"'b'"|"'c'">
+---@type table<string, "a"|"b"|"c">
local x
x.a = <??>
]]
{
{
- label = "'a'",
+ label = '"a"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'b'",
+ label = '"b"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'c'",
+ label = '"c"',
kind = define.CompletionItemKind.EnumMember,
},
}
TEST [[
----@type table<string, "'a'"|"'b'"|"'c'">
+---@type table<string, "a"|"b"|"c">
local x
x['a'] = <??>
]]
{
{
- label = "'a'",
+ label = '"a"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'b'",
+ label = '"b"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'c'",
+ label = '"c"',
kind = define.CompletionItemKind.EnumMember,
},
}
TEST [[
----@type table<string, "'a'"|"'b'"|"'c'">
+---@type table<string, "a"|"b"|"c">
local x = {
a = <??>
}
]]
{
{
- label = "'a'",
+ label = '"a"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'b'",
+ label = '"b"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'c'",
+ label = '"c"',
kind = define.CompletionItemKind.EnumMember,
},
}
TEST [[
----@type table<string, "'a'"|"'b'"|"'c'">
+---@type table<string, "a"|"b"|"c">
local x = {
['a'] = <??>
}
]]
{
{
- label = "'a'",
+ label = '"a"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'b'",
+ label = '"b"',
kind = define.CompletionItemKind.EnumMember,
},
{
- label = "'c'",
+ label = '"c"',
kind = define.CompletionItemKind.EnumMember,
},
}
diff --git a/test/crossfile/allreferences.lua b/test/crossfile/allreferences.lua
deleted file mode 100644
index 2753d785..00000000
--- a/test/crossfile/allreferences.lua
+++ /dev/null
@@ -1,218 +0,0 @@
-local config = require 'config'
-
-TEST {
- {
- path = 'a.lua',
- content = [[
- local <!f!> = require 'lib'
- ]],
- },
- {
- path = 'lib.lua',
- content = [[
- return <!<?function?> ()
- end!>
- ]],
- },
-}
-
-TEST {
- {
- path = 'a.lua',
- content = [[
- local m = {}
- function m.<~func~>()
- end
- return m
- ]],
- },
- {
- path = 'b.lua',
- content = [[
- local t = require 'a'
- t.<!func!>()
- ]],
- },
-}
-
-TEST {
- {
- path = 'a.lua',
- content = [[
- return <~function () end~>
- ]],
- },
- {
- path = 'b.lua',
- content = [[
- local t = require 'a'
- ]],
- },
- {
- path = 'b.lua',
- content = [[
- local t = require 'a'
- ]],
- },
- {
- path = 'b.lua',
- content = [[
- local t = require 'a'
- ]],
- },
- {
- path = 'b.lua',
- content = [[
- local <!t!> = require 'a'
- ]],
- },
-}
-
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', true)
-TEST {
- {
- path = 'a.lua',
- content = [[
- local function <~f~>()
- end
-
- return {
- <!f!> = <!f!>,
- }
- ]]
- },
- {
- path = 'b.lua',
- content = [[
- local t = require 'a'
- local <!f!> = t.<!f!>
-
- <!f!>()
-
- return {
- <!f!> = <!f!>,
- }
- ]]
- }
-}
-
-TEST {
- {
- path = 'a.lua',
- content = [[
- local function <!f!>()
- end
-
- return {
- <!f!> = <!f!>,
- }
- ]]
- },
- {
- path = 'c.lua',
- content = [[
- local t = require 'a'
- local <!f!> = t.<!f!>
-
- <!f!>()
-
- return {
- <!f!> = <!f!>,
- }
- ]]
- },
- {
- path = 'b.lua',
- content = [[
- local t = require 'a'
- local <!f!> = t.<!f!>
-
- <~f~>()
-
- return {
- <!f!> = <!f!>,
- }
- ]]
- }
-}
-
-TEST {
- {
- path = 'a.lua',
- content = [[
- local function <~f~>()
- end
-
- return {
- <!f!> = <!f!>,
- }
- ]]
- },
- {
- path = 'b1.lua',
- content = [[
- local t = require 'a'
- t.<!f!>()
- ]]
- },
- {
- path = 'b2.lua',
- content = [[
- local t = require 'a'
- t.<!f!>()
- ]]
- },
- {
- path = 'b3.lua',
- content = [[
- local t = require 'a'
- t.<!f!>()
- ]]
- },
- {
- path = 'b4.lua',
- content = [[
- local t = require 'a'
- t.<!f!>()
- ]]
- },
- {
- path = 'b5.lua',
- content = [[
- local t = require 'a'
- t.<!f!>()
- ]]
- },
- {
- path = 'b6.lua',
- content = [[
- local t = require 'a'
- t.<!f!>()
- ]]
- },
- {
- path = 'b7.lua',
- content = [[
- local t = require 'a'
- t.<!f!>()
- ]]
- },
-}
-
-TEST {
- {
- path = 'a.lua',
- content = [[
- local <~t~> = require 'b'
- return <!t!>
- ]]
- },
- {
- path = 'b.lua',
- content = [[
- local <!t!> = require 'a'
- return <!t!>
- ]]
- },
-}
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', false)
diff --git a/test/crossfile/completion.lua b/test/crossfile/completion.lua
index c271f598..79762646 100644
--- a/test/crossfile/completion.lua
+++ b/test/crossfile/completion.lua
@@ -837,7 +837,7 @@ TEST {
kind = CompletionItemKind.Variable,
description = [[
```lua
-local z: {}
+local z: table
```]]
},
}
diff --git a/test/crossfile/definition.lua b/test/crossfile/definition.lua
index eaf12b73..f44f2707 100644
--- a/test/crossfile/definition.lua
+++ b/test/crossfile/definition.lua
@@ -47,8 +47,8 @@ function TEST(datas)
uri,
}
end
- if catched['?'] or catched['~'] then
- sourceList = catched['?'] or catched['~']
+ if #catched['?'] > 0 or #catched['~'] > 0 then
+ sourceList = catched['?'] + catched['~']
sourceUri = uri
end
files.setText(uri, newScript)
@@ -149,7 +149,7 @@ config.set(nil, 'Lua.runtime.pathStrict', false)
TEST {
{
path = 'a.lua',
- content = 'local <!t!> = 1; return t',
+ content = 'return <!function () end!>',
},
{
path = 'b.lua',
@@ -160,7 +160,7 @@ TEST {
TEST {
{
path = 'a.lua',
- content = 'local <!t!> = 1; return t',
+ content = 'return <!function () end!>',
},
{
path = 'b.lua',
@@ -188,7 +188,7 @@ local <~t~>
TEST {
{
path = 'a.lua',
- content = 'local <!t!> = 1; return t',
+ content = 'return <!function () end!>',
},
{
path = 'b.lua',
@@ -355,9 +355,7 @@ TEST {
{
path = 'a.lua',
content = [[
- return <!{
- a = 1,
- }!>
+ return <!function () end!>
]],
},
{
@@ -395,8 +393,8 @@ TEST {
{
path = 'a.lua',
content = [[
- local function <!f!>()
- end
+ local <!function f()
+ end!>
return f
]]
},
@@ -455,11 +453,11 @@ TEST {
{
path = 'a.lua',
content = [[
- local function <!f!>()
- end
+ local <!function f()
+ end!>
return {
- <!f!> = f,
+ f = f,
}
]]
},
@@ -610,7 +608,7 @@ TEST {
path = 'a.lua',
content = [[
---@class Class
- local <!obj!>
+ local obj
]]
},
{
@@ -636,7 +634,7 @@ TEST {
path = 'b.lua',
content = [[
---@class Class
- local <!obj!>
+ local obj
]]
},
}
@@ -800,14 +798,11 @@ TEST {
},
}
-config.set(nil, 'Lua.IntelliSense.traceFieldInject', true)
TEST {
{
path = 'a.lua',
content = [[
-local t = GlobalTable
-
-t.settings = {
+GlobalTable.settings = {
<!test!> = 1
}
]]
@@ -821,7 +816,27 @@ print(b.<?test?>)
]]
}
}
-config.set(nil, 'Lua.IntelliSense.traceFieldInject', false)
+
+TEST {
+ {
+ path = 'a.lua',
+ content = [[
+GlobalTable = {
+ settings = {
+ <!test!> = 1
+ }
+}
+ ]]
+ },
+ {
+ path = 'b.lua',
+ content = [[
+local b = GlobalTable.settings
+
+print(b.<?test?>)
+ ]]
+ }
+}
TEST {
{
diff --git a/test/crossfile/hover.lua b/test/crossfile/hover.lua
index cb9e83aa..4461e775 100644
--- a/test/crossfile/hover.lua
+++ b/test/crossfile/hover.lua
@@ -44,7 +44,7 @@ function TEST(expect)
local script, list = catch(file.content, '?')
local uri = furi.encode(file.path)
files.setText(uri, script)
- if list['?'] then
+ if #list['?'] > 0 then
sourceUri = uri
sourcePos = (list['?'][1][1] + list['?'][1][2]) // 2
end
@@ -362,22 +362,22 @@ TEST {
path = 'b.lua',
content = [[
---@param x string
- ---| "'选项1'" # 注释1
- ---| > "'选项2'" # 注释2
+ ---| "选项1" # 注释1
+ ---| > "选项2" # 注释2
function <?f?>(x) end
]]
},
hover = [[
```lua
-function f(x: string|'选项1'|'选项2')
+function f(x: string|"选项1"|"选项2")
```
---
```lua
-x: string
- | '选项1' -- 注释1
- -> '选项2' -- 注释2
+x:
+ | "选项1" -- 注释1
+ -> "选项2" -- 注释2
```]]
}
@@ -390,23 +390,23 @@ TEST {
path = 'b.lua',
content = [[
---@alias option
- ---| "'选项1'" # 注释1
- ---| > "'选项2'" # 注释2
+ ---| "选项1" # 注释1
+ ---| > "选项2" # 注释2
---@param x option
function <?f?>(x) end
]]
},
hover = [[
```lua
-function f(x: '选项1'|'选项2')
+function f(x: "选项1"|"选项2")
```
---
```lua
-x: option
- | '选项1' -- 注释1
- -> '选项2' -- 注释2
+x:
+ | "选项1" -- 注释1
+ -> "选项2" -- 注释2
```]]
}
@@ -419,8 +419,8 @@ TEST {
path = 'b.lua',
content = [[
---@alias option
- ---| "'选项1'" # 注释1
- ---| > "'选项2'" # 注释2
+ ---| "选项1" # 注释1
+ ---| > "选项2" # 注释2
---@return option x
function <?f?>() end
]]
@@ -428,15 +428,15 @@ TEST {
hover = [[
```lua
function f()
- -> x: '选项1'|'选项2'
+ -> x: "选项1"|"选项2"
```
---
```lua
-x: option
- | '选项1' -- 注释1
- -> '选项2' -- 注释2
+x:
+ | "选项1" -- 注释1
+ -> "选项2" -- 注释2
```]]
}
@@ -449,8 +449,8 @@ TEST {
path = 'b.lua',
content = [[
---@alias option
- ---| "'选项1'" # 注释1
- ---| > "'选项2'" # 注释2
+ ---| "选项1" # 注释1
+ ---| > "选项2" # 注释2
---@return option
function <?f?>() end
]]
@@ -458,15 +458,15 @@ TEST {
hover = [[
```lua
function f()
- -> '选项1'|'选项2'
+ -> "选项1"|"选项2"
```
---
```lua
-return #1: option
- | '选项1' -- 注释1
- -> '选项2' -- 注释2
+return #1:
+ | "选项1" -- 注释1
+ -> "选项2" -- 注释2
```]]
}
@@ -673,8 +673,8 @@ TEST {{ path = 'a.lua', content = '', }, {
path = 'b.lua',
content = [[
---@param a boolean # xxx
- ---| 'true' # ttt
- ---| 'false' # fff
+ ---| true # ttt
+ ---| false # fff
local function <?f?>(a)
end
]]
@@ -689,7 +689,7 @@ function f(a: boolean|true|false)
@*param* `a` — xxx
```lua
-a: boolean
+a:
| true -- ttt
| false -- fff
```]]}
@@ -825,7 +825,7 @@ local <?food?>
},
hover = [[
```lua
-local food: any
+local food: unknown
```
---
@@ -976,17 +976,17 @@ end
},
hover = [[
```lua
-function f(p: a|b)
+function f(p: "a"|"b")
```
---
```lua
-p: T
- | a -- comment 1
- -- comment 2
- | b -- comment 3
- -- comment 4
+p:
+ | "a" -- comment 1
+ -- comment 2
+ | "b" -- comment 3
+ -- comment 4
```]]}
--TEST {{ path = 'a.lua', content = '', }, {
@@ -1044,13 +1044,13 @@ end
for _, x in ipairs({} and {}) do
- print(<?x?>) -- `x` is infered as `string`
+ print(<?x?>) -- `x` is infered as `string` (fixed bug)
end
]],
},
hover = [[
```lua
-local x: any
+local x: unknown
```]]
}
diff --git a/test/crossfile/init.lua b/test/crossfile/init.lua
index 1ed2a943..aec9a044 100644
--- a/test/crossfile/init.lua
+++ b/test/crossfile/init.lua
@@ -1,6 +1,5 @@
require 'crossfile.definition'
require 'crossfile.references'
-require 'crossfile.allreferences'
require 'crossfile.hover'
require 'crossfile.completion'
require 'crossfile.diagnostic'
diff --git a/test/crossfile/references.lua b/test/crossfile/references.lua
index 18e9c5f9..1a9f2508 100644
--- a/test/crossfile/references.lua
+++ b/test/crossfile/references.lua
@@ -1,3 +1,4 @@
+---@diagnostic disable: await-in-sync
local files = require 'files'
local furi = require 'file-uri'
local core = require 'core.reference'
@@ -68,7 +69,7 @@ function TEST(datas)
}
end
end
- if catched['?'] or catched['~'] then
+ if #catched['?'] > 0 or #catched['~'] > 0 then
sourceList = catched['?'] + catched['~']
sourceUri = uri
end
@@ -100,16 +101,15 @@ end
TEST {
{
- path = 'lib.lua',
+ path = 'a.lua',
content = [[
- return <!function ()
- end!>
+ <!ROOT!> = 1
]],
},
{
- path = 'a.lua',
+ path = 'b.lua',
content = [[
- local <~f~> = require 'lib'
+ print(<~ROOT~>)
]],
},
}
@@ -118,13 +118,13 @@ TEST {
{
path = 'a.lua',
content = [[
- <!ROOT!> = 1
+ <~ROOT~> = 1
]],
},
{
path = 'b.lua',
content = [[
- print(<~ROOT~>)
+ print(<!ROOT!>)
]],
},
}
@@ -133,15 +133,41 @@ TEST {
{
path = 'a.lua',
content = [[
- <~ROOT~> = 1
- ]],
+ ---@type A
+ local t
+
+ t.<!f!>()
+ ]]
},
{
path = 'b.lua',
content = [[
- print(<!ROOT!>)
- ]],
+ ---@class A
+ local mt
+
+ function mt.<~f~>()
+ end
+ ]]
+ }
+}
+
+TEST {
+ {
+ path = 'a.lua',
+ content = [[
+ local t = {}
+ t.<~x~> = 1
+ return t
+ ]]
},
+ {
+ path = 'b.lua',
+ content = [[
+ local t = require 'a'
+
+ print(t.<!x!>)
+ ]]
+ }
}
TEST {
@@ -149,14 +175,13 @@ TEST {
path = 'a.lua',
content = [[
local f = require 'lib'
- local <~o~> = f()
+ <!f!>()
]],
},
{
path = 'lib.lua',
content = [[
- return function ()
- return <!{}!>
+ return <?function?> ()
end
]],
},
@@ -166,20 +191,78 @@ TEST {
{
path = 'a.lua',
content = [[
- ---@type A
- local t
+ local m = {}
+ function m.<~func~>()
+ end
+ return m
+ ]],
+ },
+ {
+ path = 'b.lua',
+ content = [[
+ local t = require 'a'
+ t.<!func!>()
+ ]],
+ },
+}
- t.<!f!>()
- ]]
+TEST {
+ {
+ path = 'a.lua',
+ content = [[
+ return <?function?> () end
+ ]],
},
{
path = 'b.lua',
content = [[
- ---@class A
- local mt
+ local t = require 'a'
+ ]],
+ },
+ {
+ path = 'b.lua',
+ content = [[
+ local t = require 'a'
+ ]],
+ },
+ {
+ path = 'b.lua',
+ content = [[
+ local t = require 'a'
+ ]],
+ },
+ {
+ path = 'b.lua',
+ content = [[
+ local t = require 'a'
+ <!t!>()
+ ]],
+ },
+}
- function mt.<~f~>()
+TEST {
+ {
+ path = 'a.lua',
+ content = [[
+ local function <~f~>()
end
+
+ return {
+ f = <!f!>,
+ }
+ ]]
+ },
+ {
+ path = 'b.lua',
+ content = [[
+ local t = require 'a'
+ local f = t.f
+
+ f()
+
+ return {
+ f = f,
+ }
]]
}
}
@@ -188,17 +271,105 @@ TEST {
{
path = 'a.lua',
content = [[
- local t = {}
- t.<~x~> = 1
- return t
+ local <?function?> f()
+ end
+
+ return {
+ f = f,
+ }
]]
},
{
path = 'b.lua',
content = [[
local t = require 'a'
+ local f = t.f
- print(t.<!x!>)
+ <!f!>()
+
+ return {
+ f = f,
+ }
]]
}
}
+
+TEST {
+ {
+ path = 'a.lua',
+ content = [[
+ local <?function?> f()
+ end
+
+ return {
+ f = f,
+ }
+ ]]
+ },
+ {
+ path = 'b1.lua',
+ content = [[
+ local t = require 'a'
+ t.<!f!>()
+ ]]
+ },
+ {
+ path = 'b2.lua',
+ content = [[
+ local t = require 'a'
+ t.<!f!>()
+ ]]
+ },
+ {
+ path = 'b3.lua',
+ content = [[
+ local t = require 'a'
+ t.<!f!>()
+ ]]
+ },
+ {
+ path = 'b4.lua',
+ content = [[
+ local t = require 'a'
+ t.<!f!>()
+ ]]
+ },
+ {
+ path = 'b5.lua',
+ content = [[
+ local t = require 'a'
+ t.<!f!>()
+ ]]
+ },
+ {
+ path = 'b6.lua',
+ content = [[
+ local t = require 'a'
+ t.<!f!>()
+ ]]
+ },
+ {
+ path = 'b7.lua',
+ content = [[
+ local t = require 'a'
+ t.<!f!>()
+ ]]
+ },
+}
+
+TEST {
+ {
+ path = 'a.lua',
+ content = [[
+ local <~t~> = require 'b'
+ return <!t!>
+ ]]
+ },
+ {
+ path = 'b.lua',
+ content = [[
+ local t = require 'a'
+ return t
+ ]]
+ },
+}
diff --git a/test/definition/bug.lua b/test/definition/bug.lua
index 77797f40..b564f764 100644
--- a/test/definition/bug.lua
+++ b/test/definition/bug.lua
@@ -134,7 +134,7 @@ t:<?add?>()
TEST [[
local t = {}
-t.<!f1!> = 1
+t.f1 = 1
t.<!f2!> = t.f1
print(t.<?f2?>)
@@ -142,9 +142,9 @@ print(t.<?f2?>)
TEST [[
local t = {}
-t.<!f1!> = 1
+t.f1 = 1
t.<!f2!> = t.f1
-t.<!f1!> = t.f2
+t.f1 = t.f2
print(t.<?f2?>)
]]
@@ -172,67 +172,65 @@ string.xx:<?format?>()
--v.<?bar1?>
--]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', true)
TEST [[
local A, B
function A:get1()
- local <!a!> = B:get()
+ local a = B:get()
return a
end
function A:get2()
- local <!a!> = B:get()
+ local a = B:get()
return a
end
function A:get3()
- local <!a!> = B:get()
+ local a = B:get()
return a
end
function A:get4()
- local <!a!> = B:get()
+ local a = B:get()
return a
end
function A:get5()
- local <!a!> = B:get()
+ local a = B:get()
return a
end
function A:get6()
- local <!a!> = B:get()
+ local a = B:get()
return a
end
function A:get7()
- local <!a!> = B:get()
+ local a = B:get()
return a
end
function A:get8()
- local <!a!> = B:get()
+ local a = B:get()
return a
end
function B:get()
- local <!b!>
- <!b!> = A:get1()
- <!b!> = A:get2()
- <!b!> = A:get3()
- <!b!> = A:get4()
- <!b!> = A:get5()
- <!b!> = A:get6()
- <!b!> = A:get7()
- <!b!> = A:get8()
+ local b
+ b = A:get1()
+ b = A:get2()
+ b = A:get3()
+ b = A:get4()
+ b = A:get5()
+ b = A:get6()
+ b = A:get7()
+ b = A:get8()
return b
end
local <!b!> = B:get()
print(<?b?>)
]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', false)
TEST [[
g[a.b.c] = 1
@@ -253,80 +251,3 @@ local <!v!> = t[a]
t[a] = <?v?>
]]
-
-TEST [[
----@class A
----@field x number
-
----@class B: A
----@field <!x!> boolean
-
----@type B
-local t
-
-local <!<?v?>!> = t.x
-]]
-
-TEST [[
----@class A
----@field <!x!> number
-
----@class B: A
-
----@type B
-local t
-
-local <!<?v?>!> = t.x
-]]
-
-TEST [[
----@class A
-local A
-
-function A:x() end
-
----@class B: A
-local B
-
-function B:<!x!>() end
-
----@type B
-local t
-
-local <!<?v?>!> = t.x
-]]
-
-TEST [[
----@class A
-local A
-
-function A:<!x!>() end
-
----@class B: A
-local B
-
----@type B
-local t
-
-local <!<?v?>!> = t.x
-]]
-
--- TODO
---TEST [[
------@class A
---local A
---
------@return A
---function A:x() end
---
------@class B: A
---local <!B!>
---
------@return B
---function B:x() end
---
------@type B
---local t
---
---local <!<?v?>!> = t.x()
---]]
diff --git a/test/definition/call.lua b/test/definition/call.lua
deleted file mode 100644
index 15364396..00000000
--- a/test/definition/call.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-TEST [[
-function f()
- local <!x!>
- return x
-end
-local <!y!> = f()
-print(<?y?>)
-]]
diff --git a/test/definition/field.lua b/test/definition/field.lua
new file mode 100644
index 00000000..5b5b67f9
--- /dev/null
+++ b/test/definition/field.lua
@@ -0,0 +1,23 @@
+TEST [[
+X.<!y!> = 1
+
+local t = X
+
+print(t.<?y?>)
+]]
+
+TEST [[
+X.x.<!y!> = 1
+
+local t = X.x
+
+print(t.<?y?>)
+]]
+
+TEST [[
+X.x.<!y!> = 1
+
+local t = X
+
+print(t.x.<?y?>)
+]]
diff --git a/test/definition/function.lua b/test/definition/function.lua
index f5d32e78..95dd1b57 100644
--- a/test/definition/function.lua
+++ b/test/definition/function.lua
@@ -24,6 +24,6 @@ end
]]
TEST [[
-local <!f!> = function () end
+local <!f!> = <!function () end!>
<?f?>()
]]
diff --git a/test/definition/init.lua b/test/definition/init.lua
index fc2903c1..3badaadf 100644
--- a/test/definition/init.lua
+++ b/test/definition/init.lua
@@ -34,9 +34,9 @@ function TEST(script)
positions[i] = { result.target.start, result.target.finish }
end
end
- assert(founded(catched['!'] or {}, positions))
+ assert(founded(catched['!'], positions))
else
- assert(catched['!'] == nil)
+ assert(#catched['!'] == 0)
end
files.remove('')
@@ -44,12 +44,12 @@ end
require 'definition.local'
require 'definition.set'
+require 'definition.field'
require 'definition.arg'
require 'definition.function'
require 'definition.table'
require 'definition.method'
require 'definition.label'
-require 'definition.call'
require 'definition.special'
require 'definition.bug'
require 'definition.luadoc'
diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua
index 8124261c..97b12b85 100644
--- a/test/definition/luadoc.lua
+++ b/test/definition/luadoc.lua
@@ -17,7 +17,7 @@ local x
TEST [[
---@class Class
-local <!t!>
+local t
---@type Class
local <?<!x!>?>
]]
@@ -35,21 +35,59 @@ obj:<?cast?>()
TEST [[
---@class A
-local <!mt!> = {}
-function mt:cast()
-end
+---@field x number
----@type A
-local <!obj!>
-<?obj?>:cast()
+---@class B: A
+---@field <!x!> boolean
+
+---@type B
+local t
+
+t.<?x?>
]]
TEST [[
----@type A
-local <?<!obj!>?>
+---@class A
+---@field <!x!> number
+---@class B: A
+
+---@type B
+local t
+
+t.<?x?>
+]]
+
+TEST [[
---@class A
-local <!mt!>
+local A
+
+function A:x() end
+
+---@class B: A
+local B
+
+<!function B:x() end!>
+
+---@type B
+local t
+
+local <!<?v?>!> = t.x
+]]
+
+TEST [[
+---@class A
+local A
+
+<!function A:x() end!>
+
+---@class B: A
+local B
+
+---@type B
+local t
+
+local <!<?v?>!> = t.x
]]
TEST [[
@@ -105,6 +143,20 @@ function f(<?...?>) end
]]
TEST [[
+---@alias A <!fun()!>
+
+---@type A
+local <!<?x?>!>
+]]
+
+TEST [[
+---@class A: <!{}!>
+
+---@type A
+local <!<?x?>!>
+]]
+
+TEST [[
---@overload <!fun(y: boolean)!>
---@param x number
---@param y boolean
@@ -116,11 +168,12 @@ print(<?f?>)
TEST [[
local function f()
- return 1
+ local x
+ return x
end
---@class Class
-local <!mt!>
+local mt
---@type Class
local <?<!x!>?> = f()
@@ -153,7 +206,7 @@ y.<?a?>
TEST [[
---@class <!loli!>
-local <!unit!>
+local unit!>
function unit:pants()
end
@@ -184,34 +237,6 @@ AAAA.a.<?SSDF?>
]]
TEST [[
----@class Cat
-local <!m!> ---hahaha
----@class Dog
-local m2
----@type Cat
-local <?<!v!>?>
-]]
-
-TEST [[
----@class Cat
-local <!m!> --hahaha
----@class Dog
-local m2
----@type Cat
-local <?<!v!>?>
-]]
-
-TEST [[
----@class Cat
- local <!m!> ---hahaha
-
- ---@class Dog
- local m2
- ---@type Cat
- local <?<!v!>?>
-]]
-
-TEST [[
---@return <!fun()!>
local function f() end
@@ -224,8 +249,8 @@ TEST [[
---@return T
local function f(p) end
-local <!k!>
-local <?<!r!>?> = f(<!k!>)
+local k = <!function () end!>
+local <?<!r!>?> = f(k)
]]
TEST [[
@@ -286,22 +311,28 @@ print(v1.<?bar1?>)
TEST [[
---@class A
-local <!t!>
+local t
+
+t.<!x!> = 1
---@type A[]
local b
-local <?<!c!>?> = b[1]
+local c = b[1]
+c.<?x?>
]]
TEST [[
---@class A
-local <!t!>
+local t
+
+t.<!x!> = 1
----@type table<number, A>
+---@type { [number]: A }
local b
-local <?<!c!>?> = b[1]
+local c = b[1]
+c.<?x?>
]]
TEST [[
@@ -309,7 +340,7 @@ TEST [[
local Foo = {}
function Foo:<!bar1!>() end
----@type table<number, Foo>
+---@type { [number]: Foo }
local v1
print(v1[1].<?bar1?>)
]]
@@ -323,7 +354,7 @@ function Foo:<!bar1!>() end
local Foo2 = {}
function Foo2:bar1() end
----@type Foo2<number, Foo>
+---@type { [number]: Foo }
local v1
print(v1[1].<?bar1?>)
]]
@@ -355,16 +386,16 @@ TEST [[
---@type fun(x: T):T
local f
-local <?<!v2!>?> = f(<!{}!>)
+local <?<!v2!>?> = f(<!function () end!>)
]]
TEST [[
---@generic T
---@param x T
---@return fun():T
-local function f(<!x!>) end
+local function f(x) end
-local v1 = f(<!{}!>)
+local v1 = f(<!function () end!>)
local <?<!v2!>?> = v1()
]]
@@ -373,7 +404,7 @@ TEST [[
---@type fun(x: T):fun():T
local f
-local v1 = f(<!{}!>)
+local v1 = f(<!function () end!>)
local <?<!v2!>?> = v1()
]]
@@ -383,7 +414,7 @@ TEST [[
local function f(x) end
local v1 = f()
-local <?<!v2!>?> = v1(<!{}!>)
+local <?<!v2!>?> = v1(<!function () end!>)
]]
TEST [[
@@ -393,72 +424,150 @@ TEST [[
local function f(x) end
---@class A
-local <!a!>
+local a
+a.<!x!> = 1
---@type A[]
local b
-local <?<!c!>?> = f(b)
+local c = f(b)
+c.<?x?>
]]
TEST [[
---@generic V
----@param x table<number, V>
+---@param x { [number]: V }
---@return V
local function f(x) end
---@class A
-local <!a!>
+local a
+a.<!x!> = 1
----@type table<number, A>
+---@type { [number]: A }
local b
-local <?<!c!>?> = f(b)
+local c = f(b)
+c.<?x?>
]]
TEST [[
---@generic V
----@param x V[]
+---@param x { [number]: V }
---@return V
local function f(x) end
---@class A
-local <!a!>
+local a
+a.<!x!> = 1
----@type table<number, A>
+---@type { [integer]: A }
local b
-local <?<!c!>?> = f(b)
+local c = f(b)
+c.<?x?>
]]
TEST [[
---@generic V
----@param x table<number, V>
+---@param x { [integer]: V }
---@return V
local function f(x) end
---@class A
-local <!a!>
+local a
+a.x = 1
+
+---@type { [number]: A }
+local b
+
+local c = f(b)
+c.<?x?>
+]]
+
+TEST [[
+---@generic V
+---@param x { [number]: V }
+---@return V
+local function f(x) end
+
+---@class A
+local a
+a.<!x!> = 1
---@type A[]
local b
-local <?<!c!>?> = f(b)
+local c = f(b)
+c.<?x?>
]]
TEST [[
---@generic K
----@param x table<K, number>
+---@param x { [K]: number }
---@return K
local function f(x) end
---@class A
-local <!a!>
+local a
+a.<!x!> = 1
----@type table<A, number>
+---@type { [A]: number }
local b
-local <?<!c!>?> = f(b)
+local c = f(b)
+c.<?x?>
+]]
+
+TEST [[
+---@generic K
+---@param x { [K]: A }
+---@return K
+local function f(x) end
+
+---@class A
+local a
+a.x = 1
+
+---@type A[]
+local b
+
+local c = f(b)
+c.<?x?>
+]]
+
+TEST [[
+---@generic K
+---@param x { [K]: number }
+---@return K
+local function f(x) end
+
+---@class A
+local a
+a.<!x!> = 1
+
+---@type { [A]: integer }
+local b
+
+local c = f(b)
+c.<?x?>
+]]
+
+TEST [[
+---@generic K
+---@param x { [K]: integer }
+---@return K
+local function f(x) end
+
+---@class A
+local a
+a.x = 1
+
+---@type { [A]: number }
+local b
+
+local c = f(b)
+c.<?x?>
]]
TEST [[
@@ -466,9 +575,6 @@ TEST [[
---@return fun(t: V[]):V
local function f() end
----@class A
-local <!a!>
-
---@type A[]
local b
@@ -485,59 +591,95 @@ TEST [[
local function f(t) end
---@class A
-local <!a!>
+local a
+a.<!x!> = 1
---@type A[]
local b
local f2, c = f(b)
-local <?<!d!>?> = f2(c)
+local d = f2(c)
+d.<?x?>
]]
TEST [[
----@class C
-local <!v1!>
-
---@generic V, T
---@param t T
---@return fun(t: V): V
---@return T
local function iterator(t) end
-for <!v!> in iterator(<!v1!>) do
+for <!v!> in iterator(<!function () end!>) do
print(<?v?>)
end
]]
TEST [[
----@class C
-local <!v!>
+---@alias C <!fun()!>
----@type C
-local <!v1!>
+---@type C[]
+local v1
---@generic V, T
---@param t T
----@return fun(t: V): V
+---@return fun(t: V[]): V
---@return T
local function iterator(t) end
-for <!v!> in iterator(<!v1!>) do
+for <!v!> in iterator(v1) do
print(<?v?>)
end
]]
TEST [[
----@class C
-local <!v!>
+---@class TT<V>: { <!x: V!> }
----@type C[]
+---@type TT<A>
+local t
+
+---@class A: <!{}!>
+
+print(t.<?x?>)
+]]
+
+TEST [[
+---@alias TT<V> { <!x: V!> }
+
+---@type TT<A>
+local t
+
+---@class A: <!{}!>
+
+print(t.<?x?>)
+]]
+
+TEST [[
+---@class TT<V>: { [number]: V }
+
+---@type TT<<!{}!>>
local v1
---@generic V, T
---@param t T
----@return fun(t: V[]): V
+---@return fun(t: { [number]: V }): V
+---@return T
+local function iterator(t) end
+
+for <!v!> in iterator(v1) do
+ print(<?v?>)
+end
+]]
+
+TEST [[
+---@class TT<K, V>: { [K]: V }
+
+---@type TT<number, <!{}!>>
+local v1
+
+---@generic V, T
+---@param t T
+---@return fun(t: { [number]: V }): V
---@return T
local function iterator(t) end
@@ -551,12 +693,32 @@ TEST [[
local Foo = {}
function Foo:<!bar1!>() end
+---@type { [number]: Foo }
+local v1
+
+---@generic T: table, V
+---@param t T
+---@return fun(table: { [number]: V }, i?: integer):integer, V
+---@return T
+---@return integer i
+local function ipairs(t) end
+
+for i, v in ipairs(v1) do
+ print(v.<?bar1?>)
+end
+]]
+
+TEST [[
+---@class Foo
+local Foo = {}
+function Foo:<!bar1!>() end
+
---@type table<number, Foo>
local v1
---@generic T: table, V
---@param t T
----@return fun(table: V[], i?: integer):integer, V
+---@return fun(table: { [number]: V }, i?: integer):integer, V
---@return T
---@return integer i
local function ipairs(t) end
@@ -615,7 +777,7 @@ function Foo:<!bar1!>() end
---@generic T: table, V
---@param t T
----@return fun(table: V[], i?: integer):integer, V
+---@return fun(table: table<number, V>, i?: integer):integer, V
---@return T
---@return integer i
local function ipairs(t) end
@@ -660,22 +822,22 @@ print(t.<?x?>)
TEST [[
---@class A
----@field <![1]!>? boolean
+---@field [1]? <!{}!>
local t
-print(t[<?1?>])
+local <!<?v?>!> = t[1]
]]
TEST [[
----@type { <![1]?: boolean!> }
+---@type { [1]?: <!{}!> }
local t
-print(t[<?1?>])
+local <!<?v?>!> = t[1]
]]
TEST [[
---@class A
----@field <!['xx']!>? boolean
+---@field <!['xx']!>? <!{}!>
local t
print(t.<?xx?>)
diff --git a/test/definition/special.lua b/test/definition/special.lua
index 3f0d076a..531c5d93 100644
--- a/test/definition/special.lua
+++ b/test/definition/special.lua
@@ -32,24 +32,28 @@ local obj = setmetatable({}, { __index = mt })
obj:<?method1?>()
]]
-TEST [[
-local mt
-function mt:<!method1!>()
-end
-
-setmetatable(api, { __index = mt })
-api:<?method1?>()
-]]
+-- 不再支持在变量的引用中使用 setmetatable 操作。
+-- 这会将引用转换为定义,为了搜索定义去检查引用性价比太差了。
+-- 如果有必要,请使用 ---@class 系统。
-TEST [[
-local mt
-local api
-function mt:<!method1!>()
-end
+--TEST [[
+--local mt
+--function mt:<!method1!>()
+--end
+--
+--setmetatable(api, { __index = mt })
+--api:<?method1?>()
+--]]
-setmetatable(api, { __index = mt })
-api:<?method1?>()
-]]
+--TEST [[
+--local mt
+--local api
+--function mt:<!method1!>()
+--end
+--
+--setmetatable(api, { __index = mt })
+--api:<?method1?>()
+--]]
-- TODO 不支持从方法内部找外部的赋值
--TEST [[
diff --git a/test/definition/table.lua b/test/definition/table.lua
index 61e8746d..66e71b0c 100644
--- a/test/definition/table.lua
+++ b/test/definition/table.lua
@@ -134,32 +134,44 @@ local y = {
t.<?insert?>()
]]
+
+TEST [[
+local x
+x.y.<!z!> = 1
+print(x.y.<?z?>)
+]]
+
+
+TEST [[
+local x
+x.y = {
+ <!z!> = 1
+}
+print(x.y.<?z?>)
+]]
+
+TEST [[
+local x = {
+ y = {
+ <!z!> = 1
+ }
+}
+print(x.y.<?z?>)
+]]
+
TEST [[
local function f()
- local t = {}
- t.field1 = {
+ local t = {
<!x!> = 1,
- y = 1,
- z = 1,
- }
- t.field2 = {
- x = 1,
- y = 1,
- z = 1,
- }
- t.field3 = {
- x = 1,
- y = 1,
- z = 1,
}
return t
end
local t = f()
-t.field1.<?x?>
+t.<?x?>
]]
-TEST [[
-local t = { <!a!> }
-
-print(t[<?1?>])
-]]
+--TEST [[
+--local t = { <!a!> }
+--
+--print(t[<?1?>])
+--]]
diff --git a/test/diagnostics/common.lua b/test/diagnostics/common.lua
new file mode 100644
index 00000000..6aa1dd6a
--- /dev/null
+++ b/test/diagnostics/common.lua
@@ -0,0 +1,1389 @@
+local config = require 'config'
+
+TEST [[
+local <!x!>
+]]
+
+TEST [[
+local y
+local x <close> = y
+]]
+
+TEST [[
+local function x()
+end
+x()
+]]
+
+TEST [[
+return function (x)
+ x.a = 1
+end
+]]
+
+TEST [[
+local <!t!> = {}
+<!t!>.a = 1
+]]
+
+TEST [[
+local <!function <!x!>()
+end!>
+]]
+
+
+TEST [[
+local <!x!> = <!function () end!>
+]]
+
+TEST [[
+local <!x!>
+<!x!> = <!function () end!>
+]]
+
+TEST [[
+local <!function x()
+end!>
+local <!function <!y!>()
+ x()
+end!>
+]]
+
+TEST [[
+local print, _G
+print(<!x!>)
+print(<!log!>)
+print(<!X!>)
+print(<!Log!>)
+print(<!y!>)
+print(Z)
+print(_G)
+Z = 1
+]]
+
+TEST [[
+::<!LABEL!>::
+]]
+
+TEST [[
+<! !>
+]]
+
+TEST [[
+
+<! !>
+]]
+
+TEST [[
+X = 1<! !>
+]]
+
+TEST [[
+X = [=[
+ ]=]
+]]
+
+TEST [[
+local x
+print(x)
+local <!x!>
+print(x)
+]]
+
+TEST [[
+local x
+print(x)
+local <!x!>
+print(x)
+local <!x!>
+print(x)
+]]
+
+TEST [[
+local _
+print(_)
+local _
+print(_)
+local _ENV
+<!print!>(_ENV) -- 由于重定义了_ENV,因此print变为了未定义全局变量
+]]
+
+TEST [[
+local x
+return x, function (<!x!>)
+ return x
+end
+]]
+
+TEST [[
+print(1)
+_ENV = nil
+]]
+
+TEST [[
+local _ENV = { print = print }
+print(1)
+]]
+
+config.get(nil, 'Lua.diagnostics.disable')['undefined-env-child'] = true
+TEST [[
+_ENV = nil
+<!GLOBAL!> = 1 --> _ENV.GLOBAL = 1
+]]
+
+TEST [[
+_ENV = nil
+local _ = <!print!> --> local _ = _ENV.print
+]]
+
+TEST [[
+_ENV = {}
+GLOBAL = 1 --> _ENV.GLOBAL = 1
+]]
+
+TEST [[
+_ENV = {}
+local _ = print --> local _ = _ENV.print
+]]
+
+TEST [[
+GLOBAL = 1
+_ENV = nil
+]]
+
+config.get(nil, 'Lua.diagnostics.disable')['undefined-env-child'] = nil
+TEST [[
+<!print()
+('string')!>:sub(1, 1)
+]]
+
+TEST [[
+print()
+('string')
+]]
+
+TEST [[
+pairs
+{}
+{}
+]]
+
+TEST [[
+local x
+return x
+ : f(1)
+ : f(1)
+]]
+
+TEST [[
+return {
+ <!print
+ 'string'!>
+}
+]]
+
+TEST [[
+return {
+ <!print
+ {
+ x = 1,
+ }!>
+}
+]]
+
+TEST [[
+print()
+'string'
+]]
+
+TEST [[
+print
+{
+ x = 1,
+}
+]]
+
+TEST [[
+local function x(a, b)
+ return a, b
+end
+x(1, 2, <!3!>)
+]]
+
+TEST [[
+local function x(a, b, ...)
+ return a, b, ...
+end
+x(1, 2, 3, 4, 5)
+]]
+
+TEST [[
+local m = {}
+function m:x(a, b)
+ return a, b
+end
+m:x(1, 2, <!3!>)
+]]
+
+TEST [[
+local m = {}
+function m:x(a, b)
+ return a, b
+end
+m.x(1, 2, 3, <!4!>)
+]]
+
+TEST [[
+local m = {}
+function m.x(a, b)
+ return a, b
+end
+m:x(1, <!2!>, <!3!>, <!4!>)
+]]
+
+TEST [[
+local m = {}
+function m.x()
+end
+m:x()
+]]
+
+TEST [[
+InstanceName = 1
+Instance = _G[InstanceName]
+]]
+
+TEST [[
+local _ = (''):sub(1, 2)
+]]
+
+TEST [=[
+return [[
+
+]]
+]=]
+
+config.get(nil, 'Lua.diagnostics.disable')['close-non-object'] = true
+TEST [[
+local _ <close> = function () end
+]]
+
+config.get(nil, 'Lua.diagnostics.disable')['close-non-object'] = nil
+TEST [[
+local _ <close> = <!1!>
+]]
+
+config.get(nil, 'Lua.diagnostics.disable')['unused-local'] = true
+TEST [[
+local f = <!function () end!>
+]]
+
+TEST [[
+local f;f = <!function () end!>
+]]
+
+TEST [[
+local <!function f() end!>
+]]
+
+config.get(nil, 'Lua.diagnostics.disable')['unused-local'] = nil
+TEST [[
+local mt, x
+function mt:m()
+ function x:m()
+ end
+end
+return mt, x
+]]
+
+TEST [[
+local mt = {}
+function mt:f()
+end
+return mt
+]]
+
+TEST [[
+local <!mt!> = {}
+function <!mt!>:f()
+end
+]]
+
+TEST [[
+local <!x!> = {}
+<!x!>.a = 1
+]]
+
+TEST [[
+local <!x!> = {}
+<!x!>['a'] = 1
+]]
+
+TEST [[
+local function f(<!self!>)
+end
+f()
+]]
+
+TEST [[
+local function f(<!...!>)
+end
+f()
+]]
+
+TEST [[
+local function f(var)
+ print(var)
+end
+local var
+f(var)
+]]
+
+TEST [[
+local function f(a, b)
+ return a, b
+end
+f(1, 2, <!3!>, <!4!>)
+]]
+
+TEST [[
+local mt = {}
+function mt:f(a, b)
+ return a, b
+end
+mt.f(1, 2, 3, <!4!>)
+]]
+
+
+TEST [[
+local mt = {}
+function mt.f(a, b)
+ return a, b
+end
+mt:f(1, <!2!>, <!3!>, <!4!>)
+]]
+
+TEST [[
+local mt = {}
+function mt:f(a, b)
+ return a, b
+end
+mt:f(1, 2, <!3!>, <!4!>)
+]]
+
+TEST [[
+local function f(a, b, ...)
+ return a, b, ...
+end
+f(1, 2, 3, 4)
+]]
+
+TEST [[
+local _ = next({}, 1, <!2!>)
+print(1, 2, 3, 4, 5)
+]]
+
+TEST [[
+local function f(callback)
+ callback(1, 2, 3)
+end
+f(function () end)
+]]
+
+--TEST [[
+--local realTostring = tostring
+--tostring = function () end
+--tostring(<!1!>)
+--tostring = realTostring
+--tostring(1)
+--]]
+
+TEST [[
+<!aa!> = 1
+tostring = 1
+ROOT = 1
+_G.bb = 1
+]]
+
+TEST [[
+local f = load('')
+f(1, 2, 3)
+]]
+
+TEST [[
+local _ = <!unpack!>()
+]]
+
+TEST [[
+X = table[<!x!>]
+]]
+
+TEST [[
+return {
+ <!x!> = 1,
+ y = 2,
+ <!x!> = 3,
+}
+]]
+
+TEST [[
+return {
+ x = 1,
+ y = 2,
+}, {
+ x = 1,
+ y = 2,
+}
+]]
+
+TEST [[
+local m = {}
+function m.open()
+end
+
+m:open()
+]]
+
+TEST [[
+local m = {}
+function m:open()
+end
+
+m.open('ok')
+]]
+
+TEST [[
+<!if true then
+end!>
+]]
+
+TEST [[
+<!if true then
+else
+end!>
+]]
+
+TEST [[
+if true then
+else
+ return
+end
+]]
+
+TEST [[
+while true do
+end
+]]
+
+TEST [[
+<!for _ = 1, 10 do
+end!>
+]]
+
+TEST [[
+<!for _ in pairs(_VERSION) do
+end!>
+]]
+
+TEST [[
+local _ = 1, <!2!>
+]]
+
+TEST [[
+_ = 1, <!2!>
+]]
+
+TEST [[
+local function x()
+ do
+ local k
+ print(k)
+ x()
+ end
+ local k = 1
+ print(k)
+end
+]]
+
+TEST [[
+local function x()
+ local loc
+ x()
+ print(loc)
+end
+]]
+
+TEST [[
+local <!t!> = {}
+<!t!>[1] = 1
+]]
+
+TEST [[
+T1 = 1
+_ENV.T2 = 1
+_G.T3 = 1
+_ENV._G.T4 = 1
+_G._G._G.T5 = 1
+rawset(_G, 'T6', 1)
+rawset(_ENV, 'T7', 1)
+print(T1)
+print(T2)
+print(T3)
+print(T4)
+print(T5)
+print(T6)
+print(T7)
+]]
+
+TEST [[
+local x
+x = <!x or 0 + 1!>
+]]
+
+TEST [[
+local x, y
+x = <!x + y or 0!>
+]]
+
+TEST [[
+local x, y, z
+x = x and y or '' .. z
+]]
+
+TEST [[
+local x
+x = x or -1
+]]
+
+TEST [[
+local x
+x = x or (0 + 1)
+]]
+
+TEST [[
+local x, y
+x = (x + y) or 0
+]]
+
+TEST [[
+local t = {}
+t.a = 1
+t.a = 2
+return t
+]]
+
+TEST [[
+table.insert({}, 1, 2, <!3!>)
+]]
+
+TEST [[
+while true do
+ break
+ <!print()
+ print()!>
+end
+]]
+
+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
+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()
+]]
+
+TEST [[
+---@class c
+c = {}
+]]
+
+TEST [[
+---@generic T: any
+---@param v T
+---@param message any
+---@return T
+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 -- TODO 这里应该给警告
+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 = 1, 1 do
+ print(i)
+end
+]]
+
+TEST [[
+---@param a number
+return function (<!a!>)
+end
+]]
+
+TEST [[
+---@meta
+
+---@param a number
+return function (a)
+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 [[
+---@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
+
+<!f!>(function () ---@async
+ return nil
+end)
+]]
+
+TEST [[
+local function f(cb)
+ pcall(cb)
+end
+
+<!f!>(function () ---@async
+ return nil
+end)
+]]
+
+TEST [[
+---@param c any
+local function f(c)
+ return c
+end
+
+f(function () ---@async
+ return nil
+end)
+]]
+
+TEST [[
+---@param ... any
+local function f(...)
+ return ...
+end
+
+f(function () ---@async
+ return nil
+end)
+]]
+
+TEST [[
+---@vararg any
+local function f(...)
+ return ...
+end
+
+f(function () ---@async
+ return nil
+end)
+]]
+
+TEST [[
+local function f(...)
+ return ...
+end
+
+f(function () ---@async
+ return nil
+end)
+]]
+
+TEST [[
+local function f(...)
+ return ...
+end
+
+f(1, function () ---@async
+ return nil
+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'):gsub()
+]]
+
+TEST [[
+local value
+value = '1'
+value = value:gsub()
+]]
diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua
index 58414b60..75d9da6c 100644
--- a/test/diagnostics/init.lua
+++ b/test/diagnostics/init.lua
@@ -43,1543 +43,11 @@ function TEST(script, ...)
error(('%s\n%s'):format(util.dump(catched['!']), util.dump(results)))
end
else
- assert(catched['!'] == nil)
+ assert(#catched['!'] == 0)
end
files.remove('')
end
-TEST [[
-local <!x!>
-]]
-
-TEST [[
-local y
-local x <close> = y
-]]
-
-TEST [[
-local function x()
-end
-x()
-]]
-
-TEST [[
-return function (x)
- x.a = 1
-end
-]]
-
-TEST [[
-local <!t!> = {}
-<!t!>.a = 1
-]]
-
-TEST [[
-local <!function <!x!>()
-end!>
-]]
-
-
-TEST [[
-local <!x!> = <!function () end!>
-]]
-
-TEST [[
-local <!x!>
-<!x!> = <!function () end!>
-]]
-
-TEST [[
-local <!function x()
-end!>
-local <!function <!y!>()
- x()
-end!>
-]]
-
-TEST [[
-local print, _G
-print(<!x!>)
-print(<!log!>)
-print(<!X!>)
-print(<!Log!>)
-print(<!y!>)
-print(Z)
-print(_G)
-Z = 1
-]]
-
-TEST [[
-::<!LABEL!>::
-]]
-
-TEST [[
-<! !>
-]]
-
-TEST [[
-
-<! !>
-]]
-
-TEST [[
-X = 1<! !>
-]]
-
-TEST [[
-X = [=[
- ]=]
-]]
-
-TEST [[
-local x
-print(x)
-local <!x!>
-print(x)
-]]
-
-TEST [[
-local x
-print(x)
-local <!x!>
-print(x)
-local <!x!>
-print(x)
-]]
-
-TEST [[
-local _
-print(_)
-local _
-print(_)
-local _ENV
-<!print!>(_ENV) -- 由于重定义了_ENV,因此print变为了未定义全局变量
-]]
-
-TEST [[
-local x
-return x, function (<!x!>)
- return x
-end
-]]
-
-TEST [[
-print(1)
-_ENV = nil
-]]
-
-TEST [[
-local _ENV = { print = print }
-print(1)
-]]
-
-config.get(nil, 'Lua.diagnostics.disable')['undefined-env-child'] = true
-TEST [[
-_ENV = nil
-<!GLOBAL!> = 1 --> _ENV.GLOBAL = 1
-]]
-
-TEST [[
-_ENV = nil
-local _ = <!print!> --> local _ = _ENV.print
-]]
-
-TEST [[
-_ENV = {}
-GLOBAL = 1 --> _ENV.GLOBAL = 1
-]]
-
-TEST [[
-_ENV = {}
-local _ = print --> local _ = _ENV.print
-]]
-
-TEST [[
-GLOBAL = 1
-_ENV = nil
-]]
-
-config.get(nil, 'Lua.diagnostics.disable')['undefined-env-child'] = nil
-TEST [[
-<!print()
-('string')!>:sub(1, 1)
-]]
-
-TEST [[
-print()
-('string')
-]]
-
-TEST [[
-pairs
-{}
-{}
-]]
-
-TEST [[
-local x
-return x
- : f(1)
- : f(1)
-]]
-
-TEST [[
-return {
- <!print
- 'string'!>
-}
-]]
-
-TEST [[
-return {
- <!print
- {
- x = 1,
- }!>
-}
-]]
-
-TEST [[
-print()
-'string'
-]]
-
-TEST [[
-print
-{
- x = 1,
-}
-]]
-
-TEST [[
-local function x(a, b)
- return a, b
-end
-x(1, 2, <!3!>)
-]]
-
-TEST [[
-local function x(a, b, ...)
- return a, b, ...
-end
-x(1, 2, 3, 4, 5)
-]]
-
-TEST [[
-local m = {}
-function m:x(a, b)
- return a, b
-end
-m:x(1, 2, <!3!>)
-]]
-
-TEST [[
-local m = {}
-function m:x(a, b)
- return a, b
-end
-m.x(1, 2, 3, <!4!>)
-]]
-
-TEST [[
-local m = {}
-function m.x(a, b)
- return a, b
-end
-m:x(1, <!2!>, <!3!>, <!4!>)
-]]
-
-TEST [[
-local m = {}
-function m.x()
-end
-m:x()
-]]
-
-TEST [[
-InstanceName = 1
-Instance = _G[InstanceName]
-]]
-
-TEST [[
-local _ = (''):sub(1, 2)
-]]
-
-TEST [=[
-return [[
-
-]]
-]=]
-
-config.get(nil, 'Lua.diagnostics.disable')['close-non-object'] = true
-TEST [[
-local _ <close> = function () end
-]]
-
-config.get(nil, 'Lua.diagnostics.disable')['close-non-object'] = nil
-TEST [[
-local _ <close> = <!1!>
-]]
-
-config.get(nil, 'Lua.diagnostics.disable')['unused-local'] = true
-TEST [[
-local f = <!function () end!>
-]]
-
-TEST [[
-local f;f = <!function () end!>
-]]
-
-TEST [[
-local <!function f() end!>
-]]
-
-config.get(nil, 'Lua.diagnostics.disable')['unused-local'] = nil
-TEST [[
-local mt, x
-function mt:m()
- function x:m()
- end
-end
-return mt, x
-]]
-
-TEST [[
-local mt = {}
-function mt:f()
-end
-return mt
-]]
-
-TEST [[
-local <!mt!> = {}
-function <!mt!>:f()
-end
-]]
-
-TEST [[
-local <!x!> = {}
-<!x!>.a = 1
-]]
-
-TEST [[
-local <!x!> = {}
-<!x!>['a'] = 1
-]]
-
-TEST [[
-local function f(<!self!>)
-end
-f()
-]]
-
-TEST [[
-local function f(<!...!>)
-end
-f()
-]]
-
-TEST [[
-local function f(var)
- print(var)
-end
-local var
-f(var)
-]]
-
-TEST [[
-local function f(a, b)
- return a, b
-end
-f(1, 2, <!3!>, <!4!>)
-]]
-
-TEST [[
-local mt = {}
-function mt:f(a, b)
- return a, b
-end
-mt.f(1, 2, 3, <!4!>)
-]]
-
-
-TEST [[
-local mt = {}
-function mt.f(a, b)
- return a, b
-end
-mt:f(1, <!2!>, <!3!>, <!4!>)
-]]
-
-TEST [[
-local mt = {}
-function mt:f(a, b)
- return a, b
-end
-mt:f(1, 2, <!3!>, <!4!>)
-]]
-
-TEST [[
-local function f(a, b, ...)
- return a, b, ...
-end
-f(1, 2, 3, 4)
-]]
-
-TEST [[
-local _ = next({}, 1, <!2!>)
-print(1, 2, 3, 4, 5)
-]]
-
-TEST [[
-local function f(callback)
- callback(1, 2, 3)
-end
-f(function () end)
-]]
-
---TEST [[
---local realTostring = tostring
---tostring = function () end
---tostring(<!1!>)
---tostring = realTostring
---tostring(1)
---]]
-
-TEST [[
-<!aa!> = 1
-tostring = 1
-ROOT = 1
-_G.bb = 1
-]]
-
-TEST [[
-local f = load('')
-f(1, 2, 3)
-]]
-
-TEST [[
-local _ = <!unpack!>()
-]]
-
-TEST [[
-X = table[<!x!>]
-]]
-
-TEST [[
-return {
- <!x!> = 1,
- y = 2,
- <!x!> = 3,
-}
-]]
-
-TEST [[
-return {
- x = 1,
- y = 2,
-}, {
- x = 1,
- y = 2,
-}
-]]
-
-TEST [[
-local m = {}
-function m.open()
-end
-
-m:open()
-]]
-
-TEST [[
-local m = {}
-function m:open()
-end
-
-m.open('ok')
-]]
-
-TEST [[
-<!if true then
-end!>
-]]
-
-TEST [[
-<!if true then
-else
-end!>
-]]
-
-TEST [[
-if true then
-else
- return
-end
-]]
-
-TEST [[
-while true do
-end
-]]
-
-TEST [[
-<!for _ = 1, 10 do
-end!>
-]]
-
-TEST [[
-<!for _ in pairs(_VERSION) do
-end!>
-]]
-
-TEST [[
-local _ = 1, <!2!>
-]]
-
-TEST [[
-_ = 1, <!2!>
-]]
-
-TEST [[
-local function x()
- do
- local k
- print(k)
- x()
- end
- local k = 1
- print(k)
-end
-]]
-
-TEST [[
-local function x()
- local loc
- x()
- print(loc)
-end
-]]
-
-TEST [[
-local <!t!> = {}
-<!t!>[1] = 1
-]]
-
-TEST [[
-T1 = 1
-_ENV.T2 = 1
-_G.T3 = 1
-_ENV._G.T4 = 1
-_G._G._G.T5 = 1
-rawset(_G, 'T6', 1)
-rawset(_ENV, 'T7', 1)
-print(T1)
-print(T2)
-print(T3)
-print(T4)
-print(T5)
-print(T6)
-print(T7)
-]]
-
-TEST [[
-local x
-x = <!x or 0 + 1!>
-]]
-
-TEST [[
-local x, y
-x = <!x + y or 0!>
-]]
-
-TEST [[
-local x, y, z
-x = x and y or '' .. z
-]]
-
-TEST [[
-local x
-x = x or -1
-]]
-
-TEST [[
-local x
-x = x or (0 + 1)
-]]
-
-TEST [[
-local x, y
-x = (x + y) or 0
-]]
-
-TEST [[
-local t = {}
-t.a = 1
-t.a = 2
-return t
-]]
-
-TEST [[
-table.insert({}, 1, 2, <!3!>)
-]]
-
-TEST [[
-while true do
- break
- <!print()
- print()!>
-end
-]]
-
-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 [[
----@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
-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()
-]]
-
-TEST [[
----@class c
-c = {}
-]]
-
-TEST [[
----@generic T: any
----@param v T
----@param message any
----@return T
-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 -- TODO 这里应该给警告
-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 = 1, 1 do
- print(i)
-end
-]]
-
-TEST [[
----@param a number
-return function (<!a!>)
-end
-]]
-
-TEST [[
----@meta
-
----@param a number
-return function (a)
-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 [[
----@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 = {}
-]]
-
-config.get(nil, 'Lua.diagnostics.neededFileStatus')['unused-local'] = 'None'
-TEST [[
----@param table table
----@param metatable table
----@return table
-function Setmetatable(table, metatable) end
-
-Setmetatable(<!1!>, {})
-]]
-
-TEST [[
----@param table table
----@param metatable table
----@return table
-function Setmetatable(table, metatable) end
-
-Setmetatable(<!'name'!>, {})
-
-]]
-
-TEST [[
----@param table table
----@param metatable table
----@return table
-function Setmetatable(table, metatable) end
-
----@type table
-local name
----@type function
-local mt
----err
-Setmetatable(name, <!mt!>)
-]]
-
-TEST [[
----@param p1 string
----@param p2 number
----@return table
-local function func1(p1, p2) end
-
----@type string
-local s
----@type table
-local t
----err
-func1(s, <!t!>)
-]]
-
-TEST [[
----@class bird
----@field wing string
-
----@class eagle
----@field family bird
-
----@class chicken
----@field family bird
-
----@param bd eagle
-local function fly(bd) end
-
----@type chicken
-local h
-fly(<!h!>)
-]]
-
-TEST [[
----@overload fun(x: number, y: number)
----@param x boolean
----@param y boolean
-local function f(x, y) end
-
-f(true, true) -- OK
-f(0, 0) -- OK
-
-]]
-
-TEST [[
----@class bird
-local m = {}
-setmetatable(m, {}) -- OK
-]]
-
-TEST [[
----@class childString: string
-local s
----@param name string
-local function f(name) end
-f(s)
-]]
-
-TEST [[
----@class childString: string
-
----@type string
-local s
----@param name childString
-local function f(name) end
-f(<!s!>)
-]]
-
-TEST [[
----@alias searchmode '"ref"'|'"def"'|'"field"'|'"allref"'|'"alldef"'|'"allfield"'
-
----@param mode searchmode
-local function searchRefs(mode)end
-searchRefs('ref')
-]]
-
-TEST [[
----@class markdown
-local mt = {}
----@param language string
----@param text string|markdown
-function mt:add(language, text)
- if not text then
- return
- end
-end
----@type markdown
-local desc
-
-desc:add('md', 'hover')
-]]
-
----可选参数和枚举
-TEST [[
----@param str string
----@param mode? '"left"'|'"right"'
----@return string
-local function trim(str, mode)
- if mode == "left" then
- print(1)
- end
-end
-trim('str', 'left')
-trim('str', nil)
-]]
-
-config.get(nil, 'Lua.diagnostics.neededFileStatus')['unused-local'] = 'Any'
-
----不完整的函数参数定义,会跳过检查
-TEST [[
----@param mode string
-local function status(source, field, mode)
- print(source, field, mode)
-end
-status(1, 2, 'name')
-]]
-
-
-TEST [[
----@alias range {start: number, end: number}
----@param uri string
----@param range range
-local function location(uri, range)
- print(uri, range)
-end
----@type range
-local val = {}
-location('uri', val)
-]]
-
--- 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
-
-<!f!>(function () ---@async
- return nil
-end)
-]]
-
-TEST [[
-local function f(cb)
- pcall(cb)
-end
-
-<!f!>(function () ---@async
- return nil
-end)
-]]
-
-TEST [[
----@param c any
-local function f(c)
- return c
-end
-
-f(function () ---@async
- return nil
-end)
-]]
-
-TEST [[
----@param ... any
-local function f(...)
- return ...
-end
-
-f(function () ---@async
- return nil
-end)
-]]
-
-TEST [[
----@vararg any
-local function f(...)
- return ...
-end
-
-f(function () ---@async
- return nil
-end)
-]]
-
-TEST [[
-local function f(...)
- return ...
-end
-
-f(function () ---@async
- return nil
-end)
-]]
-
-TEST [[
-local function f(...)
- return ...
-end
-
-f(1, function () ---@async
- return nil
-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 [[
-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
-]]
+require 'diagnostics.common'
+--require 'diagnostics.type-check'
diff --git a/test/diagnostics/type-check.lua b/test/diagnostics/type-check.lua
new file mode 100644
index 00000000..9d9eb3ec
--- /dev/null
+++ b/test/diagnostics/type-check.lua
@@ -0,0 +1,164 @@
+local config = require 'config'
+
+config.get(nil, 'Lua.diagnostics.neededFileStatus')['unused-local'] = 'None'
+TEST [[
+---@param table table
+---@param metatable table
+---@return table
+function Setmetatable(table, metatable) end
+
+Setmetatable(<!1!>, {})
+]]
+
+TEST [[
+---@param table table
+---@param metatable table
+---@return table
+function Setmetatable(table, metatable) end
+
+Setmetatable(<!'name'!>, {})
+
+]]
+
+TEST [[
+---@param table table
+---@param metatable table
+---@return table
+function Setmetatable(table, metatable) end
+
+---@type table
+local name
+---@type function
+local mt
+---err
+Setmetatable(name, <!mt!>)
+]]
+
+TEST [[
+---@param p1 string
+---@param p2 number
+---@return table
+local function func1(p1, p2) end
+
+---@type string
+local s
+---@type table
+local t
+---err
+func1(s, <!t!>)
+]]
+
+TEST [[
+---@class bird
+---@field wing string
+
+---@class eagle
+---@field family bird
+
+---@class chicken
+---@field family bird
+
+---@param bd eagle
+local function fly(bd) end
+
+---@type chicken
+local h
+fly(<!h!>)
+]]
+
+TEST [[
+---@overload fun(x: number, y: number)
+---@param x boolean
+---@param y boolean
+local function f(x, y) end
+
+f(true, true) -- OK
+f(0, 0) -- OK
+
+]]
+
+TEST [[
+---@class bird
+local m = {}
+setmetatable(m, {}) -- OK
+]]
+
+TEST [[
+---@class childString: string
+local s
+---@param name string
+local function f(name) end
+f(s)
+]]
+
+TEST [[
+---@class childString: string
+
+---@type string
+local s
+---@param name childString
+local function f(name) end
+f(<!s!>)
+]]
+
+TEST [[
+---@alias searchmode '"ref"'|'"def"'|'"field"'|'"allref"'|'"alldef"'|'"allfield"'
+
+---@param mode searchmode
+local function searchRefs(mode)end
+searchRefs('ref')
+]]
+
+TEST [[
+---@class markdown
+local mt = {}
+---@param language string
+---@param text string|markdown
+function mt:add(language, text)
+ if not text then
+ return
+ end
+end
+---@type markdown
+local desc
+
+desc:add('md', 'hover')
+]]
+
+---可选参数和枚举
+TEST [[
+---@param str string
+---@param mode? '"left"'|'"right"'
+---@return string
+local function trim(str, mode)
+ if mode == "left" then
+ print(1)
+ end
+end
+trim('str', 'left')
+trim('str', nil)
+]]
+
+config.get(nil, 'Lua.diagnostics.neededFileStatus')['unused-local'] = 'Any'
+
+---不完整的函数参数定义,会跳过检查
+TEST [[
+---@param mode string
+local function status(source, field, mode)
+ print(source, field, mode)
+end
+status(1, 2, 'name')
+]]
+
+
+TEST [[
+---@alias range {start: number, end: number}
+---@param uri string
+---@param range range
+local function location(uri, range)
+ print(uri, range)
+end
+---@type range
+local val = {}
+location('uri', val)
+]]
diff --git a/test/example/guide.txt b/test/example/guide.txt
index cff05faf..1aef61ae 100644
--- a/test/example/guide.txt
+++ b/test/example/guide.txt
@@ -2718,7 +2718,7 @@ function m.viewInferType(infers)
or src.type == 'doc.type.name'
or src.type == 'doc.type.array'
or src.type == 'doc.type.table'
- or src.type == 'doc.type.enum'
+ or src.type == 'doc.type.string'
or src.type == 'doc.resume' then
local tp = infer.type or 'any'
if not mark[tp] then
diff --git a/test/full/example.lua b/test/full/example.lua
index ed5c3b16..e8352547 100644
--- a/test/full/example.lua
+++ b/test/full/example.lua
@@ -5,7 +5,6 @@ local diag = require 'core.diagnostics'
local config = require 'config'
local fs = require 'bee.filesystem'
local luadoc = require "parser.luadoc"
-local noder = require 'core.noder'
-- 临时
---@diagnostic disable: await-in-sync
diff --git a/test/highlight/init.lua b/test/highlight/init.lua
index 8e07c5f0..0cca79f1 100644
--- a/test/highlight/init.lua
+++ b/test/highlight/init.lua
@@ -1,3 +1,4 @@
+---@diagnostic disable: await-in-sync
local core = require 'core.highlight'
local files = require 'files'
local catch = require 'catch'
diff --git a/test/hover/init.lua b/test/hover/init.lua
index c5d8a7fc..2ae6837f 100644
--- a/test/hover/init.lua
+++ b/test/hover/init.lua
@@ -6,18 +6,19 @@ local config = require 'config'
rawset(_G, 'TEST', true)
local accept = {
- ['local'] = true,
- ['setlocal'] = true,
- ['getlocal'] = true,
- ['setglobal'] = true,
- ['getglobal'] = true,
- ['field'] = true,
- ['method'] = true,
- ['string'] = true,
- ['number'] = true,
- ['integer'] = true,
- ['doc.type.name'] = true,
- ['function'] = true,
+ ['local'] = true,
+ ['setlocal'] = true,
+ ['getlocal'] = true,
+ ['setglobal'] = true,
+ ['getglobal'] = true,
+ ['field'] = true,
+ ['method'] = true,
+ ['string'] = true,
+ ['number'] = true,
+ ['integer'] = true,
+ ['doc.type.name'] = true,
+ ['doc.class.name'] = true,
+ ['function'] = true,
}
---@diagnostic disable: await-in-sync
@@ -28,7 +29,7 @@ function TEST(script)
local hover = core.byUri('', catched['?'][1][1])
assert(hover)
expect = expect:gsub('^[\r\n]*(.-)[\r\n]*$', '%1'):gsub('\r\n', '\n')
- local label = tostring(hover):match('```lua[\r\n]*(.-)[\r\n]*```'):gsub('\r\n', '\n')
+ local label = hover:string():gsub('\r\n', '\n'):match('```lua[\r\n]*(.-)[\r\n]*```')
assert(expect == label)
files.remove('')
end
@@ -149,7 +150,7 @@ obj.<?xxx?>()
TEST [[
obj.<?xxx?>()
]]
-[[global obj.xxx: any]]
+[[global obj.xxx: unknown]]
TEST [[
local <?x?> = 1
@@ -183,7 +184,7 @@ t = {
TEST [[
local <?obj?> = {}
]]
-"local obj: {}"
+"local obj: table"
--TEST [[
--local mt = {}
@@ -272,9 +273,8 @@ TEST [[
local type
w2l:get_default()[<?type?>]
]]
-"local type: any"
+"local type: unknown"
--- TODO 可选参数(或多原型)
TEST [[
<?load?>()
]]
@@ -312,7 +312,7 @@ end
]]
[[
function x()
- -> any
+ -> unknown
]]
TEST [[
@@ -368,19 +368,19 @@ local function f()
end
local <?n?> = f()
]]
-[[local n: any]]
+[[local n: unknown]]
TEST [[
local <?n?> = table.unpack(t)
]]
-[[local n: any]]
+[[local n: unknown]]
TEST [[
local <?n?>
table.pack(n)
]]
[[
-local n: any
+local n: unknown
]]
TEST [[
@@ -451,7 +451,7 @@ local any = collectgarbage()
t[any] = any
]]
[[
-local t: {}
+local t: table
]]
TEST[[
@@ -627,7 +627,7 @@ end
local <?r?> = a(1)
]]
[[
-local r: string
+local r: string = "a"
]]
TEST[[
@@ -637,7 +637,7 @@ end
local _, <?r?> = pcall(a, 1)
]]
[[
-local r: string
+local r: string = "a"
]]
TEST[[
@@ -647,15 +647,6 @@ local <?n?> = rawlen()
local n: integer
]]
--- TODO 暂未实现
---TEST[[
---local <?n?> = pairs()
---]]
---[[
---function n<next>(table: table [, index: any])
--- -> key: any, value: any
---]]
-
TEST[[
local <?x?> = '\a'
]]
@@ -699,8 +690,8 @@ end
]]
[[
function f()
- -> any
- 2. any
+ -> nil
+ 2. nil
]]
TEST [[
@@ -710,7 +701,7 @@ end
local <?x?> = f()
]]
[[
-local x: any
+local x: nil
]]
TEST [[
@@ -721,7 +712,7 @@ end
]]
[[
function f()
- -> integer
+ -> integer|nil
]]
TEST [[
@@ -791,7 +782,7 @@ io.<?popen?>()
[[
function io.popen(prog: string, mode?: "r"|"w")
-> file*?
- 2. errmsg?: string
+ 2. errmsg: string?
]]
TEST [[
@@ -838,7 +829,6 @@ local t: {
}
]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', true)
TEST [[
local x
x = 1
@@ -849,7 +839,6 @@ print(<?x?>)
[[
local x: number = 1
]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', false)
TEST [[
local <?x?> <close> = 1
@@ -1068,7 +1057,7 @@ end
local <?r?> = f(1)
]]
[[
-local r: integer
+local r: integer = 1
]]
TEST [[
@@ -1099,6 +1088,18 @@ TEST [[
---@vararg Class
local function f(...)
+ local <?t?> = {...}
+end
+]]
+[[
+local t: Class[]
+]]
+
+TEST [[
+---@class Class
+
+---@vararg Class
+local function f(...)
local t = {...}
local <?v?> = t[1]
end
@@ -1340,7 +1341,7 @@ TEST [[
local <?f?>
]]
[[
-local f: fun(x: boolean):boolean
+local f: fun(x?: boolean):boolean?
]]
TEST [[
@@ -1364,7 +1365,7 @@ end
[[
function f(x: any, y: any)
-> first: table
- 2. second?: string
+ 2. second: string?
]]
TEST [[
@@ -1396,7 +1397,7 @@ TEST [[
local <?t?>
]]
[[
-local t: string|'enum1'|'enum2'
+local t: string|"enum1"|"enum2"
]]
TEST [[
@@ -1405,7 +1406,7 @@ TEST [[
---@type <?A?>
]]
[[
-展开为 string|'enum1'|'enum2'
+展开为 string|"enum1"|"enum2"
]]
TEST [[
@@ -1415,7 +1416,7 @@ TEST [[
local <?t?>
]]
[[
-local t: string|'enum1'|'enum2'
+local t: string|"enum1"|"enum2"
]]
TEST [[
@@ -1425,7 +1426,7 @@ TEST [[
local <?t?>
]]
[[
-local t: string|'enum1'|'enum2'
+local t: string|"enum1"|"enum2"
]]
TEST [[
@@ -1511,7 +1512,7 @@ local x --- @type boolean
local <?y?>
]]
[[
-local y: any
+local y: unknown
]]
TEST [[
@@ -1571,7 +1572,7 @@ TEST [[
local <?x?>--测试
]]
[[
-local x: any
+local x: unknown
]]
TEST [[
@@ -1593,7 +1594,7 @@ print(u.x)
]]
[[
local u: number {
- x: any,
+ x: unknown,
}
]]
@@ -1636,7 +1637,7 @@ local f
<?f?>()
]]
[[
-local f: any
+local f: unknown
]]
TEST [[
@@ -1675,7 +1676,7 @@ TEST [[
]]
[[
global a: {
- b: integer,
+ b: integer = 600,
}
]]
@@ -1683,7 +1684,7 @@ TEST [[
a.<?b?> = 10 * 60
]]
[[
-global a.b: integer
+global a.b: integer = 600
]]
TEST [[
@@ -1691,7 +1692,7 @@ a.<?b?>.c = 1 * 1
]]
[[
global a.b: {
- c: integer,
+ c: integer = 1,
}
]]
@@ -1729,37 +1730,20 @@ local t = nil
t.<?x?>()
]]
[[
-field t.x: any
+field t.x: unknown
]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', true)
TEST [[
---@class A
local a
-local b = nil
+local b
b = a
print(b.<?x?>)
]]
[[
-field A.x: any
-]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', false)
-
-TEST [[
----@class A
----@field x number
----@field y number
-
----@type A<string, number>
-local <?t?>
-]]
-[[
-local t: A<string, number> {
- x: number,
- y: number,
-}
+field A.x: unknown
]]
TEST [[
@@ -1803,3 +1787,32 @@ local <?x?> = 1 // 2
local x: integer = 1
]]
config.set(nil, 'Lua.runtime.nonstandardSymbol', {})
+
+config.set(nil, 'Lua.hover.expandAlias', false)
+TEST [[
+---@alias uri string
+
+---@type uri
+local <?uri?>
+]]
+[[
+local uri: uri
+]]
+
+config.set(nil, 'Lua.hover.expandAlias', true)
+TEST [[
+---@alias uri string
+
+---@type uri
+local <?uri?>
+]]
+[[
+local uri: string
+]]
+
+TEST [[
+local <?x?> = '1' .. '2'
+]]
+[[
+local x: string = "12"
+]]
diff --git a/test/references/all.lua b/test/references/all.lua
index 4ba63579..9395df86 100644
--- a/test/references/all.lua
+++ b/test/references/all.lua
@@ -3,7 +3,7 @@ local config = require 'config'
TEST [[
---@class A
local a = {}
-a.<?x?> = 1
+a.<~x~> = 1
---@return A
local function f() end
@@ -15,7 +15,7 @@ return b.<!x!>
TEST [[
---@class A
local a = {}
-a.<?x?> = 1
+a.<~x~> = 1
---@return table
---@return A
@@ -26,40 +26,42 @@ return a.x, b.<!x!>
]]
TEST [[
-local <?mt?> = {}
+local <~mt~> = {}
function <!mt!>:x()
- <!self!>:x()
+ self:x()
end
]]
TEST [[
local mt = {}
-function mt:<?x?>()
+function mt:<~x~>()
self:<!x!>()
end
]]
-TEST [[
----@class Dog
-local mt = {}
-function mt:<?eat?>()
-end
-
----@class Master
-local mt2 = {}
-function mt2:init()
- ---@type Dog
- local foo = self:doSomething()
- ---@type Dog
- self.dog = getDog()
-end
-function mt2:feed()
- self.dog:<!eat!>()
-end
-function mt2:doSomething()
-end
-]]
-
+--TEST [[
+-----@class Dog
+--local mt = {}
+--function mt:<~eat~>()
+--end
+--
+-----@class Master
+--local mt2 = {}
+--function mt2:init()
+-- ---@type Dog
+-- local foo = self:doSomething()
+-- ---@type Dog
+-- self.dog = getDog()
+--end
+--function mt2:feed()
+-- self.dog:<!eat!>()
+--end
+--function mt2:doSomething()
+--end
+--]]
+
+-- TODO: How to search references of function?
+--[=[
TEST [[
local function f()
return <~<!function~> ()
@@ -77,55 +79,20 @@ end
local _, <!f2!> = f()
]]
-
-config.set(nil, 'Lua.IntelliSense.traceReturn', true)
-TEST [[
-local <?x?>
-local function f()
- return <!x!>
-end
-local <!y!> = f()
-]]
-
-TEST [[
-local <?x?>
-local function f()
- return function ()
- return <!x!>
- end
-end
-local <!y!> = f()()
-]]
-config.set(nil, 'Lua.IntelliSense.traceReturn', false)
+]=]
TEST [[
---@class A
local t
---@class B: A
-local <?v?>
-]]
-
--- TODO
--- 泛型的反向搜索
-do return end
-TEST [[
----@class Dog
-local <?Dog?> = {}
-
----@generic T
----@param type1 T
----@return T
-function foobar(type1)
-end
-
-local <!v1!> = foobar(<!Dog!>)
+local <~v~>
]]
TEST [[
---@class Dog
local Dog = {}
-function Dog:<?eat?>()
+function Dog:<~eat~>()
end
---@generic T
@@ -142,7 +109,7 @@ v1:<!eat!>()
TEST [[
---@class Dog
local Dog = {}
-function Dog:<?eat?>()
+function Dog:<~eat~>()
end
---@class Master
@@ -159,51 +126,3 @@ end
local v1 = Master:foobar("", Dog)
v1.<!eat!>()
]]
-
-TEST [[
----@class A
-local <?A?>
-
----@generic T
----@param self T
----@return T
-function m.f(self) end
-
-local <!b!> = m.f(<!A!>)
-]]
-
-TEST [[
----@class A
-local <?A?>
-
----@generic T
----@param self T
----@return T
-function m:f() end
-
-local <!b!> = m.f(<!A!>)
-]]
-
-TEST [[
----@class A
-local <?A?>
-
----@generic T
----@param self T
----@return T
-function <!A!>.f(self) end
-
-local <!b!> = <!A!>:f()
-]]
-
-TEST [[
----@class A
-local <?A?>
-
----@generic T
----@param self T
----@return T
-function <!A!>:f() end
-
-local <!b!> = <!A!>:f()
-]]
diff --git a/test/references/common.lua b/test/references/common.lua
index b46aa81f..5217200d 100644
--- a/test/references/common.lua
+++ b/test/references/common.lua
@@ -1,35 +1,35 @@
local config = require "config"
TEST [[
-local <?a?> = 1
+local <~a~> = 1
<!a!> = <!a!>
]]
TEST [[
-<?a?> = 1
+<~a~> = 1
<!a!> = <!a!>
]]
TEST [[
local t
-t.<?a?> = 1
+t.<~a~> = 1
t.<!a!> = t.<!a!>
]]
TEST [[
-t.<?a?> = 1
+t.<~a~> = 1
t.<!a!> = t.<!a!>
]]
TEST [[
:: <!LABEL!> ::
-goto <?LABEL?>
+goto <~LABEL~>
if true then
goto <!LABEL!>
end
]]
TEST [[
-:: <?LABEL?> ::
+:: <~LABEL~> ::
goto <!LABEL!>
if true then
goto <!LABEL!>
@@ -38,183 +38,128 @@ end
TEST [[
local a = 1
-local <?a?> = 1
+local <~a~> = 1
<!a!> = <!a!>
]]
TEST [[
-local <!a!>
-local <?b?> = <!a!>
-]]
-
-TEST [[
-local <?a?>
-local <!b!> = <!a!>
-]]
-
-TEST [[
-local t = {
- <!a!> = 1
-}
-print(t.<?a?>)
+local <~a~>
+local b = <!a!>
]]
TEST [[
local t = {
- <?a?> = 1
+ <~a~> = 1
}
print(t.<!a!>)
]]
TEST [[
-t[<?'a'?>] = 1
+t[<~'a'~>] = 1
print(t.<!a!>)
]]
TEST [[
local t = {
- [<?'a'?>] = 1
+ [<~'a'~>] = 1
}
print(t.<!a!>)
]]
TEST [[
table.<!dump!>()
-function table.<?dump?>()
+function table.<~dump~>()
end
]]
TEST [[
local t = {}
-t.<?x?> = 1
+t.<~x~> = 1
t[a.b.c] = 1
]]
TEST [[
local t = {}
t.x = 1
-t[a.b.<?x?>] = 1
-]]
-
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', true)
-TEST [[
-local t
-local <!f!> = t.<?f?>
-
-<!f!>()
-
-return {
- <!f!> = <!f!>,
-}
+t[a.b.<~x~>] = 1
]]
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', false)
TEST [[
self = {
results = {
- <?labels?> = {},
+ <~labels~> = {},
}
}
self[self.results.<!labels!>] = lbl
]]
TEST [[
-a.b.<?c?> = 1
+a.b.<~c~> = 1
print(a.b.<!c!>)
]]
TEST [[
local <!mt!> = {}
-function <!mt!>:x()
- <?self?>:x()
+function mt:x()
+ <~self~>:x()
end
]]
TEST [[
-local mt = {}
-function mt:<!x!>()
- self:<?x?>()
+local <~mt~> = {}
+function <!mt!>:x()
+ self:x()
end
]]
TEST [[
-a.<!b!>.c = 1
-print(a.<?b?>.c)
-]]
-
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', true)
-TEST [[
-local <?f?>
-local t = {
- <!a!> = <!f!>
-}
-print(t.<!a!>)
-]]
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', false)
-
-TEST [[
-local <!f!>
-local <!t!> = <?f?>
-]]
-
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', true)
-TEST [[
-local <!f!>
-a.<!t!> = <?f?>
-]]
-
-TEST [[
-<!t!>.<!f!> = <?t?>
+local mt = {}
+function mt:<!x!>()
+ self:<~x~>()
+end
]]
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', false)
TEST [[
-local <!f!>
-local <?t?> = <!f!>
+local mt = {}
+function mt:<~x~>()
+ self:<!x!>()
+end
]]
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', true)
TEST [[
-local <!t!>
-<!t!>.<!f!> = <?t?>
+a.<!b!>.c = 1
+print(a.<~b~>.c)
]]
-config.set(nil, 'Lua.IntelliSense.traceBeSetted', false)
TEST [[
-_G.<?xxx?> = 1
+_G.<~xxx~> = 1
print(<!xxx!>)
]]
TEST [[
----@class <!Class!>
----@type <?Class?>
----@type <!Class!>
-]]
-
-TEST [[
----@class <?Class?>
+---@class <~Class~>
---@type <!Class!>
---@type <!Class!>
]]
TEST [[
---@class Class
-local <?t?>
+local <~t~>
---@type Class
-local <!x!>
+local x
]]
TEST [[
---@class Class
-local <!t!>
+local t
---@type Class
-local <?x?>
+local <~x~>
]]
-- BUG
TEST [[
----@return <?xxx?>
+---@return <~xxx~>
function f() end
]]
@@ -223,19 +168,19 @@ TEST [[
---@class B: A
---@type A
-local <?t?>
-]]
-
-TEST [[
----@class A
-local a
-
----@type A
-local b
-
----@type A
-local c
-
-b.<?x?> = 1
-c.<!x!> = 1
-]]
+local <~t~>
+]]
+
+--TEST [[
+-----@class A
+--local a
+--
+-----@type A
+--local b
+--
+-----@type A
+--local c
+--
+--b.<~x~> = 1
+--c.<!x!> = 1
+--]]
diff --git a/test/references/init.lua b/test/references/init.lua
index 81dfb481..1b1cc73b 100644
--- a/test/references/init.lua
+++ b/test/references/init.lua
@@ -1,3 +1,4 @@
+---@diagnostic disable: await-in-sync
local core = require 'core.reference'
local files = require 'files'
local catch = require 'catch'
@@ -23,7 +24,7 @@ function TEST(script)
files.setText('', newScript)
local input = catched['?'] + catched['~']
- local expect = catched['!'] + catched['?']
+ local expect = catched['!'] + catched['~']
local results = core('', input[1][1])
if results then
local positions = {}
diff --git a/test/rename/init.lua b/test/rename/init.lua
index 31421ada..64e3916a 100644
--- a/test/rename/init.lua
+++ b/test/rename/init.lua
@@ -1,3 +1,4 @@
+---@diagnostic disable: await-in-sync
local core = require 'core.rename'
local files = require 'files'
local catch = require 'catch'
@@ -90,7 +91,6 @@ local function f(b)
end
]]
---config.set('Lua.IntelliSense.traceBeSetted', true)
TEST ('a', '!!!') [[
t = {
a = 0
diff --git a/test/type_inference/init.lua b/test/type_inference/init.lua
index 7316730e..bad1a876 100644
--- a/test/type_inference/init.lua
+++ b/test/type_inference/init.lua
@@ -1,6 +1,6 @@
local files = require 'files'
local guide = require 'parser.guide'
-local infer = require 'core.infer'
+local infer = require 'vm.infer'
local config = require 'config'
local catch = require 'catch'
@@ -8,17 +8,21 @@ rawset(_G, 'TEST', true)
local function getSource(pos)
local ast = files.getState('')
- return guide.eachSourceContain(ast.ast, pos, function (source)
+ local result
+ guide.eachSourceContain(ast.ast, pos, function (source)
if source.type == 'local'
or source.type == 'getlocal'
or source.type == 'setlocal'
or source.type == 'setglobal'
or source.type == 'getglobal'
or source.type == 'field'
- or source.type == 'method' then
- return source
+ or source.type == 'method'
+ or source.type == 'function'
+ or source.type == 'table' then
+ result = source
end
end)
+ return result
end
function TEST(wanted)
@@ -27,9 +31,9 @@ function TEST(wanted)
files.setText('', newScript)
local source = getSource(catched['?'][1][1])
assert(source)
- local result = infer.searchAndViewInfers(source)
+ local result = infer.getInfer(source):view()
if wanted ~= result then
- infer.searchAndViewInfers(source)
+ infer.getInfer(source):view()
end
assert(wanted == result)
files.remove('')
@@ -52,12 +56,38 @@ TEST 'number' [[
local <?var?> = 1.0
]]
+TEST 'unknown' [[
+local <?var?>
+]]
+
+TEST 'unknown' [[
+local <?var?>
+var = y
+]]
+
+TEST 'any' [[
+function f(<?x?>)
+
+end
+]]
+
+TEST 'any' [[
+function f(<?x?>)
+ x = 1
+end
+]]
+
+TEST 'number' [[
+local <?var?>
+var = 1
+var = 1.0
+]]
+
TEST 'string' [[
local var = '111'
t.<?x?> = var
]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', true)
TEST 'string' [[
local <?var?>
var = '111'
@@ -68,7 +98,6 @@ local var
var = '111'
print(<?var?>)
]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', false)
TEST 'function' [[
function <?xx?>()
@@ -80,19 +109,17 @@ local function <?xx?>()
end
]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', true)
TEST 'function' [[
local xx
<?xx?> = function ()
end
]]
-config.set(nil, 'Lua.IntelliSense.traceLocalSet', false)
TEST 'table' [[
local <?t?> = {}
]]
-TEST 'any' [[
+TEST 'unknown' [[
<?x?>()
]]
@@ -100,7 +127,7 @@ TEST 'boolean' [[
<?x?> = not y
]]
-TEST 'any' [[
+TEST 'integer' [[
<?x?> = #y
]]
@@ -112,7 +139,7 @@ TEST 'integer' [[
<?x?> = #{}
]]
-TEST 'any' [[
+TEST 'number' [[
<?x?> = - y
]]
@@ -120,7 +147,7 @@ TEST 'number' [[
<?x?> = - 1.0
]]
-TEST 'any' [[
+TEST 'integer' [[
<?x?> = ~ y
]]
@@ -144,7 +171,7 @@ TEST 'boolean' [[
<?x?> = a == b
]]
-TEST 'any' [[
+TEST 'integer' [[
<?x?> = a << b
]]
@@ -152,7 +179,7 @@ TEST 'integer' [[
<?x?> = 1 << 2
]]
-TEST 'any' [[
+TEST 'string' [[
<?x?> = a .. b
]]
@@ -160,7 +187,15 @@ TEST 'string' [[
<?x?> = 'a' .. 'b'
]]
-TEST 'any' [[
+TEST 'string' [[
+<?x?> = 'a' .. 1
+]]
+
+TEST 'string' [[
+<?x?> = 'a' .. 1.0
+]]
+
+TEST 'number' [[
<?x?> = a + b
]]
@@ -168,6 +203,10 @@ TEST 'number' [[
<?x?> = 1 + 2.0
]]
+TEST 'integer' [[
+<?x?> = 1 + 2
+]]
+
TEST 'tablelib' [[
---@class tablelib
table = {}
@@ -185,29 +224,38 @@ TEST 'function' [[
---@class stringlib
local string
-string.sub = function () end
+string.xxx = function () end
+
+return ('x').<?xxx?>
+]]
+
+TEST 'function' [[
+---@class stringlib
+String = {}
+
+String.xxx = function () end
-return ('x').<?sub?>
+return ('x').<?xxx?>
]]
TEST 'function' [[
---@class stringlib
local string
-string.sub = function () end
+string.xxx = function () end
-<?x?> = ('x').sub
+<?x?> = ('x').xxx
]]
TEST 'function' [[
---@class stringlib
local string
-string.sub = function () end
+string.xxx = function () end
_VERSION = 'Lua 5.4'
-<?x?> = _VERSION.sub
+<?x?> = _VERSION.xxx
]]
TEST 'table' [[
@@ -221,7 +269,7 @@ end
<?y?> = x()
]]
-TEST 'integer' [[
+TEST 'integer|nil' [[
local function x()
return 1
return nil
@@ -229,7 +277,7 @@ end
<?y?> = x()
]]
-TEST 'any' [[
+TEST 'unknown|nil' [[
local function x()
return a
return nil
@@ -237,7 +285,7 @@ end
<?y?> = x()
]]
-TEST 'any' [[
+TEST 'unknown|nil' [[
local function x()
return nil
return f()
@@ -245,6 +293,14 @@ end
<?y?> = x()
]]
+TEST 'unknown' [[
+local function x()
+ return nil
+ return f()
+end
+_, <?y?> = x()
+]]
+
TEST 'integer' [[
local function x()
return 1
@@ -292,7 +348,7 @@ local <?x?> = f()
--]]
-- 不根据对方函数内的使用情况来推测
-TEST 'any' [[
+TEST 'unknown' [[
local function x(a)
_ = a + 1
end
@@ -300,7 +356,7 @@ local b
x(<?b?>)
]]
-TEST 'any' [[
+TEST 'unknown' [[
local function x(a, ...)
local _, <?b?>, _ = ...
end
@@ -308,18 +364,18 @@ x(nil, 'xx', 1, true)
]]
-- 引用不跨越参数
-TEST 'any' [[
+TEST 'unknown' [[
local function x(a, ...)
return true, 'ss', ...
end
local _, _, _, <?b?>, _ = x(nil, true, 1, 'yy')
]]
-TEST 'any' [[
+TEST 'unknown' [[
local <?x?> = next()
]]
-TEST 'any' [[
+TEST 'unknown' [[
local a, b
function a()
return b()
@@ -342,6 +398,11 @@ TEST 'string' [[
local <?x?>
]]
+TEST '1' [[
+---@type 1
+local <?v?>
+]]
+
TEST 'string[]' [[
---@class string
@@ -358,7 +419,62 @@ local <?x?>
]]
TEST '"enum1"|"enum2"' [[
----@type '"enum1"' | '"enum2"'
+---@type 'enum1' | 'enum2'
+local <?x?>
+]]
+
+TEST '"enum1"|"enum2"' [[
+---@type 'enum1' | 'enum2'
+local <?x?>
+]]
+
+config.set(nil, 'Lua.hover.expandAlias', false)
+TEST 'A' [[
+---@alias A 'enum1' | 'enum2'
+
+---@type A
+local <?x?>
+]]
+
+TEST 'A' [[
+---@alias A 'enum1' | 'enum2' | A
+
+---@type A
+local <?x?>
+]]
+
+TEST 'A' [[
+---@alias A 'enum1' | 'enum2' | B
+
+---@type A
+local <?x?>
+]]
+config.set(nil, 'Lua.hover.expandAlias', true)
+TEST '"enum1"|"enum2"' [[
+---@alias A 'enum1' | 'enum2'
+
+---@type A
+local <?x?>
+]]
+
+TEST '"enum1"|"enum2"' [[
+---@alias A 'enum1' | 'enum2' | A
+
+---@type A
+local <?x?>
+]]
+
+TEST '"enum1"|"enum2"|B' [[
+---@alias A 'enum1' | 'enum2' | B
+
+---@type A
+local <?x?>
+]]
+
+TEST '1|true' [[
+---@alias A 1 | true
+
+---@type A
local <?x?>
]]
@@ -367,6 +483,21 @@ TEST 'fun()' [[
local <?x?>
]]
+TEST 'fun(a: string, b: any, ...: any)' [[
+---@type fun(a: string, b, ...)
+local <?x?>
+]]
+
+TEST 'fun(a: string, b: any, c?: boolean, ...: any):c, d?, ...' [[
+---@type fun(a: string, b, c?: boolean, ...):c, d?, ...
+local <?x?>
+]]
+
+TEST 'table' [[
+---@type { [string]: string }
+local <?x?>
+]]
+
TEST 'table<string, number>' [[
---@class string
---@class number
@@ -414,13 +545,29 @@ print(t.<?a?>)
]]
TEST '"aaa"|"bbb"' [[
----@type table<string, '"aaa"'|'"bbb"'>
+---@type table<string, 'aaa'|'bbb'>
local t = {}
print(t.<?a?>)
]]
TEST 'integer' [[
+---@generic K
+---@type fun(a?: K):K
+local f
+
+local <?n?> = f(1)
+]]
+
+TEST 'unknown' [[
+---@generic K
+---@type fun(a?: K):K
+local f
+
+local <?n?> = f(nil)
+]]
+
+TEST 'integer' [[
---@class integer
---@generic T: table, V
@@ -537,22 +684,120 @@ local t
local <?k?>, v = f2(t)
]]
+TEST 'fun(a: <V>):integer, <V>' [[
+---@generic K, V
+---@param a K
+---@return fun(a: V):K, V
+local function f(a) end
+
+local <?f2?> = f(1)
+]]
+
+TEST 'integer' [[
+---@generic K, V
+---@param a K
+---@return fun(a: V):K, V
+local function f(a) end
+
+local f2 = f(1)
+local <?i?>, v = f2(true)
+]]
+
+TEST 'boolean' [[
+---@generic K, V
+---@param a K
+---@return fun(a: V):K, V
+local function f(a) end
+
+local f2 = f(1)
+local i, <?v?> = f2(true)
+]]
+
+TEST 'fun(table: table<<K>, <V>>, index?: <K>):<K>, <V>' [[
+---@generic T: table, K, V
+---@param t T
+---@return fun(table: table<K, V>, index?: K):K, V
+---@return T
+---@return nil
+local function pairs(t) end
+
+local <?next?> = pairs(dummy)
+]]
+
TEST 'string' [[
----@class string
+---@generic T: table, K, V
+---@param t T
+---@return fun(table: table<K, V>, index?: K):K, V
+---@return T
+---@return nil
+local function pairs(t) end
+
+local next = pairs(dummy)
+
+---@type table<string, boolean>
+local t
+local <?k?>, v = next(t)
+]]
+TEST 'boolean' [[
---@generic T: table, K, V
---@param t T
----@return fun(table: table<K, V>, index: K):K, V
+---@return fun(table: table<K, V>, index?: K):K, V
---@return T
---@return nil
local function pairs(t) end
-local f = pairs(t)
+local next = pairs(dummy)
---@type table<string, boolean>
local t
+local k, <?v?> = next(t)
+]]
+
+TEST 'string' [[
+---@generic T: table, K, V
+---@param t T
+---@return fun(table: table<K, V>, index?: K):K, V
+---@return T
+---@return nil
+local function pairs(t) end
+
+local next = pairs(dummy)
+
+---@type table<string, boolean>
+local t
+local <?k?>, v = next(t, nil)
+]]
+
+TEST 'boolean' [[
+---@generic T: table, K, V
+---@param t T
+---@return fun(table: table<K, V>, index?: K):K, V
+---@return T
+---@return nil
+local function pairs(t) end
+
+local next = pairs(dummy)
-for <?k?>, v in f, t do
+---@type table<string, boolean>
+local t
+local k, <?v?> = next(t, nil)
+]]
+
+TEST 'string' [[
+---@generic T: table, K, V
+---@param t T
+---@return fun(table: table<K, V>, index?: K):K, V
+---@return T
+---@return nil
+local function pairs(t) end
+
+local next = pairs(dummy)
+
+---@type table<string, boolean>
+local t
+
+for <?k?>, v in next, t do
end
]]
@@ -575,8 +820,6 @@ end
]]
TEST 'string' [[
----@class string
-
---@generic T: table, K, V
---@param t T
---@return fun(table: table<K, V>, index?: K):K, V
@@ -591,8 +834,6 @@ end
]]
TEST 'boolean' [[
----@class boolean
-
---@generic T: table, K, V
---@param t T
---@return fun(table: table<K, V>, index: K):K, V
@@ -608,8 +849,6 @@ end
]]
TEST 'boolean' [[
----@class boolean
-
---@generic T: table, V
---@param t T
---@return fun(table: V[], i?: integer):integer, V
@@ -625,8 +864,6 @@ end
]]
TEST 'boolean' [[
----@class boolean
-
---@generic T: table, K, V
---@param t T
---@return fun(table: table<K, V>, index: K):K, V
@@ -642,8 +879,6 @@ end
]]
TEST 'integer' [[
----@class integer
-
---@generic T: table, K, V
---@param t T
---@return fun(table: table<K, V>, index?: K):K, V
@@ -749,13 +984,13 @@ string.gsub():gsub():<?gsub?>()
]]
config.set(nil, 'Lua.hover.enumsLimit', 5)
-TEST 'a|b|c|d|e...(+5)' [[
+TEST '"a"|"b"|"c"|"d"|"e"...(+5)' [[
---@type 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'
local <?t?>
]]
config.set(nil, 'Lua.hover.enumsLimit', 1)
-TEST 'a...(+9)' [[
+TEST '"a"...(+9)' [[
---@type 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'
local <?t?>
]]
@@ -828,13 +1063,18 @@ TEST 'fun():number, boolean' [[
local <?t?>
]]
---[[
-l:value
-l:work|&1|&1
-f:|&1|&1
-dfun:|&1
-dn:Class
+
+TEST 'fun(value: Class)' [[
+---@class Class
+
+---@param callback fun(value: Class)
+function work(callback)
+end
+
+work(<?function?> (value)
+end)
]]
+
TEST 'Class' [[
---@class Class
@@ -846,14 +1086,14 @@ work(function (<?value?>)
end)
]]
-TEST 'Class' [[
+TEST 'fun(value: Class)' [[
---@class Class
---@param callback fun(value: Class)
function work(callback)
end
-pcall(work, function (<?value?>)
+pcall(work, <?function?> (value)
end)
]]
@@ -919,11 +1159,22 @@ end
--f = function (<?x?>) end
--]]
+TEST 'fun(i: integer)' [[
+--- @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 = {}
+
+emit.on("died", <?function?> (i)
+end)
+]]
+
TEST 'integer' [[
--- @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))
+--- @field on fun(eventName: 'won', cb: fun(s: string))
local emit = {}
emit.on("died", function (<?i?>)
@@ -933,8 +1184,8 @@ end)
TEST 'integer' [[
--- @class Emit
--- @field on fun(self: Emit, eventName: string, cb: function)
---- @field on fun(self: Emit, eventName: '"died"', cb: fun(i: integer))
---- @field on fun(self: Emit, eventName: '"won"', cb: fun(s: string))
+--- @field on fun(self: Emit, eventName: 'died', cb: fun(i: integer))
+--- @field on fun(self: Emit, eventName: 'won', cb: fun(s: string))
local emit = {}
emit:on("died", function (<?i?>)
@@ -971,14 +1222,14 @@ local x
<?x?> = 1
]]
-TEST 'any' [[
+TEST 'unknown' [[
---@return number
local function f(x)
local <?y?> = x()
end
]]
-TEST 'any' [[
+TEST 'unknown' [[
local mt
---@return number
@@ -987,7 +1238,7 @@ function mt:f() end
local <?v?> = mt()
]]
-TEST 'any' [[
+TEST 'unknown' [[
local <?mt?>
---@class X
@@ -1001,7 +1252,7 @@ local mt
function mt:f(<?x?>) end
]]
-TEST 'any' [[
+TEST 'unknown' [[
local <?mt?>
---@type number
@@ -1031,6 +1282,22 @@ mt:loop(function (<?i?>)
end)
]]
+TEST 'C' [[
+---@class D
+---@field y integer # D comment
+
+---@class C
+---@field x integer # C comment
+---@field d D
+
+---@param c C
+local function f(c) end
+
+f <?{?>
+ x = ,
+}
+]]
+
TEST 'integer' [[
---@class D
---@field y integer # D comment
@@ -1076,3 +1343,79 @@ function F(<?x?>) end
---@param x boolean
function F(x) end
]]
+
+TEST 'B' [[
+---@class A
+local A
+
+---@return A
+function A:x() end
+
+---@class B: A
+local B
+
+---@return B
+function B:x() end
+
+---@type B
+local t
+
+local <?v?> = t.x()
+]]
+
+TEST 'function' [[
+---@overload fun()
+function <?f?>() end
+]]
+
+TEST 'integer' [[
+---@type table<string, integer>
+local t
+
+t.<?a?>
+]]
+
+TEST '"a"|"b"|"c"' [[
+---@type table<string, "a"|"b"|"c">
+local t
+
+t.<?a?>
+]]
+
+TEST 'integer' [[
+---@class A
+---@field x integer
+
+---@type A
+local t
+t.<?x?>
+]]
+
+TEST 'boolean' [[
+local <?var?> = true
+var = 1
+var = 1.0
+]]
+
+TEST 'unknown' [[
+---@return ...
+local function f() end
+
+local <?x?> = f()
+]]
+
+TEST 'unknown' [[
+---@return ...
+local function f() end
+
+local _, <?x?> = f()
+]]
+
+TEST 'unknown' [[
+local t = {
+ x = 1,
+ y = 2,
+}
+
+local <?x?> = t[#t]
+]]