Skip to content

Commit 3e32694

Browse files
committed
simplify the linebreaking code
1 parent 0ba301f commit 3e32694

File tree

2 files changed

+76
-121
lines changed

2 files changed

+76
-121
lines changed

src/utilities.jl

Lines changed: 70 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,45 @@ function parsedocs(mod::Module)
174174
end
175175
end
176176

177+
"""
178+
$(:SIGNATURES)
179+
180+
Decides whether a length of method is too big to be visually appealing.
181+
"""
182+
method_length_over_limit(len::Int) = len > 60
183+
184+
function printmethod_format(buffer::IOBuffer, binding::String, args::Vector{String}, kws::Vector{String}; return_type = "")
185+
186+
sep_delim = " "
187+
paren_delim = ""
188+
indent = ""
189+
190+
if method_length_over_limit(
191+
length(binding) +
192+
1 +
193+
sum(length.(args)) +
194+
sum(length.(kws)) +
195+
2*max(0, length(args)-1) +
196+
2*length(kws) +
197+
1 +
198+
length(return_type))
199+
200+
sep_delim = "\n"
201+
paren_delim = "\n"
202+
indent = " "
203+
end
204+
205+
print(buffer, binding)
206+
print(buffer, "($paren_delim")
207+
join(buffer, Ref(indent).*args, ",$sep_delim")
208+
if !isempty(kws)
209+
print(buffer, ";$sep_delim")
210+
join(buffer, Ref(indent).*kws, ",$sep_delim")
211+
end
212+
print(buffer, "$paren_delim)")
213+
print(buffer, return_type)
214+
return buffer
215+
end
177216

178217
"""
179218
$(:SIGNATURES)
@@ -193,27 +232,10 @@ f(x; a = 1, b...) = x
193232
sig = printmethod(Docs.Binding(Main, :f), f, first(methods(f)))
194233
```
195234
"""
196-
function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Method)
197-
# TODO: print qualified?
198-
print(buffer, binding.var)
199-
print(buffer, "(")
200-
local args = arguments(method)
201-
local kws = keywords(func, method)
202-
203-
#=
204-
Calculate how long the string of the args and kwargs are. If too long,
205-
break signature up into a nicely formatted multiline method signature.
206-
=#
207-
nl_delim, nl = get_format_delimiters(args, kws; delim=" ", break_point=40)
208-
209-
join(buffer, args, ", $nl_delim")
210-
if !isempty(kws)
211-
print(buffer, "; $nl_delim")
212-
join(buffer, kws, ", $nl_delim")
213-
end
214-
print(buffer, "$nl)")
215-
return buffer
216-
end
235+
printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Method) =
236+
printmethod_format(buffer, string(binding.var),
237+
string.(arguments(method)),
238+
string.(keywords(func, method)))
217239

218240
"""
219241
$(:SIGNATURES)
@@ -281,19 +303,16 @@ sig = printmethod(Docs.Binding(Main, :f), f, first(methods(f)))
281303
"""
282304
function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Method, typesig)
283305
# TODO: print qualified?
284-
print(buffer, binding.var)
285-
print(buffer, "(")
286-
local args = arguments(method)
287-
local kws = keywords(func, method)
288-
local where_syntax = []
306+
local args = string.(arguments(method))
307+
local kws = string.(keywords(func, method))
289308

290309
# find inner tuple type
291-
function f(t)
310+
function find_inner_tuple_type(t)
292311
# t is always either a UnionAll which represents a generic type or a Tuple where each parameter is the argument
293312
if t isa DataType && t <: Tuple
294313
t
295314
elseif t isa UnionAll
296-
f(t.body)
315+
find_inner_tuple_type(t.body)
297316
else
298317
error("Expected `typeof($t)` to be `Tuple` or `UnionAll` but found `$typeof(t)`")
299318
end
@@ -317,63 +336,35 @@ function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Meth
317336
typ
318337
end
319338

320-
function get_type_at_i(typesig, i)
321-
if typesig isa UnionAll
322-
# e.g. Tuple{Vector{T}} where T<:Number
323-
# or Tuple{String, T, T} where T<:Number
324-
# or Tuple{Type{T}, String, Union{Nothing, Function}} where T<:Number
325-
t = [x for x in f(typesig).types]
326-
[get_typesig(x, x) for x in t][i]
327-
else
328-
# e.g. Tuple{Vector{Int}}
329-
typesig.types[i]
330-
end
331-
end
332-
333-
#=
334-
Calculate how long the string of the args and kwargs are. If too long,
335-
break signature up into a nicely formatted multiline method signature.
336-
=#
337-
nl_delim, nl = get_format_delimiters(
338-
args,
339-
kws;
340-
type_info = join([string(get_type_at_i(typesig, i)) for i in eachindex(args)]),
341-
delim=" ",
342-
break_point=40
343-
)
344-
345-
for (i, sym) in enumerate(args)
346-
t = get_type_at_i(typesig, i)
347-
339+
# if `typesig` is an UnionAll, it may be
340+
# e.g. Tuple{Vector{T}} where T<:Number
341+
# or Tuple{String, T, T} where T<:Number
342+
# or Tuple{Type{T}, String, Union{Nothing, Function}} where T<:Number
343+
# in the other case, it's usually something like Tuple{Vector{Int}}.
344+
argtypes = typesig isa UnionAll ?
345+
[get_typesig(t, t) for t in find_inner_tuple_type(typesig).types] :
346+
collect(typesig.types)
347+
348+
args = map(args, argtypes) do arg,t
349+
type = ""
350+
suffix = ""
348351
if isvarargtype(t)
349-
elt = vararg_eltype(t)
350-
if elt === Any
351-
print(buffer, "$nl_delim$sym...")
352-
else
353-
print(buffer, "$nl_delim$sym::$elt...")
354-
end
355-
elseif t === Any
356-
print(buffer, "$nl_delim$sym")
357-
else
358-
print(buffer, "$nl_delim$sym::$t")
352+
t = vararg_eltype(t)
353+
suffix = "..."
359354
end
360-
361-
if i != length(args)
362-
print(buffer, ", ")
355+
if t!==Any
356+
type = "::$t"
363357
end
364-
end
365358

366-
if !isempty(kws)
367-
print(buffer, "; $nl_delim")
368-
join(buffer, kws, ", $nl_delim")
359+
string(arg)*type*suffix
369360
end
370-
print(buffer, "$nl)")
361+
371362
rt = Base.return_types(func, typesig)
372-
if length(rt) >= 1 && rt[1] !== Nothing && rt[1] !== Union{}
373-
formatted_rt = format_return_type_string(rt[1])
374-
print(buffer, " -> $formatted_rt")
375-
end
376-
buffer
363+
364+
return printmethod_format(buffer, string(binding.var), args, string.(kws);
365+
return_type =
366+
length(rt) >= 1 && rt[1] !== Nothing && rt[1] !== Union{} ?
367+
" -> $(rt[1])" : "")
377368
end
378369

379370
printmethod(b, f, m) = String(take!(printmethod(IOBuffer(), b, f, m)))
@@ -536,39 +527,3 @@ if !isdefined(Base, :ismutabletype)
536527
return isa(t, DataType) && t.mutable
537528
end
538529
end
539-
540-
"""
541-
$(:SIGNATURES)
542-
543-
Return two strings used to format method signatures by breaking long signatures
544-
into multiline signatures. If the line width of the `args` and `kws` of a method
545-
is longer than `break_point`, then return a new line joined with `delim` and a
546-
new line character. Otherwise, return an empty string, so that the formatting is
547-
unaffected.
548-
"""
549-
function get_format_delimiters(args, kws; delim=" ", break_point=40, type_info = "")
550-
estimated_line_width = length(join(string.(args))) +
551-
length(join(string.(kws))) + length(type_info)
552-
553-
nl_delim = estimated_line_width > break_point ? "\n$delim" : ""
554-
nl = estimated_line_width > break_point ? "\n" : ""
555-
556-
return nl_delim, nl
557-
end
558-
559-
"""
560-
$(:SIGNATURES)
561-
562-
Format the return type to look prettier.
563-
"""
564-
function format_return_type_string(rt; delim = " ", break_point=40)
565-
if startswith(string(rt), "Tuple{") && length(string(rt)) > break_point
566-
string(
567-
"Tuple{\n$delim",
568-
join([string(x) for x in rt.types],",\n$delim"),
569-
"\n}",
570-
)
571-
else #TODO Unions{...} look ugly, but represent one type, so maybe should be on one line
572-
string(rt)
573-
end
574-
end

test/tests.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,9 @@ end
190190
f = str -> replace(str, " " => "")
191191
str = f(str)
192192
if Sys.iswindows()
193-
@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)
193+
@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)
194194
else
195-
@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)
195+
@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)
196196
end
197197
@test occursin("\n```\n", str)
198198

@@ -307,7 +307,7 @@ end
307307
@test occursin("\n```julia\n", str)
308308
if VERSION > v"1.3.0"
309309
@test occursin("\nk_5(::Type{T<:Number}, x::String) -> String\n", str)
310-
@test occursin("\nk_5(\n ::Type{T<:Number}, \n x::String, \n func::Union{Nothing, Function}\n) -> String\n", str)
310+
@test occursin("\nk_5(\n ::Type{T<:Number},\n x::String,\n func::Union{Nothing, Function}\n) -> String\n", str)
311311
@test occursin("\n```\n", str)
312312
else
313313
# TODO: remove this test when julia 1.0.0 support is dropped.
@@ -343,11 +343,11 @@ end
343343
str = String(take!(buf))
344344
@test occursin("\n```julia\n", str)
345345
if VERSION > v"1.7" || VERSION < v"1.1"
346-
@test occursin("\nk_7(x::Union{Nothing, T} where T<:Integer) -> Union{Nothing, T} where T<:Integer\n", str)
346+
@test occursin("\nk_7(\n x::Union{Nothing, T} where T<:Integer\n) -> Union{Nothing, T} where T<:Integer\n", str)
347347
else
348-
@test occursin("\nk_7(x::Union{Nothing, T} where T<:Integer) -> Union{Nothing, Integer}\n", str)
348+
@test occursin("\nk_7(\n x::Union{Nothing, T} where T<:Integer\n) -> Union{Nothing, Integer}\n", str)
349349
end
350-
@test occursin("\nk_7(\n x::Union{Nothing, T} where T<:Integer, \n y::Integer\n) -> Union{Nothing, T} where T<:Integer\n", str)
350+
@test occursin("\nk_7(\n x::Union{Nothing, T} where T<:Integer,\n y::Integer\n) -> Union{Nothing, T} where T<:Integer\n", str)
351351
@test occursin("\n```\n", str)
352352

353353
doc.data = Dict(

0 commit comments

Comments
 (0)