Skip to content

Commit a6a08d7

Browse files
committed
move Markdown to stdlib
1 parent 9877594 commit a6a08d7

File tree

36 files changed

+691
-747
lines changed

36 files changed

+691
-747
lines changed

base/boot.jl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,6 @@ end
410410
macro __doc__(x)
411411
Expr(:escape, Expr(:block, Expr(:meta, :doc), x))
412412
end
413-
macro doc_str(s)
414-
Expr(:escape, s)
415-
end
416413
atdoc = (source, mod, str, expr) -> Expr(:escape, expr)
417414
atdoc!(λ) = global atdoc = λ
418415

base/docs/Docs.jl

Lines changed: 29 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,11 @@ function.
6060

6161
include("bindings.jl")
6262

63-
import Base.Markdown: @doc_str, MD
6463
import Base.Meta: quot, isexpr
6564
import Base: Callable, with_output_color
6665
import ..CoreDocs: lazy_iterpolate
6766

68-
export doc
67+
export doc, apropos
6968

7069
# Basic API / Storage
7170

@@ -174,25 +173,6 @@ end
174173

175174
docexpr(__source__, __module__, args...) = Expr(:call, docstr, args...)
176175

177-
function formatdoc(d::DocStr)
178-
buffer = IOBuffer()
179-
for part in d.text
180-
formatdoc(buffer, d, part)
181-
end
182-
Markdown.MD(Any[Markdown.parse(seekstart(buffer))])
183-
end
184-
@noinline formatdoc(buffer, d, part) = print(buffer, part)
185-
186-
function parsedoc(d::DocStr)
187-
if d.object === nothing
188-
md = formatdoc(d)
189-
md.meta[:module] = d.data[:module]
190-
md.meta[:path] = d.data[:path]
191-
d.object = md
192-
end
193-
d.object
194-
end
195-
196176
"""
197177
MultiDoc
198178
@@ -270,167 +250,6 @@ function getdoc end
270250
getdoc(x, sig) = getdoc(x)
271251
getdoc(x) = nothing
272252

273-
"""
274-
Docs.doc(binding, sig)
275-
276-
Return all documentation that matches both `binding` and `sig`.
277-
278-
If `getdoc` returns a non-`nothing` result on the value of the binding, then a
279-
dynamic docstring is returned instead of one based on the binding itself.
280-
"""
281-
function doc(binding::Binding, sig::Type = Union{})
282-
if defined(binding)
283-
result = getdoc(resolve(binding), sig)
284-
result === nothing || return result
285-
end
286-
results, groups = DocStr[], MultiDoc[]
287-
# Lookup `binding` and `sig` for matches in all modules of the docsystem.
288-
for mod in modules
289-
dict = meta(mod)
290-
if haskey(dict, binding)
291-
multidoc = dict[binding]
292-
push!(groups, multidoc)
293-
for msig in multidoc.order
294-
sig <: msig && push!(results, multidoc.docs[msig])
295-
end
296-
end
297-
end
298-
if isempty(groups)
299-
# When no `MultiDoc`s are found that match `binding` then we check whether `binding`
300-
# is an alias of some other `Binding`. When it is we then re-run `doc` with that
301-
# `Binding`, otherwise if it's not an alias then we generate a summary for the
302-
# `binding` and display that to the user instead.
303-
alias = aliasof(binding)
304-
alias == binding ? summarize(alias, sig) : doc(alias, sig)
305-
else
306-
# There was at least one match for `binding` while searching. If there weren't any
307-
# matches for `sig` then we concatenate *all* the docs from the matching `Binding`s.
308-
if isempty(results)
309-
for group in groups, each in group.order
310-
push!(results, group.docs[each])
311-
end
312-
end
313-
# Get parsed docs and concatenate them.
314-
md = catdoc(map(parsedoc, results)...)
315-
# Save metadata in the generated markdown.
316-
if isa(md, Markdown.MD)
317-
md.meta[:results] = results
318-
md.meta[:binding] = binding
319-
md.meta[:typesig] = sig
320-
end
321-
return md
322-
end
323-
end
324-
325-
# Some additional convenience `doc` methods that take objects rather than `Binding`s.
326-
doc(obj::UnionAll) = doc(Base.unwrap_unionall(obj))
327-
doc(object, sig::Type = Union{}) = doc(aliasof(object, typeof(object)), sig)
328-
doc(object, sig...) = doc(object, Tuple{sig...})
329-
330-
"""
331-
Docs.fielddoc(binding, field)
332-
333-
Return documentation for a particular `field` of a type if it exists.
334-
"""
335-
function fielddoc(binding::Binding, field::Symbol)
336-
for mod in modules
337-
dict = meta(mod)
338-
if haskey(dict, binding)
339-
multidoc = dict[binding]
340-
if haskey(multidoc.docs, Union{})
341-
fields = multidoc.docs[Union{}].data[:fields]
342-
if haskey(fields, field)
343-
doc = fields[field]
344-
return isa(doc, Markdown.MD) ? doc : Markdown.parse(doc)
345-
end
346-
end
347-
end
348-
end
349-
fields = join(["`$f`" for f in fieldnames(resolve(binding))], ", ", ", and ")
350-
fields = isempty(fields) ? "no fields" : "fields $fields"
351-
Markdown.parse("`$(resolve(binding))` has $fields.")
352-
end
353-
354-
# As with the additional `doc` methods, this converts an object to a `Binding` first.
355-
fielddoc(object, field::Symbol) = fielddoc(aliasof(object, typeof(object)), field)
356-
357-
# Object Summaries.
358-
# =================
359-
360-
function summarize(binding::Binding, sig)
361-
io = IOBuffer()
362-
println(io, "No documentation found.\n")
363-
if defined(binding)
364-
summarize(io, resolve(binding), binding)
365-
else
366-
println(io, "Binding `", binding, "` does not exist.")
367-
end
368-
md = Markdown.parse(seekstart(io))
369-
# Save metadata in the generated markdown.
370-
md.meta[:results] = DocStr[]
371-
md.meta[:binding] = binding
372-
md.meta[:typesig] = sig
373-
return md
374-
end
375-
376-
function summarize(io::IO, λ::Function, binding)
377-
kind = startswith(string(binding.var), '@') ? "macro" : "`Function`"
378-
println(io, "`", binding, "` is a ", kind, ".")
379-
println(io, "```\n", methods(λ), "\n```")
380-
end
381-
382-
function summarize(io::IO, T::DataType, binding)
383-
println(io, "# Summary")
384-
println(io, "```")
385-
println(io,
386-
T.abstract ? "abstract type" :
387-
T.mutable ? "mutable struct" :
388-
Base.isstructtype(T) ? "struct" : "primitive type",
389-
" ", T, " <: ", supertype(T)
390-
)
391-
println(io, "```")
392-
if !T.abstract && T.name !== Tuple.name && !isempty(fieldnames(T))
393-
println(io, "# Fields")
394-
println(io, "```")
395-
pad = maximum(length(string(f)) for f in fieldnames(T))
396-
for (f, t) in zip(fieldnames(T), T.types)
397-
println(io, rpad(f, pad), " :: ", t)
398-
end
399-
println(io, "```")
400-
end
401-
if !isempty(subtypes(T))
402-
println(io, "# Subtypes")
403-
println(io, "```")
404-
for t in subtypes(T)
405-
println(io, t)
406-
end
407-
println(io, "```")
408-
end
409-
if supertype(T) != Any
410-
println(io, "# Supertype Hierarchy")
411-
println(io, "```")
412-
Base.show_supertypes(io, T)
413-
println(io)
414-
println(io, "```")
415-
end
416-
end
417-
418-
function summarize(io::IO, m::Module, binding)
419-
readme = Pkg.dir(string(m), "README.md")
420-
if isfile(readme)
421-
println(io, "Displaying the `README.md` for the module instead.\n")
422-
println(io, "---\n")
423-
println(io, read(readme, String))
424-
else
425-
println(io, "No docstring or `README.md` found for module `", m, "`.\n")
426-
end
427-
end
428-
429-
function summarize(io::IO, ::T, binding) where T
430-
println(io, "`", binding, "` is of type `", T, "`.\n")
431-
summarize(io, T, binding)
432-
end
433-
434253
# Utilities.
435254
# ==========
436255

@@ -442,12 +261,6 @@ catdoc(xs...) = vcat(xs...)
442261

443262
const keywords = Dict{Symbol, DocStr}()
444263

445-
isdoc(s::AbstractString) = true
446-
447-
isdoc(x) = isexpr(x, :string) ||
448-
(isexpr(x, :macrocall) && x.args[1] === Symbol("@doc_str")) ||
449-
(isexpr(x, :call) && x.args[1] === Base.Markdown.doc_str)
450-
451264
function unblock(ex)
452265
isexpr(ex, :block) || return ex
453266
exs = filter(ex -> !(isa(ex, LineNumberNode) || isexpr(ex, :line)), ex.args)
@@ -511,13 +324,20 @@ function metadata(__source__, __module__, expr, ismodule)
511324
if isexpr(expr, :struct)
512325
# Field docs for concrete types.
513326
fields = []
514-
tmp = nothing
327+
last_docstr = nothing
515328
for each in expr.args[3].args
516-
if isdoc(each)
517-
tmp = each
518-
elseif tmp !== nothing && (isa(each, Symbol) || isexpr(each, :(::)))
519-
push!(fields, (namify(each), tmp))
520-
tmp = nothing
329+
if isa(each, Symbol) || isexpr(each, :(::))
330+
# a field declaration
331+
if last_docstr !== nothing
332+
push!(fields, (namify(each), last_docstr))
333+
last_docstr = nothing
334+
end
335+
elseif isexpr(each, :function) || isexpr(each, :(=))
336+
break
337+
elseif isa(each, String) || isexpr(each, :string) || isexpr(each, :call) ||
338+
(isexpr(each, :macrocall) && each.args[1] === Symbol("@doc_str"))
339+
# forms that might be doc strings
340+
last_docstr = each
521341
end
522342
end
523343
dict = :($(Dict)($([:($(Pair)($(quot(f)), $d)) for (f, d) in fields]...)))
@@ -654,6 +474,16 @@ isquotedmacrocall(x) =
654474
isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol})
655475
is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where)
656476

477+
function docm(source::LineNumberNode, mod::Module, ex)
478+
if isexpr(ex, :->) && length(ex.args) > 1
479+
docm(source, mod, ex.args...)
480+
else
481+
# TODO: this is a shim to continue to allow `@doc` for looking up docstrings
482+
REPL = Base.root_module(Base, :REPL)
483+
return REPL.lookup_doc(ex)
484+
end
485+
end
486+
657487
function docm(source::LineNumberNode, mod::Module, meta, ex, define = true)
658488
# Some documented expressions may be decorated with macro calls which obscure the actual
659489
# expression. Expand the macro calls and remove extra blocks.
@@ -730,27 +560,6 @@ function docerror(ex)
730560
:($(error)($txt, "\n"))
731561
end
732562

733-
function docm(source::LineNumberNode, mod::Module, ex)
734-
if isexpr(ex, :->)
735-
docm(source, mod, ex.args...)
736-
elseif haskey(keywords, ex)
737-
parsedoc(keywords[ex])
738-
elseif isa(ex, Union{Expr, Symbol})
739-
binding = esc(bindingexpr(namify(ex)))
740-
if isexpr(ex, :call) || isexpr(ex, :macrocall)
741-
sig = esc(signature(ex))
742-
:($(doc)($binding, $sig))
743-
else
744-
:($(doc)($binding))
745-
end
746-
else
747-
:($(doc)($(typeof)($(esc(ex)))))
748-
end
749-
end
750-
751-
# MD support
752-
catdoc(md::MD...) = MD(md...)
753-
754563
include("utils.jl")
755564

756565
# Swap out the bootstrap macro with the real one.
@@ -775,4 +584,9 @@ function loaddocs(docs)
775584
empty!(docs)
776585
end
777586

587+
function formatdoc end
588+
function parsedoc end
589+
function apropos end
590+
function doc end
591+
778592
end

0 commit comments

Comments
 (0)