Skip to content

Commit

Permalink
Fix attaching docstrings to where call syntax (JuliaLang#33446)
Browse files Browse the repository at this point in the history
* Allow documenting where-expressions

I.e. docstrings can now also be attached to expressions that look as
follows:

"""
"""
foo(::T) where T

Note that it was already fine to attach docstrings to such methods when
the docstring was attached to the function body:

"""
"""
function foo(::T) where T
  ...
end

* Better fix

* Add tests
  • Loading branch information
mortenpi authored and fredrikekre committed Oct 9, 2019
1 parent b75fce2 commit 8e155c7
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
19 changes: 16 additions & 3 deletions base/docs/Docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -366,13 +366,15 @@ end

function calldoc(__source__, __module__, str, def::Expr)
@nospecialize str
args = def.args[2:end]
args = callargs(def)
if isempty(args) || all(validcall, args)
objectdoc(__source__, __module__, str, nothing, def, signature(def))
else
docerror(def)
end
end
callargs(ex::Expr) = isexpr(ex, :where) ? callargs(ex.args[1]) :
isexpr(ex, :call) ? ex.args[2:end] : error("Invalid expression to callargs: $ex")
validcall(x) = isa(x, Symbol) || isexpr(x, (:(::), :..., :kw, :parameters))

function moduledoc(__source__, __module__, meta, def, def′::Expr)
Expand Down Expand Up @@ -502,6 +504,12 @@ function docm(source::LineNumberNode, mod::Module, ex)
end
end

# iscallexpr checks if an expression is a :call expression. The call expression may be
# also part of a :where expression, so it unwraps the :where layers until it reaches the
# "actual" expression
iscallexpr(ex::Expr) = isexpr(ex, :where) ? iscallexpr(ex.args[1]) : isexpr(ex, :call)
iscallexpr(ex) = false

function docm(source::LineNumberNode, mod::Module, meta, ex, define::Bool = true)
@nospecialize meta ex
# Some documented expressions may be decorated with macro calls which obscure the actual
Expand Down Expand Up @@ -530,9 +538,14 @@ function docm(source::LineNumberNode, mod::Module, meta, ex, define::Bool = true
# function f end
# f(...)
#
isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(source, mod, meta, def, x, signature(x)) :
# Including if the "call" expression is wrapped in "where" expression(s) (#32960), i.e.
#
# f(::T) where T
# f(::T, ::U) where T where U
#
isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(source, mod, meta, def, x, signature(x)) :
isexpr(x, [:function, :macro]) && !isexpr(x.args[1], :call) ? objectdoc(source, mod, meta, def, x) :
isexpr(x, :call) ? calldoc(source, mod, meta, x) :
iscallexpr(x) ? calldoc(source, mod, meta, x) :

# Type definitions.
#
Expand Down
12 changes: 12 additions & 0 deletions test/docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ t(::Int, ::Any)
"t-3"
t{S <: Integer}(::S)

# Docstrings to parametric methods after definition using where syntax (#32960):
tw(x::T) where T = nothing
tw(x::T, y::U) where {T, U <: Integer} = nothing
tw(x::T, y::U, z::V) where T where U <: Integer where V <: AbstractFloat = nothing

"tw-1"
tw(x::T) where T
"tw-2"
tw(x::T, y::U) where {T, U <: Integer}
"tw-3"
tw(x::T, y::U, z::V) where T where U <: Integer where V <: AbstractFloat

"FieldDocs"
mutable struct FieldDocs
"one"
Expand Down

0 comments on commit 8e155c7

Please sign in to comment.