Docstring for `Method`

Hey everyone,

I’m trying to do something that I thought would be easy but is actually rather tricky.
I simply want to get the docstring of a Method.

For example:

"""
my f
"""
f(x::Int) = 2x


"""
with strings
"""
f(x::String) = print(x)

"""
and keyword args
"""
f(; y=1) = print(y)

methods

gives:

# 3 methods for generic function "f":
[1] f(; y) in Main at /Users/federicoclaudi/Documents/Github/Term.jl/workspace.jl:16
[2] f(x::Int64) in Main at /Users/federicoclaudi/Documents/Github/Term.jl/workspace.jl:5
[3] f(x::String) in Main at /Users/federicoclaudi/Documents/Github/Term.jl/workspace.jl:11

if, say, I wanted to get the docstring of the second method, what should I do?
I know about Docs.Binding and Docs.meta to get multidocs like it’s done, for example, in the REPL but I was hoping there was a more direct way to get at this.
Specifically, when the methods are constructors for a DataType there might be multiple methods that differ only in their keyword arguments and the approach above doesn’t distinguish them since they share the same signature.

Thank you,
Federico

Is this what you are asking for?

help?> f(::String)
  with strings

julia> @doc f(::String)
  with strings
1 Like

Hey thanks for getting back to me so quickly.

I’m afraid not. I need the docstring for a specific method, not for all of them. There’s way to use the signature, but it still doesn’t always cover all cases. Isn’t there a way, given an object of type Method to get the actual docstring that belongs to ?

I don’t think that’s possible, you can’t have two methods with the same type signature that only differ by keyword arguments, because the keyword arguments don’t count for dispatch.

That;s fair, I think you’re right.

This is the solution I landed on, it seems to get the job done, leaving it here in case folks find it useful:

using Base.Docs: meta, Binding, doc
import Markdown

"""
    get_methods_with_docstrings(obj::Union{Union, DataType, Function})

Get the docstring for each method for an object (function/datatype).
"""
function get_methods_with_docstrings(obj::Union{Union, DataType, Function})::Tuple{Vector, Vector}
    # get the parent module and the methods list for the object
    mod = parentmodule(obj)
    mm = methods(obj)

    # get the module's multidoc
    binding = Binding(mod, Symbol(obj))    
    dict = meta(mod)
    multidoc = dict[binding]
    
    # for each module, attempt to get the docstring as markdown
    docstrings = []
    for m in mm
        # cleanup signature
        sig = length(m.sig.types) == 1 ? Tuple{} : Tuple{m.sig.types[2:end]...}
        
        haskey(multidoc.docs, sig) || begin
            push!(docstrings, nothing)
        end
        docs = multidoc.docs[sig].text[1] |> Markdown.parse
        push!(docstrings, docs)
    end

    return mm, docstrings
end