444 lines
15 KiB
Lua
444 lines
15 KiB
Lua
|
|
local SUITE = require 'TestSuite' 'function'
|
|
SUITE:setEnviroment{
|
|
format = require('pretty')
|
|
}
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Compat
|
|
if not loadstring then loadstring = load end -- Lua 5.3 compat
|
|
local HAS_ADV_GETLOCAL = not not debug.getinfo(1, 'u').nparams -- Lua 5.1 compat
|
|
local HAS_UNICODE_IDEN = not not loadstring 'local ϕ = 1; return ϕ' -- Lua 5.1 compat
|
|
local HAS_JIT_LIBRARY = type(rawget(_G, 'jit')) == 'table' -- Non-LuaJIT compat
|
|
--
|
|
|
|
local function format_test (t)
|
|
if t.adv_getlocal and not HAS_ADV_GETLOCAL then return end
|
|
if t.single then
|
|
return SUITE:addTest(t.name or t.expect, function ()
|
|
local format = format({t.input}, t.options):gsub('^{%s+(.-)%s+}$', function(a) return '{ '..a..' }' end)
|
|
assert_equal('{ '..t.expect..' }', format)
|
|
end, { line = debug.getinfo(2).currentline })
|
|
end
|
|
SUITE:addTest(t.name or t.expect, function ()
|
|
assert_equal(t.expect, format(t.input, t.options))
|
|
end, { line = debug.getinfo(2).currentline })
|
|
end
|
|
|
|
local function curline (delta) return debug.getinfo(2).currentline + (delta or 0) end
|
|
|
|
local TEST_UPVALUE = 42
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Basic inline functions
|
|
|
|
format_test {
|
|
name = 'Function basic formatting',
|
|
adv_getlocal = true,
|
|
single = true,
|
|
input = function () end,
|
|
expect = 'function () ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Function with a single argument',
|
|
adv_getlocal = true,
|
|
single = true,
|
|
input = function (a) end,
|
|
expect = 'function (a) ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Function with multiple arguments',
|
|
adv_getlocal = true,
|
|
single = true,
|
|
input = function (a, b) end,
|
|
expect = 'function (a, b) ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Function with vararg',
|
|
adv_getlocal = true,
|
|
single = true,
|
|
input = function (...) end,
|
|
expect = 'function (...) ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Function with vararg and multiple arguments',
|
|
adv_getlocal = true,
|
|
single = true,
|
|
input = function (a, b, ...) end,
|
|
expect = 'function (a, b, ...) ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Function with upvalues don\'t affected by them in single mode 1',
|
|
adv_getlocal = true,
|
|
single = true,
|
|
input = function () l = TEST_UPVALUE end,
|
|
expect = 'function () ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Function with upvalues don\'t affected by them in single mode 2',
|
|
adv_getlocal = true,
|
|
single = true,
|
|
input = function () TEST_UPVALUE = true end,
|
|
expect = 'function () ... end',
|
|
}
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Basic elaborate functions
|
|
|
|
local func_line = curline(3)
|
|
format_test {
|
|
name = 'Singleline elaborate function',
|
|
input = function () end,
|
|
expect = 'function ()\n -- Source file: \'./test/test_function.lua\' [Line: '..func_line..']\n\n ...\nend',
|
|
}
|
|
|
|
local func_line = curline(3)
|
|
format_test {
|
|
name = 'Multiline elaborate function',
|
|
input = function ()
|
|
end,
|
|
expect = 'function ()\n -- Source file: \'./test/test_function.lua\' [Lines: '..func_line..' - '..(func_line+1)..']\n\n ...\nend',
|
|
}
|
|
|
|
local func_line = curline(3) -- Must be exactly 3 lines above function
|
|
format_test {
|
|
name = 'Elaborate function with upvalue included 1',
|
|
input = function () l = TEST_UPVALUE end,
|
|
adv_getlocal = true,
|
|
expect = 'function ()\n -- Source file: \'./test/test_function.lua\' [Line: '..func_line..']\n -- Up values: { TEST_UPVALUE = 42 }\n\n ...\nend'
|
|
}
|
|
|
|
local func_line = curline(3) -- Must be exactly 3 lines above function
|
|
format_test {
|
|
name = 'Elaborate function with upvalue included 2',
|
|
input = function () TEST_UPVALUE = true end,
|
|
adv_getlocal = true,
|
|
expect = 'function ()\n -- Source file: \'./test/test_function.lua\' [Line: '..func_line..']\n -- Up values: { TEST_UPVALUE = 42 }\n\n ...\nend'
|
|
}
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Elaborate functions with documentation
|
|
|
|
format_test {
|
|
name = 'Basic Func with docs',
|
|
input = function ()
|
|
-- This is docs
|
|
return true
|
|
end,
|
|
expect = 'function ()\n -- This is docs\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Comments after other code won\'t be included as docs',
|
|
input = function ()
|
|
-- This is also docs
|
|
if true then return false end
|
|
-- Some other comment, that won't appear as docs.
|
|
return true
|
|
end,
|
|
expect = 'function ()\n -- This is also docs\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'We can leave a space between doc lines',
|
|
input = function ()
|
|
-- This is docs
|
|
|
|
-- This is also docs
|
|
return true
|
|
end,
|
|
expect = 'function ()\n -- This is docs\n -- This is also docs\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'We can also leave a line with an empty comment',
|
|
input = function ()
|
|
-- This is docs
|
|
--
|
|
-- This is also docs
|
|
return true
|
|
end,
|
|
expect = 'function ()\n -- This is docs\n -- \n -- This is also docs\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'No opvalues when docs are there',
|
|
input = function ()
|
|
-- This is docs
|
|
return TEST_UPVALUE
|
|
end,
|
|
expect = 'function ()\n -- This is docs\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Can find docs when body contains the word "function"',
|
|
input = function ()
|
|
-- Hi
|
|
_function()
|
|
end,
|
|
expect = 'function ()\n -- Hi\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Can find docs from string-loaded function',
|
|
input = loadstring 'return function ()\n-- Hello\nreturn 2\nend' (),
|
|
expect = 'function ()\n -- Hello\n\n return 2\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'String-loaded functions without docs, won\'t display Source file comment',
|
|
input = loadstring 'return function (a) return a end' (),
|
|
expect = 'function (a)\n -- Loaded from string\n\n return a\nend',
|
|
}
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Builtins
|
|
|
|
format_test {
|
|
single = true,
|
|
input = math.abs,
|
|
expect = 'builtin function (x) ... end',
|
|
}
|
|
|
|
format_test {
|
|
input = math.abs,
|
|
expect = 'builtin function (x)\n -- math.abs\n -- Returns the absolute value of x.\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
single = true,
|
|
input = math.random,
|
|
expect = 'builtin function ([m [, n]) ... end',
|
|
}
|
|
|
|
format_test {
|
|
input = math.random,
|
|
expect = 'builtin function ([m [, n])\n -- math.random\n -- When called without arguments, returns a uniform pseudo-random real\n -- number in the range [0,1). When called with an integer number m,\n -- math.random returns a uniform pseudo-random integer in the range [1, m].\n -- When called with two integer numbers m and n, math.random returns a\n -- uniform pseudo-random integer in the range [m, n].\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
input = string.byte,
|
|
expect = 'builtin function (s [, i [, j]])\n -- string.byte\n -- Returns the internal numerical codes of the characters s[i], s[i+1],\n -- ..., s[j]. The default value for i is 1; the default value for j is\n -- i.\n -- Note that numerical codes are not necessarily portable across\n -- platforms.\n\n ...\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'If builtin is key, display short name, instead of function signature',
|
|
input = { [math.random] = 365 },
|
|
expect = '{ [math.random] = 365 }',
|
|
}
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Embedding functions loaded with loadstring
|
|
|
|
format_test {
|
|
name = 'Embed functions loaded with loadstring',
|
|
single = true,
|
|
input = loadstring('return function (a, b) return a + b end')(),
|
|
expect = 'function (a, b) return a + b end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embed functions with extra whitespace stripped',
|
|
single = true,
|
|
input = loadstring('return function (a, b)\n return a + b\nend')(),
|
|
expect = 'function (a, b) return a + b end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding loaded chunk',
|
|
single = true,
|
|
input = loadstring 'return 42',
|
|
expect = 'function (...) return 42 end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding loaded file',
|
|
single = true,
|
|
input = loadfile 'init.lua',
|
|
expect = 'function (...) ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding nested function, when on same line is too hard 1',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('return function () return function () end end')(),
|
|
expect = 'function () ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding nested function, when on same line is too hard 2',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('return function () return function () end end')()(),
|
|
expect = 'function () ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding nested function, when they end on different lines is too hard',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('return function () return function () end\nend')()(),
|
|
expect = 'function () ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embed functions which contains the word "function"',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('return function () function_body() end')(),
|
|
expect = 'function () function_body() end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embed functions defined with OOP style',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('local obj = {} \n function obj:a () return self end \n return obj.a')(),
|
|
expect = 'function (self) return self end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embed functions in single mode without documentation',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('return function () -- Hi\nreturn 1234 end')(),
|
|
expect = 'function () return 1234 end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embed functions and ignore the whitespace after the documentation',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('return function () -- Hi\n\n\t \t\t return 1234 end')(),
|
|
expect = 'function () return 1234 end',
|
|
}
|
|
|
|
--[[ NOTE: This turned out to be hard. Requires traversal of AST.
|
|
format_test {
|
|
name = 'Embed correct function, when two are on the same line, but with different arguments 1',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring 'return { a = function (a) return a end, b = function (b) return b end }' ()['a'],
|
|
expect = 'function (a) return a end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embed correct function, when two are on the same line, but with different arguments 2',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring 'return { a = function (a) return a end, b = function (b) return b end }' ()['b'],
|
|
expect = 'function (b) return b end',
|
|
}
|
|
--]]
|
|
|
|
format_test {
|
|
name = 'If embedding a function would be too long, ignore',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('return function () return 1234578901235789012357890 end')(),
|
|
expect = 'function () ... end',
|
|
}
|
|
|
|
format_test {
|
|
name = 'If embedding a function would include newline, ignore',
|
|
single = true,
|
|
adv_getlocal = true,
|
|
input = loadstring('return function ()\n\ta = math.random()\nreturn a + 15 end')(),
|
|
expect = 'function () ... end',
|
|
}
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Elaborate embedded functions
|
|
|
|
format_test {
|
|
name = 'Embed functions when elaborate formatting',
|
|
adv_getlocal = true,
|
|
input = loadstring('return function () return 1234 end')(),
|
|
expect = 'function ()\n -- Loaded from string\n\n return 1234\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding function without body, includes only the documentation',
|
|
input = loadstring 'return function () end' (),
|
|
expect = 'function ()\n -- Loaded from string\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding function with a nice name, includes name in documentation',
|
|
input = loadstring 'local function ahab () end; return ahab' (),
|
|
expect = 'function ()\n -- ahab\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding function with a indexed name, includes name in documentation',
|
|
input = loadstring 'local obj = {}; function obj.ahab () return "isaac" end; return obj.ahab' (),
|
|
expect = 'function ()\n -- obj.ahab\n\n return "isaac"\nend',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Embedding function with a OOP name, includes name in documentation',
|
|
input = loadstring 'local obj = {}; function obj:ahab () end; return obj.ahab' (),
|
|
expect = 'function (self)\n -- obj:ahab\nend',
|
|
}
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Indent functions nicely
|
|
|
|
format_test {
|
|
name = 'Align the tail part, letting people focus on the important aspects.',
|
|
input = { random = math.random, abs = math.abs },
|
|
expect = '{\n abs = builtin function (x) ... end,\n random = builtin function ([m [, n]) ... end\n}',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Align the function part, even if some are builtin and some are not.',
|
|
adv_getlocal = true,
|
|
input = { random = math.random, abs = function (x) return x < 0 and -x or x end },
|
|
expect = '{\n abs = function (x) ... end,\n random = builtin function ([m [, n]) ... end\n}',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Align the function part, even if one is loaded from a string.',
|
|
adv_getlocal = true,
|
|
input = { random = math.random, abs = loadstring('return function () return 1 end')() },
|
|
expect = '{\n abs = function () return 1 end,\n random = builtin function ([m [, n]) ... end\n}',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Align the end part when both are loaded from strings.',
|
|
adv_getlocal = true,
|
|
input = { a = loadstring'return function(a) return a end'(), b = loadstring'return function (...) return ... end'() },
|
|
expect = '{\n a = function (a) return a end,\n b = function (...) return ... end\n}',
|
|
}
|
|
|
|
format_test {
|
|
name = 'Align without special indent if there is function modifier.',
|
|
adv_getlocal = true,
|
|
input = { max = function(a, b) return a > b and a or b end,
|
|
abs = function (x) return x < 0 and -x or x end
|
|
},
|
|
expect = '{\n abs = function (x) ... end,\n max = function (a, b) ... end\n}',
|
|
}
|
|
|
|
if HAS_UNICODE_IDEN then
|
|
format_test {
|
|
name = 'Align functions with unicode-named parameters nicely',
|
|
adv_getlocal = true,
|
|
input = loadstring 'return {\nfunction (ψ) return ψ end,\nfunction (b) return b end\n}' (),
|
|
expect = '{\n function (ψ) return ψ end\n function (b) return b end\n}',
|
|
}
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
return SUITE
|