Moved function formatting into own file.
This commit is contained in:
parent
0a79b830ba
commit
8f956bf444
177
function.lua
Normal file
177
function.lua
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
|
||||||
|
-- Import
|
||||||
|
|
||||||
|
local LIBRARY
|
||||||
|
do
|
||||||
|
local thispath = ... and select('1', ...):match('.+%.') or ''
|
||||||
|
local was_loaded, library = pcall(require, thispath..'library')
|
||||||
|
LIBRARY = was_loaded and library or {}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Constants
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Util
|
||||||
|
|
||||||
|
local function get_function_info (f)
|
||||||
|
-- NOTE: Works best in LuaJIT or Lua 5.2+
|
||||||
|
|
||||||
|
-- Regarding get-info:
|
||||||
|
-- * No need to includ 'f'. Function is already known
|
||||||
|
-- * No need to include 'L' (active lines) option. Ignored
|
||||||
|
-- * No need to include 'n' (name and namewhat). Won't work.
|
||||||
|
local info = debug.getinfo(f, 'Su')
|
||||||
|
info.params = {}
|
||||||
|
info.ups = {}
|
||||||
|
info.env = debug.getfenv and debug.getfenv(f)
|
||||||
|
info.builtin = info.source == '=[C]'
|
||||||
|
for i = 1, info.nparams or 0 do info.params[i] = debug.getlocal(f, i) end
|
||||||
|
if info.isvararg or not info.nparams then info.params[#info.params+1] = '...' end
|
||||||
|
-- Get upvalues
|
||||||
|
for i = 1, info.nups do
|
||||||
|
local k, v = debug.getupvalue(f, i)
|
||||||
|
if k == '_ENV' and not debug.getfenv then
|
||||||
|
info.env = v
|
||||||
|
else
|
||||||
|
info.ups[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if info.source:sub(1,1) == '=' then info.defined_how = 'C'
|
||||||
|
elseif info.source:sub(1,1) == '@' then info.defined_how = 'file'
|
||||||
|
else info.defined_how = 'string'
|
||||||
|
end
|
||||||
|
|
||||||
|
if info.builtin and LIBRARY[f] then
|
||||||
|
info.name = LIBRARY[f].name
|
||||||
|
info.params[1] = LIBRARY[f].para
|
||||||
|
info.doc = LIBRARY[f].docs
|
||||||
|
end
|
||||||
|
|
||||||
|
return info
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_line_index (str, line_nr)
|
||||||
|
local index = 0
|
||||||
|
for _ = 2, line_nr do
|
||||||
|
index = str:find('\n', index, true)
|
||||||
|
if not index then return #str end
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
return index
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_full_function_str (str, start_line, end_line)
|
||||||
|
local start_line_index = get_line_index(str, start_line)
|
||||||
|
local end_line_index = get_line_index(str, end_line + 1)
|
||||||
|
|
||||||
|
local matched_function = str:sub(start_line_index, end_line_index):match('function.+end')
|
||||||
|
return matched_function
|
||||||
|
end
|
||||||
|
|
||||||
|
local function width_of_strings_in_l (l, start_i, end_i)
|
||||||
|
-- FIXME: Copy of the one in pretty.lua
|
||||||
|
local width = 0
|
||||||
|
for i = start_i or 1, (end_i or #l) do
|
||||||
|
width = width + #l[i]
|
||||||
|
end
|
||||||
|
return width
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return function (value, options, depth, l, format_value)
|
||||||
|
local info = get_function_info(value)
|
||||||
|
|
||||||
|
if info.defined_how == 'string' then
|
||||||
|
-- Function was defined as a string.
|
||||||
|
l[#l+1] = get_full_function_str(info.source, info.linedefined, info.lastlinedefined)
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Include function modifier, and alignment info.
|
||||||
|
l[#l+1] = info.builtin and 'builtin ' or ''
|
||||||
|
l[#l+1] = { #l[#l], 'func_mod'}
|
||||||
|
|
||||||
|
-- Build rest of function signature
|
||||||
|
l[#l+1] = 'function ('
|
||||||
|
local top_before = #l
|
||||||
|
for _, param in ipairs(info.params) do l[#l+1], l[#l+2] = param, ', ' end
|
||||||
|
if l[#l] == ', ' then l[#l] = nil end
|
||||||
|
l[#l+1] = ')'
|
||||||
|
l[#l+1] = { width_of_strings_in_l(l, top_before), 'func_def' }
|
||||||
|
|
||||||
|
-- Cleanup and finish
|
||||||
|
if not options.more_function_info or depth ~= 0 then
|
||||||
|
l[#l+1] = ' ... end'
|
||||||
|
elseif options._all_function_info then
|
||||||
|
-- NOTE: This is for testing/debugging/experimentation purposes.
|
||||||
|
|
||||||
|
local file = io.open(info.short_src, 'r')
|
||||||
|
local function_str = get_full_function_str(file:read('*all'), info.linedefined, info.lastlinedefined)
|
||||||
|
file:close()
|
||||||
|
|
||||||
|
l[#l+1] = '\n\t--[[ Function Body\n\t'
|
||||||
|
l[#l+1] = function_str
|
||||||
|
l[#l+1] = '\n\t--]]'
|
||||||
|
|
||||||
|
l[#l+1] = '\n\t--[[\n\tNative repr:'
|
||||||
|
l[#l+1] = tostring(value)
|
||||||
|
l[#l+1] = '\n\t'
|
||||||
|
format_value(info, options, depth + 1, l)
|
||||||
|
l[#l+1] = '--]]'
|
||||||
|
else
|
||||||
|
-- More info! --
|
||||||
|
|
||||||
|
-- Name
|
||||||
|
if info.name then
|
||||||
|
l[#l+1] = '\n'
|
||||||
|
l[#l+1] = options.indent
|
||||||
|
l[#l+1] = '-- '
|
||||||
|
l[#l+1] = info.name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Doc
|
||||||
|
if info.doc then
|
||||||
|
for doc_line in info.doc:gmatch('[^\n]+') do
|
||||||
|
l[#l+1] = '\n'
|
||||||
|
l[#l+1] = options.indent
|
||||||
|
l[#l+1] = '-- '
|
||||||
|
|
||||||
|
l[#l+1] = doc_line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- source
|
||||||
|
if not info.builtin then
|
||||||
|
l[#l+1] = '\n'
|
||||||
|
l[#l+1] = options.indent
|
||||||
|
l[#l+1] = '-- source_file: \''
|
||||||
|
l[#l+1] = info.short_src
|
||||||
|
l[#l+1] = '\' [Line'
|
||||||
|
if info.linedefined == info.lastlinedefined then
|
||||||
|
l[#l+1] = ': '
|
||||||
|
l[#l+1] = tostring(info.linedefined)
|
||||||
|
else
|
||||||
|
l[#l+1] = 's: '
|
||||||
|
l[#l+1] = tostring(info.linedefined)
|
||||||
|
l[#l+1] = ' - '
|
||||||
|
l[#l+1] = tostring(info.lastlinedefined)
|
||||||
|
end
|
||||||
|
l[#l+1] = ']'
|
||||||
|
end
|
||||||
|
|
||||||
|
-- upvalues
|
||||||
|
if info.nups > 0 and not info.builtin then
|
||||||
|
l[#l+1] = '\n'
|
||||||
|
l[#l+1] = options.indent
|
||||||
|
l[#l+1] = '-- up_values: '
|
||||||
|
format_value(info.ups, options, depth + 1, l)
|
||||||
|
end
|
||||||
|
|
||||||
|
l[#l+1] = '\n\n'
|
||||||
|
l[#l+1] = options.indent
|
||||||
|
l[#l+1] = '...\nend'
|
||||||
|
end
|
||||||
|
end
|
181
pretty.lua
181
pretty.lua
|
@ -2,18 +2,20 @@
|
||||||
-- Ensure loading library, if it exists, no matter where pretty.lua was loaded from.
|
-- Ensure loading library, if it exists, no matter where pretty.lua was loaded from.
|
||||||
|
|
||||||
-- Load the library component
|
-- Load the library component
|
||||||
local LIBRARY, format_number, analyze_structure, TABLE_TYPE
|
local format_number, format_function, analyze_structure, TABLE_TYPE
|
||||||
do
|
do
|
||||||
local thispath = ... and select('1', ...):match('.+%.') or ''
|
local thispath = ... and select('1', ...):match('.+%.') or ''
|
||||||
|
|
||||||
-- Load library info
|
-- Load number and function formatting
|
||||||
local was_loaded, library = pcall(require, thispath..'library')
|
format_number = select(2, pcall(require, thispath..'number'))
|
||||||
LIBRARY = was_loaded and library or {}
|
format_function = select(2, pcall(require, thispath..'function'))
|
||||||
|
|
||||||
-- Load number formatting
|
-- Load other stuff
|
||||||
was_loaded, format_number = pcall(require, thispath..'number')
|
local was_loaded
|
||||||
was_loaded, analyze_structure = pcall(require, thispath..'analyze_structure')
|
was_loaded, analyze_structure = pcall(require, thispath..'analyze_structure')
|
||||||
|
assert(was_loaded)
|
||||||
was_loaded, TABLE_TYPE = pcall(require, thispath..'table_type')
|
was_loaded, TABLE_TYPE = pcall(require, thispath..'table_type')
|
||||||
|
assert(was_loaded)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
|
|
||||||
|
@ -192,62 +194,6 @@ local function escape_string (str)
|
||||||
return table.concat(l, '')
|
return table.concat(l, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_function_info (f)
|
|
||||||
-- NOTE: Works best in LuaJIT or Lua 5.2+
|
|
||||||
|
|
||||||
-- Regarding get-info:
|
|
||||||
-- * No need to includ 'f'. Function is already known
|
|
||||||
-- * No need to include 'L' (active lines) option. Ignored
|
|
||||||
-- * No need to include 'n' (name and namewhat). Won't work.
|
|
||||||
local info = debug.getinfo(f, 'Su')
|
|
||||||
info.params = {}
|
|
||||||
info.ups = {}
|
|
||||||
info.env = debug.getfenv and debug.getfenv(f)
|
|
||||||
info.builtin = info.source == '=[C]'
|
|
||||||
for i = 1, info.nparams or 0 do info.params[i] = debug.getlocal(f, i) end
|
|
||||||
if info.isvararg or not info.nparams then info.params[#info.params+1] = '...' end
|
|
||||||
-- Get upvalues
|
|
||||||
for i = 1, info.nups do
|
|
||||||
local k, v = debug.getupvalue(f, i)
|
|
||||||
if k == '_ENV' and not debug.getfenv then
|
|
||||||
info.env = v
|
|
||||||
else
|
|
||||||
info.ups[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if info.source:sub(1,1) == '=' then info.defined_how = 'C'
|
|
||||||
elseif info.source:sub(1,1) == '@' then info.defined_how = 'file'
|
|
||||||
else info.defined_how = 'string'
|
|
||||||
end
|
|
||||||
|
|
||||||
if info.builtin and LIBRARY[f] then
|
|
||||||
info.name = LIBRARY[f].name
|
|
||||||
info.params[1] = LIBRARY[f].para
|
|
||||||
info.doc = LIBRARY[f].docs
|
|
||||||
end
|
|
||||||
|
|
||||||
return info
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_line_index (str, line_nr)
|
|
||||||
local index = 0
|
|
||||||
for _ = 2, line_nr do
|
|
||||||
index = str:find('\n', index, true)
|
|
||||||
if not index then return #str end
|
|
||||||
index = index + 1
|
|
||||||
end
|
|
||||||
return index
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_full_function_str (str, start_line, end_line)
|
|
||||||
local start_line_index = get_line_index(str, start_line)
|
|
||||||
local end_line_index = get_line_index(str, end_line + 1)
|
|
||||||
|
|
||||||
local matched_function = str:sub(start_line_index, end_line_index):match('function.+end')
|
|
||||||
return matched_function
|
|
||||||
end
|
|
||||||
|
|
||||||
local function width_of_strings_in_l (l, start_i, end_i)
|
local function width_of_strings_in_l (l, start_i, end_i)
|
||||||
local width = 0
|
local width = 0
|
||||||
for i = start_i or 1, (end_i or #l) do
|
for i = start_i or 1, (end_i or #l) do
|
||||||
|
@ -511,13 +457,9 @@ local function format_string (str, options, depth, l)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not format_number then
|
if not format_number then
|
||||||
function format_number (value, options, depth, l)
|
-- Very simple number formatting, if number.lua is not available.
|
||||||
local shorthand = options.math_shorthand
|
format_number = function (value, _, _, l)
|
||||||
if value ~= value then l[#l+1] = shorthand and 'nan' or '0/0'
|
l[#l+1] = tostring(value)
|
||||||
elseif value == 1/0 then l[#l+1] = shorthand and 'inf' or '1/0'
|
|
||||||
elseif value == -1/0 then l[#l+1] = shorthand and '-inf' or '-1/0'
|
|
||||||
else l[#l+1] = tostring(value)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -531,101 +473,10 @@ local function format_primitive (value, options, depth, l)
|
||||||
l[#l+1] = tostring(value)
|
l[#l+1] = tostring(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function format_string_defined_function (value, options, depth, l)
|
if not format_function then
|
||||||
local info = get_function_info(value)
|
-- Very simple function formatting, if function.lua is not available.
|
||||||
l[#l+1] = get_full_function_str(info.source, info.linedefined, info.lastlinedefined)
|
format_function = function (value, _, _, l)
|
||||||
end
|
l[#l+1] = 'function (...) --[['..tostring(value):sub(11)..']] end'
|
||||||
|
|
||||||
local function format_function (value, options, depth, l)
|
|
||||||
local info = get_function_info(value)
|
|
||||||
|
|
||||||
if info.defined_how == 'string' then
|
|
||||||
return format_string_defined_function(value, options, depth, l)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Include function modifier, and alignment info.
|
|
||||||
l[#l+1] = info.builtin and 'builtin ' or ''
|
|
||||||
l[#l+1] = { #l[#l], 'func_mod'}
|
|
||||||
|
|
||||||
-- Build rest of function signature
|
|
||||||
l[#l+1] = 'function ('
|
|
||||||
local top_before = #l
|
|
||||||
for _, param in ipairs(info.params) do l[#l+1], l[#l+2] = param, ', ' end
|
|
||||||
if l[#l] == ', ' then l[#l] = nil end
|
|
||||||
l[#l+1] = ')'
|
|
||||||
l[#l+1] = { width_of_strings_in_l(l, top_before), 'func_def' }
|
|
||||||
|
|
||||||
-- Cleanup and finish
|
|
||||||
if not options.more_function_info or depth ~= 0 then
|
|
||||||
l[#l+1] = ' ... end'
|
|
||||||
elseif options._all_function_info then
|
|
||||||
-- NOTE: This is for testing/debugging/experimentation purposes.
|
|
||||||
|
|
||||||
local file = io.open(info.short_src, 'r')
|
|
||||||
local function_str = get_full_function_str(file:read('*all'), info.linedefined, info.lastlinedefined)
|
|
||||||
file:close()
|
|
||||||
|
|
||||||
l[#l+1] = '\n\t--[[ Function Body\n\t'
|
|
||||||
l[#l+1] = function_str
|
|
||||||
l[#l+1] = '\n\t--]]'
|
|
||||||
|
|
||||||
l[#l+1] = '\n\t--[[\n\tNative repr:'
|
|
||||||
l[#l+1] = tostring(value)
|
|
||||||
l[#l+1] = '\n\t'
|
|
||||||
format_value(info, options, depth + 1, l)
|
|
||||||
l[#l+1] = '--]]'
|
|
||||||
else
|
|
||||||
-- More info! --
|
|
||||||
|
|
||||||
-- Name
|
|
||||||
if info.name then
|
|
||||||
l[#l+1] = '\n'
|
|
||||||
l[#l+1] = options.indent
|
|
||||||
l[#l+1] = '-- '
|
|
||||||
l[#l+1] = info.name
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Doc
|
|
||||||
if info.doc then
|
|
||||||
for doc_line in info.doc:gmatch('[^\n]+') do
|
|
||||||
l[#l+1] = '\n'
|
|
||||||
l[#l+1] = options.indent
|
|
||||||
l[#l+1] = '-- '
|
|
||||||
|
|
||||||
l[#l+1] = doc_line
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- source
|
|
||||||
if not info.builtin then
|
|
||||||
l[#l+1] = '\n'
|
|
||||||
l[#l+1] = options.indent
|
|
||||||
l[#l+1] = '-- source_file: \''
|
|
||||||
l[#l+1] = info.short_src
|
|
||||||
l[#l+1] = '\' [Line'
|
|
||||||
if info.linedefined == info.lastlinedefined then
|
|
||||||
l[#l+1] = ': '
|
|
||||||
l[#l+1] = tostring(info.linedefined)
|
|
||||||
else
|
|
||||||
l[#l+1] = 's: '
|
|
||||||
l[#l+1] = tostring(info.linedefined)
|
|
||||||
l[#l+1] = ' - '
|
|
||||||
l[#l+1] = tostring(info.lastlinedefined)
|
|
||||||
end
|
|
||||||
l[#l+1] = ']'
|
|
||||||
end
|
|
||||||
|
|
||||||
-- upvalues
|
|
||||||
if info.nups > 0 and not info.builtin then
|
|
||||||
l[#l+1] = '\n'
|
|
||||||
l[#l+1] = options.indent
|
|
||||||
l[#l+1] = '-- up_values: '
|
|
||||||
format_value(info.ups, options, depth + 1, l)
|
|
||||||
end
|
|
||||||
|
|
||||||
l[#l+1] = '\n\n'
|
|
||||||
l[#l+1] = options.indent
|
|
||||||
l[#l+1] = '...\nend'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -646,7 +497,7 @@ local TYPE_TO_FORMAT_FUNC = {
|
||||||
function format_value (value, _, depth, l)
|
function format_value (value, _, depth, l)
|
||||||
local format_func = TYPE_TO_FORMAT_FUNC[type(value)]
|
local format_func = TYPE_TO_FORMAT_FUNC[type(value)]
|
||||||
if format_func then
|
if format_func then
|
||||||
format_func(value, l.options, depth, l)
|
format_func(value, l.options, depth, l, format_value)
|
||||||
else
|
else
|
||||||
error(ERROR_UNKNOWN_TYPE:format(type(value), tostring(value)), 2)
|
error(ERROR_UNKNOWN_TYPE:format(type(value), tostring(value)), 2)
|
||||||
end
|
end
|
||||||
|
|
249
test/test_function.lua
Normal file
249
test/test_function.lua
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
|
||||||
|
local SUITE = require('TestSuite').new('function')
|
||||||
|
SUITE:setEnviroment{
|
||||||
|
format = require('pretty')
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local HAS_ADV_GETLOCAL = not not debug.getinfo(1, 'u').nparams -- Lua 5.1 compat
|
||||||
|
if not loadstring then loadstring = load end -- Lua 5.3 compat
|
||||||
|
|
||||||
|
local function format_test (t)
|
||||||
|
if t.longterm then return end
|
||||||
|
if t.adv_getlocal and not HAS_ADV_GETLOCAL then return end
|
||||||
|
SUITE:addTest(t.expect, function ()
|
||||||
|
local input_value = t.input
|
||||||
|
local input_options = t.options
|
||||||
|
local expected_result = t.expect
|
||||||
|
local actual_result = format(input_value, input_options)
|
||||||
|
if not t.approx or type(actual_result) ~= 'string' then
|
||||||
|
assert_equal(expected_result, actual_result)
|
||||||
|
else
|
||||||
|
if not actual_result:match(expected_result) then
|
||||||
|
error(ASSERT_ERROR_APPROX:format(expected_result, actual_result))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function curline (delta)
|
||||||
|
return debug.getinfo(2).currentline + (delta or 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Function printing
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = function () end,
|
||||||
|
expect = 'function () ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = function (a) end,
|
||||||
|
expect = 'function (a) ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = function (a, b) end,
|
||||||
|
expect = 'function (a, b) ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = function (...) end,
|
||||||
|
expect = 'function (...) ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = function (a, b, ...) end,
|
||||||
|
expect = 'function (a, b, ...) ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
local SOME_RANDOM_UPVALUE = false
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = function () l = SOME_RANDOM_UPVALUE end,
|
||||||
|
expect = 'function () ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = function () SOME_RANDOM_UPVALUE = true end,
|
||||||
|
expect = 'function () ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
-- More function info is ignored if not at depth 0.
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = { a = function () SOME_RANDOM_UPVALUE = true end },
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = '{\n\ta = function () ... end\n}',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local func_line = curline(2) -- Must be exactly 2 lines above function
|
||||||
|
format_test {
|
||||||
|
input = function () l = SOME_RANDOM_UPVALUE end,
|
||||||
|
adv_getlocal = true,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'function ()\n\t-- source_file: \'./test/test_function.lua\' [Line: '..func_line..']\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
|
||||||
|
}
|
||||||
|
|
||||||
|
local func_line = curline(2) -- Must be exactly 2 lines above function
|
||||||
|
format_test {
|
||||||
|
input = function () SOME_RANDOM_UPVALUE = true end,
|
||||||
|
adv_getlocal = true,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'function ()\n\t-- source_file: \'./test/test_function.lua\' [Line: '..func_line..']\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local func_line = curline(2) -- Must be exactly 2 lines above function
|
||||||
|
format_test {
|
||||||
|
input = function () end,
|
||||||
|
adv_getlocal = true,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'function ()\n\t-- source_file: \'./test/test_function.lua\' [Line: '..func_line..']\n\n\t...\nend'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local index = 0
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
input = function () index = index + 1; return index end,
|
||||||
|
adv_getlocal = true,
|
||||||
|
expect = 'function () ... end'
|
||||||
|
}
|
||||||
|
|
||||||
|
local func_line = curline(2) -- Must be exactly 2 lines above function
|
||||||
|
format_test {
|
||||||
|
input = function () index = index + 1; return index end,
|
||||||
|
adv_getlocal = true,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'function ()\n\t-- source_file: \'./test/test_function.lua\' [Line: '..func_line..']\n\t-- up_values: { index = 0 }\n\n\t...\nend'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = loadstring('return function () end')(),
|
||||||
|
expect = 'function () end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = loadstring('return function () return function () end end')(),
|
||||||
|
expect = 'function () return function () end end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = loadstring('return function () return function () end\nend')()(),
|
||||||
|
expect = 'function () end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
-- NOTE: This is HARD to fix. It's thus longerterm
|
||||||
|
adv_getlocal = true,
|
||||||
|
input = loadstring('return function () return function () end end')()(),
|
||||||
|
expect = 'function () end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
-- More function info allows one to even get the function whole, if it was defined in a string.
|
||||||
|
input = loadstring('return function (a, b) return a + b end')(),
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'function (a, b) return a + b end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
-- More function info allows one to even get the function whole, if it was defined in a string.
|
||||||
|
input = loadstring('return function (a, b)\n\treturn a + b\nend')(),
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'function (a, b)\n\treturn a + b\nend',
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
local func_line = curline(2) -- Must be exactly 2 lines above function
|
||||||
|
format_test {
|
||||||
|
input = function ()
|
||||||
|
-- NOTE: This function must cover 3 lines of code!
|
||||||
|
end,
|
||||||
|
adv_getlocal = true,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'function ()\n\t-- source_file: \'./test/test_function.lua\' [Lines: '..func_line..' - '..(func_line+2)..']\n\n\t...\nend',
|
||||||
|
}
|
||||||
|
|
||||||
|
local func_line = curline(2) -- Must be exactly 2 lines above function
|
||||||
|
format_test {
|
||||||
|
input = function () --[[ NOTE: This function must cover a single line of code! ]] end,
|
||||||
|
adv_getlocal = true,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'function ()\n\t-- source_file: \'./test/test_function.lua\' [Line: '..func_line..']\n\n\t...\nend',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
input = math.abs,
|
||||||
|
expect = 'builtin function (x) ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
input = math.abs,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'builtin function (x)\n\t-- math.abs\n\t-- Returns the absolute value of x.\n\n\t...\nend',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
input = math.random,
|
||||||
|
expect = 'builtin function ([m [, n]) ... end',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
input = math.random,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'builtin function ([m [, n])\n\t-- math.random\n\t-- When called without arguments, returns a uniform pseudo-random real number in the range [0,1). When called with an integer number m, math.random returns a uniform pseudo-random integer in the range [1, m]. When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n].\n\n\t...\nend',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
input = string.byte,
|
||||||
|
options = { more_function_info = true },
|
||||||
|
expect = 'builtin function (s [, i [, j]])\n\t-- string.byte\n\t-- Returns the internal numerical codes of the characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the default value for j is i.\n\t-- Note that numerical codes are not necessarily portable across platforms.\n\n\t...\nend',
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Indent functions nicely
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
-- The tail part should align, letting people focus on the important aspects.
|
||||||
|
input = { random = math.random, abs = math.abs },
|
||||||
|
expect = '{\n\tabs = builtin function (x) ... end,\n\trandom = builtin function ([m [, n]) ... end\n}',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
-- The function part should align, 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\tabs = function (x) ... end,\n\trandom = builtin function ([m [, n]) ... end\n}',
|
||||||
|
}
|
||||||
|
|
||||||
|
format_test {
|
||||||
|
-- No special indent if no special 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\tabs = function (x) ... end,\n\tmax = function (a, b) ... end\n}',
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return SUITE
|
|
@ -12,15 +12,8 @@ Approximate strings not similar enough:
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- Lua 5.1 compat:
|
local HAS_ADV_GETLOCAL = not not debug.getinfo(1, 'u').nparams -- Lua 5.1 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.3 compat:
|
|
||||||
|
|
||||||
if not loadstring then
|
|
||||||
loadstring = load
|
|
||||||
end
|
|
||||||
|
|
||||||
local function format_test (t)
|
local function format_test (t)
|
||||||
if t.longterm then return end
|
if t.longterm then return end
|
||||||
|
@ -260,221 +253,6 @@ format_test {
|
||||||
expect = 'false',
|
expect = 'false',
|
||||||
}
|
}
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
-- Function printing
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = function () end,
|
|
||||||
expect = 'function () ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = function (a) end,
|
|
||||||
expect = 'function (a) ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = function (a, b) end,
|
|
||||||
expect = 'function (a, b) ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = function (...) end,
|
|
||||||
expect = 'function (...) ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = function (a, b, ...) end,
|
|
||||||
expect = 'function (a, b, ...) ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
local SOME_RANDOM_UPVALUE = false
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = function () l = SOME_RANDOM_UPVALUE end,
|
|
||||||
expect = 'function () ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = function () SOME_RANDOM_UPVALUE = true end,
|
|
||||||
expect = 'function () ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
-- More function info is ignored if not at depth 0.
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = { a = function () SOME_RANDOM_UPVALUE = true end },
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = '{\n\ta = function () ... end\n}',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
|
|
||||||
format_test {
|
|
||||||
input = function () l = SOME_RANDOM_UPVALUE end,
|
|
||||||
adv_getlocal = true,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
|
|
||||||
}
|
|
||||||
|
|
||||||
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
|
|
||||||
format_test {
|
|
||||||
input = function () SOME_RANDOM_UPVALUE = true end,
|
|
||||||
adv_getlocal = true,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
|
|
||||||
format_test {
|
|
||||||
input = function () end,
|
|
||||||
adv_getlocal = true,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\n\t...\nend'
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local index = 0
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
input = function () index = index + 1; return index end,
|
|
||||||
adv_getlocal = true,
|
|
||||||
expect = 'function () ... end'
|
|
||||||
}
|
|
||||||
|
|
||||||
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
|
|
||||||
format_test {
|
|
||||||
input = function () index = index + 1; return index end,
|
|
||||||
adv_getlocal = true,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { index = 0 }\n\n\t...\nend'
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = loadstring('return function () end')(),
|
|
||||||
expect = 'function () end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = loadstring('return function () return function () end end')(),
|
|
||||||
expect = 'function () return function () end end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
longterm = true,
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = loadstring('return function () return function () end\nend')()(),
|
|
||||||
expect = 'function () end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
-- NOTE: This is HARD to fix. It's thus longerterm
|
|
||||||
longterm = true,
|
|
||||||
adv_getlocal = true,
|
|
||||||
input = loadstring('return function () return function () end end')()(),
|
|
||||||
expect = 'function () end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
-- More function info allows one to even get the function whole, if it was defined in a string.
|
|
||||||
input = loadstring('return function (a, b) return a + b end')(),
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'function (a, b) return a + b end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
-- More function info allows one to even get the function whole, if it was defined in a string.
|
|
||||||
input = loadstring('return function (a, b)\n\treturn a + b\nend')(),
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'function (a, b)\n\treturn a + b\nend',
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
|
|
||||||
format_test {
|
|
||||||
input = function ()
|
|
||||||
-- NOTE: This function must cover 3 lines of code!
|
|
||||||
end,
|
|
||||||
adv_getlocal = true,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Lines: '..func_line..' - '..(func_line+2)..']\n\n\t...\nend',
|
|
||||||
}
|
|
||||||
|
|
||||||
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
|
|
||||||
format_test {
|
|
||||||
input = function () --[[ NOTE: This function must cover a single line of code! ]] end,
|
|
||||||
adv_getlocal = true,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\n\t...\nend',
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
input = math.abs,
|
|
||||||
expect = 'builtin function (x) ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
input = math.abs,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'builtin function (x)\n\t-- math.abs\n\t-- Returns the absolute value of x.\n\n\t...\nend',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
input = math.random,
|
|
||||||
expect = 'builtin function ([m [, n]) ... end',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
input = math.random,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'builtin function ([m [, n])\n\t-- math.random\n\t-- When called without arguments, returns a uniform pseudo-random real number in the range [0,1). When called with an integer number m, math.random returns a uniform pseudo-random integer in the range [1, m]. When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n].\n\n\t...\nend',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
input = string.byte,
|
|
||||||
options = { more_function_info = true },
|
|
||||||
expect = 'builtin function (s [, i [, j]])\n\t-- string.byte\n\t-- Returns the internal numerical codes of the characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the default value for j is i.\n\t-- Note that numerical codes are not necessarily portable across platforms.\n\n\t...\nend',
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Indent functions nicely
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
-- The tail part should align, letting people focus on the important aspects.
|
|
||||||
input = { random = math.random, abs = math.abs },
|
|
||||||
expect = '{\n\tabs = builtin function (x) ... end,\n\trandom = builtin function ([m [, n]) ... end\n}',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
-- The function part should align, 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\tabs = function (x) ... end,\n\trandom = builtin function ([m [, n]) ... end\n}',
|
|
||||||
}
|
|
||||||
|
|
||||||
format_test {
|
|
||||||
-- No special indent if no special 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\tabs = function (x) ... end,\n\tmax = function (a, b) ... end\n}',
|
|
||||||
}
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Userdata printing
|
-- Userdata printing
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user