JuliaDocs / DocStringExtensions.jl

Extensions for Julia's docsystem.
https://DocStringExtensions.juliadocs.org/latest
Other
116 stars 30 forks source link

Default argument value in function documentation #107

Open ShuhuaGao opened 3 years ago

ShuhuaGao commented 3 years ago

Consider the following documentation for a function f1 in a module CGP

"""
$(TYPEDSIGNATURES)
"""
function f1(a::Int, b::Int=0)
    return a + b
end

The generated documentation is Snipaste_2021-02-05_14-53-00

Two signatures are produced, but information of the default value is lost. I have to document the default value of b manually.

Is it possible to produce a single signature that contains the default value? Something like follows

f1(a::Int64, b::Int64=0) -> Int64
MichaelHatherly commented 3 years ago

I recall trying to add this a long time ago, works well for the small cases such as numbers and the like, but as soon as you have a default value being some kind of complex nested object the info becomes more of a hindrance than a help. Would need some kind of display limiting if we tried this again.

ShuhuaGao commented 3 years ago

Would need some kind of display limiting if we tried this again.

It makes sense since most default values tend to be constants of some primitive types, e.g., numbers and string. For other more complicated cases, a placeholder may be used, like #i for the i-th default value. The author is required to document these placeholders manually.

f(a::Int64, b::ComplexType=#1, c::ComplexType=#2)

The same issue exists in keyword arguments. Consider the following function

"""
$(TYPEDSIGNATURES)
"""
function f_default(a::Int=1, b::Int=2; c::String="Hello", d::Float64=3.14)
end

which generates Snipaste_2021-02-05_16-42-02 Also, it is not obvious to see from the above signatures whether the signature f_default(a::Int64; c) is legal. Of course, listing all possible methods may encounter the combinational explosion problem. Thus, showing default values of selected types or a placeholder otherwise may be a solution.

andyDoucette commented 3 years ago

+1 on this. Having the defaults in the signatures is very important. I think 98% of the time, the defaults are simple things like integers, short strings, bools, etc. Converting the default to a string and having a maximum length with a "..." at the end if it exceeds that should cover the vast majority of the cases, I'd think. I'd do it myself but I have no idea how to even get the default. :) Cudos to making this package.

MichaelHatherly commented 3 years ago

It's possible to retrieve default argument values, it's just probably going to require digging into the output of code_lowered since the documented Expr itself is never saved. You'd want to start by looking at how the current TYPEDSIGNATURES does it's thing and then use a code_lowered to access the IR and extract values from there. This is unlikely to be a particularly easy thing to do robustly.

JanWeidnerPTW commented 1 year ago

since the documented Expr itself is never saved.

Is there some technical obstacle with saving the documented expression? The expression seems to be very valuable information.

MichaelHatherly commented 1 year ago

https://github.com/JuliaDocs/DocStringExtensions.jl/pull/133 is intended to add support for this kind of thing. I just need some spare time to actually finish it off though.

JanWeidnerPTW commented 1 year ago

Awesome! BTW let me take this opportunity to thank you for all the great work you did on the julia documentation system @MichaelHatherly

MichaelHatherly commented 1 year ago

Thanks @JanWeidnerPTW!

MichaelHatherly commented 1 year ago

I'll probably merge #133 sometime thing week, after which it's just a matter of using the feature to implement a fix for this one.

JamesWrigley commented 2 months ago

Could you elaborate a bit on that? It's not clear to me how to get the expression into an Abbreviation.

MichaelHatherly commented 2 months ago

Could you elaborate a bit on that? It's not clear to me how to get the expression into an Abbreviation.

Define an interpolation method that takes an Abbreviation object and adds the interpolation second argument (which is the expression that is being documented) to a new instance of the Abbreviation object and returns that. E.g.

julia> using DocStringExtensions

julia> struct CapturedExpr <: DocStringExtensions.Abbreviation
           expr::Union{Nothing,Expr}
       end

julia> DocStringExtensions.interpolation(ce::CapturedExpr, ex) = CapturedExpr(ex)

julia> const CAPTURED_EXPR = CapturedExpr(nothing)
CapturedExpr(nothing)

julia> function DocStringExtensions.format(ce::CapturedExpr, buf, doc)
           println(buf, "```")
           Meta.show_sexpr(buf, ce.expr)
           println(buf, "\n```")
       end

julia> """
       This is the captured expression:

       $(CAPTURED_EXPR)
       """
       f(x) = x + 1
f

help?> f
search: f fd for fma fld fld1 fill fdio frexp foldr foldl flush floor float first fill! fetch fldmod filter falses finally foreach fldmod1 findmin findmax findall

  This is the captured expression:

  (:(=), (:call, :f, :x), (:block,
      :(#= REPL[7]:6 =#),
      (:call, :+, :x, 1)
    ))