diff --git a/inspect.lua b/inspect.lua index e2e3806..73f0a23 100644 --- a/inspect.lua +++ b/inspect.lua @@ -124,6 +124,19 @@ local function getNonSequentialKeys(t) return keys, keysLength, sequenceLength end +local function getToStringResultSafely(t, mt) + if type(t) ~= "userdata" then + return + end + local __tostring = type(mt) == 'table' and rawget(mt, '__tostring') + local str, ok + if type(__tostring) == 'function' then + ok, str = pcall(__tostring, t) + str = ok and str or 'error: ' .. tostring(str) + end + if type(str) == 'string' and #str > 0 then return str end +end + local function countTableAppearances(t, tableAppearances) tableAppearances = tableAppearances or {} @@ -293,6 +306,20 @@ function Inspector:putValue(v) self:puts(tostring(v)) elseif tv == 'table' then self:putTable(v) + elseif tv == 'userdata' then + local mt = getmetatable(v) + local toStringResult = mt and getToStringResultSafely(v, mt) + if toStringResult then + self:puts('') + self:puts(' -- ', escape(toStringResult)) + else + local str = tostring(v) + if str == "userdata: NULL" then + self:puts('') + else + self:puts('') + end + end else self:puts('<', tv, ' ', self:getId(v), '>') end diff --git a/spec/inspect_spec.lua b/spec/inspect_spec.lua index edea720..995361d 100644 --- a/spec/inspect_spec.lua +++ b/spec/inspect_spec.lua @@ -363,6 +363,17 @@ describe( 'inspect', function() ]]), inspect(bar)) end) + it('includes the __tostring metamethod of userdata', function() + local tbl = { + f = io.tmpfile(), + } + assert.equals(unindent([[ + { + f = -- $FILE + } + ]]):gsub("$FILE", tostring(tbl.f)), inspect(tbl)) + end) + it('can be used on the __tostring metamethod of a table without errors', function() local f = function(x) return inspect(x) end local tbl = setmetatable({ x = 1 }, { __tostring = f })