diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2024-05-11 16:02:45 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2024-05-11 16:02:45 +0800 |
commit | 6fb7e1861af8d287229146c2357787c8e25b0832 (patch) | |
tree | 8d31b5e28dc554d2b0efb98e36796998653060f6 | |
parent | d6a314f694dcc1303933bbf62e7a307e3d20245c (diff) | |
download | lua-language-server-6fb7e1861af8d287229146c2357787c8e25b0832.zip |
整理代码
-rw-r--r-- | test/type_inference/common.lua | 4194 | ||||
-rw-r--r-- | test/type_inference/init.lua | 4301 | ||||
-rw-r--r-- | test/type_inference/param_match.lua | 107 |
3 files changed, 4303 insertions, 4299 deletions
diff --git a/test/type_inference/common.lua b/test/type_inference/common.lua new file mode 100644 index 00000000..5922832b --- /dev/null +++ b/test/type_inference/common.lua @@ -0,0 +1,4194 @@ +local config = require 'config' + +TEST 'nil' [[ +local <?t?> = nil +]] + +TEST 'string' [[ +local <?var?> = '111' +]] + +TEST 'boolean' [[ +local <?var?> = true +]] + +TEST 'integer' [[ +local <?var?> = 1 +]] + +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 'string' [[ +local var = '111' +t.<?x?> = var +]] + +TEST 'string' [[ +local <?var?> +var = '111' +]] + +TEST 'string' [[ +local var +<?var?> = '111' +]] + +TEST 'string' [[ +local var +var = '111' +print(<?var?>) +]] + +TEST 'function' [[ +function <?xx?>() +end +]] + +TEST 'function' [[ +local function <?xx?>() +end +]] + +TEST 'function' [[ +local xx +<?xx?> = function () +end +]] + +TEST 'table' [[ +local <?t?> = {} +]] + +TEST 'unknown' [[ +<?x?>() +]] + +TEST 'boolean' [[ +<?x?> = not y +]] + +TEST 'integer' [[ +<?x?> = #y +]] + +TEST 'integer' [[ +<?x?> = #'aaaa' +]] + +TEST 'integer' [[ +<?x?> = #{} +]] + +TEST 'number' [[ +<?x?> = - y +]] + +TEST 'number' [[ +<?x?> = - 1.0 +]] + +TEST 'integer' [[ +<?x?> = ~ y +]] + +TEST 'integer' [[ +<?x?> = ~ 1 +]] + +TEST 'boolean' [[ +<?x?> = 1 < 2 +]] + +TEST 'integer' [[ +local a = true +local b = 1 +<?x?> = a and b +]] + +TEST 'integer' [[ +local a = false +local b = 1 +<?x?> = a or b +]] + +TEST 'boolean' [[ +<?x?> = a == b +]] + +TEST 'unknown' [[ +<?x?> = a << b +]] + +TEST 'integer' [[ +<?x?> = 1 << 2 +]] + +TEST 'unknown' [[ +<?x?> = a .. b +]] + +TEST 'string' [[ +<?x?> = 'a' .. 'b' +]] + +TEST 'string' [[ +<?x?> = 'a' .. 1 +]] + +TEST 'string' [[ +<?x?> = 'a' .. 1.0 +]] + +TEST 'unknown' [[ +<?x?> = a + b +]] + +TEST 'number' [[ +<?x?> = 1 + 2.0 +]] + +TEST 'integer' [[ +<?x?> = 1 + 2 +]] + +TEST 'integer' [[ +---@type integer +local a + +<?x?> = - a +]] + +TEST 'number' [[ +local a + +<?x?> = - a +]] + +TEST 'unknown' [[ +<?x?> = 1 + X +]] + +TEST 'unknown' [[ +<?x?> = 1.0 + X +]] + +TEST 'tablelib' [[ +---@class tablelib +table = {} + +<?table?>() +]] + +TEST 'string' [[ +_VERSION = 'Lua 5.4' + +<?x?> = _VERSION +]] + +TEST 'function' [[ +---@class stringlib +local string + +string.xxx = function () end + +return ('x').<?xxx?> +]] + +TEST 'function' [[ +---@class stringlib +String = {} + +String.xxx = function () end + +return ('x').<?xxx?> +]] + +TEST 'function' [[ +---@class stringlib +local string + +string.xxx = function () end + +<?x?> = ('x').xxx +]] + +TEST 'function' [[ +---@class stringlib +local string + +string.xxx = function () end + +_VERSION = 'Lua 5.4' + +<?x?> = _VERSION.xxx +]] + +TEST 'table' [[ +<?x?> = setmetatable({}) +]] + +TEST 'integer' [[ +local function x() + return 1 +end +<?y?> = x() +]] + +TEST 'integer|nil' [[ +local function x() + return 1 + return nil +end +<?y?> = x() +]] + +TEST 'unknown|nil' [[ +local function x() + return a + return nil +end +<?y?> = x() +]] + +TEST 'unknown|nil' [[ +local function x() + return nil + return f() +end +<?y?> = x() +]] + +TEST 'unknown|nil' [[ +local function x() + return nil + return f() +end +_, <?y?> = x() +]] + +TEST 'integer' [[ +local function x() + return 1 +end +_, <?y?> = pcall(x) +]] + +TEST 'integer' [[ +function x() + return 1 +end +_, <?y?> = pcall(x) +]] + +TEST 'integer' [[ +local function x() + return 1 +end +_, <?y?> = xpcall(x) +]] + +TEST 'A' [[ +---@class A + +---@return A +local function f2() end + +local function f() + return f2() +end + +local <?x?> = f() +]] + +-- 不根据调用者的输入参数来推测 +--TEST 'number' [[ +--local function x(a) +-- return <?a?> +--end +--x(1) +--]] + +--TEST 'table' [[ +--setmetatable(<?b?>) +--]] + +-- 不根据对方函数内的使用情况来推测 +TEST 'unknown' [[ +local function x(a) + _ = a + 1 +end +local b +x(<?b?>) +]] + +TEST 'unknown' [[ +local function x(a, ...) + local _, <?b?>, _ = ... +end +x(nil, 'xx', 1, true) +]] + +-- 引用不跨越参数 +TEST 'unknown' [[ +local function x(a, ...) + return true, 'ss', ... +end +local _, _, _, <?b?>, _ = x(nil, true, 1, 'yy') +]] + +TEST 'unknown' [[ +local <?x?> = next() +]] + +TEST 'unknown' [[ +local a, b +function a() + return b() +end +function b() + return a() +end +local <?x?> = a() +]] + +TEST 'class' [[ +---@class class +local <?x?> +]] + +TEST 'string' [[ +---@class string + +---@type string +local <?x?> +]] + +TEST '1' [[ +---@type 1 +local <?v?> +]] + +TEST 'string[]' [[ +---@class string + +---@type string[] +local <?x?> +]] + +TEST 'string|table' [[ +---@class string +---@class table + +---@type string | table +local <?x?> +]] + +TEST [['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?> +]] + +TEST 'fun()' [[ +---@type 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?, ...unknown' [[ +---@type fun(a: string, b, c?: boolean, ...):c, d?, ... +local <?x?> +]] + +TEST '{ [string]: string }' [[ +---@type { [string]: string } +local <?x?> +]] + +TEST 'table<string, number>' [[ +---@class string +---@class number + +---@type table<string, number> +local <?x?> +]] + +TEST 'A<string, number>' [[ +---@class A + +---@type A<string, number> +local <?x?> +]] + +TEST 'string' [[ +---@class string + +---@type string[] +local x +local <?y?> = x[1] +]] + +TEST 'string' [[ +---@class string + +---@return string[] +local function f() end +local x = f() +local <?y?> = x[1] +]] + +TEST 'table' [[ +local t = {} +local <?v?> = setmetatable(t) +]] + +TEST 'CCC' [[ +---@class CCC + +---@type table<string, CCC> +local t = {} + +print(t.<?a?>) +]] + +TEST [['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 'unknown' [[ +---@generic K +---@type fun(a: K|integer):K +local f + +local <?n?> = f(1) +]] + +TEST 'integer' [[ +---@class integer + +---@generic T: table, V +---@param t T +---@return fun(table: V[], i?: integer):integer, V +---@return T +---@return integer i +local function ipairs() end + +for <?i?> in ipairs() do +end +]] + +TEST 'table<string, boolean>' [[ +---@generic K, V +---@param t table<K, V> +---@return K +---@return V +local function next(t) end + +---@type table<string, boolean> +local t +local k, v = next(<?t?>) +]] + +TEST 'string' [[ +---@class string + +---@generic K, V +---@param t table<K, V> +---@return K +---@return V +local function next(t) end + +---@type table<string, boolean> +local t +local <?k?>, v = next(t) +]] + +TEST 'boolean' [[ +---@class boolean + +---@generic K, V +---@param t table<K, V> +---@return K +---@return V +local function next(t) end + +---@type table<string, boolean> +local t +local k, <?v?> = next(t) +]] + +TEST 'boolean' [[ +---@generic K +---@type fun(arg: K):K +local f + +local <?r?> = f(true) +]] + +TEST 'string' [[ +---@class string + +---@generic K, V +---@type fun(arg: table<K, V>):K, V +local f + +---@type table<string, boolean> +local t + +local <?k?>, v = f(t) +]] + +TEST 'boolean' [[ +---@class boolean + +---@generic K, V +---@type fun(arg: table<K, V>):K, V +local f + +---@type table<string, boolean> +local t + +local k, <?v?> = f(t) +]] + +TEST 'fun()' [[ +---@return fun() +local function f() end + +local <?r?> = f() +]] + +TEST 'table<string, boolean>' [[ +---@return table<string, boolean> +local function f() end + +local <?r?> = f() +]] + +TEST 'string' [[ +---@class string + +---@generic K, V +---@return fun(arg: table<K, V>):K, V +local function f() end + +local f2 = f() + +---@type table<string, boolean> +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' [[ +---@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 T +---@return nil +local function pairs(t) end + +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) + +---@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 +]] + +TEST 'boolean' [[ +---@class boolean + +---@generic T: table, K, V +---@param t T +---@return fun(table: table<K, V>, index?: K):K, V +---@return T +local function pairs(t) end + +local f = pairs(t) + +---@type table<string, boolean> +local t + +for k, <?v?> in f, t do +end +]] + +TEST 'string' [[ +---@generic T: table, K, V +---@param t T +---@return fun(table: table<K, V>, index?: K):K, V +---@return T +local function pairs(t) end + +---@type table<string, boolean> +local t + +for <?k?>, v in pairs(t) do +end +]] + +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 + +---@type table<string, boolean> +local t + +for k, <?v?> in pairs(t) do +end +]] + +TEST 'boolean' [[ +---@generic T: table, V +---@param t T +---@return fun(table: V[], i?: integer):integer, V +---@return T +---@return integer i +local function ipairs(t) end + +---@type boolean[] +local t + +for _, <?v?> in ipairs(t) do +end +]] + +TEST 'boolean' [[ +---@generic T: table, V +---@param t T +---@return fun(table: V[], i?: integer):integer, V +---@return T +---@return integer i +local function ipairs(t) end + +---@type table<integer, boolean> +local t + +for _, <?v?> in ipairs(t) do +end +]] + +TEST 'boolean' [[ +---@generic T: table, V +---@param t T +---@return fun(table: V[], i?: integer):integer, V +---@return T +---@return integer i +local function ipairs(t) end + +---@class MyClass +---@field [integer] boolean +local t + +for _, <?v?> in ipairs(t) do +end +]] + +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 + +---@type boolean[] +local t + +for k, <?v?> in pairs(t) do +end +]] + +TEST 'integer' [[ +---@generic T: table, K, V +---@param t T +---@return fun(table: table<K, V>, index?: K):K, V +---@return T +local function pairs(t) end + +---@type boolean[] +local t + +for <?k?>, v in pairs(t) do +end +]] + +TEST 'E' [[ +---@class A +---@class B: A +---@class C: B +---@class D: C + +---@class E: D +local m + +function m:f() + return <?self?> +end +]] + +TEST 'Cls' [[ +---@class Cls +local Cls = {} + +---@generic T +---@param self T +---@return T +function Cls.new(self) return self end + +local <?test?> = Cls:new() +]] + +TEST 'Cls' [[ +---@class Cls +local Cls = {} + +---@generic T +---@param self T +---@return T +function Cls:new() return self end + +local <?test?> = Cls:new() +]] + +TEST 'Cls' [[ +---@class Cls +local Cls = {} + +---@generic T +---@param self T +---@return T +function Cls.new(self) return self end + +local <?test?> = Cls.new(Cls) +]] + +TEST 'Cls' [[ +---@class Cls +local Cls = {} + +---@generic T +---@param self T +---@return T +function Cls:new() return self end + +local <?test?> = Cls.new(Cls) +]] + +TEST 'Rct' [[ +---@class Obj +local Obj = {} + +---@generic T +---@param self T +---@return T +function Obj.new(self) return self end + + +---@class Pnt:Obj +local Pnt = {x = 0, y = 0} + + +---@class Rct:Pnt +local Rct = {w = 0, h = 0} + + +local <?test?> = Rct.new(Rct) + +-- local test = Rct:new() + +return test +]] + +TEST 'function' [[ +string.gsub():gsub():<?gsub?>() +]] + +config.set(nil, 'Lua.hover.enumsLimit', 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)]] [[ +---@type 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j' +local <?t?> +]] + +config.set(nil, 'Lua.hover.enumsLimit', 0) +TEST '...(+10)' [[ +---@type 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j' +local <?t?> +]] + +config.set(nil, 'Lua.hover.enumsLimit', 5) + +TEST 'string|fun():string' [[ +---@type string | fun(): string +local <?t?> +]] + +TEST 'string' [[ +local valids = { + ['Lua 5.1'] = false, + ['Lua 5.2'] = false, + ['Lua 5.3'] = false, + ['Lua 5.4'] = false, + ['LuaJIT'] = false, +} + +for <?k?>, v in pairs(valids) do +end +]] + +TEST 'boolean' [[ +local valids = { + ['Lua 5.1'] = false, + ['Lua 5.2'] = false, + ['Lua 5.3'] = false, + ['Lua 5.4'] = false, + ['LuaJIT'] = false, +} + +for k, <?v?> in pairs(valids) do +end +]] + +TEST 'string' [[ +local t = { + a = 1, + b = 1, +} + +for <?k?>, v in pairs(t) do +end +]] + +TEST 'integer' [[ +local t = {'a', 'b'} + +for <?k?>, v in pairs(t) do +end +]] + +TEST 'string' [[ +local t = {'a', 'b'} + +for k, <?v?> in pairs(t) do +end +]] + +TEST 'fun():number, boolean' [[ +---@type fun():number, boolean +local <?t?> +]] + + +TEST 'fun(value: Class)' [[ +---@class Class + +---@param callback fun(value: Class) +function work(callback) +end + +work(<?function?> (value) +end) +]] + +TEST 'Class' [[ +---@class Class + +---@param callback fun(value: Class) +function work(callback) +end + +work(function (<?value?>) +end) +]] + +TEST 'fun(value: Class)' [[ +---@class Class + +---@param callback fun(value: Class) +function work(callback) +end + +pcall(work, <?function?> (value) +end) +]] + +TEST 'Class' [[ +---@class Class + +---@param callback fun(value: Class) +function work(callback) +end + +xpcall(work, debug.traceback, function (<?value?>) +end) +]] + +TEST 'string' [[ +---@generic T +---@param x T +---@return { x: T } +local function f(x) end + +local t = f('') + +print(t.<?x?>) +]] + +TEST 'string' [[ +---@generic T +---@param t T[] +---@param callback fun(v: T) +local function f(t, callback) end + +---@type string[] +local t + +f(t, function (<?v?>) end) +]] + +TEST 'unknown' [[ +---@generic T +---@param t T[] +---@param callback fun(v: T) +local function f(t, callback) end + +local t = {} + +f(t, function (<?v?>) end) +]] + +TEST 'table' [[ +local <?t?> = setmetatable({}, { __index = function () end }) +]] + +TEST 'player' [[ +---@class player +local t + +<?t?>:getOwner() +]] + +TEST 'string[][]' [[ +---@type string[][] +local <?t?> +]] + +TEST 'table' [[ +---@type {}[] +local t + +local <?v?> = t[1] +]] + +TEST 'string' [[ +---@type string[][] +local v = {} + +for _, a in ipairs(v) do + for i, <?b?> in ipairs(a) do + end +end +]] + +--TEST 'number' [[ +-----@param x number +--local f +-- +--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)) +local emit = {} + +emit.on("died", function (<?i?>) +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)) +local emit = {} + +emit:on("died", function (<?i?>) +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)) +local emit = {} + +emit.on(self, "died", function (<?i?>) +end) +]] + +TEST '👍' [[ +---@class 👍 +local <?x?> +]] + +TEST 'integer' [[ +---@type boolean +local x + +<?x?> = 1 +]] + +TEST 'integer' [[ +---@class Class +local x + +<?x?> = 1 +]] + +TEST 'unknown' [[ +---@return number +local function f(x) + local <?y?> = x() +end +]] + +TEST 'unknown' [[ +local mt + +---@return number +function mt:f() end + +local <?v?> = mt() +]] + +TEST 'unknown' [[ +local <?mt?> + +---@class X +function mt:f(x) end +]] + +TEST 'any' [[ +local mt + +---@class X +function mt:f(<?x?>) end +]] + +TEST 'unknown' [[ +local <?mt?> + +---@type number +function mt:f(x) end +]] + +TEST 'any' [[ +local mt + +---@type number +function mt:f(<?x?>) end +]] + +TEST 'Test' [[ +---@class Test +_G.<?Test?> = {} +]] + +TEST 'integer' [[ +local mt = {} + +---@param callback fun(i: integer) +function mt:loop(callback) end + +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 + +---@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 + +---@class C +---@field x integer # C comment +---@field d D + +---@param c C +local function f(c) end + +f { + d = { + <?y?> = , + } +} +]] + +TEST 'integer' [[ +for <?i?> = a, b, c do end +]] + +TEST 'number' [[ +---@param x number +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] +]] + +TEST 'string' [[ +local t = { + x = 1, + [1] = 'x', +} + +local <?x?> = t[#t] +]] + +TEST 'string' [[ +local t = { 'x' } + +local <?x?> = t[#t] +]] + +TEST '(string|integer)[]' [[ +---@type (string|integer)[] +local <?x?> +]] + +TEST 'boolean' [[ +---@type table<string, boolean> +local t + +---@alias uri string + +---@type string +local uri + +local <?v?> = t[uri] +]] + +TEST 'A' [[ +---@class A +G = {} + +<?G?>:A() +]] + +TEST 'A' [[ +---@type A +local <?x?> = nil +]] + +TEST 'A' [[ +---@class A +---@field b B +local mt + +function mt:f() + self.b:x() + print(<?self?>) +end +]] + +TEST 'string?' [[ +---@return string? +local function f() end + +local <?x?> = f() +]] + +TEST 'AA' [[ +---@class AA +---@overload fun():AA +local AAA + + +local <?x?> = AAA() +]] + +TEST 'AA' [[ +---@class AA +---@overload fun():AA +AAA = {} + + +local <?x?> = AAA() +]] + +TEST 'string' [[ +local <?x?> +x = '1' +x = 1 +]] + +TEST 'string' [[ +local x +<?x?> = '1' +x = 1 +]] + +TEST 'integer' [[ +local x +x = '1' +<?x?> = 1 +]] + +TEST 'unknown' [[ +local x +print(<?x?>) +x = '1' +x = 1 +]] + +TEST 'string' [[ +local x +x = '1' +print(<?x?>) +x = 1 +]] + +TEST 'integer' [[ +local x +x = '1' +x = 1 +print(<?x?>) +]] + +TEST 'unknown' [[ +local x + +function A() + print(<?x?>) +end +]] + +TEST 'string' [[ +local x + +function A() + print(<?x?>) +end + +x = '1' +x = 1 +]] + +TEST 'string' [[ +local x + +x = '1' + +function A() + print(<?x?>) +end + +x = 1 +]] + +TEST 'integer' [[ +local x + +x = '1' +x = 1 + +function A() + print(<?x?>) +end + +]] + +TEST 'boolean' [[ +local x + +function A() + x = true + print(<?x?>) +end + +x = '1' +x = 1 +]] + +TEST 'unknown' [[ +local x + +function A() + x = true +end + +print(<?x?>) +x = '1' +x = 1 +]] + +TEST 'boolean' [[ +local x + +function A() + x = true + function B() + print(<?x?>) + end +end + +x = '1' +x = 1 +]] + +TEST 'table' [[ +local x + +function A() + x = true + function B() + x = {} + print(<?x?>) + end +end + +x = '1' +x = 1 +]] + +TEST 'boolean' [[ +local x + +function A() + x = true + function B() + x = {} + end + print(<?x?>) +end + +x = '1' +x = 1 +]] + +TEST 'unknown' [[ +local x + +function A() + x = true + function B() + x = {} + end +end + +function C() + print(<?x?>) +end + +x = '1' +x = 1 +]] + +TEST 'integer' [[ +local x +x = true +do + x = 1 +end +print(<?x?>) +]] + +TEST 'boolean' [[ +local x +x = true +function XX() + do + x = 1 + end +end +print(<?x?>) +]] + +TEST 'integer?' [[ +---@type integer? +local <?x?> +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if <?x?> then + print(x) +end +]] +--[[ +context 0 integer? + +save copy 'block' +save copy 'out' +push 'block' +get +push copy +truthy +falsy ref 'out' +get +save HEAD 'final' +push 'out' + +push copy HEAD +merge 'final' +]] + +TEST 'integer' [[ +---@type integer? +local x + +if x then + print(<?x?>) +end +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if x then + print(x) +end + +print(<?x?>) +]] + +TEST 'nil' [[ +---@type integer? +local x + +if not x then + print(<?x?>) +end + +print(x) +]] + +TEST 'integer' [[ +---@type integer? +local x + +if not x then + x = 1 +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +if not x then + return +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +if xxx and x then + print(<?x?>) +end +]] + +TEST 'unknown' [[ +---@type integer? +local x + +if not x and x then + print(<?x?>) +end +]] + +TEST 'integer' [[ +---@type integer? +local x + +if x and not mark[x] then + print(<?x?>) +end +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if xxx and x then +end + +print(<?x?>) +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if xxx and x then + return +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +if x ~= nil then + print(<?x?>) +end + +print(x) +]] + +TEST 'integer|nil' [[ +---@type integer? +local x + +if x ~= nil then + print(x) +end + +print(<?x?>) +]] + +TEST 'nil' [[ +---@type integer? +local x + +if x == nil then + print(<?x?>) +end + +print(x) +]] + +TEST 'integer|nil' [[ +---@type integer? +local x + +if x == nil then + print(x) +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +<?x?> = x or 1 +]] + +TEST 'integer' [[ +---@type integer? +local x + +<?x?> = x or y +]] + +TEST 'integer' [[ +---@type integer? +local x + +if not x then + return +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +if not x then + goto ANYWHERE +end + +print(<?x?>) +]] + +TEST 'integer' [=[ +local x + +print(<?x?>--[[@as integer]]) +]=] + +TEST 'integer' [=[ +print(<?io?>--[[@as integer]]) +]=] + +TEST 'integer' [=[ +print(io.<?open?>--[[@as integer]]) +]=] + +TEST 'integer' [=[ +local <?x?> = io['open']--[[@as integer]]) +]=] + +TEST 'integer' [=[ +local <?x?> = 1 + 1--[[@as integer]]) +]=] + +TEST 'integer' [=[ +local <?x?> = not 1--[[@as integer]]) +]=] + +TEST 'integer' [=[ +local <?x?> = ()--[[@as integer]]) +]=] + +TEST 'integer?' [[ +---@param x? integer +local function f(<?x?>) + +end +]] + +TEST 'integer' [[ +local x = 1 +x = <?x?> +]] + +TEST 'integer?' [[ +---@class A +---@field x? integer +local t + +t.<?x?> +]] + +TEST 'integer?' [[ +---@type { x?: integer } +local t + +t.<?x?> +]] + +TEST 'boolean' [[ +---@class A +---@field [integer] boolean +local t + +local <?x?> = t[1] +]] + +TEST 'unknown' [[ +local <?x?> = y and z +]] + +TEST 'integer' [[ +---@type integer? +local x + +assert(x) + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +assert(x ~= nil) + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer | nil +local x + +assert(x) + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer | nil +local x + +assert(x ~= nil) + +print(<?x?>) +]] + +TEST 'integer' [[ +local x + +assert(x == 1) + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +if x and <?x?>.y then +end +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if x and x.y then +end + +print(<?x?>) +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if x and x.y then + return +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +if not x or <?x?>.y then +end +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if not x or x.y then + print(<?x?>) +end +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if x or x.y then + print(<?x?>) +end +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if x.y or x then + print(<?x?>) +end +]] + +TEST 'integer?' [[ +---@type integer? +local x + +if x.y or not x then + print(<?x?>) +end +]] + +TEST 'integer' [[ +---@type integer? +local x + +if not x or not y then + return +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +if not y or not x then + return +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +while true do + if not x then + break + end + print(<?x?>) +end +]] + +TEST 'integer?' [[ +---@type integer? +local x + +while true do + if not x then + break + end +end + +print(<?x?>) +]] + +TEST 'integer' [[ +---@type integer? +local x + +while x do + print(<?x?>) +end +]] + +TEST 'integer' [[ +---@type fun():integer? +local iter + +for <?x?> in iter do +end +]] + +TEST 'integer' [[ +local x + +---@type integer +<?x?> = XXX +]] + +TEST 'unknown' [[ +for _ = 1, 999 do + local <?x?> +end +]] + +TEST 'integer' [[ +local x + +---@cast x integer + +print(<?x?>) +]] + +TEST 'unknown' [[ +local x + +---@cast x integer + +local x +print(<?x?>) +]] + +TEST 'unknown' [[ +local x + +if true then + local x + ---@cast x integer + print(x) +end + +print(<?x?>) +]] + +TEST 'boolean|integer' [[ +local x = 1 + +---@cast x +boolean + +print(<?x?>) +]] + +TEST 'boolean' [[ +---@type integer|boolean +local x + +---@cast x -integer + +print(<?x?>) +]] + +TEST 'boolean?' [[ +---@type boolean +local x + +---@cast x +? + +print(<?x?>) +]] + +TEST 'boolean' [[ +---@type boolean? +local x + +---@cast x -? + +print(<?x?>) +]] + +TEST 'nil' [[ +---@type string? +local x + +if x then + return +else + print(<?x?>) +end + +print(x) +]] + +TEST 'string' [[ +---@type string? +local x + +if not x then + return +else + print(<?x?>) +end + +print(x) +]] + +TEST 'string' [[ +---@type string? +local x + +if not x then + return +else + print(x) +end + +print(<?x?>) +]] + +TEST 'true' [[ +---@type boolean | nil +local x + +if not x then + return +end + +print(<?x?>) +]] + +TEST 'true' [[ +---@type boolean +local t + +if t then + print(<?t?>) + return +end + +print(t) +]] + +TEST 'false' [[ +---@type boolean +local t + +if t then + print(t) + return +end + +print(<?t?>) +]] + +TEST 'nil' [[ +---@type integer? +local t + +if t then +else + print(<?t?>) +end + +print(t) +]] + +TEST 'table' [[ +local function f() + if x then + return y + end + return {} +end + +local <?z?> = f() +]] + +TEST 'integer|table' [[ +local function returnI() + return 1 +end + +local function f() + if x then + return returnI() + end + return {} +end + +local <?z?> = f() +]] + +TEST 'number' [[ +for _ in _ do + ---@type number + local <?x?> +end +]] + +TEST 'unknown' [[ +for _ in _ do + ---@param x number + local <?x?> +end +]] + +TEST 'unknown' [[ +---@type number +for <?x?> in _ do +end +]] + +TEST 'number' [[ +---@param x number +for <?x?> in _ do +end +]] + +TEST 'table' [[ +---@alias tp table + +---@type tp +local <?x?> +]] + +TEST '{ name: boolean }' [[ +---@alias tp {name: boolean} + +---@type tp +local <?x?> +]] + +TEST 'boolean|{ name: boolean }' [[ +---@alias tp boolean | {name: boolean} + +---@type tp +local <?x?> +]] + +TEST '`1`|`true`' [[ +---@type `1` | `true` +local <?x?> +]] + +TEST 'function' [[ +local x + +function x() end + +print(<?x?>) +]] + +TEST 'unknown' [[ +local x + +if x.field == 'haha' then + print(<?x?>) +end +]] + +TEST 'string' [[ +---@type string? +local t + +if not t or xxx then + return +end + +print(<?t?>) +]] + +TEST 'table' [[ +---@type table|nil +local t + +return function () + if not t then + return + end + + print(<?t?>) +end +]] + +TEST 'table' [[ +---@type table|nil +local t + +f(function () + if not t then + return + end + + print(<?t?>) +end) +]] + +TEST 'table' [[ +---@type table? +local t + +t = t or {} + +print(<?t?>) +]] + +TEST 'unknown|nil' [[ +local x + +if x == nil then +end + +print(<?x?>) +]] + +TEST 'table<xxx, true>' [[ +---@alias xxx table<xxx, true> + +---@type xxx +local <?t?> +]] + +TEST 'xxx[][]' [[ +---@alias xxx xxx[] + +---@type xxx +local <?t?> +]] + +TEST 'fun(x: fun(x: xxx))' [[ +---@alias xxx fun(x: xxx) + +---@type xxx +local <?t?> +]] + +TEST 'table' [[ +---@type table|nil +local t + +while t do + print(<?t?>) +end +]] + +TEST 'table|nil' [[ +---@type table|nil +local t + +while <?t?> do + print(t) +end +]] + +TEST 'table' [[ +---@type table|nil +local t + +while t ~= nil do + print(<?t?>) +end +]] + +TEST 'table|nil' [[ +---@type table|nil +local t + +while <?t?> ~= nil do + print(t) +end +]] + +TEST 'integer' [[ +---@type integer? +local n + +if not n then + error('n is nil') +end + +print(<?n?>) +]] + +TEST 'integer' [[ +---@type integer? +local n + +if not n then + os.exit() +end + +print(<?n?>) +]] + +TEST 'table' [[ +---@type table? +local n + +print((n and <?n?>.x)) +]] + +TEST 'table' [[ +---@type table? +local n + +n = n and <?n?>.x or 1 +]] + +TEST 'table' [[ +---@type table? +local n + +n = ff[n and <?n?>.x] +]] + +TEST 'integer' [[ +local x + +if type(x) == 'integer' then + print(<?x?>) +end +]] + +TEST 'boolean|integer' [[ +local x + +if type(x) == 'integer' +or type(x) == 'boolean' then + print(<?x?>) +end +]] + +TEST 'fun()' [[ +---@type fun()? +local x + +if type(x) == 'function' then + print(<?x?>) +end +]] + +TEST 'function' [[ +local x + +if type(x) == 'function' then + print(<?x?>) +end +]] + +TEST 'integer' [[ +local x +local tp = type(x) + +if tp == 'integer' then + print(<?x?>) +end +]] + +TEST 'integer' [[ +---@type integer? +local x + +if (x == nil) then +else + print(<?x?>) +end +]] + +TEST 'B' [[ +---@class A +---@class B + +---@type A +local x + +---@type B +x = call(x) + +print(<?x?>) +]] + +TEST 'nil' [[ +local function f() +end + +local <?x?> = f() +]] + +TEST 'integer[]' [[ +---@type integer[] +local x +if not x then + return +end + +print(<?x?>) +]] + +TEST 'unknown' [[ +---@type string[] +local t + +local <?x?> = t.x +]] + +TEST 'integer|unknown' [[ +local function f() + return GG +end + +local t + +t.x = 1 +t.x = f() + +print(t.<?x?>) +]] + +TEST 'integer' [[ +local function f() + if X then + return X + else + return 1 + end +end + +local <?n?> = f() +]] + +TEST 'unknown' [[ +local function f() + return t[k] +end + +local <?n?> = f() +]] + +TEST 'integer|nil' [[ +local function f() + if x then + return + else + return 1 + end +end + +local <?n?> = f() +]] + +TEST 'integer' [[ +---@class A +---@field x integer +local m + +m.<?x?> = true + +print(m.x) +]] + +TEST 'integer' [[ +---@class A +---@field x integer +local m + +m.x = true + +print(m.<?x?>) +]] + +TEST 'integer' [[ +---@class A +---@field x integer --> 1st +local m = { + x = '' --> 2nd +} + +---@type boolean +m.x = true --> 3rd (with ---@type above) + +m.x = {} --> 4th + +print(m.<?x?>) +]] + +TEST 'string' [[ +---@class A +----@field x integer --> 1st +local m = { + x = '' --> 2nd +} + +---@type boolean +m.x = true --> 3rd (with ---@type above) + +m.x = {} --> 4th + +print(m.<?x?>) +]] + +TEST 'boolean' [[ +---@class A +----@field x integer --> 1st +local m = { + --x = '' --> 2nd +} + +---@type boolean +m.x = true --> 3rd (with ---@type above) + +m.x = {} --> 4th + +print(m.<?x?>) +]] + +TEST 'table' [[ +---@class A +----@field x integer --> 1st +local m = { + --x = '' --> 2nd +} + +---@type boolean +--m.x = true --> 3rd (with ---@type above) + +m.x = {} --> 4th + +print(m.<?x?>) +]] + +TEST 'boolean?' [[ +---@generic T +---@param x T +---@return T +local function echo(x) end + +---@type boolean? +local b + +local <?x?> = echo(b) +]] + +TEST 'boolean' [[ +---@generic T +---@param x T? +---@return T +local function echo(x) end + +---@type boolean? +local b + +local <?x?> = echo(b) +]] + +TEST 'boolean' [[ +---@generic T +---@param x? T +---@return T +local function echo(x) end + +---@type boolean? +local b + +local <?x?> = echo(b) +]] + +TEST 'boolean' [[ +---@type {[integer]: boolean, xx: integer} +local t + +local <?n?> = t[1] +]] + +TEST 'boolean' [[ +---@type integer +local i + +---@type {[integer]: boolean, xx: integer} +local t + +local <?n?> = t[i] +]] + +TEST 'string' [=[ +local x = true +local y = x--[[@as integer]] --is `integer` here +local z = <?x?>--[[@as string]] --is `true` here +]=] + +TEST 'integer' [[ +---@type integer +local x + +if type(x) == 'number' then + print(<?x?>) +end +]] + +TEST 'boolean' [[ +---@class A +---@field [integer] boolean +local mt + +function mt:f() + ---@type integer + local index + local <?x?> = self[index] +end +]] + +TEST 'boolean' [[ +---@class A +---@field [B] boolean + +---@class B + +---@type A +local a + +---@type B +local b + +local <?x?> = a[b] +]] + +TEST 'number' [[ +---@type {x: string ; y: boolean; z: number} +local t + +local <?z?> = t.z +]] + +TEST 'fun():number, boolean' [[ +---@type {f: fun():number, boolean} +local t + +local <?f?> = t.f +]] + +TEST 'fun():number' [[ +---@type {(f: fun():number), x: boolean} +local t + +local <?f?> = t.f +]] + +TEST 'boolean' [[ +---@param ... boolean +local function f(...) + local <?n?> = ... +end +]] + +TEST 'boolean' [[ +---@param ... boolean +local function f(...) + local _, <?n?> = ... +end +]] + +TEST 'boolean' [[ +---@return boolean ... +local function f() end + +local <?n?> = f() +]] + +TEST 'boolean' [[ +---@return boolean ... +local function f() end + +local _, <?n?> = f() +]] + +TEST 'boolean' [[ +---@type fun():name1: boolean, name2:number +local f + +local <?n?> = f() +]] + +TEST 'number' [[ +---@type fun():name1: boolean, name2:number +local f + +local _, <?n?> = f() +]] +TEST 'boolean' [[ +---@type fun():(name1: boolean, name2:number) +local f + +local <?n?> = f() +]] + +TEST 'number' [[ +---@type fun():(name1: boolean, name2:number) +local f + +local _, <?n?> = f() +]] + +TEST 'boolean' [[ +---@type fun():...: boolean +local f + +local _, <?n?> = f() +]] + +TEST 'string' [[ +local s +while true do + s = '' +end +print(<?s?>) +]] + +TEST 'string' [[ +local s +for _ in _ do + s = '' +end +print(<?s?>) +]] + +TEST 'A' [[ +---@class A: string + +---@type A +local <?s?> = '' +]] + +TEST 'number' [[ +---@return number +local function f() end +local x, <?y?> = 1, f() +]] + +TEST 'boolean' [[ +---@return number, boolean +local function f() end +local x, y, <?z?> = 1, f() +]] + +TEST 'number' [[ +---@return number, boolean +local function f() end +local x, y, <?z?> = 1, 2, f() +]] + +TEST 'unknown' [[ +local f + +print(<?f?>) + +function f() end +]] + +TEST 'unknown' [[ +local f + +do + print(<?f?>) +end + +function f() end +]] + +TEST 'function' [[ +local f + +function A() + print(<?f?>) +end + +function f() end +]] + +TEST 'number' [[ +---@type number|nil +local n + +local t = { + x = n and <?n?>, +} +]] + +TEST 'table' [[ +---@type table? +local n + +if not n or not <?n?>.x then +end +]] + +TEST 'table' [[ +---@type table? +local n + +if not n or not <?n?>[1] then +end +]] + +TEST 'number' [[ +---@type number|false +local n + +---@cast n -false + +print(<?n?>) +]] + +TEST 'table' [[ +---@type number|table +local n + +if n +---@cast n table +and <?n?>.type == 'xxx' then +end +]] + +TEST 'integer' [[ +---@type integer? +local n +if true then + n = 0 +end +local <?x?> = n or 0 +]] + +TEST 'number' [=[ +local <?x?> = F()--[[@as number]] +]=] + +TEST 'number' [=[ +local function f() + return F()--[[@as number]] +end + +local <?x?> = f() +]=] + +TEST 'number' [=[ +local <?x?> = X --[[@as number]] +]=] + +TEST 'number' [[ +---@return number?, number? +local function f() end + +for <?x?>, y in f do +end +]] + +TEST 'number' [[ +---@return number?, number? +local function f() end + +for x, <?y?> in f do +end +]] + +TEST 'number|nil' [[ +---@type table|nil +local a + +---@type number|nil +local b + +local <?c?> = a and b +]] + +TEST 'number|table|nil' [[ +---@type table|nil +local a + +---@type number|nil +local b + +local <?c?> = a or b +]] + +TEST 'number|table|nil' [[ +---@type table|nil +local a + +---@type number|nil +local b + +local c = a and b +local <?d?> = a or b +]] + +TEST 'number' [[ +local x + +---@return number +local function f() +end + +x = f() + +print(<?x?>) +]] + +TEST 'number' [[ +local x + +---@return number +local function f() +end + +_, x = pcall(f) + +print(<?x?>) +]] + +TEST 'string' [[ +---@type table<string|number, string> +local t + +---@type number +local n +---@type string +local s + +local <?test?> = t[n] +local test2 = t[s] --test and test2 are unknow +]] + +TEST 'string' [[ +---@type table<string|number, string> +local t + +---@type number +local n +---@type string +local s + +local test = t[n] +local <?test2?> = t[s] --test and test2 are unknow +]] + +TEST 'table<number, boolean>' [[ +---@type table<number, boolean> +local t + +<?t?> = {} +]] + +TEST 'integer' [[ +---@type integer[]|A +local t + +local <?x?> = t[1] +]] + +TEST 'integer' [[ +---@type integer +---@diagnostic disable +local <?t?> +]] + +TEST 'A' [[ +---@class A +---@diagnostic disable +local <?t?> +]] + +TEST '{ [string]: number, [true]: string, [1]: boolean, tag: integer }' [[ +---@type {[string]: number, [true]: string, [1]: boolean, tag: integer} +local <?t?> +]] + +TEST 'unknown' [[ +local mt = {} +mt.<?x?> = nil +]] + +TEST 'unknown' [[ +mt = {} +mt.<?x?> = nil +]] + +TEST 'A' [[ +---@class A +---@operator unm: A + +---@type A +local a +local <?b?> = -a +]] + +TEST 'A' [[ +---@class A +---@operator bnot: A + +---@type A +local a +local <?b?> = ~a +]] + +TEST 'A' [[ +---@class A +---@operator len: A + +---@type A +local a +local <?b?> = #a +]] + +TEST 'A' [[ +---@class A +---@operator add: A + +---@type A +local a +local <?b?> = a + 1 +]] + +TEST 'A' [[ +---@class A +---@operator sub: A + +---@type A +local a +local <?b?> = a - 1 +]] + +TEST 'A' [[ +---@class A +---@operator mul: A + +---@type A +local a +local <?b?> = a * 1 +]] + +TEST 'A' [[ +---@class A +---@operator div: A + +---@type A +local a +local <?b?> = a / 1 +]] + +TEST 'A' [[ +---@class A +---@operator mod: A + +---@type A +local a +local <?b?> = a % 1 +]] + +TEST 'A' [[ +---@class A +---@operator pow: A + +---@type A +local a +local <?b?> = a ^ 1 +]] + +TEST 'A' [[ +---@class A +---@operator idiv: A + +---@type A +local a +local <?b?> = a // 1 +]] + +TEST 'A' [[ +---@class A +---@operator band: A + +---@type A +local a +local <?b?> = a & 1 +]] + +TEST 'A' [[ +---@class A +---@operator bor: A + +---@type A +local a +local <?b?> = a | 1 +]] + +TEST 'A' [[ +---@class A +---@operator bxor: A + +---@type A +local a +local <?b?> = a ~ 1 +]] + +TEST 'A' [[ +---@class A +---@operator shl: A + +---@type A +local a +local <?b?> = a << 1 +]] + +TEST 'A' [[ +---@class A +---@operator shr: A + +---@type A +local a +local <?b?> = a >> 1 +]] + +TEST 'A' [[ +---@class A +---@operator concat: A + +---@type A +local a +local <?b?> = a .. 1 +]] + +TEST 'A' [[ +---@class A +---@operator add(boolean): boolean +---@operator add(integer): A + +---@type A +local a +local <?b?> = a + 1 +]] + +TEST 'boolean' [[ +---@class A +---@operator add(boolean): boolean +---@operator add(integer): A + +---@type A +local a +local <?b?> = a + true +]] + +TEST 'A' [[ +---@class A +---@operator call: A + +---@type A +local a +local <?b?> = a() +]] + +TEST 'A' [[ +---@class A +---@operator call: A + +---@type A +local a + +local t = { + <?x?> = a(), +} +]] + +TEST 'boolean' [[ +---@class A +---@field n number +---@field [string] boolean +local t + +local <?x?> = t.xx +]] + +TEST 'number' [[ +---@class A +---@field n number +---@field [string] boolean +local t + +local <?x?> = t.n +]] + +TEST 'string' [[ +---@class string +---@operator mod: string + +local <?b?> = '' % 1 +]] + +TEST 'string|integer' [[ +---@type boolean +local bool + +local <?x?> = bool and '' or 0 +]] + +TEST 'string|integer' [[ +local bool + +if X then + bool = true +else + bool = false +end + +local <?x?> = bool and '' or 0 +]] + +TEST 'boolean' [[ +---@type boolean|true|false +local <?b?> +]] + +TEST 'integer|false' [[ +local <?b?> = X == 1 and X == 1 and 1 +]] + +TEST 'unknown|nil' [[ +local function f() + if X then + return ({})[1] + end + return nil +end + +local <?n?> = f() +]] + +TEST 'integer' [[ +---@generic T +---@vararg T # ERROR +---@return T +local function test(...) + return ... +end + +local <?n?> = test(1) +]] + +TEST 'boolean' [[ +---@type boolean, number +local <?x?>, y +]] + +TEST 'number' [[ +---@type boolean, number +local x, <?y?> +]] + +TEST 'unknown' [[ +---@type _, number +local <?x?>, y +]] + +TEST 'number[]' [[ +local t +---@cast t number[]? + +local x = t and <?t?>[i] +]] + +TEST 'number?' [[ +---@type number[]? +local t + +local <?x?> = t and t[i] +]] + +TEST 'number' [[ +---@type number +local x + +if not <?x?>.y then + x = nil +end +]] + +TEST 'number' [[ +---@type number|nil +local x +while x == nil do + if x == nil then + return + end + + x = nil +end + +print(<?x?>) +]] + +TEST 'integer' [[ +local A = { + ---@class XXX + B = {} +} + +A.B.C = 1 + +print(A.B.<?C?>) +]] + +TEST '-2|-3|1' [[ +---@type 1|-2|-3 +local <?n?> +]] + +TEST 'table' [[ +---@enum A +local m = {} + +print(<?m?>) +]] + +TEST 'A' [[ +---@class A +---@overload fun():A +local m = {} + +---@return A +function m:init() + return <?self?> +end +]] + +TEST 'string' [[ +---@vararg string +function F(...) + local t = {...} + for k, <?v?> in pairs(t) do + end +end +]] + +TEST 'string' [[ +---@vararg string +function F(...) + local t = {...} + for k, <?v?> in ipairs(t) do + end +end +]] + +TEST 'integerA' [[ +---@type integerA +for <?i?> = 1, 10 do +end +]] + +TEST 'string' [[ +---@class A +---@field x string + +---@class B : A +local t = {} + +t.x = t.x + +print(t.<?x?>) +]] + +TEST 'unknown' [[ +local t = { + x = 1, +} + +local x + +local <?v?> = t[x] +]] + +TEST 'A|B' [[ +---@class A +---@class B: A + +---@type A|B +local <?t?> +]] + +TEST 'function' [[ +---@class myClass +local myClass = { has = { nested = {} } } + +function myClass.has.nested.fn() end + +---@type myClass +local class + +class.has.nested.<?fn?>() +]] + +TEST 'integer[]' [[ +---@generic T +---@param f fun(x: T) +---@return T[] +local function x(f) end + +---@param x integer +local <?arr?> = x(function (x) end) +]] + +TEST 'integer[]' [[ +---@generic T +---@param f fun():T +---@return T[] +local function x(f) end + +local <?arr?> = x(function () + return 1 +end) +]] + +TEST 'integer[]' [[ +---@generic T +---@param f fun():T +---@return T[] +local function x(f) end + +---@return integer +local <?arr?> = x(function () end) +]] + +TEST 'integer[]' [[ +---@generic T +---@param f fun(x: T) +---@return T[] +local function x(f) end + +---@type fun(x: integer) +local cb + +local <?arr?> = x(cb) +]] + +TEST 'integer[]' [[ +---@generic T +---@param f fun():T +---@return T[] +local function x(f) end + +---@type fun(): integer +local cb + +local <?arr?> = x(cb) +]] + +TEST 'integer' [[ +---@return fun(x: integer) +local function f() + return function (<?x?>) + end +end +]] + +TEST 'string' [[ +---@class A +---@field f fun(x: string) + +---@type A +local t = { + f = function (<?x?>) end +} +]] + +config.set(nil, 'Lua.runtime.special', { + ['xx.assert'] = 'assert' +}) + +TEST 'number' [[ +---@type number? +local t + +xx.assert(t) + +print(<?t?>) +]] + +config.set(nil, 'Lua.runtime.special', nil) + +TEST 'A' [[ +---@class A +local mt + +---@return <?self?> +function mt:init() +end +]] + +TEST 'A' [[ +---@class A +local mt + +---@return self +function mt:init() +end + +local <?o?> = mt:init() +]] + +TEST 'A' [[ +---@class A +---@field x <?self?> +]] + +TEST 'A' [[ +---@class A +---@field x self + +---@type A +local o + +print(o.<?x?>) +]] + +TEST 'A' [[ +---@class A +---@overload fun(): self +local A + +local <?o?> = A() +]] + +TEST 'number' [[ +---@type table<'Test1', fun(x: number)> +local t = { + ["Test1"] = function(<?x?>) end, +} +]] + +TEST 'number' [[ +---@type table<5, fun(x: number)> +local t = { + [5] = function(<?x?>) end, +} +]] + +TEST 'number' [[ +---@type fun(x: number) +local function f(<?x?>) end +]] + +TEST 'boolean' [[ +---@generic T: string | boolean | table +---@param x T +---@return T +local function f(x) + return x +end + +local <?x?> = f(true) +]] + +TEST 'number' [[ +---@class A +---@field [1] number +---@field [2] boolean +local t + +local <?n?> = t[1] +]] + +TEST 'boolean' [[ +---@class A +---@field [1] number +---@field [2] boolean +local t + +local <?n?> = t[2] +]] + +TEST 'N' [[ +---@class N: number +local x + +if x == 0.1 then + print(<?x?>) +end +]] + +TEST 'vec3' [[ +---@class mat4 +---@operator mul(vec3): vec3 -- matrix * vector +---@operator mul(number): mat4 -- matrix * constant + +---@class vec3: number + +---@type mat4, vec3 +local m, v + +local <?r?> = m * v +]] + +TEST 'mat4' [[ +---@class mat4 +---@operator mul(number): mat4 -- matrix * constant +---@operator mul(vec3): vec3 -- matrix * vector + +---@class vec3: number + +---@type mat4, vec3 +local m, v + +local <?r?> = m * v +]] + +TEST 'A|B' [[ +---@class A +---@class B + +---@type A|B +local t + +if x then + ---@cast t A +else + print(<?t?>) +end +]] + +TEST 'A|B' [[ +---@class A +---@class B + +---@type A|B +local t + +if x then + ---@cast t A +elseif <?t?> then +end +]] + +TEST 'A|B' [[ +---@class A +---@class B + +---@type A|B +local t + +if x then + ---@cast t A + print(t) +elseif <?t?> then +end +]] + +TEST 'A|B' [[ +---@class A +---@class B + +---@type A|B +local t + +if x then + ---@cast t A + print(t) +elseif <?t?> then + ---@cast t A + print(t) +end +]] + +TEST 'function' [[ +local function x() + print(<?x?>) +end +]] + +TEST 'number' [[ +---@type number? +local x + +do + if not x then + return + end +end + +print(<?x?>) +]] + +TEST 'number' [[ +---@type number[] +local xs + +---@type fun(x): number? +local f + +for _, <?x?> in ipairs(xs) do + x = f(x) +end +]] + +TEST 'number' [[ +---@type number? +X = Y + +if X then + print(<?X?>) +end +]] + +TEST 'number' [[ +---@type number|boolean +X = Y + +if type(X) == 'number' then + print(<?X?>) +end +]] + +TEST 'boolean' [[ +---@type number|boolean +X = Y + +if type(X) ~= 'number' then + print(<?X?>) +end +]] + +TEST 'boolean' [[ +---@type number +X = Y + +---@cast X boolean + +print(<?X?>) +]] + +TEST 'number' [[ +---@type number +local t + +if xxx == <?t?> then + print(t) +end +]] + +TEST 'V' [[ +---@class V +X = 1 + +print(<?X?>) +]] + +TEST 'V' [[ +---@class V +X.Y = 1 + +print(X.<?Y?>) +]] + +TEST 'integer' [[ +local x = {} + +x.y = 1 +local y = x.y +x.y = nil + +print(<?y?>) +]] + +TEST 'function' [[ +function X() + <?Y?>() +end + +function Y() +end +]] + +TEST 'A_Class' [[ +---@class A_Class +local A = { x = 5 } + +function A:func() + for i = 1, <?self?>.x do + print(i) + end + + self.y = 3 + self.y = self.y + 3 +end +]] + +TEST 'number' [[ +---@type number? +local n +local <?v?> = n or error('') +]] + +TEST 'Foo' [[ +---@class Foo +---@operator mul(Foo): Foo +---@operator mul(Bar): Foo +---@class Bar + +---@type Foo +local foo + +---@type Foo|Bar +local fooOrBar + +local <?b?> = foo * fooOrBar +]] + +TEST 'number' [[ +local a = 4; +local b = 2; + +local <?c?> = a / b; +]] + +TEST 'string' [[ +local a = '4'; +local b = '2'; + +local <?c?> = a .. b; +]] + +TEST 'number|{ [1]: string }' [[ +---@alias Some +---| { [1]: string } +---| number + +local x ---@type Some + +print(<?x?>) +]] + +TEST 'integer' [[ +---@class metatable : table +---@field __index table + +---@param table table +---@param metatable? metatable +---@return table +function setmetatable(table, metatable) end + +local m = setmetatable({},{ __index = { a = 1 } }) + +m.<?a?> +]] + +TEST 'integer' [[ +---@class metatable : table +---@field __index table + +---@param table table +---@param metatable? metatable +---@return table +function setmetatable(table, metatable) end + +local mt = {a = 1 } +local m = setmetatable({},{ __index = mt }) + +m.<?a?> +]] + +TEST 'integer' [[ +local x = 1 +repeat +until <?x?> +]] + +-- #2144 +TEST 'A' [=[ +local function f() + return {} --[[@as A]] +end + +local <?x?> = f() +]=] + +TEST 'A' [=[ +local function f() + ---@type A + return {} +end + +local <?x?> = f() +]=] + +TEST 'boolean|number' [[ +---@alias A number +---@alias(partial) A boolean + +---@type A +local <?x?> +]] diff --git a/test/type_inference/init.lua b/test/type_inference/init.lua index da4590a6..35900bc3 100644 --- a/test/type_inference/init.lua +++ b/test/type_inference/init.lua @@ -44,4302 +44,5 @@ function TEST(wanted) end end -TEST 'nil' [[ -local <?t?> = nil -]] - -TEST 'string' [[ -local <?var?> = '111' -]] - -TEST 'boolean' [[ -local <?var?> = true -]] - -TEST 'integer' [[ -local <?var?> = 1 -]] - -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 'string' [[ -local var = '111' -t.<?x?> = var -]] - -TEST 'string' [[ -local <?var?> -var = '111' -]] - -TEST 'string' [[ -local var -<?var?> = '111' -]] - -TEST 'string' [[ -local var -var = '111' -print(<?var?>) -]] - -TEST 'function' [[ -function <?xx?>() -end -]] - -TEST 'function' [[ -local function <?xx?>() -end -]] - -TEST 'function' [[ -local xx -<?xx?> = function () -end -]] - -TEST 'table' [[ -local <?t?> = {} -]] - -TEST 'unknown' [[ -<?x?>() -]] - -TEST 'boolean' [[ -<?x?> = not y -]] - -TEST 'integer' [[ -<?x?> = #y -]] - -TEST 'integer' [[ -<?x?> = #'aaaa' -]] - -TEST 'integer' [[ -<?x?> = #{} -]] - -TEST 'number' [[ -<?x?> = - y -]] - -TEST 'number' [[ -<?x?> = - 1.0 -]] - -TEST 'integer' [[ -<?x?> = ~ y -]] - -TEST 'integer' [[ -<?x?> = ~ 1 -]] - -TEST 'boolean' [[ -<?x?> = 1 < 2 -]] - -TEST 'integer' [[ -local a = true -local b = 1 -<?x?> = a and b -]] - -TEST 'integer' [[ -local a = false -local b = 1 -<?x?> = a or b -]] - -TEST 'boolean' [[ -<?x?> = a == b -]] - -TEST 'unknown' [[ -<?x?> = a << b -]] - -TEST 'integer' [[ -<?x?> = 1 << 2 -]] - -TEST 'unknown' [[ -<?x?> = a .. b -]] - -TEST 'string' [[ -<?x?> = 'a' .. 'b' -]] - -TEST 'string' [[ -<?x?> = 'a' .. 1 -]] - -TEST 'string' [[ -<?x?> = 'a' .. 1.0 -]] - -TEST 'unknown' [[ -<?x?> = a + b -]] - -TEST 'number' [[ -<?x?> = 1 + 2.0 -]] - -TEST 'integer' [[ -<?x?> = 1 + 2 -]] - -TEST 'integer' [[ ----@type integer -local a - -<?x?> = - a -]] - -TEST 'number' [[ -local a - -<?x?> = - a -]] - -TEST 'unknown' [[ -<?x?> = 1 + X -]] - -TEST 'unknown' [[ -<?x?> = 1.0 + X -]] - -TEST 'tablelib' [[ ----@class tablelib -table = {} - -<?table?>() -]] - -TEST 'string' [[ -_VERSION = 'Lua 5.4' - -<?x?> = _VERSION -]] - -TEST 'function' [[ ----@class stringlib -local string - -string.xxx = function () end - -return ('x').<?xxx?> -]] - -TEST 'function' [[ ----@class stringlib -String = {} - -String.xxx = function () end - -return ('x').<?xxx?> -]] - -TEST 'function' [[ ----@class stringlib -local string - -string.xxx = function () end - -<?x?> = ('x').xxx -]] - -TEST 'function' [[ ----@class stringlib -local string - -string.xxx = function () end - -_VERSION = 'Lua 5.4' - -<?x?> = _VERSION.xxx -]] - -TEST 'table' [[ -<?x?> = setmetatable({}) -]] - -TEST 'integer' [[ -local function x() - return 1 -end -<?y?> = x() -]] - -TEST 'integer|nil' [[ -local function x() - return 1 - return nil -end -<?y?> = x() -]] - -TEST 'unknown|nil' [[ -local function x() - return a - return nil -end -<?y?> = x() -]] - -TEST 'unknown|nil' [[ -local function x() - return nil - return f() -end -<?y?> = x() -]] - -TEST 'unknown|nil' [[ -local function x() - return nil - return f() -end -_, <?y?> = x() -]] - -TEST 'integer' [[ -local function x() - return 1 -end -_, <?y?> = pcall(x) -]] - -TEST 'integer' [[ -function x() - return 1 -end -_, <?y?> = pcall(x) -]] - -TEST 'integer' [[ -local function x() - return 1 -end -_, <?y?> = xpcall(x) -]] - -TEST 'A' [[ ----@class A - ----@return A -local function f2() end - -local function f() - return f2() -end - -local <?x?> = f() -]] - --- 不根据调用者的输入参数来推测 ---TEST 'number' [[ ---local function x(a) --- return <?a?> ---end ---x(1) ---]] - ---TEST 'table' [[ ---setmetatable(<?b?>) ---]] - --- 不根据对方函数内的使用情况来推测 -TEST 'unknown' [[ -local function x(a) - _ = a + 1 -end -local b -x(<?b?>) -]] - -TEST 'unknown' [[ -local function x(a, ...) - local _, <?b?>, _ = ... -end -x(nil, 'xx', 1, true) -]] - --- 引用不跨越参数 -TEST 'unknown' [[ -local function x(a, ...) - return true, 'ss', ... -end -local _, _, _, <?b?>, _ = x(nil, true, 1, 'yy') -]] - -TEST 'unknown' [[ -local <?x?> = next() -]] - -TEST 'unknown' [[ -local a, b -function a() - return b() -end -function b() - return a() -end -local <?x?> = a() -]] - -TEST 'class' [[ ----@class class -local <?x?> -]] - -TEST 'string' [[ ----@class string - ----@type string -local <?x?> -]] - -TEST '1' [[ ----@type 1 -local <?v?> -]] - -TEST 'string[]' [[ ----@class string - ----@type string[] -local <?x?> -]] - -TEST 'string|table' [[ ----@class string ----@class table - ----@type string | table -local <?x?> -]] - -TEST [['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?> -]] - -TEST 'fun()' [[ ----@type 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?, ...unknown' [[ ----@type fun(a: string, b, c?: boolean, ...):c, d?, ... -local <?x?> -]] - -TEST '{ [string]: string }' [[ ----@type { [string]: string } -local <?x?> -]] - -TEST 'table<string, number>' [[ ----@class string ----@class number - ----@type table<string, number> -local <?x?> -]] - -TEST 'A<string, number>' [[ ----@class A - ----@type A<string, number> -local <?x?> -]] - -TEST 'string' [[ ----@class string - ----@type string[] -local x -local <?y?> = x[1] -]] - -TEST 'string' [[ ----@class string - ----@return string[] -local function f() end -local x = f() -local <?y?> = x[1] -]] - -TEST 'table' [[ -local t = {} -local <?v?> = setmetatable(t) -]] - -TEST 'CCC' [[ ----@class CCC - ----@type table<string, CCC> -local t = {} - -print(t.<?a?>) -]] - -TEST [['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 'unknown' [[ ----@generic K ----@type fun(a: K|integer):K -local f - -local <?n?> = f(1) -]] - -TEST 'integer' [[ ----@class integer - ----@generic T: table, V ----@param t T ----@return fun(table: V[], i?: integer):integer, V ----@return T ----@return integer i -local function ipairs() end - -for <?i?> in ipairs() do -end -]] - -TEST 'table<string, boolean>' [[ ----@generic K, V ----@param t table<K, V> ----@return K ----@return V -local function next(t) end - ----@type table<string, boolean> -local t -local k, v = next(<?t?>) -]] - -TEST 'string' [[ ----@class string - ----@generic K, V ----@param t table<K, V> ----@return K ----@return V -local function next(t) end - ----@type table<string, boolean> -local t -local <?k?>, v = next(t) -]] - -TEST 'boolean' [[ ----@class boolean - ----@generic K, V ----@param t table<K, V> ----@return K ----@return V -local function next(t) end - ----@type table<string, boolean> -local t -local k, <?v?> = next(t) -]] - -TEST 'boolean' [[ ----@generic K ----@type fun(arg: K):K -local f - -local <?r?> = f(true) -]] - -TEST 'string' [[ ----@class string - ----@generic K, V ----@type fun(arg: table<K, V>):K, V -local f - ----@type table<string, boolean> -local t - -local <?k?>, v = f(t) -]] - -TEST 'boolean' [[ ----@class boolean - ----@generic K, V ----@type fun(arg: table<K, V>):K, V -local f - ----@type table<string, boolean> -local t - -local k, <?v?> = f(t) -]] - -TEST 'fun()' [[ ----@return fun() -local function f() end - -local <?r?> = f() -]] - -TEST 'table<string, boolean>' [[ ----@return table<string, boolean> -local function f() end - -local <?r?> = f() -]] - -TEST 'string' [[ ----@class string - ----@generic K, V ----@return fun(arg: table<K, V>):K, V -local function f() end - -local f2 = f() - ----@type table<string, boolean> -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' [[ ----@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 T ----@return nil -local function pairs(t) end - -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) - ----@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 -]] - -TEST 'boolean' [[ ----@class boolean - ----@generic T: table, K, V ----@param t T ----@return fun(table: table<K, V>, index?: K):K, V ----@return T -local function pairs(t) end - -local f = pairs(t) - ----@type table<string, boolean> -local t - -for k, <?v?> in f, t do -end -]] - -TEST 'string' [[ ----@generic T: table, K, V ----@param t T ----@return fun(table: table<K, V>, index?: K):K, V ----@return T -local function pairs(t) end - ----@type table<string, boolean> -local t - -for <?k?>, v in pairs(t) do -end -]] - -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 - ----@type table<string, boolean> -local t - -for k, <?v?> in pairs(t) do -end -]] - -TEST 'boolean' [[ ----@generic T: table, V ----@param t T ----@return fun(table: V[], i?: integer):integer, V ----@return T ----@return integer i -local function ipairs(t) end - ----@type boolean[] -local t - -for _, <?v?> in ipairs(t) do -end -]] - -TEST 'boolean' [[ ----@generic T: table, V ----@param t T ----@return fun(table: V[], i?: integer):integer, V ----@return T ----@return integer i -local function ipairs(t) end - ----@type table<integer, boolean> -local t - -for _, <?v?> in ipairs(t) do -end -]] - -TEST 'boolean' [[ ----@generic T: table, V ----@param t T ----@return fun(table: V[], i?: integer):integer, V ----@return T ----@return integer i -local function ipairs(t) end - ----@class MyClass ----@field [integer] boolean -local t - -for _, <?v?> in ipairs(t) do -end -]] - -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 - ----@type boolean[] -local t - -for k, <?v?> in pairs(t) do -end -]] - -TEST 'integer' [[ ----@generic T: table, K, V ----@param t T ----@return fun(table: table<K, V>, index?: K):K, V ----@return T -local function pairs(t) end - ----@type boolean[] -local t - -for <?k?>, v in pairs(t) do -end -]] - -TEST 'E' [[ ----@class A ----@class B: A ----@class C: B ----@class D: C - ----@class E: D -local m - -function m:f() - return <?self?> -end -]] - -TEST 'Cls' [[ ----@class Cls -local Cls = {} - ----@generic T ----@param self T ----@return T -function Cls.new(self) return self end - -local <?test?> = Cls:new() -]] - -TEST 'Cls' [[ ----@class Cls -local Cls = {} - ----@generic T ----@param self T ----@return T -function Cls:new() return self end - -local <?test?> = Cls:new() -]] - -TEST 'Cls' [[ ----@class Cls -local Cls = {} - ----@generic T ----@param self T ----@return T -function Cls.new(self) return self end - -local <?test?> = Cls.new(Cls) -]] - -TEST 'Cls' [[ ----@class Cls -local Cls = {} - ----@generic T ----@param self T ----@return T -function Cls:new() return self end - -local <?test?> = Cls.new(Cls) -]] - -TEST 'Rct' [[ ----@class Obj -local Obj = {} - ----@generic T ----@param self T ----@return T -function Obj.new(self) return self end - - ----@class Pnt:Obj -local Pnt = {x = 0, y = 0} - - ----@class Rct:Pnt -local Rct = {w = 0, h = 0} - - -local <?test?> = Rct.new(Rct) - --- local test = Rct:new() - -return test -]] - -TEST 'function' [[ -string.gsub():gsub():<?gsub?>() -]] - -config.set(nil, 'Lua.hover.enumsLimit', 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)]] [[ ----@type 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j' -local <?t?> -]] - -config.set(nil, 'Lua.hover.enumsLimit', 0) -TEST '...(+10)' [[ ----@type 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j' -local <?t?> -]] - -config.set(nil, 'Lua.hover.enumsLimit', 5) - -TEST 'string|fun():string' [[ ----@type string | fun(): string -local <?t?> -]] - -TEST 'string' [[ -local valids = { - ['Lua 5.1'] = false, - ['Lua 5.2'] = false, - ['Lua 5.3'] = false, - ['Lua 5.4'] = false, - ['LuaJIT'] = false, -} - -for <?k?>, v in pairs(valids) do -end -]] - -TEST 'boolean' [[ -local valids = { - ['Lua 5.1'] = false, - ['Lua 5.2'] = false, - ['Lua 5.3'] = false, - ['Lua 5.4'] = false, - ['LuaJIT'] = false, -} - -for k, <?v?> in pairs(valids) do -end -]] - -TEST 'string' [[ -local t = { - a = 1, - b = 1, -} - -for <?k?>, v in pairs(t) do -end -]] - -TEST 'integer' [[ -local t = {'a', 'b'} - -for <?k?>, v in pairs(t) do -end -]] - -TEST 'string' [[ -local t = {'a', 'b'} - -for k, <?v?> in pairs(t) do -end -]] - -TEST 'fun():number, boolean' [[ ----@type fun():number, boolean -local <?t?> -]] - - -TEST 'fun(value: Class)' [[ ----@class Class - ----@param callback fun(value: Class) -function work(callback) -end - -work(<?function?> (value) -end) -]] - -TEST 'Class' [[ ----@class Class - ----@param callback fun(value: Class) -function work(callback) -end - -work(function (<?value?>) -end) -]] - -TEST 'fun(value: Class)' [[ ----@class Class - ----@param callback fun(value: Class) -function work(callback) -end - -pcall(work, <?function?> (value) -end) -]] - -TEST 'Class' [[ ----@class Class - ----@param callback fun(value: Class) -function work(callback) -end - -xpcall(work, debug.traceback, function (<?value?>) -end) -]] - -TEST 'string' [[ ----@generic T ----@param x T ----@return { x: T } -local function f(x) end - -local t = f('') - -print(t.<?x?>) -]] - -TEST 'string' [[ ----@generic T ----@param t T[] ----@param callback fun(v: T) -local function f(t, callback) end - ----@type string[] -local t - -f(t, function (<?v?>) end) -]] - -TEST 'unknown' [[ ----@generic T ----@param t T[] ----@param callback fun(v: T) -local function f(t, callback) end - -local t = {} - -f(t, function (<?v?>) end) -]] - -TEST 'table' [[ -local <?t?> = setmetatable({}, { __index = function () end }) -]] - -TEST 'player' [[ ----@class player -local t - -<?t?>:getOwner() -]] - -TEST 'string[][]' [[ ----@type string[][] -local <?t?> -]] - -TEST 'table' [[ ----@type {}[] -local t - -local <?v?> = t[1] -]] - -TEST 'string' [[ ----@type string[][] -local v = {} - -for _, a in ipairs(v) do - for i, <?b?> in ipairs(a) do - end -end -]] - ---TEST 'number' [[ ------@param x number ---local f --- ---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)) -local emit = {} - -emit.on("died", function (<?i?>) -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)) -local emit = {} - -emit:on("died", function (<?i?>) -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)) -local emit = {} - -emit.on(self, "died", function (<?i?>) -end) -]] - -TEST '👍' [[ ----@class 👍 -local <?x?> -]] - -TEST 'integer' [[ ----@type boolean -local x - -<?x?> = 1 -]] - -TEST 'integer' [[ ----@class Class -local x - -<?x?> = 1 -]] - -TEST 'unknown' [[ ----@return number -local function f(x) - local <?y?> = x() -end -]] - -TEST 'unknown' [[ -local mt - ----@return number -function mt:f() end - -local <?v?> = mt() -]] - -TEST 'unknown' [[ -local <?mt?> - ----@class X -function mt:f(x) end -]] - -TEST 'any' [[ -local mt - ----@class X -function mt:f(<?x?>) end -]] - -TEST 'unknown' [[ -local <?mt?> - ----@type number -function mt:f(x) end -]] - -TEST 'any' [[ -local mt - ----@type number -function mt:f(<?x?>) end -]] - -TEST 'Test' [[ ----@class Test -_G.<?Test?> = {} -]] - -TEST 'integer' [[ -local mt = {} - ----@param callback fun(i: integer) -function mt:loop(callback) end - -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 - ----@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 - ----@class C ----@field x integer # C comment ----@field d D - ----@param c C -local function f(c) end - -f { - d = { - <?y?> = , - } -} -]] - -TEST 'integer' [[ -for <?i?> = a, b, c do end -]] - -TEST 'number' [[ ----@param x number -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] -]] - -TEST 'string' [[ -local t = { - x = 1, - [1] = 'x', -} - -local <?x?> = t[#t] -]] - -TEST 'string' [[ -local t = { 'x' } - -local <?x?> = t[#t] -]] - -TEST '(string|integer)[]' [[ ----@type (string|integer)[] -local <?x?> -]] - -TEST 'boolean' [[ ----@type table<string, boolean> -local t - ----@alias uri string - ----@type string -local uri - -local <?v?> = t[uri] -]] - -TEST 'A' [[ ----@class A -G = {} - -<?G?>:A() -]] - -TEST 'A' [[ ----@type A -local <?x?> = nil -]] - -TEST 'A' [[ ----@class A ----@field b B -local mt - -function mt:f() - self.b:x() - print(<?self?>) -end -]] - -TEST 'string?' [[ ----@return string? -local function f() end - -local <?x?> = f() -]] - -TEST 'AA' [[ ----@class AA ----@overload fun():AA -local AAA - - -local <?x?> = AAA() -]] - -TEST 'AA' [[ ----@class AA ----@overload fun():AA -AAA = {} - - -local <?x?> = AAA() -]] - -TEST 'string' [[ -local <?x?> -x = '1' -x = 1 -]] - -TEST 'string' [[ -local x -<?x?> = '1' -x = 1 -]] - -TEST 'integer' [[ -local x -x = '1' -<?x?> = 1 -]] - -TEST 'unknown' [[ -local x -print(<?x?>) -x = '1' -x = 1 -]] - -TEST 'string' [[ -local x -x = '1' -print(<?x?>) -x = 1 -]] - -TEST 'integer' [[ -local x -x = '1' -x = 1 -print(<?x?>) -]] - -TEST 'unknown' [[ -local x - -function A() - print(<?x?>) -end -]] - -TEST 'string' [[ -local x - -function A() - print(<?x?>) -end - -x = '1' -x = 1 -]] - -TEST 'string' [[ -local x - -x = '1' - -function A() - print(<?x?>) -end - -x = 1 -]] - -TEST 'integer' [[ -local x - -x = '1' -x = 1 - -function A() - print(<?x?>) -end - -]] - -TEST 'boolean' [[ -local x - -function A() - x = true - print(<?x?>) -end - -x = '1' -x = 1 -]] - -TEST 'unknown' [[ -local x - -function A() - x = true -end - -print(<?x?>) -x = '1' -x = 1 -]] - -TEST 'boolean' [[ -local x - -function A() - x = true - function B() - print(<?x?>) - end -end - -x = '1' -x = 1 -]] - -TEST 'table' [[ -local x - -function A() - x = true - function B() - x = {} - print(<?x?>) - end -end - -x = '1' -x = 1 -]] - -TEST 'boolean' [[ -local x - -function A() - x = true - function B() - x = {} - end - print(<?x?>) -end - -x = '1' -x = 1 -]] - -TEST 'unknown' [[ -local x - -function A() - x = true - function B() - x = {} - end -end - -function C() - print(<?x?>) -end - -x = '1' -x = 1 -]] - -TEST 'integer' [[ -local x -x = true -do - x = 1 -end -print(<?x?>) -]] - -TEST 'boolean' [[ -local x -x = true -function XX() - do - x = 1 - end -end -print(<?x?>) -]] - -TEST 'integer?' [[ ----@type integer? -local <?x?> -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if <?x?> then - print(x) -end -]] ---[[ -context 0 integer? - -save copy 'block' -save copy 'out' -push 'block' -get -push copy -truthy -falsy ref 'out' -get -save HEAD 'final' -push 'out' - -push copy HEAD -merge 'final' -]] - -TEST 'integer' [[ ----@type integer? -local x - -if x then - print(<?x?>) -end -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if x then - print(x) -end - -print(<?x?>) -]] - -TEST 'nil' [[ ----@type integer? -local x - -if not x then - print(<?x?>) -end - -print(x) -]] - -TEST 'integer' [[ ----@type integer? -local x - -if not x then - x = 1 -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -if not x then - return -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -if xxx and x then - print(<?x?>) -end -]] - -TEST 'unknown' [[ ----@type integer? -local x - -if not x and x then - print(<?x?>) -end -]] - -TEST 'integer' [[ ----@type integer? -local x - -if x and not mark[x] then - print(<?x?>) -end -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if xxx and x then -end - -print(<?x?>) -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if xxx and x then - return -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -if x ~= nil then - print(<?x?>) -end - -print(x) -]] - -TEST 'integer|nil' [[ ----@type integer? -local x - -if x ~= nil then - print(x) -end - -print(<?x?>) -]] - -TEST 'nil' [[ ----@type integer? -local x - -if x == nil then - print(<?x?>) -end - -print(x) -]] - -TEST 'integer|nil' [[ ----@type integer? -local x - -if x == nil then - print(x) -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -<?x?> = x or 1 -]] - -TEST 'integer' [[ ----@type integer? -local x - -<?x?> = x or y -]] - -TEST 'integer' [[ ----@type integer? -local x - -if not x then - return -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -if not x then - goto ANYWHERE -end - -print(<?x?>) -]] - -TEST 'integer' [=[ -local x - -print(<?x?>--[[@as integer]]) -]=] - -TEST 'integer' [=[ -print(<?io?>--[[@as integer]]) -]=] - -TEST 'integer' [=[ -print(io.<?open?>--[[@as integer]]) -]=] - -TEST 'integer' [=[ -local <?x?> = io['open']--[[@as integer]]) -]=] - -TEST 'integer' [=[ -local <?x?> = 1 + 1--[[@as integer]]) -]=] - -TEST 'integer' [=[ -local <?x?> = not 1--[[@as integer]]) -]=] - -TEST 'integer' [=[ -local <?x?> = ()--[[@as integer]]) -]=] - -TEST 'integer?' [[ ----@param x? integer -local function f(<?x?>) - -end -]] - -TEST 'integer' [[ -local x = 1 -x = <?x?> -]] - -TEST 'integer?' [[ ----@class A ----@field x? integer -local t - -t.<?x?> -]] - -TEST 'integer?' [[ ----@type { x?: integer } -local t - -t.<?x?> -]] - -TEST 'boolean' [[ ----@class A ----@field [integer] boolean -local t - -local <?x?> = t[1] -]] - -TEST 'unknown' [[ -local <?x?> = y and z -]] - -TEST 'integer' [[ ----@type integer? -local x - -assert(x) - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -assert(x ~= nil) - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer | nil -local x - -assert(x) - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer | nil -local x - -assert(x ~= nil) - -print(<?x?>) -]] - -TEST 'integer' [[ -local x - -assert(x == 1) - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -if x and <?x?>.y then -end -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if x and x.y then -end - -print(<?x?>) -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if x and x.y then - return -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -if not x or <?x?>.y then -end -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if not x or x.y then - print(<?x?>) -end -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if x or x.y then - print(<?x?>) -end -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if x.y or x then - print(<?x?>) -end -]] - -TEST 'integer?' [[ ----@type integer? -local x - -if x.y or not x then - print(<?x?>) -end -]] - -TEST 'integer' [[ ----@type integer? -local x - -if not x or not y then - return -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -if not y or not x then - return -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -while true do - if not x then - break - end - print(<?x?>) -end -]] - -TEST 'integer?' [[ ----@type integer? -local x - -while true do - if not x then - break - end -end - -print(<?x?>) -]] - -TEST 'integer' [[ ----@type integer? -local x - -while x do - print(<?x?>) -end -]] - -TEST 'integer' [[ ----@type fun():integer? -local iter - -for <?x?> in iter do -end -]] - -TEST 'integer' [[ -local x - ----@type integer -<?x?> = XXX -]] - -TEST 'unknown' [[ -for _ = 1, 999 do - local <?x?> -end -]] - -TEST 'integer' [[ -local x - ----@cast x integer - -print(<?x?>) -]] - -TEST 'unknown' [[ -local x - ----@cast x integer - -local x -print(<?x?>) -]] - -TEST 'unknown' [[ -local x - -if true then - local x - ---@cast x integer - print(x) -end - -print(<?x?>) -]] - -TEST 'boolean|integer' [[ -local x = 1 - ----@cast x +boolean - -print(<?x?>) -]] - -TEST 'boolean' [[ ----@type integer|boolean -local x - ----@cast x -integer - -print(<?x?>) -]] - -TEST 'boolean?' [[ ----@type boolean -local x - ----@cast x +? - -print(<?x?>) -]] - -TEST 'boolean' [[ ----@type boolean? -local x - ----@cast x -? - -print(<?x?>) -]] - -TEST 'nil' [[ ----@type string? -local x - -if x then - return -else - print(<?x?>) -end - -print(x) -]] - -TEST 'string' [[ ----@type string? -local x - -if not x then - return -else - print(<?x?>) -end - -print(x) -]] - -TEST 'string' [[ ----@type string? -local x - -if not x then - return -else - print(x) -end - -print(<?x?>) -]] - -TEST 'true' [[ ----@type boolean | nil -local x - -if not x then - return -end - -print(<?x?>) -]] - -TEST 'true' [[ ----@type boolean -local t - -if t then - print(<?t?>) - return -end - -print(t) -]] - -TEST 'false' [[ ----@type boolean -local t - -if t then - print(t) - return -end - -print(<?t?>) -]] - -TEST 'nil' [[ ----@type integer? -local t - -if t then -else - print(<?t?>) -end - -print(t) -]] - -TEST 'table' [[ -local function f() - if x then - return y - end - return {} -end - -local <?z?> = f() -]] - -TEST 'integer|table' [[ -local function returnI() - return 1 -end - -local function f() - if x then - return returnI() - end - return {} -end - -local <?z?> = f() -]] - -TEST 'number' [[ -for _ in _ do - ---@type number - local <?x?> -end -]] - -TEST 'unknown' [[ -for _ in _ do - ---@param x number - local <?x?> -end -]] - -TEST 'unknown' [[ ----@type number -for <?x?> in _ do -end -]] - -TEST 'number' [[ ----@param x number -for <?x?> in _ do -end -]] - -TEST 'table' [[ ----@alias tp table - ----@type tp -local <?x?> -]] - -TEST '{ name: boolean }' [[ ----@alias tp {name: boolean} - ----@type tp -local <?x?> -]] - -TEST 'boolean|{ name: boolean }' [[ ----@alias tp boolean | {name: boolean} - ----@type tp -local <?x?> -]] - -TEST '`1`|`true`' [[ ----@type `1` | `true` -local <?x?> -]] - -TEST 'function' [[ -local x - -function x() end - -print(<?x?>) -]] - -TEST 'unknown' [[ -local x - -if x.field == 'haha' then - print(<?x?>) -end -]] - -TEST 'string' [[ ----@type string? -local t - -if not t or xxx then - return -end - -print(<?t?>) -]] - -TEST 'table' [[ ----@type table|nil -local t - -return function () - if not t then - return - end - - print(<?t?>) -end -]] - -TEST 'table' [[ ----@type table|nil -local t - -f(function () - if not t then - return - end - - print(<?t?>) -end) -]] - -TEST 'table' [[ ----@type table? -local t - -t = t or {} - -print(<?t?>) -]] - -TEST 'unknown|nil' [[ -local x - -if x == nil then -end - -print(<?x?>) -]] - -TEST 'table<xxx, true>' [[ ----@alias xxx table<xxx, true> - ----@type xxx -local <?t?> -]] - -TEST 'xxx[][]' [[ ----@alias xxx xxx[] - ----@type xxx -local <?t?> -]] - -TEST 'fun(x: fun(x: xxx))' [[ ----@alias xxx fun(x: xxx) - ----@type xxx -local <?t?> -]] - -TEST 'table' [[ ----@type table|nil -local t - -while t do - print(<?t?>) -end -]] - -TEST 'table|nil' [[ ----@type table|nil -local t - -while <?t?> do - print(t) -end -]] - -TEST 'table' [[ ----@type table|nil -local t - -while t ~= nil do - print(<?t?>) -end -]] - -TEST 'table|nil' [[ ----@type table|nil -local t - -while <?t?> ~= nil do - print(t) -end -]] - -TEST 'integer' [[ ----@type integer? -local n - -if not n then - error('n is nil') -end - -print(<?n?>) -]] - -TEST 'integer' [[ ----@type integer? -local n - -if not n then - os.exit() -end - -print(<?n?>) -]] - -TEST 'table' [[ ----@type table? -local n - -print((n and <?n?>.x)) -]] - -TEST 'table' [[ ----@type table? -local n - -n = n and <?n?>.x or 1 -]] - -TEST 'table' [[ ----@type table? -local n - -n = ff[n and <?n?>.x] -]] - -TEST 'integer' [[ -local x - -if type(x) == 'integer' then - print(<?x?>) -end -]] - -TEST 'boolean|integer' [[ -local x - -if type(x) == 'integer' -or type(x) == 'boolean' then - print(<?x?>) -end -]] - -TEST 'fun()' [[ ----@type fun()? -local x - -if type(x) == 'function' then - print(<?x?>) -end -]] - -TEST 'function' [[ -local x - -if type(x) == 'function' then - print(<?x?>) -end -]] - -TEST 'integer' [[ -local x -local tp = type(x) - -if tp == 'integer' then - print(<?x?>) -end -]] - -TEST 'integer' [[ ----@type integer? -local x - -if (x == nil) then -else - print(<?x?>) -end -]] - -TEST 'B' [[ ----@class A ----@class B - ----@type A -local x - ----@type B -x = call(x) - -print(<?x?>) -]] - -TEST 'nil' [[ -local function f() -end - -local <?x?> = f() -]] - -TEST 'integer[]' [[ ----@type integer[] -local x -if not x then - return -end - -print(<?x?>) -]] - -TEST 'unknown' [[ ----@type string[] -local t - -local <?x?> = t.x -]] - -TEST 'integer|unknown' [[ -local function f() - return GG -end - -local t - -t.x = 1 -t.x = f() - -print(t.<?x?>) -]] - -TEST 'integer' [[ -local function f() - if X then - return X - else - return 1 - end -end - -local <?n?> = f() -]] - -TEST 'unknown' [[ -local function f() - return t[k] -end - -local <?n?> = f() -]] - -TEST 'integer|nil' [[ -local function f() - if x then - return - else - return 1 - end -end - -local <?n?> = f() -]] - -TEST 'integer' [[ ----@class A ----@field x integer -local m - -m.<?x?> = true - -print(m.x) -]] - -TEST 'integer' [[ ----@class A ----@field x integer -local m - -m.x = true - -print(m.<?x?>) -]] - -TEST 'integer' [[ ----@class A ----@field x integer --> 1st -local m = { - x = '' --> 2nd -} - ----@type boolean -m.x = true --> 3rd (with ---@type above) - -m.x = {} --> 4th - -print(m.<?x?>) -]] - -TEST 'string' [[ ----@class A -----@field x integer --> 1st -local m = { - x = '' --> 2nd -} - ----@type boolean -m.x = true --> 3rd (with ---@type above) - -m.x = {} --> 4th - -print(m.<?x?>) -]] - -TEST 'boolean' [[ ----@class A -----@field x integer --> 1st -local m = { - --x = '' --> 2nd -} - ----@type boolean -m.x = true --> 3rd (with ---@type above) - -m.x = {} --> 4th - -print(m.<?x?>) -]] - -TEST 'table' [[ ----@class A -----@field x integer --> 1st -local m = { - --x = '' --> 2nd -} - ----@type boolean ---m.x = true --> 3rd (with ---@type above) - -m.x = {} --> 4th - -print(m.<?x?>) -]] - -TEST 'boolean?' [[ ----@generic T ----@param x T ----@return T -local function echo(x) end - ----@type boolean? -local b - -local <?x?> = echo(b) -]] - -TEST 'boolean' [[ ----@generic T ----@param x T? ----@return T -local function echo(x) end - ----@type boolean? -local b - -local <?x?> = echo(b) -]] - -TEST 'boolean' [[ ----@generic T ----@param x? T ----@return T -local function echo(x) end - ----@type boolean? -local b - -local <?x?> = echo(b) -]] - -TEST 'boolean' [[ ----@overload fun():boolean ----@param x integer ----@return number -function f(x) -end - -local <?x?> = f() -]] - -TEST 'number' [[ ----@overload fun():boolean ----@param x integer ----@return number -function f(x) -end - -local <?x?> = f(1) -]] - -TEST 'boolean' [[ ----@overload fun():boolean ----@param x integer ----@return number -function f(x) -end - -function r0() - return -end - -local <?x?> = f(r0()) -]] - -TEST 'number' [[ ----@overload fun():boolean ----@param x integer ----@return number -function f(x) -end - -function r1() - return 1 -end - -local <?x?> = f(r1()) -]] - -TEST 'boolean' [[ ----@overload fun():boolean ----@param x integer ----@return number -function f(x) -end - ----@type fun() -local r0 - -local <?x?> = f(r0()) -]] - -TEST 'number' [[ ----@overload fun():boolean ----@param x integer ----@return number -function f(x) -end - ----@type fun():integer -local r1 - -local <?x?> = f(r1()) -]] - -TEST 'boolean' [[ ----@overload fun(x: number, y: number):string ----@overload fun(x: number):number ----@return boolean -local function f() end - -local <?n1?> = f() -local n2 = f(0) -local n3 = f(0, 0) -]] - -TEST 'number' [[ ----@overload fun(x: number, y: number):string ----@overload fun(x: number):number ----@return boolean -local function f() end - -local n1 = f() -local <?n2?> = f(0) -local n3 = f(0, 0) -]] - -TEST 'string' [[ ----@overload fun(x: number, y: number):string ----@overload fun(x: number):number ----@return boolean -local function f() end - -local n1 = f() -local n2 = f(0) -local <?n3?> = f(0, 0) -]] - -TEST 'boolean' [[ ----@type {[integer]: boolean, xx: integer} -local t - -local <?n?> = t[1] -]] - -TEST 'boolean' [[ ----@type integer -local i - ----@type {[integer]: boolean, xx: integer} -local t - -local <?n?> = t[i] -]] - -TEST 'string' [=[ -local x = true -local y = x--[[@as integer]] --is `integer` here -local z = <?x?>--[[@as string]] --is `true` here -]=] - -TEST 'integer' [[ ----@type integer -local x - -if type(x) == 'number' then - print(<?x?>) -end -]] - -TEST 'boolean' [[ ----@class A ----@field [integer] boolean -local mt - -function mt:f() - ---@type integer - local index - local <?x?> = self[index] -end -]] - -TEST 'boolean' [[ ----@class A ----@field [B] boolean - ----@class B - ----@type A -local a - ----@type B -local b - -local <?x?> = a[b] -]] - -TEST 'number' [[ ----@type {x: string ; y: boolean; z: number} -local t - -local <?z?> = t.z -]] - -TEST 'fun():number, boolean' [[ ----@type {f: fun():number, boolean} -local t - -local <?f?> = t.f -]] - -TEST 'fun():number' [[ ----@type {(f: fun():number), x: boolean} -local t - -local <?f?> = t.f -]] - -TEST 'boolean' [[ ----@param ... boolean -local function f(...) - local <?n?> = ... -end -]] - -TEST 'boolean' [[ ----@param ... boolean -local function f(...) - local _, <?n?> = ... -end -]] - -TEST 'boolean' [[ ----@return boolean ... -local function f() end - -local <?n?> = f() -]] - -TEST 'boolean' [[ ----@return boolean ... -local function f() end - -local _, <?n?> = f() -]] - -TEST 'boolean' [[ ----@type fun():name1: boolean, name2:number -local f - -local <?n?> = f() -]] - -TEST 'number' [[ ----@type fun():name1: boolean, name2:number -local f - -local _, <?n?> = f() -]] -TEST 'boolean' [[ ----@type fun():(name1: boolean, name2:number) -local f - -local <?n?> = f() -]] - -TEST 'number' [[ ----@type fun():(name1: boolean, name2:number) -local f - -local _, <?n?> = f() -]] - -TEST 'boolean' [[ ----@type fun():...: boolean -local f - -local _, <?n?> = f() -]] - -TEST 'string' [[ -local s -while true do - s = '' -end -print(<?s?>) -]] - -TEST 'string' [[ -local s -for _ in _ do - s = '' -end -print(<?s?>) -]] - -TEST 'A' [[ ----@class A: string - ----@type A -local <?s?> = '' -]] - -TEST 'number' [[ ----@return number -local function f() end -local x, <?y?> = 1, f() -]] - -TEST 'boolean' [[ ----@return number, boolean -local function f() end -local x, y, <?z?> = 1, f() -]] - -TEST 'number' [[ ----@return number, boolean -local function f() end -local x, y, <?z?> = 1, 2, f() -]] - -TEST 'unknown' [[ -local f - -print(<?f?>) - -function f() end -]] - -TEST 'unknown' [[ -local f - -do - print(<?f?>) -end - -function f() end -]] - -TEST 'function' [[ -local f - -function A() - print(<?f?>) -end - -function f() end -]] - -TEST 'number' [[ ----@type number|nil -local n - -local t = { - x = n and <?n?>, -} -]] - -TEST 'table' [[ ----@type table? -local n - -if not n or not <?n?>.x then -end -]] - -TEST 'table' [[ ----@type table? -local n - -if not n or not <?n?>[1] then -end -]] - -TEST 'number' [[ ----@type number|false -local n - ----@cast n -false - -print(<?n?>) -]] - -TEST 'table' [[ ----@type number|table -local n - -if n ----@cast n table -and <?n?>.type == 'xxx' then -end -]] - -TEST 'integer' [[ ----@type integer? -local n -if true then - n = 0 -end -local <?x?> = n or 0 -]] - -TEST 'number' [=[ -local <?x?> = F()--[[@as number]] -]=] - -TEST 'number' [=[ -local function f() - return F()--[[@as number]] -end - -local <?x?> = f() -]=] - -TEST 'number' [=[ -local <?x?> = X --[[@as number]] -]=] - -TEST 'number' [[ ----@return number?, number? -local function f() end - -for <?x?>, y in f do -end -]] - -TEST 'number' [[ ----@return number?, number? -local function f() end - -for x, <?y?> in f do -end -]] - -TEST 'number|nil' [[ ----@type table|nil -local a - ----@type number|nil -local b - -local <?c?> = a and b -]] - -TEST 'number|table|nil' [[ ----@type table|nil -local a - ----@type number|nil -local b - -local <?c?> = a or b -]] - -TEST 'number|table|nil' [[ ----@type table|nil -local a - ----@type number|nil -local b - -local c = a and b -local <?d?> = a or b -]] - -TEST 'number' [[ -local x - ----@return number -local function f() -end - -x = f() - -print(<?x?>) -]] - -TEST 'number' [[ -local x - ----@return number -local function f() -end - -_, x = pcall(f) - -print(<?x?>) -]] - -TEST 'string' [[ ----@type table<string|number, string> -local t - ----@type number -local n ----@type string -local s - -local <?test?> = t[n] -local test2 = t[s] --test and test2 are unknow -]] - -TEST 'string' [[ ----@type table<string|number, string> -local t - ----@type number -local n ----@type string -local s - -local test = t[n] -local <?test2?> = t[s] --test and test2 are unknow -]] - -TEST 'table<number, boolean>' [[ ----@type table<number, boolean> -local t - -<?t?> = {} -]] - -TEST 'integer' [[ ----@type integer[]|A -local t - -local <?x?> = t[1] -]] - -TEST 'integer' [[ ----@type integer ----@diagnostic disable -local <?t?> -]] - -TEST 'A' [[ ----@class A ----@diagnostic disable -local <?t?> -]] - -TEST '{ [string]: number, [true]: string, [1]: boolean, tag: integer }' [[ ----@type {[string]: number, [true]: string, [1]: boolean, tag: integer} -local <?t?> -]] - -TEST 'unknown' [[ -local mt = {} -mt.<?x?> = nil -]] - -TEST 'unknown' [[ -mt = {} -mt.<?x?> = nil -]] - -TEST 'A' [[ ----@class A ----@operator unm: A - ----@type A -local a -local <?b?> = -a -]] - -TEST 'A' [[ ----@class A ----@operator bnot: A - ----@type A -local a -local <?b?> = ~a -]] - -TEST 'A' [[ ----@class A ----@operator len: A - ----@type A -local a -local <?b?> = #a -]] - -TEST 'A' [[ ----@class A ----@operator add: A - ----@type A -local a -local <?b?> = a + 1 -]] - -TEST 'A' [[ ----@class A ----@operator sub: A - ----@type A -local a -local <?b?> = a - 1 -]] - -TEST 'A' [[ ----@class A ----@operator mul: A - ----@type A -local a -local <?b?> = a * 1 -]] - -TEST 'A' [[ ----@class A ----@operator div: A - ----@type A -local a -local <?b?> = a / 1 -]] - -TEST 'A' [[ ----@class A ----@operator mod: A - ----@type A -local a -local <?b?> = a % 1 -]] - -TEST 'A' [[ ----@class A ----@operator pow: A - ----@type A -local a -local <?b?> = a ^ 1 -]] - -TEST 'A' [[ ----@class A ----@operator idiv: A - ----@type A -local a -local <?b?> = a // 1 -]] - -TEST 'A' [[ ----@class A ----@operator band: A - ----@type A -local a -local <?b?> = a & 1 -]] - -TEST 'A' [[ ----@class A ----@operator bor: A - ----@type A -local a -local <?b?> = a | 1 -]] - -TEST 'A' [[ ----@class A ----@operator bxor: A - ----@type A -local a -local <?b?> = a ~ 1 -]] - -TEST 'A' [[ ----@class A ----@operator shl: A - ----@type A -local a -local <?b?> = a << 1 -]] - -TEST 'A' [[ ----@class A ----@operator shr: A - ----@type A -local a -local <?b?> = a >> 1 -]] - -TEST 'A' [[ ----@class A ----@operator concat: A - ----@type A -local a -local <?b?> = a .. 1 -]] - -TEST 'A' [[ ----@class A ----@operator add(boolean): boolean ----@operator add(integer): A - ----@type A -local a -local <?b?> = a + 1 -]] - -TEST 'boolean' [[ ----@class A ----@operator add(boolean): boolean ----@operator add(integer): A - ----@type A -local a -local <?b?> = a + true -]] - -TEST 'A' [[ ----@class A ----@operator call: A - ----@type A -local a -local <?b?> = a() -]] - -TEST 'A' [[ ----@class A ----@operator call: A - ----@type A -local a - -local t = { - <?x?> = a(), -} -]] - -TEST 'boolean' [[ ----@class A ----@field n number ----@field [string] boolean -local t - -local <?x?> = t.xx -]] - -TEST 'number' [[ ----@class A ----@field n number ----@field [string] boolean -local t - -local <?x?> = t.n -]] - -TEST 'string' [[ ----@class string ----@operator mod: string - -local <?b?> = '' % 1 -]] - -TEST 'string|integer' [[ ----@type boolean -local bool - -local <?x?> = bool and '' or 0 -]] - -TEST 'string|integer' [[ -local bool - -if X then - bool = true -else - bool = false -end - -local <?x?> = bool and '' or 0 -]] - -TEST 'boolean' [[ ----@type boolean|true|false -local <?b?> -]] - -TEST 'integer|false' [[ -local <?b?> = X == 1 and X == 1 and 1 -]] - -TEST 'unknown|nil' [[ -local function f() - if X then - return ({})[1] - end - return nil -end - -local <?n?> = f() -]] - -TEST 'integer' [[ ----@generic T ----@vararg T # ERROR ----@return T -local function test(...) - return ... -end - -local <?n?> = test(1) -]] - -TEST 'boolean' [[ ----@type boolean, number -local <?x?>, y -]] - -TEST 'number' [[ ----@type boolean, number -local x, <?y?> -]] - -TEST 'unknown' [[ ----@type _, number -local <?x?>, y -]] - -TEST 'number[]' [[ -local t ----@cast t number[]? - -local x = t and <?t?>[i] -]] - -TEST 'number?' [[ ----@type number[]? -local t - -local <?x?> = t and t[i] -]] - -TEST 'number' [[ ----@type number -local x - -if not <?x?>.y then - x = nil -end -]] - -TEST 'number' [[ ----@type number|nil -local x -while x == nil do - if x == nil then - return - end - - x = nil -end - -print(<?x?>) -]] - -TEST 'integer' [[ -local A = { - ---@class XXX - B = {} -} - -A.B.C = 1 - -print(A.B.<?C?>) -]] - -TEST '-2|-3|1' [[ ----@type 1|-2|-3 -local <?n?> -]] - -TEST 'table' [[ ----@enum A -local m = {} - -print(<?m?>) -]] - -TEST 'A' [[ ----@class A ----@overload fun():A -local m = {} - ----@return A -function m:init() - return <?self?> -end -]] - -TEST 'string' [[ ----@vararg string -function F(...) - local t = {...} - for k, <?v?> in pairs(t) do - end -end -]] - -TEST 'string' [[ ----@vararg string -function F(...) - local t = {...} - for k, <?v?> in ipairs(t) do - end -end -]] - -TEST 'integerA' [[ ----@type integerA -for <?i?> = 1, 10 do -end -]] - -TEST 'string' [[ ----@class A ----@field x string - ----@class B : A -local t = {} - -t.x = t.x - -print(t.<?x?>) -]] - -TEST 'unknown' [[ -local t = { - x = 1, -} - -local x - -local <?v?> = t[x] -]] - -TEST 'A|B' [[ ----@class A ----@class B: A - ----@type A|B -local <?t?> -]] - -TEST 'function' [[ ----@class myClass -local myClass = { has = { nested = {} } } - -function myClass.has.nested.fn() end - ----@type myClass -local class - -class.has.nested.<?fn?>() -]] - -TEST 'integer[]' [[ ----@generic T ----@param f fun(x: T) ----@return T[] -local function x(f) end - ----@param x integer -local <?arr?> = x(function (x) end) -]] - -TEST 'integer[]' [[ ----@generic T ----@param f fun():T ----@return T[] -local function x(f) end - -local <?arr?> = x(function () - return 1 -end) -]] - -TEST 'integer[]' [[ ----@generic T ----@param f fun():T ----@return T[] -local function x(f) end - ----@return integer -local <?arr?> = x(function () end) -]] - -TEST 'integer[]' [[ ----@generic T ----@param f fun(x: T) ----@return T[] -local function x(f) end - ----@type fun(x: integer) -local cb - -local <?arr?> = x(cb) -]] - -TEST 'integer[]' [[ ----@generic T ----@param f fun():T ----@return T[] -local function x(f) end - ----@type fun(): integer -local cb - -local <?arr?> = x(cb) -]] - -TEST 'integer' [[ ----@return fun(x: integer) -local function f() - return function (<?x?>) - end -end -]] - -TEST 'string' [[ ----@class A ----@field f fun(x: string) - ----@type A -local t = { - f = function (<?x?>) end -} -]] - -config.set(nil, 'Lua.runtime.special', { - ['xx.assert'] = 'assert' -}) - -TEST 'number' [[ ----@type number? -local t - -xx.assert(t) - -print(<?t?>) -]] - -config.set(nil, 'Lua.runtime.special', nil) - -TEST 'A' [[ ----@class A -local mt - ----@return <?self?> -function mt:init() -end -]] - -TEST 'A' [[ ----@class A -local mt - ----@return self -function mt:init() -end - -local <?o?> = mt:init() -]] - -TEST 'A' [[ ----@class A ----@field x <?self?> -]] - -TEST 'A' [[ ----@class A ----@field x self - ----@type A -local o - -print(o.<?x?>) -]] - -TEST 'A' [[ ----@class A ----@overload fun(): self -local A - -local <?o?> = A() -]] - -TEST 'number' [[ ----@type table<'Test1', fun(x: number)> -local t = { - ["Test1"] = function(<?x?>) end, -} -]] - -TEST 'number' [[ ----@type table<5, fun(x: number)> -local t = { - [5] = function(<?x?>) end, -} -]] - -TEST 'number' [[ ----@type fun(x: number) -local function f(<?x?>) end -]] - -TEST 'boolean' [[ ----@generic T: string | boolean | table ----@param x T ----@return T -local function f(x) - return x -end - -local <?x?> = f(true) -]] - -TEST 'number' [[ ----@class A ----@field [1] number ----@field [2] boolean -local t - -local <?n?> = t[1] -]] - -TEST 'boolean' [[ ----@class A ----@field [1] number ----@field [2] boolean -local t - -local <?n?> = t[2] -]] - -TEST 'N' [[ ----@class N: number -local x - -if x == 0.1 then - print(<?x?>) -end -]] - -TEST 'vec3' [[ ----@class mat4 ----@operator mul(vec3): vec3 -- matrix * vector ----@operator mul(number): mat4 -- matrix * constant - ----@class vec3: number - ----@type mat4, vec3 -local m, v - -local <?r?> = m * v -]] - -TEST 'mat4' [[ ----@class mat4 ----@operator mul(number): mat4 -- matrix * constant ----@operator mul(vec3): vec3 -- matrix * vector - ----@class vec3: number - ----@type mat4, vec3 -local m, v - -local <?r?> = m * v -]] - -TEST 'A|B' [[ ----@class A ----@class B - ----@type A|B -local t - -if x then - ---@cast t A -else - print(<?t?>) -end -]] - -TEST 'A|B' [[ ----@class A ----@class B - ----@type A|B -local t - -if x then - ---@cast t A -elseif <?t?> then -end -]] - -TEST 'A|B' [[ ----@class A ----@class B - ----@type A|B -local t - -if x then - ---@cast t A - print(t) -elseif <?t?> then -end -]] - -TEST 'A|B' [[ ----@class A ----@class B - ----@type A|B -local t - -if x then - ---@cast t A - print(t) -elseif <?t?> then - ---@cast t A - print(t) -end -]] - -TEST 'function' [[ -local function x() - print(<?x?>) -end -]] - -TEST 'number' [[ ----@type number? -local x - -do - if not x then - return - end -end - -print(<?x?>) -]] - -TEST 'number' [[ ----@type number[] -local xs - ----@type fun(x): number? -local f - -for _, <?x?> in ipairs(xs) do - x = f(x) -end -]] - -TEST 'number' [[ ----@type number? -X = Y - -if X then - print(<?X?>) -end -]] - -TEST 'number' [[ ----@type number|boolean -X = Y - -if type(X) == 'number' then - print(<?X?>) -end -]] - -TEST 'boolean' [[ ----@type number|boolean -X = Y - -if type(X) ~= 'number' then - print(<?X?>) -end -]] - -TEST 'boolean' [[ ----@type number -X = Y - ----@cast X boolean - -print(<?X?>) -]] - -TEST 'number' [[ ----@type number -local t - -if xxx == <?t?> then - print(t) -end -]] - -TEST 'V' [[ ----@class V -X = 1 - -print(<?X?>) -]] - -TEST 'V' [[ ----@class V -X.Y = 1 - -print(X.<?Y?>) -]] - -TEST 'integer' [[ -local x = {} - -x.y = 1 -local y = x.y -x.y = nil - -print(<?y?>) -]] - -TEST 'function' [[ -function X() - <?Y?>() -end - -function Y() -end -]] - -TEST 'A_Class' [[ ----@class A_Class -local A = { x = 5 } - -function A:func() - for i = 1, <?self?>.x do - print(i) - end - - self.y = 3 - self.y = self.y + 3 -end -]] - -TEST 'number' [[ ----@type number? -local n -local <?v?> = n or error('') -]] - -TEST 'Foo' [[ ----@class Foo ----@operator mul(Foo): Foo ----@operator mul(Bar): Foo ----@class Bar - ----@type Foo -local foo - ----@type Foo|Bar -local fooOrBar - -local <?b?> = foo * fooOrBar -]] - -TEST 'number' [[ -local a = 4; -local b = 2; - -local <?c?> = a / b; -]] - -TEST 'string' [[ -local a = '4'; -local b = '2'; - -local <?c?> = a .. b; -]] - -TEST 'number|{ [1]: string }' [[ ----@alias Some ----| { [1]: string } ----| number - -local x ---@type Some - -print(<?x?>) -]] - -TEST 'integer' [[ ----@class metatable : table ----@field __index table - ----@param table table ----@param metatable? metatable ----@return table -function setmetatable(table, metatable) end - -local m = setmetatable({},{ __index = { a = 1 } }) - -m.<?a?> -]] - -TEST 'integer' [[ ----@class metatable : table ----@field __index table - ----@param table table ----@param metatable? metatable ----@return table -function setmetatable(table, metatable) end - -local mt = {a = 1 } -local m = setmetatable({},{ __index = mt }) - -m.<?a?> -]] - -TEST 'integer' [[ -local x = 1 -repeat -until <?x?> -]] - --- #2144 -TEST 'A' [=[ -local function f() - return {} --[[@as A]] -end - -local <?x?> = f() -]=] - -TEST 'A' [=[ -local function f() - ---@type A - return {} -end - -local <?x?> = f() -]=] - -TEST 'boolean|number' [[ ----@alias A number ----@alias(partial) A boolean - ----@type A -local <?x?> -]] +require 'type_inference.common' +require 'type_inference.param_match' diff --git a/test/type_inference/param_match.lua b/test/type_inference/param_match.lua new file mode 100644 index 00000000..3bb167bc --- /dev/null +++ b/test/type_inference/param_match.lua @@ -0,0 +1,107 @@ + +TEST 'boolean' [[ +---@overload fun(x: number, y: number):string +---@overload fun(x: number):number +---@return boolean +local function f() end + +local <?n1?> = f() +local n2 = f(0) +local n3 = f(0, 0) +]] + +TEST 'number' [[ +---@overload fun(x: number, y: number):string +---@overload fun(x: number):number +---@return boolean +local function f() end + +local n1 = f() +local <?n2?> = f(0) +local n3 = f(0, 0) +]] + +TEST 'string' [[ +---@overload fun(x: number, y: number):string +---@overload fun(x: number):number +---@return boolean +local function f() end + +local n1 = f() +local n2 = f(0) +local <?n3?> = f(0, 0) +]] + +TEST 'boolean' [[ +---@overload fun():boolean +---@param x integer +---@return number +function f(x) +end + +local <?x?> = f() +]] + +TEST 'number' [[ +---@overload fun():boolean +---@param x integer +---@return number +function f(x) +end + +local <?x?> = f(1) +]] + +TEST 'boolean' [[ +---@overload fun():boolean +---@param x integer +---@return number +function f(x) +end + +function r0() + return +end + +local <?x?> = f(r0()) +]] + +TEST 'number' [[ +---@overload fun():boolean +---@param x integer +---@return number +function f(x) +end + +function r1() + return 1 +end + +local <?x?> = f(r1()) +]] + +TEST 'boolean' [[ +---@overload fun():boolean +---@param x integer +---@return number +function f(x) +end + +---@type fun() +local r0 + +local <?x?> = f(r0()) +]] + +TEST 'number' [[ +---@overload fun():boolean +---@param x integer +---@return number +function f(x) +end + +---@type fun():integer +local r1 + +local <?x?> = f(r1()) +]] |