Skip to content

Commit

Permalink
make @doc x work without REPL loaded (#54499)
Browse files Browse the repository at this point in the history
fix #52141, fix #52986
  • Loading branch information
JeffBezanson authored May 27, 2024
1 parent 768921e commit 6f569c7
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
45 changes: 45 additions & 0 deletions base/docs/Docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,49 @@ isquotedmacrocall(@nospecialize x) =
isbasicdoc(@nospecialize x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol})
is_signature(@nospecialize x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where)

function _doc(binding::Binding, sig::Type = Union{})
if defined(binding)
result = getdoc(resolve(binding), sig)
result === nothing || return result
end
# Lookup first match for `binding` and `sig` in all modules of the docsystem.
for mod in modules
dict = meta(mod; autoinit=false)
isnothing(dict) && continue
if haskey(dict, binding)
multidoc = dict[binding]
for msig in multidoc.order
sig <: msig && return multidoc.docs[msig]
end
end
end
return nothing
end

# Some additional convenience `doc` methods that take objects rather than `Binding`s.
_doc(obj::UnionAll) = _doc(Base.unwrap_unionall(obj))
_doc(object, sig::Type = Union{}) = _doc(aliasof(object, typeof(object)), sig)
_doc(object, sig...) = _doc(object, Tuple{sig...})

function simple_lookup_doc(ex)
if isa(ex, Expr) && ex.head !== :(.) && Base.isoperator(ex.head)
# handle syntactic operators, e.g. +=, ::, .=
ex = ex.head
end
if haskey(keywords, ex)
return keywords[ex]
elseif !isa(ex, Expr) && !isa(ex, Symbol)
return :($(_doc)($(typeof)($(esc(ex)))))
end
binding = esc(bindingexpr(namify(ex)))
if isexpr(ex, :call) || isexpr(ex, :macrocall) || isexpr(ex, :where)
sig = esc(signature(ex))
:($(_doc)($binding, $sig))
else
:($(_doc)($binding))
end
end

function docm(source::LineNumberNode, mod::Module, ex)
@nospecialize ex
if isexpr(ex, :->) && length(ex.args) > 1
Expand All @@ -571,6 +614,8 @@ function docm(source::LineNumberNode, mod::Module, ex)
# TODO: this is a shim to continue to allow `@doc` for looking up docstrings
REPL = Base.REPL_MODULE_REF[]
return invokelatest(REPL.lookup_doc, ex)
else
return simple_lookup_doc(ex)
end
return nothing
end
Expand Down
3 changes: 3 additions & 0 deletions test/docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import Base.Docs: meta, @var, DocStr, parsedoc

# check that @doc can work before REPL is loaded
@test !startswith(read(`$(Base.julia_cmd()) -E '@doc sin'`, String), "nothing")

using Markdown
using REPL

Expand Down

0 comments on commit 6f569c7

Please sign in to comment.