Ignore __pairs when iterating over tables

Related with #33
master
Enrique García Cota 7 years ago
parent b6bb292f68
commit 9dc10c968f
  1. 67
      inspect.lua
  2. 12
      spec/inspect_spec.lua

@ -33,6 +33,10 @@ local tostring = tostring
inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end}) inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end}) inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
local function rawpairs(t)
return next, t, nil
end
-- Apostrophizes the string if it has quotes, but not aphostrophes -- Apostrophizes the string if it has quotes, but not aphostrophes
-- Otherwise, it returns a regular quoted string -- Otherwise, it returns a regular quoted string
local function smartQuote(str) local function smartQuote(str)
@ -108,13 +112,16 @@ local function getSequenceLength(t)
end end
local function getNonSequentialKeys(t) local function getNonSequentialKeys(t)
local keys = {} local keys, keysLength = {}, 0
local sequenceLength = getSequenceLength(t) local sequenceLength = getSequenceLength(t)
for k,_ in pairs(t) do for k,_ in rawpairs(t) do
if not isSequenceKey(k, sequenceLength) then table.insert(keys, k) end if not isSequenceKey(k, sequenceLength) then
keysLength = keysLength + 1
keys[keysLength] = k
end
end end
table.sort(keys, sortKeys) table.sort(keys, sortKeys)
return keys, sequenceLength return keys, keysLength, sequenceLength
end end
local function getToStringResultSafely(t, mt) local function getToStringResultSafely(t, mt)
@ -133,7 +140,7 @@ local function countTableAppearances(t, tableAppearances)
if type(t) == 'table' then if type(t) == 'table' then
if not tableAppearances[t] then if not tableAppearances[t] then
tableAppearances[t] = 1 tableAppearances[t] = 1
for k,v in pairs(t) do for k,v in rawpairs(t) do
countTableAppearances(k, tableAppearances) countTableAppearances(k, tableAppearances)
countTableAppearances(v, tableAppearances) countTableAppearances(v, tableAppearances)
end end
@ -162,29 +169,28 @@ local function makePath(path, ...)
end end
local function processRecursive(process, item, path, visited) local function processRecursive(process, item, path, visited)
if item == nil then return nil end
if item == nil then return nil end if visited[item] then return visited[item] end
if visited[item] then return visited[item] end
local processed = process(item, path)
local processed = process(item, path) if type(processed) == 'table' then
if type(processed) == 'table' then local processedCopy = {}
local processedCopy = {} visited[item] = processedCopy
visited[item] = processedCopy local processedKey
local processedKey
for k,v in rawpairs(processed) do
for k,v in pairs(processed) do processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited) if processedKey ~= nil then
if processedKey ~= nil then processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
end
end end
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field
setmetatable(processedCopy, mt)
processed = processedCopy
end end
return processed
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field
setmetatable(processedCopy, mt)
processed = processedCopy
end
return processed
end end
@ -246,7 +252,7 @@ function Inspector:putTable(t)
else else
if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
local nonSequentialKeys, sequenceLength = getNonSequentialKeys(t) local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t)
local mt = getmetatable(t) local mt = getmetatable(t)
local toStringResult = getToStringResultSafely(t, mt) local toStringResult = getToStringResultSafely(t, mt)
@ -265,7 +271,8 @@ function Inspector:putTable(t)
count = count + 1 count = count + 1
end end
for _,k in ipairs(nonSequentialKeys) do for i=1, nonSequentialKeysLength do
local k = nonSequentialKeys[i]
if count > 0 then self:puts(',') end if count > 0 then self:puts(',') end
self:tabify() self:tabify()
self:putKey(k) self:putKey(k)
@ -282,7 +289,7 @@ function Inspector:putTable(t)
end end
end) end)
if #nonSequentialKeys > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing } if nonSequentialKeysLength > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing }
self:tabify() self:tabify()
elseif sequenceLength > 0 then -- array tables have one extra space before closing } elseif sequenceLength > 0 then -- array tables have one extra space before closing }
self:puts(' ') self:puts(' ')
@ -303,7 +310,7 @@ function Inspector:putValue(v)
elseif tv == 'table' then elseif tv == 'table' then
self:putTable(v) self:putTable(v)
else else
self:puts('<',tv,' ',self:getId(v),'>') self:puts('<', tv, ' ', self:getId(v), '>')
end end
end end

@ -92,6 +92,18 @@ describe( 'inspect', function()
local arr = setmetatable({1,2,3}, {__len = function() return nil end}) local arr = setmetatable({1,2,3}, {__len = function() return nil end})
assert.equals("{ 1, 2, 3,\n <metatable> = {\n __len = <function 1>\n }\n}", inspect(arr)) assert.equals("{ 1, 2, 3,\n <metatable> = {\n __len = <function 1>\n }\n}", inspect(arr))
end) end)
it('handles tables with a __pairs metamethod (ignoring the __pairs metamethod and using next)', function()
local t = setmetatable({ {}, name = "yeah" }, { __pairs = function() end })
assert.equals(
unindent([[{ {},
name = "yeah",
<metatable> = {
__pairs = <function 1>
}
}]]),
inspect(t))
end)
end end
it('works with simple dictionary tables', function() it('works with simple dictionary tables', function()

Loading…
Cancel
Save