Skip to content

Commit 6f569c7

Browse files
authored
make @doc x work without REPL loaded (#54499)
fix #52141, fix #52986
1 parent 768921e commit 6f569c7

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

base/docs/Docs.jl

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,49 @@ isquotedmacrocall(@nospecialize x) =
563563
isbasicdoc(@nospecialize x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol})
564564
is_signature(@nospecialize x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where)
565565

566+
function _doc(binding::Binding, sig::Type = Union{})
567+
if defined(binding)
568+
result = getdoc(resolve(binding), sig)
569+
result === nothing || return result
570+
end
571+
# Lookup first match for `binding` and `sig` in all modules of the docsystem.
572+
for mod in modules
573+
dict = meta(mod; autoinit=false)
574+
isnothing(dict) && continue
575+
if haskey(dict, binding)
576+
multidoc = dict[binding]
577+
for msig in multidoc.order
578+
sig <: msig && return multidoc.docs[msig]
579+
end
580+
end
581+
end
582+
return nothing
583+
end
584+
585+
# Some additional convenience `doc` methods that take objects rather than `Binding`s.
586+
_doc(obj::UnionAll) = _doc(Base.unwrap_unionall(obj))
587+
_doc(object, sig::Type = Union{}) = _doc(aliasof(object, typeof(object)), sig)
588+
_doc(object, sig...) = _doc(object, Tuple{sig...})
589+
590+
function simple_lookup_doc(ex)
591+
if isa(ex, Expr) && ex.head !== :(.) && Base.isoperator(ex.head)
592+
# handle syntactic operators, e.g. +=, ::, .=
593+
ex = ex.head
594+
end
595+
if haskey(keywords, ex)
596+
return keywords[ex]
597+
elseif !isa(ex, Expr) && !isa(ex, Symbol)
598+
return :($(_doc)($(typeof)($(esc(ex)))))
599+
end
600+
binding = esc(bindingexpr(namify(ex)))
601+
if isexpr(ex, :call) || isexpr(ex, :macrocall) || isexpr(ex, :where)
602+
sig = esc(signature(ex))
603+
:($(_doc)($binding, $sig))
604+
else
605+
:($(_doc)($binding))
606+
end
607+
end
608+
566609
function docm(source::LineNumberNode, mod::Module, ex)
567610
@nospecialize ex
568611
if isexpr(ex, :->) && length(ex.args) > 1
@@ -571,6 +614,8 @@ function docm(source::LineNumberNode, mod::Module, ex)
571614
# TODO: this is a shim to continue to allow `@doc` for looking up docstrings
572615
REPL = Base.REPL_MODULE_REF[]
573616
return invokelatest(REPL.lookup_doc, ex)
617+
else
618+
return simple_lookup_doc(ex)
574619
end
575620
return nothing
576621
end

test/docs.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

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

5+
# check that @doc can work before REPL is loaded
6+
@test !startswith(read(`$(Base.julia_cmd()) -E '@doc sin'`, String), "nothing")
7+
58
using Markdown
69
using REPL
710

0 commit comments

Comments
 (0)