Skip to content

Commit

Permalink
methodshow: single-line printing for Method by default
Browse files Browse the repository at this point in the history
Currently `show(::IO, ::Method)` prints the method object in
multiple-line as like:
```julia
julia> only(methods(sin, (Float64,)))
sin(x::T) where T<:Union{Float32, Float64}
     @ Base.Math special/trig.jl:29
```
and this could be confusing when used within a container e.g.:
```julia
julia> Any[only(methods(sin, (Float64,)))]
1-element Vector{Any}:
 sin(x::T) where T<:Union{Float32, Float64}
     @ Base.Math special/trig.jl:29

julia> code_lowered() do; Base.Experimental.@opaque a::Int -> sin(a); end
1-element Vector{Core.CodeInfo}:
 CodeInfo(
1 ─ %1 = Core.apply_type(Core.Tuple, Main.Int)
│   %2 = Core.apply_type(Core.Union)
│   %3 = $(Expr(:new_opaque_closure, :(%1), :(%2), :(Core.Any), opaque closure(...)
     @ Main none:0))
└──      return %3
)
```

This commit refactors the `show` method for `Method` object so that
`show(::IO, ::Method)` prints it within a single line by default and
`show(::IO, ::MIME"text/plain", ::Method)` prints within 2-lines,
that I believe is more aligned with printing implementations for
the other types:
```julia
julia> Any[only(methods(sin, (Float64,)))]
1-element Vector{Any}:
 sin(x::T) where T<:Union{Float32, Float64} @ Base.Math special/trig.jl:29

julia> code_lowered() do; Base.Experimental.@opaque a::Int -> sin(a); end
1-element Vector{Core.CodeInfo}:
 CodeInfo(
1 ─ %1 = Core.apply_type(Core.Tuple, Main.Int)
│   %2 = Core.apply_type(Core.Union)
│   %3 = $(Expr(:new_opaque_closure, :(%1), :(%2), :(Core.Any), opaque closure(...) @ Main none:0))
└──      return %3
)
```
  • Loading branch information
aviatesk committed Aug 3, 2022
1 parent eedf3f1 commit ed84454
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 24 deletions.
22 changes: 12 additions & 10 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ function showerror_ambiguous(io::IO, meths, f, args)
sigfix = Any
for m in meths
print(io, " ")
show(io, m; digit_align_width=-2)
show_method(io, m; digit_align_width=0)
println(io)
sigfix = typeintersect(m.sig, sigfix)
end
Expand Down Expand Up @@ -543,8 +543,8 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=()
println(iob)

m = parentmodule_before_main(method.module)
color = get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m)
print_module_path_file(iob, m, string(file), line, color, 1)
modulecolor = get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m)
print_module_path_file(iob, m, string(file), line; modulecolor, digit_align_width = 3)

# TODO: indicate if it's in the wrong world
push!(lines, (buf, right_matches))
Expand Down Expand Up @@ -685,15 +685,15 @@ end
# Print a stack frame where the module color is determined by looking up the parent module in
# `modulecolordict`. If the module does not have a color, yet, a new one can be drawn
# from `modulecolorcycler`.
function print_stackframe(io, i, frame::StackFrame, n::Int, digit_align_width, modulecolordict, modulecolorcycler)
function print_stackframe(io, i, frame::StackFrame, n::Int, ndigits_max, modulecolordict, modulecolorcycler)
m = Base.parentmodule(frame)
modulecolor = if m !== nothing
m = parentmodule_before_main(m)
get!(() -> popfirst!(modulecolorcycler), modulecolordict, m)
else
:default
end
print_stackframe(io, i, frame, n, digit_align_width, modulecolor)
print_stackframe(io, i, frame, n, ndigits_max, modulecolor)
end

# Gets the topmost parent module that isn't Main
Expand All @@ -707,7 +707,7 @@ function parentmodule_before_main(m)
end

# Print a stack frame where the module color is set manually with `modulecolor`.
function print_stackframe(io, i, frame::StackFrame, n::Int, digit_align_width, modulecolor)
function print_stackframe(io, i, frame::StackFrame, n::Int, ndigits_max, modulecolor)
file, line = string(frame.file), frame.line
file = fixup_stdlib_path(file)
stacktrace_expand_basepaths() && (file = something(find_source_file(file), file))
Expand All @@ -722,8 +722,10 @@ function print_stackframe(io, i, frame::StackFrame, n::Int, digit_align_width, m
inlined = getfield(frame, :inlined)
modul = parentmodule(frame)

digit_align_width = ndigits_max + 2

# frame number
print(io, " ", lpad("[" * string(i) * "]", digit_align_width + 2))
print(io, " ", lpad("[" * string(i) * "]", digit_align_width))
print(io, " ")

StackTraces.show_spec_linfo(IOContext(io, :backtrace=>true), frame)
Expand All @@ -733,14 +735,14 @@ function print_stackframe(io, i, frame::StackFrame, n::Int, digit_align_width, m
println(io)

# @ Module path / file : line
print_module_path_file(io, modul, file, line, modulecolor, digit_align_width)
print_module_path_file(io, modul, file, line; modulecolor, digit_align_width)

# inlined
printstyled(io, inlined ? " [inlined]" : "", color = :light_black)
end

function print_module_path_file(io, modul, file, line, modulecolor = :light_black, digit_align_width = 0)
printstyled(io, " " ^ (digit_align_width + 2) * "@", color = :light_black)
function print_module_path_file(io, modul, file, line; modulecolor = :light_black, digit_align_width = 0)
printstyled(io, " " ^ digit_align_width * "@", color = :light_black)

# module
if modul !== nothing && modulecolor !== nothing
Expand Down
19 changes: 14 additions & 5 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,12 @@ function sym_to_string(sym)
end
end

function show(io::IO, m::Method; modulecolor = :light_black, digit_align_width = -1)
# default compact view
show(io::IO, m::Method; kwargs...) = show_method(IOContext(io, :compact=>true), m; kwargs...)

show(io::IO, ::MIME"text/plain", m::Method; kwargs...) = show_method(io, m; kwargs...)

function show_method(io::IO, m::Method; modulecolor = :light_black, digit_align_width = 1)
tv, decls, file, line = arg_decl_parts(m)
sig = unwrap_unionall(m.sig)
if sig === Tuple
Expand Down Expand Up @@ -242,8 +247,12 @@ function show(io::IO, m::Method; modulecolor = :light_black, digit_align_width =
end

# module & file, re-using function from errorshow.jl
println(io)
print_module_path_file(io, m.module, string(file), line, modulecolor, digit_align_width+4)
if get(io, :compact, false) # single-line mode
print_module_path_file(io, m.module, string(file), line; modulecolor, digit_align_width)
else
println(io)
print_module_path_file(io, m.module, string(file), line; modulecolor, digit_align_width=digit_align_width+4)
end
end

function show_method_list_header(io::IO, ms::MethodList, namefmt::Function)
Expand Down Expand Up @@ -313,7 +322,7 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru
m = parentmodule_before_main(meth.module)
get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m)
end
show(io, meth; modulecolor)
show_method(io, meth; modulecolor)

file, line = updated_methodloc(meth)
if last_shown_line_infos !== nothing
Expand All @@ -327,7 +336,7 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru
if rest > 0
println(io)
if rest == 1
show(io, last)
show_method(io, last)
else
print(io, "... $rest methods not shown")
if hasname
Expand Down
18 changes: 9 additions & 9 deletions test/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -431,25 +431,25 @@ let err_str,
Base.stacktrace_contract_userdir() && (sp = Base.contractuser(sp))

@test sprint(show, which(String, Tuple{})) ==
"String()\n @ $curmod_str $sp:$(method_defs_lineno + 0)"
"String() @ $curmod_str $sp:$(method_defs_lineno + 0)"
@test sprint(show, which("a", Tuple{})) ==
"(::String)()\n @ $curmod_str $sp:$(method_defs_lineno + 1)"
"(::String)() @ $curmod_str $sp:$(method_defs_lineno + 1)"
@test sprint(show, which(EightBitType, Tuple{})) ==
"$(curmod_prefix)EightBitType()\n @ $curmod_str $sp:$(method_defs_lineno + 2)"
"$(curmod_prefix)EightBitType() @ $curmod_str $sp:$(method_defs_lineno + 2)"
@test sprint(show, which(reinterpret(EightBitType, 0x54), Tuple{})) ==
"(::$(curmod_prefix)EightBitType)()\n @ $curmod_str $sp:$(method_defs_lineno + 3)"
"(::$(curmod_prefix)EightBitType)() @ $curmod_str $sp:$(method_defs_lineno + 3)"
@test sprint(show, which(EightBitTypeT, Tuple{})) ==
"$(curmod_prefix)EightBitTypeT()\n @ $curmod_str $sp:$(method_defs_lineno + 4)"
"$(curmod_prefix)EightBitTypeT() @ $curmod_str $sp:$(method_defs_lineno + 4)"
@test sprint(show, which(EightBitTypeT{Int32}, Tuple{})) ==
"$(curmod_prefix)EightBitTypeT{T}() where T\n @ $curmod_str $sp:$(method_defs_lineno + 5)"
"$(curmod_prefix)EightBitTypeT{T}() where T @ $curmod_str $sp:$(method_defs_lineno + 5)"
@test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) ==
"(::$(curmod_prefix)EightBitTypeT)()\n @ $curmod_str $sp:$(method_defs_lineno + 6)"
"(::$(curmod_prefix)EightBitTypeT)() @ $curmod_str $sp:$(method_defs_lineno + 6)"
@test startswith(sprint(show, which(Complex{Int}, Tuple{Int})),
"Complex{T}(")
@test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{LineNumberNode, Module, Vararg{Any}})),
"var\"@doc\"(__source__::LineNumberNode, __module__::Module, x...)\n @ Core boot.jl:")
"var\"@doc\"(__source__::LineNumberNode, __module__::Module, x...) @ Core boot.jl:")
@test startswith(sprint(show, which(FunctionLike(), Tuple{})),
"(::$(curmod_prefix)FunctionLike)()\n @ $curmod_str $sp:$(method_defs_lineno + 7)")
"(::$(curmod_prefix)FunctionLike)() @ $curmod_str $sp:$(method_defs_lineno + 7)")
@test startswith(sprint(show, which(StructWithUnionAllMethodDefs{<:Integer}, (Any,))),
"($(curmod_prefix)StructWithUnionAllMethodDefs{T} where T<:Integer)(x)")
@test repr("text/plain", FunctionLike()) == "(::$(curmod_prefix)FunctionLike) (generic function with 1 method)"
Expand Down
12 changes: 12 additions & 0 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2380,3 +2380,15 @@ Base.show(io::IO, ces::⛵) = Base.print(io, '⛵')
@test Base.alignment(stdout, ()) == (0, 2)
@test Base.alignment(IOContext(IOBuffer(), :color=>true), ColoredLetter()) == (0, 1)
@test Base.alignment(IOContext(IOBuffer(), :color=>false), ColoredLetter()) == (0, 1)

# `show` implementations for `Method`
let buf = IOBuffer()

# single line printing by default
show(buf, only(methods(sin, (Float64,))))
@test !occursin('\n', String(take!(buf)))

# two-line printing for rich display
show(buf, MIME("text/plain"), only(methods(sin, (Float64,))))
@test occursin('\n', String(take!(buf)))
end

0 comments on commit ed84454

Please sign in to comment.