diff --git a/base/methodshow.jl b/base/methodshow.jl index 1be14a73ec338..cf8e59de3a8b4 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -2,6 +2,14 @@ # Method and method table pretty-printing +const empty_sym = Symbol("") +function strip_gensym(sym) + if sym === Symbol("#self#") || sym === Symbol("#unused#") + return empty_sym + end + return Symbol(replace(String(sym), r"^(.*)#(.*#)?\d+$" => s"\1")) +end + function argtype_decl(env, n, @nospecialize(sig::DataType), i::Int, nargs, isva::Bool) # -> (argname, argtype) t = sig.parameters[i] if i == nargs && isva && !isvarargtype(t) @@ -10,13 +18,13 @@ function argtype_decl(env, n, @nospecialize(sig::DataType), i::Int, nargs, isva: if isa(n,Expr) n = n.args[1] # handle n::T in arg list end - s = string(n)::String - i = findfirst(isequal('#'), s) - if i !== nothing - s = s[1:prevind(s, i)::Int] - end - if t === Any && !isempty(s) - return s, "" + n = strip_gensym(n) + local s + if n === empty_sym + s = "" + else + s = sprint(show_sym, n) + t === Any && return s, "" end if isvarargtype(t) v1, v2 = nothing, nothing @@ -73,8 +81,6 @@ function arg_decl_parts(m::Method, html=false) return tv, decls, file, line end -const empty_sym = Symbol("") - # NOTE: second argument is deprecated and is no longer used function kwarg_decl(m::Method, kwtype = nothing) mt = get_methodtable(m) @@ -184,6 +190,15 @@ function functionloc(@nospecialize(f)) return functionloc(first(mt)) end +function sym_to_string(sym) + s = String(sym) + if endswith(s, "...") + return string(sprint(show_sym, Symbol(s[1:end-3])), "...") + else + return sprint(show_sym, sym) + end +end + function show(io::IO, m::Method) tv, decls, file, line = arg_decl_parts(m) sig = unwrap_unionall(m.sig) @@ -193,12 +208,16 @@ function show(io::IO, m::Method) return end print(io, decls[1][2], "(") - join(io, String[isempty(d[2]) ? d[1] : d[1]*"::"*d[2] for d in decls[2:end]], - ", ", ", ") + join( + io, + String[isempty(d[2]) ? d[1] : string(d[1], "::", d[2]) for d in decls[2:end]], + ", ", + ", ", + ) kwargs = kwarg_decl(m) if !isempty(kwargs) print(io, "; ") - join(io, kwargs, ", ", ", ") + join(io, map(sym_to_string, kwargs), ", ", ", ") end print(io, ")") show_method_params(io, tv) @@ -339,12 +358,18 @@ function show(io::IO, ::MIME"text/html", m::Method) return end print(io, decls[1][2], "(") - join(io, String[isempty(d[2]) ? d[1] : d[1]*"::"*d[2]*"" - for d in decls[2:end]], ", ", ", ") + join( + io, + String[ + isempty(d[2]) ? d[1] : string(d[1], "::", d[2], "") for d in decls[2:end] + ], + ", ", + ", ", + ) kwargs = kwarg_decl(m) if !isempty(kwargs) print(io, "; ") - join(io, kwargs, ", ", ", ") + join(io, map(sym_to_string, kwargs), ", ", ", ") print(io, "") end print(io, ")") diff --git a/base/show.jl b/base/show.jl index 1984a6349edea..b03ccf0f474e2 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2028,7 +2028,7 @@ function show_signature_function(io::IO, @nospecialize(ft), demangle=false, farg if ft <: Function && isa(uw, DataType) && isempty(uw.parameters) && isdefined(uw.name.module, uw.name.mt.name) && ft == typeof(getfield(uw.name.module, uw.name.mt.name)) - print(io, (demangle ? demangle_function_name : identity)(uw.name.mt.name)) + show_sym(io, (demangle ? demangle_function_name : identity)(uw.name.mt.name)) elseif isa(ft, DataType) && ft.name === Type.body.name && (f = ft.parameters[1]; !isa(f, TypeVar)) uwf = unwrap_unionall(f) diff --git a/test/errorshow.jl b/test/errorshow.jl index 2d370d7f05246..047e34bad69f6 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -426,7 +426,7 @@ let err_str, @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}})), - "@doc(__source__::LineNumberNode, __module__::Module, x...) in Core at boot.jl:") + "var\"@doc\"(__source__::LineNumberNode, __module__::Module, x...) in Core at boot.jl:") @test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") @test startswith(sprint(show, which(StructWithUnionAllMethodDefs{<:Integer}, (Any,))), diff --git a/test/show.jl b/test/show.jl index f2cfc21a9578f..06012a76f38f8 100644 --- a/test/show.jl +++ b/test/show.jl @@ -2018,3 +2018,23 @@ end @test Base.make_typealias(M37012.AStruct{1}) === nothing @test isempty(Base.make_typealiases(M37012.AStruct{1})[1]) @test string(M37012.AStruct{1}) == "$(curmod_prefix)M37012.AStruct{1}" + +@testset "method printing with non-standard identifiers" for _show in ( + show, + (io, x) -> show(io, MIME("text/html"), x), +) + @eval var","(x) = x + @test occursin("var\",\"(x)", sprint(_show, methods(var","))) + + @eval f1(var"a.b") = 3 + @test occursin("f1(var\"a.b\")", sprint(_show, methods(f1))) + + @eval f2(; var"123") = 5 + @test occursin("f2(; var\"123\")", sprint(_show, methods(f2))) + + @eval f3(; var"%!"...) = 7 + @test occursin("f3(; var\"%!\"...)", sprint(_show, methods(f3))) + + @eval f4(; var"...") = 9 + @test_broken occursin("f4(; var\"...\")", sprint(_show, methods(f4))) +end