local files = require 'files' local config = require 'config' local vm = require 'vm' local guide = require 'parser.guide' rawset(_G, 'TEST', true) local function getSource(pos) local ast = files.getAst('') return guide.eachSourceContain(ast.ast, pos, function (source) if source.type == 'local' or source.type == 'getlocal' or source.type == 'setlocal' or source.type == 'setglobal' or source.type == 'getglobal' or source.type == 'field' or source.type == 'method' then return source end end) end function TEST(wanted) return function (script) files.removeAll() local start = script:find('', 1, true) local pos = (start + finish) // 2 + 1 local newScript = script:gsub('<[!?]', ' '):gsub('[!?]>', ' ') files.setText('', newScript) local source = getSource(pos) assert(source) local result = vm.getType(source) or 'any' assert(wanted == result) end end config.config.runtime.version = 'Lua 5.4' TEST 'string' [[ local = '111' ]] TEST 'boolean' [[ local = true ]] TEST 'integer' [[ local = 1 ]] TEST 'number' [[ local = 1.0 ]] TEST 'string' [[ local var = '111' t. = var ]] TEST 'any' [[ local var = '111' ]] TEST 'string' [[ local var var = '111' print() ]] TEST 'function' [[ function () end ]] TEST 'function' [[ local function () end ]] TEST 'function' [[ local xx = function () end ]] TEST 'table' [[ local = {} ]] TEST 'function' [[ () ]] TEST 'table' [[ .x = 1 ]] TEST 'boolean' [[ = not y ]] TEST 'integer' [[ = #y ]] TEST 'number' [[ = - y ]] TEST 'integer' [[ = ~ y ]] TEST 'integer' [[ local a = true local b = 1 = a and b ]] TEST 'integer' [[ local a = false local b = 1 = a or b ]] TEST 'boolean' [[ = a == b ]] TEST 'integer' [[ = a << b ]] TEST 'string' [[ = a .. b ]] TEST 'number' [[ = a + b ]] TEST 'table' [[ () ]] TEST 'string' [[ = _VERSION ]] TEST 'function' [[ = ('x').sub ]] TEST 'function' [[ = _VERSION.sub ]] TEST 'table' [[ = setmetatable({}) ]] TEST 'integer' [[ local function x() return 1 end = x() ]] TEST 'string|table' [[ local y = # ]] TEST 'integer' [[ local y = << 0 ]] TEST 'integer' [[ local function f(, b) return a << b end ]] -- 不根据调用者的输入参数来推测 --TEST 'number' [[ --local function x(a) -- return --end --x(1) --]] TEST 'table' [[ setmetatable() ]] TEST 'function' [[ string.() ]] TEST 'function' [[ (''):() ]] -- 不根据对方函数内的使用情况来推测 --TEST 'number' [[ --local function x(a) -- _ = a + 1 --end --local b --x() --]] --TEST 'number' [[ --local function x(a, ...) -- local _, , _ = ... --end --x(nil, 'xx', 1, true) --]] -- 引用不跨越参数 --TEST 'number' [[ --local function x(a, ...) -- return true, 'ss', ... --end --local _, _, _, , _ = x(nil, true, 1, 'yy') --]] -- 暂不支持这些特殊情况,之后用其他语法定义 --TEST 'integer' [[ --for in ipairs(t) do --end --]] -- --TEST 'any' [[ --local = next() --]]