1
0

Fixed issues with analýse_structure.lua

The most significant was a misclassification of tables with number
exclusive keys, with huge jumps between each one.
Example: { 1, [300] = 300 }

This was caused by logic faults in `get_table_info`, which has been fixed.

When solving above issue, a two new issues appeared:

1.	Due to a logic fault, the count of number of elements in a table was wrong,
	leading to issues with tables with boolean keys. This was fixed with simple
	logic changes.
2.	Some very small tables (1 element) would be classified as sets, and thus
	rendered wrongly. This was fixed by adding a MINIMUM_NUMBER_OF_SET_ELEMENTS
	constant.
This commit is contained in:
Jon Michael Aanes 2017-04-14 13:06:43 +02:00
parent 155c877987
commit 87b12e15b2
4 changed files with 54 additions and 33 deletions

View File

@ -38,6 +38,7 @@ local SIMPLE_VALUE_TYPES = {
} }
local SHORT_STRING_MAX_LEN = 7 local SHORT_STRING_MAX_LEN = 7
local MINIMUM_NUMBER_OF_SET_ELEMENTS = 2
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -83,14 +84,27 @@ local function largest_number_index (t)
return max_index return max_index
end end
local function nr_elements_in_map (t) local function nr_elements_in_table (t)
local k, count = nil, -1 local k, count = nil, -1
repeat repeat
k, count = next(t, k), count + 1 k, count = next(t, k), count + 1
until not k until k == nil
return count return count
end end
local function nr_elements_in_seq (t)
local i, last_elem_i, nr_elems, has_holes = 0, 0, 0, false
while i <= last_elem_i + 2 do
i = i + 1
if t[i] ~= nil then
last_elem_i, nr_elems = i, nr_elems + 1
else
has_holes = true
end
end
return nr_elems, has_holes
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function contains_only_nice_string_keys (t) local function contains_only_nice_string_keys (t)
@ -119,19 +133,6 @@ local function contains_only_nice_number_indexes (t)
return #t > 0 return #t > 0
end end
local function has_seq (t)
if not contains_only_nice_number_indexes(t) then return false end
-- Contain list of keys
local keys = {[0] = 0}
for i, _ in pairs(t) do keys[#keys+1] = i end
table.sort(keys)
-- Check to see that no indice jumps more than 2
for indice_i = 1, #keys do
if keys[indice_i - 1] < keys[indice_i] - 2 then return false end
end
return true, (#keys ~= keys[#keys])
end
local function is_set (t) local function is_set (t)
-- Predicate: Does t contain only boolean values. -- Predicate: Does t contain only boolean values.
local value_types = get_value_types(t) local value_types = get_value_types(t)
@ -202,12 +203,14 @@ local function get_table_info (t)
local key_types = get_key_types(t) local key_types = get_key_types(t)
local info = {} local info = {}
info.has_seq, info.has_holes = has_seq(t) info.nr_elems = nr_elements_in_table(t)
info.has_map = key_types.nr_types > (key_types.number and 1 or 0) info.seq_elems, info.has_holes = nr_elements_in_seq(t)
info.is_set = is_set(t) info.map_elems = info.nr_elems - info.seq_elems
info.has_seq = info.seq_elems > 0
info.has_map = info.map_elems > 0
info.is_set = is_set(t) and info.nr_elems >= MINIMUM_NUMBER_OF_SET_ELEMENTS
info.is_tabular = is_tabular(t) info.is_tabular = is_tabular(t)
info.is_short = is_short_table(t) info.is_short = is_short_table(t) -- TODO: Remove this. It's not used for anything.
info.nr_elems = nr_elements_in_map(t) -- TODO: Use this for something.
-- Determine type of table -- Determine type of table
if not info.has_seq and not info.has_map then info.type = TABLE_TYPE.EMPTY if not info.has_seq and not info.has_map then info.type = TABLE_TYPE.EMPTY
@ -251,4 +254,4 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
return analyze_structure return { analyze_structure, get_table_info }

View File

@ -2,7 +2,7 @@
-- 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 format_number, format_function, analyze_structure, TABLE_TYPE local format_number, format_function, analyze_structure, get_table_info, TABLE_TYPE
do do
local thispath = ... and select('1', ...):match('.+%.') or '' local thispath = ... and select('1', ...):match('.+%.') or ''
@ -13,7 +13,7 @@ do
-- Load other stuff -- Load other stuff
local was_loaded local was_loaded
was_loaded, analyze_structure = pcall(require, thispath..'analyze_structure') was_loaded, analyze_structure = pcall(require, thispath..'analyze_structure')
print(was_loaded, analyze_structure) analyze_structure, get_table_info = analyze_structure[1], analyze_structure[2]
assert(was_loaded, '[pretty]: Could not load vital library: analyze_structure') assert(was_loaded, '[pretty]: Could not load vital library: analyze_structure')
was_loaded, TABLE_TYPE = pcall(require, thispath..'table_type') was_loaded, TABLE_TYPE = pcall(require, thispath..'table_type')
assert(was_loaded, '[pretty]: Could not load vital library: table_type') assert(was_loaded, '[pretty]: Could not load vital library: table_type')
@ -333,12 +333,12 @@ local TABLE_TYPE_TO_PAIR_FORMAT = {
local function format_map (t, options, depth, l) local function format_map (t, options, depth, l)
-- NOTE: Assumes that the input table was pre-checked with `is_single_line_table()` -- NOTE: Assumes that the input table was pre-checked with `is_single_line_table()`
local table_type = l.info[t] and l.info[t].type or get_table_type(t) -- FIXME: This is a temp fix local table_info = l.info[t] or get_table_info(t)
local key_value_pairs = get_key_value_pairs_in_proper_order(t) local key_value_pairs = get_key_value_pairs_in_proper_order(t)
if table_type == TABLE_TYPE.SEQUENCE and l.info[t].has_holes then if table_info.type == TABLE_TYPE.SEQUENCE and l.info[t].has_holes then
fill_holes_in_key_value_pairs(key_value_pairs) fill_holes_in_key_value_pairs(key_value_pairs)
end end
local pair_format_func = TABLE_TYPE_TO_PAIR_FORMAT[table_type] local pair_format_func = TABLE_TYPE_TO_PAIR_FORMAT[table_info.type]
local start_of_table_i = #l + 1 local start_of_table_i = #l + 1
l[#l+1] = '{' l[#l+1] = '{'

View File

@ -1,7 +1,7 @@
local SUITE = require('TestSuite').new('analyze_structure') local SUITE = require('TestSuite').new('analyze_structure')
SUITE:setEnviroment { SUITE:setEnviroment {
analyze_structure = require('analyze_structure'), analyze_structure = require('analyze_structure')[1],
TABLE_TYPE = require('table_type') TABLE_TYPE = require('table_type')
} }
@ -55,6 +55,24 @@ SUITE:addTest('Pure Map', function ()
assert(table_info.has_map == true) assert(table_info.has_map == true)
end) end)
SUITE:addTest('Boolean set', function ()
local input = { [true] = true, [false] = false }
local table_info = analyze_structure(input)[input]
assert(table_info.type == TABLE_TYPE.SET, 'Returned bad type: '..table_info.type)
assert(table_info.has_seq == false)
assert(table_info.has_map == true)
end)
SUITE:addTest('A Mixed table', function ()
local input = { 300, [300] = 1 }
local table_info = analyze_structure(input)[input]
assert(table_info.has_seq == true)
assert(table_info.has_map == true)
assert(table_info.type == TABLE_TYPE.MIXED, 'Returned bad type: '..table_info.type)
end)
SUITE:addTest('String Map', function () SUITE:addTest('String Map', function ()
local input = { a = 1, b = 2, c = 3 } local input = { a = 1, b = 2, c = 3 }
local table_info = analyze_structure(input)[input] local table_info = analyze_structure(input)[input]

View File

@ -192,11 +192,6 @@ format_test {
expect = '{ [false] = false, [true] = true }', expect = '{ [false] = false, [true] = true }',
} }
format_test {
input = { [100] = 'Hi', [300] = 'Hello' },
expect = '{ [100] = \'Hi\', [300] = \'Hello\' }',
}
format_test { -- Order does not matter format_test { -- Order does not matter
input = { b = 1, a = 2 }, input = { b = 1, a = 2 },
expect = '{ a = 2, b = 1 }', expect = '{ a = 2, b = 1 }',
@ -225,9 +220,14 @@ format_test {
expect = '{\n\ta = { 1, 2, 3 },\n\tb = { 4, 5, 6 }\n}', expect = '{\n\ta = { 1, 2, 3 },\n\tb = { 4, 5, 6 }\n}',
} }
format_test {
input = { [100] = 'Hi', [300] = 'Hello' },
expect = '{ [100] = \'Hi\', [300] = \'Hello\' }',
}
format_test { format_test {
input = { 'Hi', [300] = 'Hello' }, input = { 'Hi', [300] = 'Hello' },
expect = '{\n\t[1] = \'Hi\',\n\t[300] = \'Hello\'\n}', expect = '{ [1] = \'Hi\', [300] = \'Hello\' }',
} }
format_test { format_test {