Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor getdocs code #1842

Merged
merged 8 commits into from
Jun 14, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
- highlight.js has been updated from `v11.0.1` to `v11.5.1`.
- KaTeX has been updated from `v0.13.11` to `v0.13.24`.

* ![Bugfix][badge-bugfix] When including docstrings for an alias, Documenter now correctly tries to include the exactly matching docstring first, before checking for signature subtypes. ([#1842][github-1842])

## Version `v0.27.19`

* ![Enhancement][badge-enhancement] Documenter can now build draft version of HTML documentation by passing `draft=true` to `makedocs`. Draft mode skips potentially expensive parts of the building process and can be useful to get faster feedback when writing documentation. Draft mode currently skips doctests, `@example`-, `@repl`-, `@eval`-, and `@setup`-blocks. Draft mode can be disabled (or enabled) on a per-page basis by setting `Draft = true` in an `@meta` block. ([#1836][github-1836])
Expand Down Expand Up @@ -1069,6 +1071,7 @@
[github-1836]: https://github.com/JuliaDocs/Documenter.jl/pull/1836
[github-1838]: https://github.com/JuliaDocs/Documenter.jl/pull/1838
[github-1841]: https://github.com/JuliaDocs/Documenter.jl/pull/1841
[github-1842]: https://github.com/JuliaDocs/Documenter.jl/pull/1842
[github-1844]: https://github.com/JuliaDocs/Documenter.jl/pull/1844
[github-1846]: https://github.com/JuliaDocs/Documenter.jl/pull/1846
<!-- end of issue link definitions -->
Expand Down
61 changes: 32 additions & 29 deletions src/DocSystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,23 +162,19 @@ const CACHED = IdDict{Any,Any}()
"""
$(SIGNATURES)

Find all `DocStr` objects that match the provided arguments:

Find all `DocStr` objects that match the provided arguments exactly.
- `binding`: the name of the object.
- `typesig`: the signature of the object. Default: `Union{}`.
- `compare`: how to compare signatures? Exact (`==`) or subtypes (`<:`). Default: `<:`.
- `compare`: how to compare signatures? (`==` (default), `<:` or `>:`)
- `modules`: which modules to search through. Default: *all modules*.
- `aliases`: check aliases of `binding` when nothing is found. Default: `true`.

Returns a `Vector{DocStr}` ordered by definition order in `0.5` and by
`type_morespecific` in `0.4`.
Return a `Vector{DocStr}` ordered by definition order.
"""
function getdocs(
function getspecificdocs(
binding::Docs.Binding,
typesig::Type = Union{};
typesig::Type = Union{},
compare = (==),
modules = Docs.modules,
aliases = true,
)
# Fall back to searching all modules if user provides no modules.
modules = isempty(modules) ? Docs.modules : modules
Expand All @@ -200,28 +196,35 @@ function getdocs(
end
end
end
if compare == (==)
# Exact matching of signatures:
#
# When we get a single match from using `==` as the comparision then we just return
# that one result.
#
# Otherwise we fallback to comparing signatures using `<:` to match, hopefully, a
# wider range of possible docstrings.
if length(results) == 1
results
else
getdocs(binding, typesig; compare = (<:), modules = modules, aliases = aliases)
end
else
# When nothing is found we check whether the `binding` is an alias of some other
# `Binding`. If so then we redo the search using that `Binding` instead.
if aliases && isempty(results) && (b = aliasof(binding)) != binding
getdocs(b, typesig; compare = compare, modules = modules)
else
results
results
end

"""
$(SIGNATURES)

Find all `DocStr` objects that somehow match the provided arguments.
That is, if [`getspecificdocs`](@ref) fails, get docs for aliases of
`binding` (unless `aliases` is set to `false). For `compare` being `==` also
try getting docs for `<:`.
"""
function getdocs(
binding::Docs.Binding,
typesig::Type = Union{};
compare = (==),
modules = Docs.modules,
aliases = true,
)
results = getspecificdocs(binding, typesig, compare, modules)
if isempty(results) && compare == (==)
results = getspecificdocs(binding, typesig, (<:), modules)
end
if isempty(results) && aliases && (b = aliasof(binding)) != binding
results = getspecificdocs(b, typesig, compare, modules)
if isempty(results) && compare == (==)
results = getspecificdocs(b, typesig, (<:), modules)
end
end
results
end

"""
Expand Down
37 changes: 36 additions & 1 deletion test/docsystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ import Documenter: Documenter, DocSystem

const alias_of_getdocs = DocSystem.getdocs # NOTE: won't get docstrings if in a @testset

module DocstringAliasTest
"A"
struct A end
"A(x)"
A(x) = A()
B = A
end

@testset "DocSystem" begin
## Bindings.
@test_throws ArgumentError DocSystem.binding(9000)
Expand Down Expand Up @@ -47,14 +55,18 @@ const alias_of_getdocs = DocSystem.getdocs # NOTE: won't get docstrings if in a
d_2 = DocSystem.getdocs(b, Union{Tuple{Any}, Tuple{Any, Type}}; compare = (==)),
d_3 = DocSystem.getdocs(b; modules = Module[Main]),
d_4 = DocSystem.getdocs(DocSystem.binding(@__MODULE__, :alias_of_getdocs)),
d_5 = DocSystem.getdocs(DocSystem.binding(@__MODULE__, :alias_of_getdocs); aliases = false)
d_5 = DocSystem.getdocs(DocSystem.binding(@__MODULE__, :alias_of_getdocs); aliases = false),
d_6 = DocSystem.getdocs(b, Union{Tuple{Docs.Binding}, Tuple{Docs.Binding, Type}}; compare = (==)),
d_7 = DocSystem.getdocs(DocSystem.binding(@__MODULE__, :alias_of_getdocs), Union{Tuple{Docs.Binding}, Tuple{Docs.Binding, Type}})

@test length(d_0) == 0
@test length(d_1) == 2
@test length(d_2) == 1
@test length(d_3) == 0
@test length(d_4) == 2
@test length(d_5) == 0
@test length(d_6) == 1
@test length(d_7) == 1

@test d_1[1].data[:binding] == b
@test d_1[2].data[:binding] == b
Expand All @@ -67,14 +79,37 @@ const alias_of_getdocs = DocSystem.getdocs # NOTE: won't get docstrings if in a
@test d_2[1].data[:typesig] == Union{Tuple{Any}, Tuple{Any, Type}}
@test d_2[1].data[:module] == DocSystem

@test d_6[1].data[:binding] == b
@test d_6[1].data[:typesig] == Union{Tuple{Docs.Binding}, Tuple{Docs.Binding, Type}}
@test d_6[1].data[:module] == DocSystem

@test d_1 == d_4
@test d_1 != d_5
@test d_6 == d_7
end

## `UnionAll`
let b = DocSystem.binding(@__MODULE__, Meta.parse("f(x::T) where T"))
@test b.var == :f
end

# DocstringAliasTest
a_1 = DocSystem.getdocs(Docs.Binding(DocstringAliasTest, :A))
a_2 = DocSystem.getdocs(Docs.Binding(DocstringAliasTest, :A), Union{})
a_3 = DocSystem.getdocs(Docs.Binding(DocstringAliasTest, :A), Tuple{Any})
b_1 = DocSystem.getdocs(Docs.Binding(DocstringAliasTest, :B))
b_2 = DocSystem.getdocs(Docs.Binding(DocstringAliasTest, :B), Union{})
b_3 = DocSystem.getdocs(Docs.Binding(DocstringAliasTest, :B), Tuple{Any})
@test length(a_2) == 1
@test a_2[1].data[:typesig] == Union{}
# No signature fetches the docstring of the type (Union{}) in this case
@test a_1 == a_2
@test length(a_3) == 1
@test a_3[1].data[:typesig] == Tuple{Any}
# Make sure that for an alias we get consistent docstrings
@test b_1 == a_1
@test b_2 == a_2
@test b_3 == a_3
end

end