• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37527

pending completion
#37527

push

local

web-flow
make `IRShow.method_name` inferrable (#49607)

18 of 18 new or added lines in 3 files covered. (100.0%)

68710 of 81829 relevant lines covered (83.97%)

33068903.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.09
/base/docs/Docs.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    Docs
5

6
The `Docs` module provides the `@doc` macro which can be used to set and retrieve
7
documentation metadata for Julia objects.
8

9
Please see the manual section on [documentation](@ref man-documentation) for more
10
information.
11
"""
12
module Docs
13

14
@nospecialize # don't specialize on any arguments of the methods declared herein
15

16
"""
17
# Documentation
18

19
Functions, methods and types can be documented by placing a string before the definition:
20

21
    \"\"\"
22
    # The Foo Function
23
    `foo(x)`: Foo the living hell out of `x`.
24
    \"\"\"
25
    foo(x) = ...
26

27
The `@doc` macro can be used directly to both set and retrieve documentation / metadata.
28
The macro has special parsing so that the documented object may occur on the next line:
29

30
    @doc "blah"
31
    function foo() ...
32

33
By default, documentation is written as Markdown, but any object can be used as
34
the first argument.
35

36
## Documenting objects after they are defined
37
You can document an object after its definition by
38

39
    @doc "foo" function_to_doc
40
    @doc "bar" TypeToDoc
41

42
For macros, the syntax is `@doc "macro doc" :(Module.@macro)` or `@doc "macro doc"
43
:(string_macro"")` for string macros. Without the quote `:()` the expansion of the macro
44
will be documented.
45

46
## Retrieving Documentation
47
You can retrieve docs for functions, macros and other objects as follows:
48

49
    @doc foo
50
    @doc @time
51
    @doc md""
52

53
## Functions & Methods
54
Placing documentation before a method definition (e.g. `function foo() ...` or `foo() = ...`)
55
will cause that specific method to be documented, as opposed to the whole function. Method
56
docs are concatenated together in the order they were defined to provide docs for the
57
function.
58
"""
59
:(Core.@doc)
60

61
include("bindings.jl")
62

63
import .Base.Meta: quot, isexpr
64
import .Base: Callable, with_output_color
65
using .Base: RefValue, mapany
66
import ..CoreDocs: lazy_iterpolate
67

68
export doc
69

70
# Basic API / Storage
71

72
const modules = Module[]
73
const META    = gensym(:meta)
74
const METAType = IdDict{Any,Any}
75

76
function meta(m::Module; autoinit::Bool=true)
1,470✔
77
    if !isdefined(m, META) || getfield(m, META) === nothing
1,470✔
78
        autoinit ? initmeta(m) : return nothing
×
79
    end
80
    return getfield(m, META)::METAType
735✔
81
end
82

83
function initmeta(m::Module)
462✔
84
    if !isdefined(m, META) || getfield(m, META) === nothing
885✔
85
        Core.eval(m, :($META = $(METAType())))
39✔
86
        push!(modules, m)
39✔
87
    end
88
    nothing
462✔
89
end
90

91
function signature!(tv::Vector{Any}, expr::Expr)
775✔
92
    is_macrocall = isexpr(expr, :macrocall)
775✔
93
    if is_macrocall || isexpr(expr, :call)
1,550✔
94
        sig = :(Union{Tuple{}})
365✔
95
        first_arg = is_macrocall ? 3 : 2 # skip function arguments
365✔
96
        for arg in expr.args[first_arg:end]
398✔
97
            isexpr(arg, :parameters) && continue
885✔
98
            if isexpr(arg, :kw) # optional arg
791✔
99
                push!(sig.args, :(Tuple{$((sig.args[end]::Expr).args[2:end]...)}))
32✔
100
            end
101
            push!((sig.args[end]::Expr).args, argtype(arg))
629✔
102
        end
1,055✔
103
        if isexpr(expr.args[1], :curly) && isempty(tv)
724✔
104
            append!(tv, mapany(tvar, (expr.args[1]::Expr).args[2:end]))
×
105
        end
106
        for i = length(tv):-1:1
410✔
107
            push!(sig.args, :(Tuple{$((tv[i]::Expr).args[1])}))
74✔
108
        end
103✔
109
        for i = length(tv):-1:1
410✔
110
            sig = Expr(:where, sig, tv[i])
74✔
111
        end
103✔
112
        return sig
365✔
113
    elseif isexpr(expr, :where)
410✔
114
        append!(tv, mapany(tvar, expr.args[2:end]))
45✔
115
        return signature!(tv, expr.args[1])
45✔
116
    else
117
        return signature!(tv, expr.args[1])
365✔
118
    end
119
end
120
signature!(tv::Vector{Any}, @nospecialize(other)) = :(Union{})
×
121
signature(expr::Expr) = signature!([], expr)
365✔
122
signature(@nospecialize other) = signature!([], other)
×
123

124
function argtype(expr::Expr)
506✔
125
    isexpr(expr, :(::))  && return expr.args[end]
506✔
126
    isexpr(expr, :(...)) && return :(Vararg{$(argtype(expr.args[1]))})
93✔
127
    if isexpr(expr, :meta) && length(expr.args) == 2
38✔
128
        a1 = expr.args[1]
4✔
129
        if a1 === :nospecialize || a1 === :specialize
4✔
130
            return argtype(expr.args[2])
4✔
131
        end
132
    end
133
    return argtype(expr.args[1])
34✔
134
end
135
argtype(@nospecialize other) = :Any
×
136

137
tvar(x::Expr)   = x
×
138
tvar(s::Symbol) = :($s <: Any)
51✔
139

140
# Docsystem types.
141
# ================
142

143
"""
144
    Docs.DocStr
145

146
Stores the contents of a single docstring as well as related metadata.
147

148
Both the raw text, `.text`, and the parsed markdown, `.object`, are tracked by this type.
149
Parsing of the raw text is done lazily when a request is made to render the docstring,
150
which helps to reduce total precompiled image size.
151

152
The `.data` fields stores several values related to the docstring, such as: path,
153
linenumber, source code, and fielddocs.
154
"""
155
mutable struct DocStr
156
    text   :: Core.SimpleVector
462✔
157
    object :: Any
158
    data   :: Dict{Symbol, Any}
159
end
160

161
function docstr(binding::Binding, typesig = Union{})
×
162
    @nospecialize typesig
×
163
    for m in modules
×
164
        dict = meta(m; autoinit=false)
×
165
        isnothing(dict) && continue
×
166
        if haskey(dict, binding)
×
167
            docs = dict[binding].docs
×
168
            if haskey(docs, typesig)
×
169
                return docs[typesig]
×
170
            end
171
        end
172
    end
×
173
    error("could not find matching docstring for '$binding :: $typesig'.")
×
174
end
175
docstr(object, data = Dict{Symbol,Any}()) = _docstr(object, data)
462✔
176

177
_docstr(vec::Core.SimpleVector, data::Dict{Symbol,Any}) = DocStr(vec,            nothing, data)
461✔
178
_docstr(str::AbstractString,    data::Dict{Symbol,Any}) = DocStr(Core.svec(str), nothing, data)
1✔
179
_docstr(object,                 data::Dict{Symbol,Any}) = DocStr(Core.svec(),     object, data)
×
180

181
_docstr(doc::DocStr, data::Dict{Symbol,Any}) = (doc.data = merge(data, doc.data); doc)
×
182

183
macro ref(x)
184
    binding = bindingexpr(namify(x))
185
    typesig = signature(x)
186
    return esc(docexpr(__source__, __module__, binding, typesig))
187
end
188

189
docexpr(__source__, __module__, args...) = Expr(:call, docstr, args...)
462✔
190

191
"""
192
    MultiDoc
193

194
Stores a collection of docstrings for related objects, ie. a `Function`/`DataType` and
195
associated `Method` objects.
196

197
Each documented object in a `MultiDoc` is referred to by it's signature which is represented
198
by a `Union` of `Tuple` types. For example, the following `Method` definition
199

200
    f(x, y) = ...
201

202
is stored as `Tuple{Any, Any}` in the `MultiDoc` while
203

204
    f(x::T, y = ?) where {T} = ...
205

206
is stored as `Union{Tuple{T, Any}, Tuple{T}} where T`.
207

208
Note: The `Function`/`DataType` object's signature is always `Union{}`.
209
"""
210
mutable struct MultiDoc
211
    "Ordered (via definition order) vector of object signatures."
212
    order::Vector{Type}
213
    "Documentation for each object. Keys are signatures."
214
    docs::METAType
215

216
    MultiDoc() = new(Type[], METAType())
462✔
217
end
218

219
# Docstring registration.
220
# =======================
221

222
"""
223
    Docs.doc!(__module__, binding, str, sig)
224

225
Adds a new docstring `str` to the docsystem of `__module__` for `binding` and signature `sig`.
226
"""
227
function doc!(__module__::Module, b::Binding, str::DocStr, @nospecialize sig = Union{})
472✔
228
    # Module docstrings are in the module itself
229
    if defined(b)
472✔
230
        obj = resolve(b)
459✔
231
        if isa(obj, Module)
459✔
232
            __module__ = obj
12✔
233
        end
234
    end
235
    initmeta(__module__)
462✔
236
    m = get!(meta(__module__), b, MultiDoc())
528✔
237
    if haskey(m.docs, sig)
462✔
238
        # We allow for docstrings to be updated, but print a warning since it is possible
239
        # that over-writing a docstring *may* have been accidental.  The warning
240
        # is suppressed for symbols in Main (or current active module),
241
        # for interactive use (#23011).
242
        __module__ === Base.active_module() ||
×
243
            @warn "Replacing docs for `$b :: $sig` in module `$(__module__)`"
244
    else
245
        # The ordering of docstrings for each Binding is defined by the order in which they
246
        # are initially added. Replacing a specific docstring does not change it's ordering.
247
        push!(m.order, sig)
462✔
248
    end
249
    m.docs[sig] = str
462✔
250
    str.data[:binding] = b
462✔
251
    str.data[:typesig] = sig
462✔
252
    return b
462✔
253
end
254

255
# Docstring lookup.
256
# =================
257

258
"""
259
    getdoc(obj)
260
    getdoc(obj, sig)
261

262
Return a custom docstring object associated with the object `obj` and, optionally, the tuple
263
type signature `sig`. See `MultiDoc` docs for an explanation of the possible values of `sig`.
264

265
The returned object can either be a markdown object generated by `Markdown.parse` or some
266
other custom type used to display non-markdown formatted documentation.
267

268
A return value of `nothing` can be used to signify to the docsystem that no documentation
269
was found for `obj`, in which case the docsystem will fall back to searching for the
270
`Binding` associated with `obj` instead.
271
"""
272
function getdoc end
273

274
getdoc(@nospecialize(x), @nospecialize(sig)) = getdoc(x)
×
275
getdoc(@nospecialize(x)) = nothing
×
276

277
# Utilities.
278
# ==========
279

280
"""
281
`catdoc(xs...)`: Combine the documentation metadata `xs` into a single meta object.
282
"""
283
catdoc() = nothing
×
284
catdoc(xs...) = vcat(xs...)
×
285

286
const keywords = Dict{Symbol, DocStr}()
287

288
function unblock(@nospecialize ex)
×
289
    isexpr(ex, :block) || return ex
944✔
290
    exs = filter(ex -> !(isa(ex, LineNumberNode) || isexpr(ex, :line)), ex.args)
×
291
    length(exs) == 1 || return ex
×
292
    return unblock(exs[1])
×
293
end
294

295
uncurly(@nospecialize ex) = isexpr(ex, :curly) ? ex.args[1] : ex
×
296

297
namify(@nospecialize x) = astname(x, isexpr(x, :macro))::Union{Symbol,Expr,GlobalRef}
462✔
298

299
function astname(x::Expr, ismacro::Bool)
958✔
300
    head = x.head
958✔
301
    if head === :.
958✔
302
        ismacro ? macroname(x) : x
5✔
303
    elseif head === :call && isexpr(x.args[1], :(::))
1,312✔
304
        return astname((x.args[1]::Expr).args[end], ismacro)
×
305
    else
306
        n = isexpr(x, (:module, :struct)) ? 2 : 1
953✔
307
        astname(x.args[n], ismacro)
953✔
308
    end
309
end
310
astname(q::QuoteNode, ismacro::Bool) = astname(q.value, ismacro)
×
311
astname(s::Symbol, ismacro::Bool)    = ismacro ? macroname(s) : s
457✔
312
astname(@nospecialize(other), ismacro::Bool) = other
×
313

314
macroname(s::Symbol) = Symbol('@', s)
41✔
315
macroname(x::Expr)   = Expr(x.head, x.args[1], macroname(x.args[end].value))
×
316

317
isfield(@nospecialize x) = isexpr(x, :.) &&
×
318
    (isa(x.args[1], Symbol) || isfield(x.args[1])) &&
319
    (isa(x.args[2], QuoteNode) || isexpr(x.args[2], :quote))
320

321
# @doc expression builders.
322
# =========================
323

324
"""
325
    Docs.metadata(source, module, expr, ismodule)
326

327
Build a `Dict` expression containing metadata captured from the expression `expr`.
328

329
Fields that may be included in the returned `Dict`:
330

331
- `:path`:       Symbol representing the file where `expr` is defined.
332
- `:linenumber`: Linenumber where `expr` is defined.
333
- `:module`:     Module where the docstring is defined.
334
- `:fields`:     `Dict` of all field docs found in `expr`. Only for concrete types.
335
"""
336
function metadata(__source__, __module__, expr, ismodule)
462✔
337
    args = []
462✔
338
    # Filename and linenumber of the docstring.
339
    __file__ = isa(__source__.file, Symbol) ? String(__source__.file) : ""
462✔
340
    push!(args, Pair(:path, __file__))
462✔
341
    push!(args, Pair(:linenumber, __source__.line))
462✔
342
    # Module in which the docstring is defined.
343
    if ismodule # Module docs go inside the module with name `expr`
462✔
344
        push!(args, :($Pair(:module, $expr)))
10✔
345
    else
346
        push!(args, Pair(:module, __module__))
452✔
347
    end
348
    if isexpr(expr, :struct)
482✔
349
        # Field docs for concrete types.
350
        P = Pair{Symbol,Any}
×
351
        fields = P[]
54✔
352
        last_docstr = nothing
×
353
        for each in (expr.args[3]::Expr).args
54✔
354
            if isa(each, Symbol) || isexpr(each, :(::))
1,005✔
355
                # a field declaration
356
                if last_docstr !== nothing
183✔
357
                    push!(fields, P(namify(each::Union{Symbol,Expr}), last_docstr))
×
358
                    last_docstr = nothing
183✔
359
                end
360
            elseif isexpr(each, :function) || isexpr(each, :(=))
649✔
361
                break
16✔
362
            elseif isa(each, String) || isexpr(each, :string) || isexpr(each, :call) ||
422✔
363
                (isexpr(each, :macrocall) && each.args[1] === Symbol("@doc_str"))
364
                # forms that might be doc strings
365
                last_docstr = each::Union{String,Expr}
×
366
            end
367
        end
432✔
368
        dict = :($(Dict{Symbol,Any})($([(:($(P)($(quot(f)), $d)))::Expr for (f, d) in fields]...)))
54✔
369
        push!(args, :($(Pair)(:fields, $dict)))
54✔
370
    end
371
    return :($(Dict{Symbol,Any})($(args...)))
462✔
372
end
373

374
function keyworddoc(__source__, __module__, str, def::Base.BaseDocs.Keyword)
×
375
    @nospecialize str
×
376
    docstr = esc(docexpr(__source__, __module__, lazy_iterpolate(str), metadata(__source__, __module__, def, false)))
×
377
    return :($setindex!($(keywords), $docstr, $(esc(quot(def.name)))); nothing)
×
378
end
379

380
function objectdoc(__source__, __module__, str, def, expr, sig = :(Union{}))
539✔
381
    @nospecialize str def expr sig
×
382
    binding = esc(bindingexpr(namify(expr)))
986✔
383
    docstr  = esc(docexpr(__source__, __module__, lazy_iterpolate(str), metadata(__source__, __module__, expr, false)))
454✔
384
    # Note: we want to avoid introducing line number nodes here (issue #24468)
385
    return Expr(:block, esc(def), :($(doc!)($__module__, $binding, $docstr, $(esc(sig)))))
452✔
386
end
387

388
function calldoc(__source__, __module__, str, def::Expr)
×
389
    @nospecialize str
×
390
    args = callargs(def)
×
391
    if isempty(args) || all(validcall, args)
×
392
        objectdoc(__source__, __module__, str, nothing, def, signature(def))
×
393
    else
394
        docerror(def)
×
395
    end
396
end
397
callargs(ex::Expr) = isexpr(ex, :where) ? callargs(ex.args[1]) :
×
398
    isexpr(ex, :call) ? ex.args[2:end] : error("Invalid expression to callargs: $ex")
399
validcall(x) = isa(x, Symbol) || isexpr(x, (:(::), :..., :kw, :parameters))
×
400

401
function moduledoc(__source__, __module__, meta, def, def′::Expr)
10✔
402
    @nospecialize meta def
×
403
    name  = namify(def′)
10✔
404
    docex = Expr(:call, doc!, name, bindingexpr(name),
20✔
405
        docexpr(__source__, name, lazy_iterpolate(meta), metadata(__source__, __module__, name, true)))
406
    if def === nothing
10✔
407
        esc(:(Core.eval($name, $(quot(docex)))))
×
408
    else
409
        def = unblock(def)
10✔
410
        block = def.args[3].args
10✔
411
        if !def.args[1]
10✔
412
            pushfirst!(block, :(import Base: @doc))
×
413
        end
414
        push!(block, docex)
10✔
415
        esc(Expr(:toplevel, def))
10✔
416
    end
417
end
418

419
# Shares a single doc, `meta`, between several expressions from the tuple expression `ex`.
420
function multidoc(__source__, __module__, meta, ex::Expr, define::Bool)
×
421
    @nospecialize meta
×
422
    out = Expr(:block)
×
423
    str = docexpr(__source__, __module__, lazy_iterpolate(meta), metadata(__source__, __module__, ex, false))
×
424
    ref = RefValue{DocStr}()
×
425
    first = true
×
426
    for arg in ex.args
×
427
        # The first `arg` to be documented needs to also create the docstring for the group
428
        # (after doing the action defined by the argument).
429
        # Subsequent `arg`s just need `ref` to be able to find the docstring without having
430
        # to create an entirely new one each.
431
        if first
×
432
            first = false
×
433
            docstr = :($getindex($setindex!($(ref), $str)))
×
434
        else
435
            docstr = :($getindex($(ref)))
×
436
        end
437
        push!(out.args, docm(__source__, __module__, docstr, arg, define))
×
438
    end
×
439
    return out
×
440
end
441

442
"""
443
    @__doc__(ex)
444

445
Low-level macro used to mark expressions returned by a macro that should be documented. If
446
more than one expression is marked then the same docstring is applied to each expression.
447

448
    macro example(f)
449
        quote
450
            \$(f)() = 0
451
            @__doc__ \$(f)(x) = 1
452
            \$(f)(x, y) = 2
453
        end |> esc
454
    end
455

456
`@__doc__` has no effect when a macro that uses it is not documented.
457
"""
458
:(Core.@__doc__)
459

460
function __doc__!(source, mod, meta, def, define::Bool)
×
461
    @nospecialize source mod meta def
×
462
    # Two cases must be handled here to avoid redefining all definitions contained in `def`:
463
    if define
10✔
464
        # `def` has not been defined yet (this is the common case, i.e. when not generating
465
        # the Base image). We just need to convert each `@__doc__` marker to an `@doc`.
466
        finddoc(def) do each
20✔
467
            each.head = :macrocall
468
            each.args = Any[Symbol("@doc"), source, mod, nothing, meta, each.args[end], define]
469
        end
470
    else
471
        # `def` has already been defined during Base image gen so we just need to find and
472
        # document any subexpressions marked with `@__doc__`.
473
        docs  = []
×
474
        found = finddoc(def) do each
×
475
            push!(docs, :(@doc($source, $mod, $meta, $(each.args[end]), $define)))
476
        end
477
        # If any subexpressions have been documented then replace the entire expression with
478
        # just those documented subexpressions to avoid redefining any definitions.
479
        if found
×
480
            def.head = :toplevel
×
481
            def.args = docs
×
482
        end
483
        found
×
484
    end
485
end
486
# Walk expression tree `def` and call `λ` when any `@__doc__` markers are found. Returns
487
# `true` to signify that at least one `@__doc__` has been found, and `false` otherwise.
488
function finddoc(λ, def::Expr)
×
489
    if isexpr(def, :block, 2) && isexpr(def.args[1], :meta, 1) && (def.args[1]::Expr).args[1] === :doc
×
490
        # Found the macroexpansion of an `@__doc__` expression.
491
        λ(def)
×
492
        true
×
493
    else
494
        found = false
×
495
        for each in def.args
×
496
            found |= finddoc(λ, each)
×
497
        end
×
498
        found
×
499
    end
500
end
501
finddoc(λ, @nospecialize def) = false
×
502

503
# Predicates and helpers for `docm` expression selection:
504

505
const FUNC_HEADS    = [:function, :macro, :(=)]
506
const BINDING_HEADS = [:const, :global, :(=)]
507
# For the special `:@mac` / `:(Base.@mac)` syntax for documenting a macro after definition.
508
isquotedmacrocall(@nospecialize x) =
20✔
509
    isexpr(x, :copyast, 1) &&
510
    isa(x.args[1], QuoteNode) &&
511
    isexpr(x.args[1].value, :macrocall, 2)
512
# Simple expressions / atoms the may be documented.
513
isbasicdoc(@nospecialize x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol})
20✔
514
is_signature(@nospecialize x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where)
424✔
515

516
function docm(source::LineNumberNode, mod::Module, ex)
×
517
    @nospecialize ex
×
518
    if isexpr(ex, :->) && length(ex.args) > 1
×
519
        return docm(source, mod, ex.args...)
×
520
    elseif isassigned(Base.REPL_MODULE_REF)
×
521
        # TODO: this is a shim to continue to allow `@doc` for looking up docstrings
522
        REPL = Base.REPL_MODULE_REF[]
×
523
        return REPL.lookup_doc(ex)
×
524
    end
525
    return nothing
×
526
end
527
# Drop incorrect line numbers produced by nested macro calls.
528
docm(source::LineNumberNode, mod::Module, _, _, x...) = docm(source, mod, x...)
×
529

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

536
function docm(source::LineNumberNode, mod::Module, meta, ex, define::Bool = true)
924✔
537
    @nospecialize meta ex
×
538
    # Some documented expressions may be decorated with macro calls which obscure the actual
539
    # expression. Expand the macro calls and remove extra blocks.
540
    x = unblock(macroexpand(mod, ex))
924✔
541
    # Don't try to redefine expressions. This is only needed for `Base` img gen since
542
    # otherwise calling `loaddocs` would redefine all documented functions and types.
543
    def = define ? x : nothing
462✔
544
    if isa(x, GlobalRef) && (x::GlobalRef).mod == mod
462✔
545
        x = (x::GlobalRef).name
×
546
    end
547

548
    # Keywords using the `@kw_str` macro in `base/docs/basedocs.jl`.
549
    #
550
    #   "..."
551
    #   kw"if", kw"else"
552
    #
553
    doc =
924✔
554
    isa(x, Base.BaseDocs.Keyword) ? keyworddoc(source, mod, meta, x) :
555

556
    # Method / macro definitions and "call" syntax.
557
    #
558
    #   function f(...) ... end
559
    #   f(...) = ...
560
    #   macro m(...) end
561
    #   function f end
562
    #   f(...)
563
    #
564
    # Including if the "call" expression is wrapped in "where" expression(s) (#32960), i.e.
565
    #
566
    #   f(::T) where T
567
    #   f(::T, ::U) where T where U
568
    #
569
    isexpr(x, FUNC_HEADS) && is_signature((x::Expr).args[1]) ? objectdoc(source, mod, meta, def, x::Expr, signature(x::Expr)) :
570
    isexpr(x, [:function, :macro])  && !isexpr((x::Expr).args[1], :call) ? objectdoc(source, mod, meta, def, x::Expr) :
571
    iscallexpr(x) ? calldoc(source, mod, meta, x::Expr) :
572

573
    # Type definitions.
574
    #
575
    #   struct T ... end
576
    #   abstract type T end
577
    #   primitive type T N end
578
    #
579
    isexpr(x, [:struct, :abstract, :primitive]) ? objectdoc(source, mod, meta, def, x::Expr) :
580

581
    # "Bindings". Names that resolve to objects with different names, ie.
582
    #
583
    #   const T = S
584
    #   T = S
585
    #   global T = S
586
    #
587
    isexpr(x, BINDING_HEADS) && !isexpr((x::Expr).args[1], :call) ? objectdoc(source, mod, meta, def, x::Expr) :
588

589
    # Quoted macrocall syntax. `:@time` / `:(Base.@time)`.
590
    isquotedmacrocall(x) ? objectdoc(source, mod, meta, def, x) :
591
    # Modules and baremodules.
592
    isexpr(x, :module) ? moduledoc(source, mod, meta, def, x::Expr) :
593
    # Document several expressions with the same docstring. `a, b, c`.
594
    isexpr(x, :tuple) ? multidoc(source, mod, meta, x::Expr, define) :
595
    # Errors generated by calling `macroexpand` are passed back to the call site.
596
    isexpr(x, :error) ? esc(x) :
597
    # When documenting macro-generated code we look for embedded `@__doc__` calls.
598
    __doc__!(source, mod, meta, x, define) ? esc(x) :
599
    # Any "basic" expression such as a bare function or module name or numeric literal.
600
    isbasicdoc(x) ? objectdoc(source, mod, meta, nothing, x) :
601

602
    # All other expressions are undocumentable and should be handled on a case-by-case basis
603
    # with `@__doc__`. Unbound string literals are also undocumentable since they cannot be
604
    # retrieved from the module's metadata `IdDict` without a reference to the string.
605
    docerror(ex)
606

607
    return doc
462✔
608
end
609

610
function docerror(@nospecialize ex)
×
611
    txt = """
×
612
    cannot document the following expression:
613

614
    $(isa(ex, AbstractString) ? repr(ex) : ex)"""
615
    if isexpr(ex, :macrocall)
×
616
        txt *= "\n\n'$(ex.args[1])' not documentable. See 'Base.@__doc__' docs for details."
×
617
    end
618
    return :($(error)($txt, "\n"))
×
619
end
620

621
include("utils.jl")
622

623
# Swap out the bootstrap macro with the real one.
624
Core.atdoc!(docm)
625

626
function loaddocs(docs::Vector{Core.SimpleVector})
×
627
    for (mod, ex, str, file, line) in docs
×
628
        data = Dict{Symbol,Any}(:path => string(file), :linenumber => line)
×
629
        doc = docstr(str, data)
×
630
        docstring = docm(LineNumberNode(line, file), mod, doc, ex, false) # expand the real @doc macro now
×
631
        Core.eval(mod, Expr(Core.unescape, docstring, Docs))
×
632
    end
×
633
    empty!(docs)
×
634
    nothing
×
635
end
636

637
function formatdoc end
638
function parsedoc end
639
function apropos end
640
function doc end
641

642
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc