https://github.com/JuliaLang/julia
Tip revision: b10e22a7cbd1b4abf07c553f42ac2c2b45d20ecf authored by Jameson Nash on 02 November 2015, 17:55:22 UTC
lazy-ify docs parsing
lazy-ify docs parsing
Tip revision: b10e22a
docs.jl
# This file is a part of Julia. License is MIT: http://julialang.org/license
import Base.DocObj
@doc "Doc abstract type" ->
abstract C74685 <: AbstractArray
@test stringmime("text/plain", Docs.doc(C74685))=="Doc abstract type\n"
macro macro_doctest() end
@doc "Helps test if macros can be documented with `@doc \"...\" -> @...`." ->
:@macro_doctest
@test (@doc @macro_doctest) != nothing
# issue #11548
module ModuleMacroDoc
macro m() end
end
@doc ("I am a module";) ModuleMacroDoc
@doc ("I am a macro";) :@ModuleMacroDoc.m
@test ((@doc ModuleMacroDoc)::DocObj).content == "I am a module"
@test ((@doc ModuleMacroDoc.@m)::DocObj).content == "I am a macro"
# General tests for docstrings.
module DocsTest
"DocsTest"
DocsTest
"f-1"
function f(x)
x
end
"f-2"
f(x, y) = x + y
"s-1"
@generated function s(x)
:(x)
end
"s-2"
@generated s(x, y) = :(x + y)
"g"
function g end
"AT"
abstract AT
"BT"
bitstype 8 BT
"BT2"
bitstype 8 BT2 <: Integer
"T"
type T <: AT
"T.x"
x
"T.y"
y :: Int
end
"IT"
immutable IT
"IT.x"
x :: Int
"IT.y"
y
end
"TA"
typealias TA Union{T, IT}
"@mac"
macro mac() end
"G"
G = :G
"K"
const K = :K
# Adding docstrings to methods after definition.
t(x::AbstractString) = x
t(x::Int, y) = y
t{S <: Integer}(x::S) = x
"t-1"
t(::AbstractString)
"t-2"
t(::Int, ::Any)
"t-3"
t{S <: Integer}(::S)
"FieldDocs"
type FieldDocs
"one"
one
doc"two"
two
three
end
"h/0-3"
h(x = 1, y = 2, z = 3) = x + y + z
# Issue #12700.
module Inner
macro m() end
end
import .Inner.@m
"Inner.@m"
:@m
type Foo
x
end
# value with no docs
const val = Foo(1.0)
end
import Base.Docs: meta
function docstrings_equal(d1, d2)
io1 = IOBuffer()
io2 = IOBuffer()
writemime(io1, MIME"text/markdown"(), d1)
writemime(io2, MIME"text/markdown"(), d2)
str1 = takebuf_string(io1)
str2 = takebuf_string(io2)
eq = str1 == str2
if !eq
println()
show(str1)
println()
show(str2)
println()
end
return eq
end
function docstrings_nequal(d1, d2)
io1 = IOBuffer()
io2 = IOBuffer()
writemime(io1, MIME"text/markdown"(), d1)
writemime(io2, MIME"text/markdown"(), d2)
str1 = takebuf_string(io1)
str2 = takebuf_string(io2)
eq = str1 == str2
if eq
println()
show(str1)
println()
show(str2)
println()
end
return !eq
end
@test (meta(DocsTest)[DocsTest]::DocObj).content == (doc"DocsTest"::DocObj).content
# Check that plain docstrings store a module reference.
# https://github.com/JuliaLang/julia/pull/13017#issuecomment-138618663
# @test meta(DocsTest)[DocsTest].meta[:module] == DocsTest
let f = DocsTest.f
funcdoc = meta(DocsTest)[f]
@test funcdoc.main == nothing
@test docstrings_equal(funcdoc.meta[Tuple{Any}], doc"f-1")
@test docstrings_equal(funcdoc.meta[Tuple{Any,Any}], doc"f-2")
end
let s = DocsTest.s
funcdoc = meta(DocsTest)[s]
@test funcdoc.main == nothing
@test docstrings_equal(funcdoc.meta[Tuple{Any,}], doc"s-1")
@test docstrings_equal(funcdoc.meta[Tuple{Any,Any}], doc"s-2")
end
let g = DocsTest.g
funcdoc = meta(DocsTest)[g]
@test docstrings_equal(funcdoc.meta[Union{}], doc"g")
end
let h = DocsTest.h
funcdoc = meta(DocsTest)[h]
sig = Union{Tuple{}, Tuple{Any}, Tuple{Any, Any}, Tuple{Any, Any, Any}}
@test docstrings_equal(funcdoc.meta[sig], doc"h/0-3")
end
let AT = DocsTest.AT
@test (meta(DocsTest)[AT]::DocObj).content == (doc"AT"::DocObj).content
end
let BT = DocsTest.BT
@test (meta(DocsTest)[BT]::DocObj).content == (doc"BT"::DocObj).content
end
@test (meta(DocsTest)[DocsTest.BT2]::DocObj).content == (doc"BT2"::DocObj).content
let T = DocsTest.T
typedoc = meta(DocsTest)[T]
@test docstrings_equal(typedoc.main, doc"T")
@test docstrings_equal(typedoc.fields[:x], doc"T.x")
@test docstrings_equal(typedoc.fields[:y], doc"T.y")
end
let IT = DocsTest.IT
typedoc = meta(DocsTest)[IT]
@test docstrings_equal(typedoc.main, doc"IT")
@test docstrings_equal(typedoc.fields[:x], doc"IT.x")
@test docstrings_equal(typedoc.fields[:y], doc"IT.y")
end
@test (@doc(DocsTest.TA)::DocObj).content == (doc"TA"::DocObj).content
@test (@doc(DocsTest.@mac)::DocObj).content == (doc"@mac"::DocObj).content
@test (@doc(DocsTest.G)::DocObj).content == "G"
@test (@doc(DocsTest.K)::DocObj).content == "K"
let d1 = @doc(DocsTest.t(::AbstractString)),
d2 = doc"t-1"
@test docstrings_equal(d1,d2)
end
let d1 = @doc(DocsTest.t(::AbstractString)),
d2 = doc"t-1"
@test docstrings_equal(d1,d2)
end
let d1 = @doc(DocsTest.t(::Int, ::Any)),
d2 = doc"t-2"
@test docstrings_equal(d1,d2)
end
let d1 = @doc(DocsTest.t{S <: Integer}(::S)),
d2 = doc"t-3"
@test docstrings_equal(d1,d2)
end
let fields = meta(DocsTest)[DocsTest.FieldDocs].fields
@test haskey(fields, :one) && (fields[:one]::DocObj).content == "one"
@test haskey(fields, :two) && (fields[:two]::DocObj).content == "two"
end
"BareModule"
baremodule BareModule
"f/1"
f(x) = x
"g/1"
function g(x) end
"h"
function h end
"@m"
macro m() end
"C"
const C = 1
"A"
abstract A
"T"
type T
"x"
x
"y"
y
end
end
@test docstrings_equal(@doc(BareModule), doc"BareModule")
@test docstrings_equal(@doc(BareModule.f), doc"f/1")
@test docstrings_equal(@doc(BareModule.g), doc"g/1")
@test docstrings_equal(@doc(BareModule.@m), doc"@m")
@test docstrings_equal(@doc(BareModule.C), doc"C")
@test docstrings_equal(@doc(BareModule.A), doc"A")
@test docstrings_equal(@doc(BareModule.T), doc"T")
@test_throws ErrorException @doc("...", "error")
@test_throws ErrorException @doc("...", @time 0)
# test that when no docs exist, they fallback to
# the docs for the typeof(value)
let d1 = @doc(DocsTest.val)
@test d1 !== nothing
end
# Document specific expressions generated by macro calls.
module MacroGenerated
import Base.@__doc__
macro example_1(f)
quote
$(f)() = 0
@__doc__ $(f)(x) = x
$(f)(x, y) = x + y
end |> esc
end
"f"
@example_1 f
@example_1 _f
macro example_2(f)
quote
$(f)() = 0
@__doc__ $(f)(x) = x
@__doc__ $(f)(x, y) = x + y
end |> esc
end
"g"
@example_2 g
@example_2 _g
end
let funcdoc = meta(MacroGenerated)[MacroGenerated.f]
@test funcdoc.order == [Tuple{Any}]
@test (funcdoc.meta[Tuple{Any}]::DocObj).content == (doc"f"::DocObj).content
end
@test isdefined(MacroGenerated, :_f)
let funcdoc = meta(MacroGenerated)[MacroGenerated.g]
@test funcdoc.order == [Tuple{Any}, Tuple{Any, Any}]
@test (funcdoc.meta[Tuple{Any}]::DocObj).content == (doc"g"::DocObj).content
@test (funcdoc.meta[Tuple{Any, Any}]::DocObj).content == (doc"g"::DocObj).content
end
@test isdefined(MacroGenerated, :_g)
# Issue #13385.
@test @doc(I) !== nothing
# Issue #12700.
@test (@doc(DocsTest.@m)::DocObj).content == (doc"Inner.@m"::DocObj).content
# issue 11993
# Check if we are documenting the expansion of the macro
macro m1_11993()
end
macro m2_11993()
symbol("@m1_11993")
end
@doc "This should document @m1... since its the result of expansion" @m2_11993
@test (@doc @m1_11993) !== nothing
let d = (@doc @m2_11993)
@test docstrings_equal(d, Docs.catdoc(Any[doc"""No documentation found.""",
doc"""```julia
@m2_11993()
```
"""]))
end
@doc "Now @m2... should be documented" :@m2_11993
@test (@doc @m2_11993) !== nothing
"Document inline function"
@inline f1_11993() = nothing
@test (@doc f1_11993) !== nothing
f1_11993()
@doc "Document inline function with old syntax" ->
@inline f2_11993() = nothing
@test (@doc f2_11993) !== nothing
f2_11993()
# issue #11798
module I11798
"read"
read(x) = x
end
let fd = Base.Docs.meta(I11798)[I11798.read],
d1 = fd.meta[fd.order[1]],
d2 = doc"read"
@test docstrings_equal(d1,d2)
end
module I12515
immutable EmptyType{T} end
"A new method"
Base.collect{T}(::Type{EmptyType{T}}) = "borked"
end
let fd = meta(I12515)[Base.collect]
@test fd.order[1] == Tuple{Type{I12515.EmptyType{TypeVar(:T, Any, true)}}}
end
# PR #12593
"$(1 + 1)"
f12593_1() = 1
"$(1 + 1) 2"
f12593_2() = 1
@test (@doc f12593_1) !== nothing
@test (@doc f12593_2) !== nothing
@test Docs.doc(svdvals, Tuple{Vector{Float64}}) === nothing
@test Docs.doc(svdvals, Tuple{Float64}) !== nothing
# crude test to make sure we sort docstring output by method specificity
@test docstrings_nequal(Docs.doc(getindex, Tuple{Dict{Int,Int},Int}),
Docs.doc(getindex, Tuple{Type{Int64},Int}))
# test that macro documentation works
@test (Docs.@repl @assert) !== nothing
@test (Docs.@repl 0) !== nothing
let t = @doc(DocsTest.t(::Int, ::Int))
@test docstrings_equal(Docs.@repl(DocsTest.t(0, 0)), t)
@test docstrings_equal(Docs.@repl(DocsTest.t(::Int, ::Int)), t)
end
# Issue #13467.
@test (Docs.@repl @r_str) !== nothing
# Simple tests for apropos:
@test contains(sprint(apropos, "pearson"), "cor")
@test contains(sprint(apropos, r"ind(exes|ices)"), "eachindex")
@test contains(sprint(apropos, "print"), "Profile.print")
# Issue #13068.
module I13068
module A
export foo
"""
foo from A
"""
foo(::Int) = 1
end
module B
import ..A: foo
export foo
"""
foo from B
"""
foo(::Float64) = 2
end
end
@test docstrings_equal(
@doc(I13068.A.foo),
Docs.catdoc(Any[doc"""foo from A""", doc"""foo from B"""])
)
@test docstrings_equal(Docs.doc(I13068.A.foo, Tuple{Int}), doc"foo from A")
@test docstrings_equal(Docs.doc(I13068.A.foo, Tuple{Float64}), doc"foo from B")
@test Docs.doc(I13068.A.foo, Tuple{Char}) === nothing
# Undocumented DataType Summaries.
module Undocumented
abstract A
abstract B <: A
type C <: A end
immutable D <: B
one
two::UTF8String
three::Float64
end
f = () -> nothing
undocumented() = 1
undocumented(x) = 2
undocumented(x,y) = 3
end
@test docstrings_equal(@doc(Undocumented.A), Docs.catdoc(Any[doc"""No documentation found.""", doc"""
**Summary:**
```julia
abstract Undocumented.A <: Any
```
**Subtypes:**
```julia
Undocumented.B
Undocumented.C
```
"""]))
@test docstrings_equal(@doc(Undocumented.B), Docs.catdoc(Any[doc"""No documentation found.""", doc"""
**Summary:**
```julia
abstract Undocumented.B <: Undocumented.A
```
**Subtypes:**
```julia
Undocumented.D
```
"""]))
@test docstrings_equal(@doc(Undocumented.C), Docs.catdoc(Any[doc"""No documentation found.""", doc"""
**Summary:**
```julia
type Undocumented.C <: Undocumented.A
```
"""]))
@test docstrings_equal(@doc(Undocumented.D), Docs.catdoc(Any[doc"""No documentation found.""", doc"""
**Summary:**
```julia
immutable Undocumented.D <: Undocumented.B
```
**Fields:**
```julia
one :: Any
two :: UTF8String
three :: Float64
```
"""]))
let d = @doc Undocumented.f
io = IOBuffer()
writemime(io, MIME"text/markdown"(), d)
docstr = takebuf_string(io)
@test startswith(docstr, """
No documentation found.
`Undocumented.f` is an anonymous `Function`.
""")
end
let d = @doc Undocumented.undocumented
io = IOBuffer()
writemime(io, MIME"text/markdown"(), d)
@test startswith(takebuf_string(io), """
No documentation found.
`Undocumented.undocumented` is a generic `Function`.
""")
end
# Bindings.
import Base.Docs: splitexpr, Binding
macro var(x)
:(Binding($(splitexpr(x)...)))
end
let x = Binding(Base, symbol("@time"))
@test @var(@time) == x
@test @var(Base.@time) == x
@test @var(Base.Pkg.@time) == x
end
let x = Binding(Base.LinAlg, :norm)
@test @var(norm) == x
@test @var(Base.norm) == x
@test @var(Base.LinAlg.norm) == x
@test @var(Base.Pkg.Dir.norm) == x
end
let x = Binding(Core, :Int)
@test @var(Int) == x
@test @var(Base.Int) == x
@test @var(Core.Int) == x
@test @var(Base.Pkg.Resolve.Int) == x
end
let x = Binding(Base, :Pkg)
@test @var(Pkg) == x
@test @var(Base.Pkg) == x
@test @var(Main.Pkg) == x
end
let x = Binding(Base, :VERSION)
@test @var(VERSION) == x
@test @var(Base.VERSION) == x
end