About.jl/src/functions.jl

68 lines
2.9 KiB
Julia

function about(io::IO, fn::Function)
source = Main.InteractiveUtils.which(parentmodule(fn), Symbol(fn))
methodmodules = getproperty.(methods(fn).ms, :module)
others = setdiff(methodmodules, [source])
print(io, Base.summary(fn), styled"\n Defined in {bright_red:$source}")
if length(others) > 0
print(io, styled"{shadow:({emphasis:$(sum(Ref(source) .=== methodmodules))})} extended in ")
for (i, oth) in enumerate(others)
print(io, styled"{bright_red:$oth}{shadow:({emphasis:$(sum(Ref(oth) .=== methodmodules))})}")
if length(others) == 2 && i == 1
print(io, " and ")
elseif length(others) > 2 && i < length(others)-1
print(io, ", ")
elseif length(others) > 2 && i == length(others)-1
print(io, ", and ")
end
end
end
print(io, ".\n")
end
function about(io::IO, method::Method)
fn, sig = first(method.sig.types).instance, Tuple{map(Base.unwrap_unionall, method.sig.types[2:end])...}
show(io, method)
println(io)
print_effects(io, fn, sig)
end
function about(io::IO, fn::Function, @nospecialize(sig::Type{<:Tuple}))
about(io, fn); println(io)
ms = methods(fn, sig)
if isempty(ms)
print(io, styled" {error:!} No methods matched $fn($(join(collect(Tuple{Int64, Int64, Int64}.types), \", \")))")
return
end
println(io, styled" Matched {emphasis:$(length(ms))} method$(ifelse(length(ms) > 1, \"s\", \"\")):")
for method in ms
println(io, " ", sprint(show, method, context=IOContext(io)))
end
print_effects(io, fn, sig)
end
function print_effects(io::IO, fn::Function, @nospecialize(sig::Type{<:Tuple}))
effects = Base.infer_effects(fn, sig)
ATRUE, AFALSE = Core.Compiler.ALWAYS_TRUE, Core.Compiler.ALWAYS_FALSE
echar(t::UInt8) = get(Dict(ATRUE => '✔', AFALSE => '✗'), t, '?')
echar(b::Bool) = ifelse(b, '✔', '✗')
eface(t::UInt8) = get(Dict(ATRUE => :success, AFALSE => :error), t, :warning)
eface(b::Bool) = ifelse(b, :success, :error)
hedge(t::UInt8) = get(Dict(ATRUE => styled"guaranteed to",
AFALSE => styled"{italic:not} guaranteed to"), t,
styled"???")
hedge(b::Bool) = hedge(ifelse(b, ATRUE, AFALSE))
println(io)
for (effect, description) in
[(:consistent, "return or terminate consistently"),
(:effect_free, "be free from externally semantically visible side effects"),
(:nothrow, "never throw an exception"),
(:terminates, "terminate")]
e = getfield(effects, effect)
print(io, styled" {$(eface(e)):{bold:$(echar(e))} $(rpad(effect, 11))} {shadow:$(hedge(e)) $description}")
print('\n')
end
end
about(io::IO, fn::Function, sig::NTuple{N, <:Type}) where {N} = about(io, fn, Tuple{sig...})
about(io::IO, fn::Function, sig::Type...) = about(io, fn, sig)