diff --git a/src/DocStringExtensions.jl b/src/DocStringExtensions.jl index d0ca089..d9bbe6e 100644 --- a/src/DocStringExtensions.jl +++ b/src/DocStringExtensions.jl @@ -76,7 +76,7 @@ module DocStringExtensions # Exports. export @template, FIELDS, TYPEDFIELDS, EXPORTS, METHODLIST, IMPORTS -export SIGNATURES, TYPEDSIGNATURES, TYPEDEF, DOCSTRING, FUNCTIONNAME +export SIGNATURES, TYPEDSIGNATURES, TYPEDSIGNATURESNORETURN, TYPEDEF, DOCSTRING, FUNCTIONNAME export README, LICENSE # export interpolation diff --git a/src/abbreviations.jl b/src/abbreviations.jl index a40a9de..1e0fd27 100644 --- a/src/abbreviations.jl +++ b/src/abbreviations.jl @@ -336,11 +336,13 @@ end # """ -The singleton type for [`TYPEDSIGNATURES`](@ref) abbreviations. +The type for [`TYPEDSIGNATURES`](@ref) abbreviations. $(:FIELDS) """ -struct TypedMethodSignatures <: Abbreviation end +struct TypedMethodSignatures <: Abbreviation + return_types::Bool +end """ An [`Abbreviation`](@ref) for including a simplified representation of all the method @@ -358,9 +360,17 @@ f(x::Int, y::Int; a, b...) ``` ```` """ -const TYPEDSIGNATURES = TypedMethodSignatures() +const TYPEDSIGNATURES = TypedMethodSignatures(true) + +""" +An alternative to [`TYPEDSIGNATURES`](@ref) that omits the return type. + +The return type shown by [`TYPEDSIGNATURES`](@ref) is often `-> Any`, which is usually not +correct. It is nicer to then just omit the type completely. +""" +const TYPEDSIGNATURESNORETURN = TypedMethodSignatures(false) -function format(::TypedMethodSignatures, buf, doc) +function format(tms::TypedMethodSignatures, buf, doc) local binding = doc.data[:binding] local typesig = doc.data[:typesig] local modname = doc.data[:module] @@ -395,7 +405,8 @@ function format(::TypedMethodSignatures, buf, doc) else t = tuples[findfirst(f, tuples)] end - printmethod(buf, binding, func, method, t) + printmethod(buf, binding, func, method, t; + print_return_types=tms.return_types) println(buf) end println(buf, "\n```\n") diff --git a/src/utilities.jl b/src/utilities.jl index e04d459..36f9c9a 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -338,7 +338,7 @@ f(x::Int; a = 1, b...) = x sig = printmethod(Docs.Binding(Main, :f), f, first(methods(f))) ``` """ -function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Method, typesig) +function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Method, typesig; print_return_types=true) # TODO: print qualified? local args = string.(arguments(method)) local kws = string.(keywords(func, method)) @@ -397,11 +397,24 @@ function printmethod(buffer::IOBuffer, binding::Docs.Binding, func, method::Meth end rt = Base.return_types(func, typesig) + return_type_string = if ( + print_return_types && + length(rt) >= 1 && + rt[1] !== Nothing && + rt[1] !== Union{} + ) + " -> $(rt[1])" + else + "" + end - return printmethod_format(buffer, string(binding.var), args, string.(kws); - return_type = - length(rt) >= 1 && rt[1] !== Nothing && rt[1] !== Union{} ? - " -> $(rt[1])" : "") + return printmethod_format( + buffer, + string(binding.var), + args, + string.(kws); + return_type=return_type_string + ) end printmethod(b, f, m) = String(take!(printmethod(IOBuffer(), b, f, m))) diff --git a/test/tests.jl b/test/tests.jl index 913fa9f..0c29eb1 100644 --- a/test/tests.jl +++ b/test/tests.jl @@ -455,6 +455,81 @@ end end + @testset "method signatures with types (no return type)" begin + doc.data = Dict( + :binding => Docs.Binding(M, :h_1), + :typesig => Tuple{M.A}, + :module => M, + ) + DSE.format(DSE.TYPEDSIGNATURESNORETURN, buf, doc) + str = String(take!(buf)) + @test occursin("\n```julia\n", str) + f = str -> replace(str, " " => "") + str = f(str) + if Sys.iswindows() && VERSION < v"1.8" + @test occursin(f("h_1(x::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)"), str) + end + @test !occursin("->", str) + @test occursin("\n```\n", str) + + + doc.data = Dict( + :binding => Docs.Binding(M, :g_2), + :typesig => Tuple{String}, + :module => M, + ) + DSE.format(TYPEDSIGNATURESNORETURN, buf, doc) + str = String(take!(buf)) + @test occursin("\n```julia\n", str) + @test occursin("\ng_2(x::String)", str) + @test occursin("\n```\n", str) + + doc.data = Dict( + :binding => Docs.Binding(M, :h), + :typesig => Tuple{Int, Int, Int}, + :module => M, + ) + DSE.format(DSE.TYPEDSIGNATURESNORETURN, buf, doc) + str = String(take!(buf)) + @test occursin("\n```julia\n", str) + if typeof(1) === Int64 + @test occursin("\nh(x::Int64, y::Int64, z::Int64; kwargs...)\n", str) + else + @test occursin("\nh(x::Int32, y::Int32, z::Int32; kwargs...)\n", str) + end + @test occursin("\n```\n", str) + + doc.data = Dict( + :binding => Docs.Binding(M, :h), + :typesig => Tuple{Int}, + :module => M, + ) + DSE.format(DSE.TYPEDSIGNATURESNORETURN, buf, doc) + str = String(take!(buf)) + @test occursin("\n```julia\n", str) + if typeof(1) === Int64 + # On 1.10+, automatically generated methods have keywords in the metadata, + # hence the display difference between Julia versions. + if VERSION >= v"1.10" + @test occursin("\nh(x::Int64; ...)\n", str) + else + @test occursin("\nh(x::Int64)\n", str) + end + else + # On 1.10+, automatically generated methods have keywords in the metadata, + # hence the display difference between Julia versions. + if VERSION >= v"1.10" + @test occursin("\nh(x::Int32; ...)\n", str) + else + @test occursin("\nh(x::Int32)\n", str) + end + end + @test occursin("\n```\n", str) + + end + @testset "function names" begin doc.data = Dict( :binding => Docs.Binding(M, :f),