diff --git a/analyze_structure.lua b/analyze_structure.lua index 9b0571a..2aef1e2 100644 --- a/analyze_structure.lua +++ b/analyze_structure.lua @@ -191,6 +191,7 @@ end -------------------------------------------------------------------------------- local function analyze_structure (root) + if type(root) ~= 'table' then return {} end assert(type(root) == 'table') local info, visited, next_mark, depth = { root = root }, {}, 1, { [root] = 0 } diff --git a/pretty.lua b/pretty.lua index 8dc5fa1..733d3ac 100644 --- a/pretty.lua +++ b/pretty.lua @@ -394,6 +394,7 @@ end local function format_string (str, depth, l) -- TODO: Add option for escaping unicode characters. + -- TODO: Improve cutstring argument. -- Error checking assert( type(str) == 'string' ) @@ -494,41 +495,49 @@ setmetatable(StringBuilder, { local DEBUG_OPTIONS = { _all_function_info = true, _table_addr_comment = true } local KNOWN_OPTIONS = { - _table_addr_comment = 'boolean', - _all_function_info = 'boolean', - cut_strings = 'boolean', - include_closure = 'boolean', - indent = 'string', - math_shorthand = 'boolean', - max_depth = 'number', - more_function_info = 'boolean', - recursion = 'string', - short_builtins = 'boolean', + _table_addr_comment = { type = 'boolean', default = false }, + _all_function_info = { type = 'boolean', default = false }, + cut_strings = { type = 'boolean', default = false }, + include_closure = { type = 'boolean', default = false }, + indent = { type = 'string', default = '\t' }, -- TODO: Change default to ' '. + math_shorthand = { type = 'boolean', default = false }, + max_depth = { type = 'number', default = math.huge }, + more_function_info = { type = 'boolean', default = false }, + recursion = { type = 'string', default = 'ignore', accepted = {['ignore'] = true, ['marked'] = true} }, + short_builtins = { type = 'boolean', default = false }, } local function ensure_that_all_options_are_known (options) assert(type(options) == 'table') + -- Error check options for option_name, option_value in pairs(options) do if not KNOWN_OPTIONS[option_name] then error(('[pretty]: Unknown option: %s. Was given value %s (%s)'):format(option_name, option_value, type(option_value)), 2) - elseif type(option_value) ~= KNOWN_OPTIONS[option_name] then - error(('[pretty]: Bad value given to option %s: %s (%s). Expected value of type %s'):format(option_name, option_value, type(option_value), KNOWN_OPTIONS[option_name]), 2) + elseif type(option_value) ~= KNOWN_OPTIONS[option_name].type then + error(('[pretty]: Bad value given to option %s: %s (%s). Expected value of type %s'):format(option_name, option_value, type(option_value), KNOWN_OPTIONS[option_name].type), 2) + elseif KNOWN_OPTIONS[option_name].accepted and not KNOWN_OPTIONS[option_name].accepted[option_value] then + error(('[pretty]: Bad value given to option %s: %s (%s). Expected one of: %s'):format(option_name, option_value, type(option_value), table.concat(KNOWN_OPTIONS[option_name].accepted, ', ')), 2) end end + -- Assign default values + for option_name, option_info in pairs(KNOWN_OPTIONS) do + if not options[option_name] then + options[option_name] = option_info.default + end + end + -- Returns options + return options end local function pretty_format (value, options) -- Error checking - options = options or {} - options.max_depth = options.max_depth or math.huge - options.indent = options.indent or '\t' - ensure_that_all_options_are_known(options) + local options = ensure_that_all_options_are_known(options or {}) -- Setup StringBuilder local l = StringBuilder() l.visited = { next_mark = 1 } l.options = options - l.info = (type(value) == 'table') and analyze_structure(value) or {} + l.info = analyze_structure(value) -- Format value. format_value(value, 0, l) diff --git a/test/test_resilience.lua b/test/test_resilience.lua index f3beb04..900684e 100644 --- a/test/test_resilience.lua +++ b/test/test_resilience.lua @@ -41,6 +41,11 @@ SUITE:addTest('Dont allow bad types in options', function () assert(error_msg) end) +SUITE:addTest('Dont allow bad values in recursion', function () + local error_msg = bad_call(pretty, 'Hello World', { recursion = "hello world" }) + assert(error_msg) +end) + -------------------------------------------------------------------------------- -- Survive not loading libs