Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/julia-runtest@latest
continue-on-error: ${{ matrix.version == 'nightly' }}
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
with:
Expand Down
124 changes: 71 additions & 53 deletions src/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,45 @@ function parsedocs(mod::Module)
end
end

"""
$(:SIGNATURES)

Decides whether a length of method is too big to be visually appealing.
"""
method_length_over_limit(len::Int) = len > 60

function printmethod_format(buffer::IOBuffer, binding::String, args::Vector{String}, kws::Vector{String}; return_type = "")

sep_delim = " "
paren_delim = ""
indent = ""

if method_length_over_limit(
length(binding) +
1 +
sum(length.(args)) +
sum(length.(kws)) +
2*max(0, length(args)-1) +
2*length(kws) +
1 +
length(return_type))

sep_delim = "\n"
paren_delim = "\n"
indent = " "
end

print(buffer, binding)
print(buffer, "($paren_delim")
join(buffer, Ref(indent).*args, ",$sep_delim")
if !isempty(kws)
print(buffer, ";$sep_delim")
join(buffer, Ref(indent).*kws, ",$sep_delim")
end
print(buffer, "$paren_delim)")
print(buffer, return_type)
return buffer
end

"""
$(:SIGNATURES)
Expand All @@ -193,19 +232,10 @@ f(x; a = 1, b...) = x
sig = printmethod(Docs.Binding(Main, :f), f, first(methods(f)))
```
"""
function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Method)
# TODO: print qualified?
print(buffer, binding.var)
print(buffer, "(")
join(buffer, arguments(method), ", ")
local kws = keywords(func, method)
if !isempty(kws)
print(buffer, "; ")
join(buffer, kws, ", ")
end
print(buffer, ")")
return buffer
end
printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Method) =
printmethod_format(buffer, string(binding.var),
string.(arguments(method)),
string.(keywords(func, method)))

"""
$(:SIGNATURES)
Expand Down Expand Up @@ -273,18 +303,16 @@ sig = printmethod(Docs.Binding(Main, :f), f, first(methods(f)))
"""
function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Method, typesig)
# TODO: print qualified?
print(buffer, binding.var)
print(buffer, "(")
local args = arguments(method)
local where_syntax = []
local args = string.(arguments(method))
local kws = string.(keywords(func, method))

# find inner tuple type
function f(t)
function find_inner_tuple_type(t)
# t is always either a UnionAll which represents a generic type or a Tuple where each parameter is the argument
if t isa DataType && t <: Tuple
t
elseif t isa UnionAll
f(t.body)
find_inner_tuple_type(t.body)
else
error("Expected `typeof($t)` to be `Tuple` or `UnionAll` but found `$typeof(t)`")
end
Expand All @@ -308,45 +336,35 @@ function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Meth
typ
end

for (i, sym) in enumerate(args)
if typesig isa UnionAll
# e.g. Tuple{Vector{T}} where T<:Number
# or Tuple{String, T, T} where T<:Number
# or Tuple{Type{T}, String, Union{Nothing, Function}} where T<:Number
t = [x for x in f(typesig).types]
t = [get_typesig(x, x) for x in t][i]
else
# e.g. Tuple{Vector{Int}}
t = typesig.types[i]
end
# if `typesig` is an UnionAll, it may be
# e.g. Tuple{Vector{T}} where T<:Number
# or Tuple{String, T, T} where T<:Number
# or Tuple{Type{T}, String, Union{Nothing, Function}} where T<:Number
# in the other case, it's usually something like Tuple{Vector{Int}}.
argtypes = typesig isa UnionAll ?
[get_typesig(t, t) for t in find_inner_tuple_type(typesig).types] :
collect(typesig.types)

args = map(args, argtypes) do arg,t
type = ""
suffix = ""
if isvarargtype(t)
elt = vararg_eltype(t)
if elt === Any
print(buffer, "$sym...")
else
print(buffer, "$sym::$elt...")
end
elseif t === Any
print(buffer, sym)
else
print(buffer, "$sym::$t")
t = vararg_eltype(t)
suffix = "..."
end

if i != length(args)
print(buffer, ", ")
if t!==Any
type = "::$t"
end

"$arg$type$suffix"
end
local kws = keywords(func, method)
if !isempty(kws)
print(buffer, "; ")
join(buffer, kws, ", ")
end
print(buffer, ")")

rt = Base.return_types(func, typesig)
if length(rt) >= 1 && rt[1] !== Nothing && rt[1] !== Union{}
print(buffer, " -> $(rt[1])")
end
buffer

return printmethod_format(buffer, string(binding.var), args, string.(kws);
return_type =
length(rt) >= 1 && rt[1] !== Nothing && rt[1] !== Union{} ?
" -> $(rt[1])" : "")
end

printmethod(b, f, m) = String(take!(printmethod(IOBuffer(), b, f, m)))
Expand Down
15 changes: 8 additions & 7 deletions test/tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ end
f = str -> replace(str, " " => "")
str = f(str)
if Sys.iswindows()
@test occursin(f("h_1(x::Union{Array{T,4}, Array{T,3}} where T) -> Union{Array{T,4}, Array{T,3}} where T"), str)
@test occursin(f("h_1(\nx::Union{Array{T,4}, Array{T,3}} where T\n) -> Union{Array{T,4}, Array{T,3}} where T"), str)
else
@test occursin(f("h_1(x::Union{Array{T,3}, Array{T,4}} where T) -> Union{Array{T,3}, Array{T,4}} where T"), str)
@test occursin(f("h_1(\nx::Union{Array{T,3}, Array{T,4}} where T\n) -> Union{Array{T,3}, Array{T,4}} where T"), str)
end
@test occursin("\n```\n", str)

Expand Down Expand Up @@ -307,7 +307,7 @@ end
@test occursin("\n```julia\n", str)
if VERSION > v"1.3.0"
@test occursin("\nk_5(::Type{T<:Number}, x::String) -> String\n", str)
@test occursin("\nk_5(::Type{T<:Number}, x::String, func::Union{Nothing, Function}) -> String\n", str)
@test occursin("\nk_5(\n ::Type{T<:Number},\n x::String,\n func::Union{Nothing, Function}\n) -> String\n", str)
@test occursin("\n```\n", str)
else
# TODO: remove this test when julia 1.0.0 support is dropped.
Expand Down Expand Up @@ -342,12 +342,13 @@ end
DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
str = String(take!(buf))
@test occursin("\n```julia\n", str)
if VERSION > v"1.7" || VERSION < v"1.1"
@test occursin("\nk_7(x::Union{Nothing, T} where T<:Integer) -> Union{Nothing, T} where T<:Integer\n", str)
if VERSION >= v"1.6" && VERSION < v"1.7"
@test occursin("\nk_7(\n x::Union{Nothing, T} where T<:Integer\n) -> Union{Nothing, Integer}\n", str)
@test occursin("\nk_7(\n x::Union{Nothing, T} where T<:Integer,\n y::Integer\n) -> Union{Nothing, Integer}\n", str)
else
@test occursin("\nk_7(x::Union{Nothing, T} where T<:Integer) -> Union{Nothing, Integer}\n", str)
@test occursin("\nk_7(\n x::Union{Nothing, T} where T<:Integer\n) -> Union{Nothing, T} where T<:Integer\n", str)
@test occursin("\nk_7(\n x::Union{Nothing, T} where T<:Integer,\n y::Integer\n) -> Union{Nothing, T} where T<:Integer\n", str)
end
@test occursin("\nk_7(x::Union{Nothing, T} where T<:Integer, y::Integer) -> Union{Nothing, T} where T<:Integer\n", str)
@test occursin("\n```\n", str)

doc.data = Dict(
Expand Down