Skip to content

Commit

Permalink
dump: handle recursion better (#27051)
Browse files Browse the repository at this point in the history
where better means at least as well as `show_default`
  • Loading branch information
vtjnash authored and JeffBezanson committed May 10, 2018
1 parent 5fb465f commit ee4b18f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 23 deletions.
50 changes: 29 additions & 21 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1599,7 +1599,7 @@ function show(io::IO, tv::TypeVar)
nothing
end

function dump(io::IO, x::SimpleVector, n::Int, indent)
function dump(io::IOContext, x::SimpleVector, n::Int, indent)
if isempty(x)
print(io, "empty SimpleVector")
return
Expand All @@ -1619,37 +1619,40 @@ function dump(io::IO, x::SimpleVector, n::Int, indent)
nothing
end

function dump(io::IO, @nospecialize(x), n::Int, indent)
function dump(io::IOContext, @nospecialize(x), n::Int, indent)
T = typeof(x)
if isa(x, Function)
print(io, x, " (function of type ", T, ")")
else
print(io, T)
end
if nfields(x) > 0
if n > 0
for field in (isa(x,Tuple) ? (1:length(x)) : fieldnames(T))
nf = nfields(x)
if nf > 0
if n > 0 && !show_circular(io, x)
recur_io = IOContext(io, Pair{Symbol,Any}(:SHOWN_SET, x))
for field in 1:nf
println(io)
print(io, indent, " ", field, ": ")
fname = string(fieldname(T, field))
print(io, indent, " ", fname, ": ")
if isdefined(x,field)
dump(io, getfield(x, field), n - 1, string(indent, " "))
dump(recur_io, getfield(x, field), n - 1, string(indent, " "))
else
print(io, undef_ref_str)
end
end
end
else
!isa(x,Function) && print(io, " ", x)
!isa(x, Function) && print(io, " ", x)
end
nothing
end

dump(io::IO, x::Module, n::Int, indent) = print(io, "Module ", x)
dump(io::IO, x::String, n::Int, indent) = (print(io, "String "); show(io, x))
dump(io::IO, x::Symbol, n::Int, indent) = print(io, typeof(x), " ", x)
dump(io::IO, x::Union, n::Int, indent) = print(io, x)
dump(io::IOContext, x::Module, n::Int, indent) = print(io, "Module ", x)
dump(io::IOContext, x::String, n::Int, indent) = (print(io, "String "); show(io, x))
dump(io::IOContext, x::Symbol, n::Int, indent) = print(io, typeof(x), " ", x)
dump(io::IOContext, x::Union, n::Int, indent) = print(io, x)

function dump_elts(io::IO, x::Array, n::Int, indent, i0, i1)
function dump_elts(io::IOContext, x::Array, n::Int, indent, i0, i1)
for i in i0:i1
print(io, indent, " ", i, ": ")
if !isassigned(x,i)
Expand All @@ -1661,31 +1664,33 @@ function dump_elts(io::IO, x::Array, n::Int, indent, i0, i1)
end
end

function dump(io::IO, x::Array, n::Int, indent)
function dump(io::IOContext, x::Array, n::Int, indent)
print(io, "Array{$(eltype(x))}($(size(x)))")
if eltype(x) <: Number
print(io, " ")
show(io, x)
else
if n > 0 && !isempty(x)
if n > 0 && !isempty(x) && !show_circular(io, x)
println(io)
recur_io = IOContext(io, :SHOWN_SET => x)
lx = length(x)
if get(io, :limit, false)
dump_elts(io, x, n, indent, 1, (length(x) <= 10 ? length(x) : 5))
if length(x) > 10
dump_elts(recur_io, x, n, indent, 1, (lx <= 10 ? lx : 5))
if lx > 10
println(io)
println(io, indent, " ...")
dump_elts(io, x, n, indent, length(x)-4, length(x))
dump_elts(recur_io, x, n, indent, lx - 4, lx)
end
else
dump_elts(io, x, n, indent, 1, length(x))
dump_elts(recur_io, x, n, indent, 1, lx)
end
end
end
nothing
end

# Types
function dump(io::IO, x::DataType, n::Int, indent)
function dump(io::IOContext, x::DataType, n::Int, indent)
print(io, x)
if x !== Any
print(io, " <: ", supertype(x))
Expand All @@ -1712,7 +1717,10 @@ end

const DUMP_DEFAULT_MAXDEPTH = 8

dump(io::IO, arg; maxdepth=DUMP_DEFAULT_MAXDEPTH) = (dump(io, arg, maxdepth, ""); println(io))
function dump(io::IO, @nospecialize(x); maxdepth=DUMP_DEFAULT_MAXDEPTH)
dump(IOContext(io), x, maxdepth, "")
println(io)
end

"""
dump(x; maxdepth=$DUMP_DEFAULT_MAXDEPTH)
Expand Down
21 changes: 19 additions & 2 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -726,10 +726,27 @@ test_mt(show_f5, "show_f5(A::AbstractArray{T,N}, indices::Vararg{$Int,N})")
@test_repr "continue"
@test_repr "break"

let x = [], y = []
let x = [], y = [], z = Base.ImmutableDict(x => y)
push!(x, y)
push!(y, x)
@test replstr(x) == "1-element Array{Any,1}:\n Any[Any[Any[#= circular reference @-2 =#]]]"
push!(y, z)
@test replstr(x) == "1-element Array{Any,1}:\n Any[Any[Any[#= circular reference @-2 =#]], Base.ImmutableDict(Any[Any[#= circular reference @-3 =#]]=>Any[#= circular reference @-2 =#])]"
@test repr(z) == "Base.ImmutableDict(Any[Any[Any[#= circular reference @-2 =#], Base.ImmutableDict(#= circular reference @-3 =#)]]=>Any[Any[Any[#= circular reference @-2 =#]], Base.ImmutableDict(#= circular reference @-2 =#)])"
@test sprint(dump, x) == """
Array{Any}((1,))
1: Array{Any}((2,))
1: Array{Any}((1,))#= circular reference @-2 =#
2: Base.ImmutableDict{Array{Any,1},Array{Any,1}}
parent: Base.ImmutableDict{Array{Any,1},Array{Any,1}}
parent: #undef
key: #undef
value: #undef
key: Array{Any}((1,))#= circular reference @-3 =#
value: Array{Any}((2,))#= circular reference @-2 =#
"""
dz = sprint(dump, z)
@test 10 < countlines(IOBuffer(dz)) < 40
@test sum(x -> 1, eachmatch(r"circular reference", dz)) == 4
end

# PR 16221
Expand Down

0 comments on commit ee4b18f

Please sign in to comment.