Skip to content

Commit

Permalink
Merge 4be33ab into afc3407
Browse files Browse the repository at this point in the history
  • Loading branch information
eksperimental committed Jul 5, 2019
2 parents afc3407 + 4be33ab commit 05732c2
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 15 deletions.
43 changes: 38 additions & 5 deletions lib/ex_doc/formatter/html/autolink.ex
Expand Up @@ -380,7 +380,16 @@ defmodule ExDoc.Formatter.HTML.Autolink do
pmfa = {_prefix, module, function, arity} = split_match(kind, match)
text = default_text(":", link_type, pmfa, text)

if doc = module_docs(:erlang, module, lib_dirs) do
module_or_mfa =
case kind do
:module ->
module

:function ->
{module, function, arity}
end

if doc = module_docs(:erlang, module_or_mfa, lib_dirs) do
case kind do
:module ->
"[#{text}](#{doc}#{module}.html)"
Expand Down Expand Up @@ -467,7 +476,7 @@ defmodule ExDoc.Formatter.HTML.Autolink do

all

doc = module_docs(:elixir, module, lib_dirs) ->
doc = module_docs(:elixir, {module, function, arity}, lib_dirs) ->
"[#{text}](#{doc}#{module}.html##{prefix}#{enc_h(function)}/#{arity})"

true ->
Expand Down Expand Up @@ -539,9 +548,15 @@ defmodule ExDoc.Formatter.HTML.Autolink do
defp default_lib_dirs(:erlang),
do: erlang_lib_dirs()

defp module_docs(:elixir, {module, function, arity}, lib_dirs),
do: lib_dirs_to_doc({"Elixir." <> module, function, arity}, lib_dirs)

defp module_docs(:elixir, module, lib_dirs),
do: lib_dirs_to_doc("Elixir." <> module, lib_dirs)

defp module_docs(:erlang, {module, function, arity}, lib_dirs),
do: lib_dirs_to_doc({module, function, arity}, lib_dirs)

defp module_docs(:erlang, module, lib_dirs),
do: lib_dirs_to_doc(module, lib_dirs)

Expand Down Expand Up @@ -588,7 +603,16 @@ defmodule ExDoc.Formatter.HTML.Autolink do
defp doc_prefix(%{type: c}) when c in [:callback, :macrocallback], do: "c:"
defp doc_prefix(%{type: _}), do: ""

defp lib_dirs_to_doc(module, lib_dirs) do
defp lib_dirs_to_doc(module, lib_dirs) when is_atom(module) do
lib_dirs_to_doc({"#{module}", "", ""}, lib_dirs)
end

defp lib_dirs_to_doc(module, lib_dirs) when is_binary(module) do
lib_dirs_to_doc({module, "", ""}, lib_dirs)
end

defp lib_dirs_to_doc({module, function, arity}, lib_dirs)
when is_binary(module) and is_binary(function) and is_binary(arity) do
case :code.where_is_file('#{module}.beam') do
:non_existing ->
nil
Expand All @@ -600,8 +624,17 @@ defmodule ExDoc.Formatter.HTML.Autolink do
|> Enum.filter(fn {lib_dir, _} -> String.starts_with?(path, lib_dir) end)
|> Enum.sort_by(fn {lib_dir, _} -> -byte_size(lib_dir) end)
|> case do
[{_, doc} | _] -> doc
_ -> nil
[{_doc_path, doc_url} | _] ->
case ExDoc.Retriever.docs_chunk(String.to_atom(module)) do
:hidden ->
nil

_ ->
doc_url
end

_ ->
nil
end
end
end
Expand Down
41 changes: 31 additions & 10 deletions lib/ex_doc/retriever.ex
Expand Up @@ -15,9 +15,9 @@ defmodule ExDoc.Retriever do
"""
@spec docs_from_dir(Path.t() | [Path.t()], ExDoc.Config.t()) :: [ExDoc.ModuleNode.t()]
def docs_from_dir(dir, config) when is_binary(dir) do
pattern = if config.filter_prefix, do: "Elixir.#{config.filter_prefix}*.beam", else: "*.beam"
files = Path.wildcard(Path.expand(pattern, dir))
docs_from_files(files, config)
dir
|> files_from_pattern(config)
|> docs_from_files(config)
end

def docs_from_dir(dirs, config) when is_list(dirs) do
Expand Down Expand Up @@ -46,6 +46,21 @@ defmodule ExDoc.Retriever do
end)
end

## Helpers

defp files_from_pattern(dir, config) do
pattern =
if config.filter_prefix do
"Elixir.#{config.filter_prefix}*.beam"
else
"*.beam"
end

pattern
|> Path.expand(dir)
|> Path.wildcard()
end

defp filename_to_module(name) do
name = Path.basename(name, ".beam")
String.to_atom(name)
Expand All @@ -60,10 +75,15 @@ defmodule ExDoc.Retriever do
raise Error, "module #{inspect(module)} is not defined/available"
end

if docs_chunk = docs_chunk(module) do
generate_node(module, docs_chunk, config)
else
[]
case docs_chunk(module) do
false ->
[]

:hidden ->
[]

docs_chunk ->
generate_node(module, docs_chunk, config)
end
end

Expand All @@ -76,10 +96,11 @@ defmodule ExDoc.Retriever do
end
end

@doc false
# Special case required for Elixir
defp docs_chunk(:elixir_bootstrap), do: false
def docs_chunk(:elixir_bootstrap), do: false

defp docs_chunk(module) do
def docs_chunk(module) when is_atom(module) do
unless function_exported?(Code, :fetch_docs, 1) do
raise Error,
"ExDoc 0.19+ requires Elixir v1.7 and later. " <>
Expand All @@ -89,7 +110,7 @@ defmodule ExDoc.Retriever do
if function_exported?(module, :__info__, 1) do
case Code.fetch_docs(module) do
{:docs_v1, _, _, _, :hidden, _, _} ->
false
:hidden

{:docs_v1, _, _, _, _, _, _} = docs ->
docs
Expand Down
17 changes: 17 additions & 0 deletions test/ex_doc/formatter/html_test.exs
Expand Up @@ -544,4 +544,21 @@ defmodule ExDoc.Formatter.HTMLTest do
end
end
end

describe "does not link to local modules with @moduledoc false" do
test "links" do
generate_docs(doc_config())

content = File.read!("#{output_dir()}/LinkToModuledocFalse.html")
assert content =~ ~r[<li><code class="inline">ModuledocFalse</code>]
assert content =~ ~r[<li><code class="inline">ModuledocFalse.foo/0</code>]
assert content =~ ~r[<li><code class="inline">t:ModuledocFalse.t/0</code>]

assert content =~
~r[<li><a href=\"https://hexdocs.pm/elixir/Kernel.ParallelCompiler.html#require/2\"><code class=\"inline\">Kernel.ParallelCompiler.require/2</code></a>]

content = File.read("#{output_dir()}/ModuledocFalse.html")
assert content == {:error, :enoent}
end
end
end
7 changes: 7 additions & 0 deletions test/ex_doc/retriever_test.exs
Expand Up @@ -51,6 +51,13 @@ defmodule ExDoc.RetrieverTest do
"""
end

test "returns modules with @doc false" do
assert [CompiledWithDocs, CompiledWithDocs] ==
["CompiledWithDocs", "ModuledocFalse", "CompiledWithDocs"]
|> docs_from_files()
|> Enum.map(& &1.module)
end

test "returns module group" do
[module_node] =
docs_from_files(["CompiledWithDocs"], groups_for_modules: [Group: [CompiledWithDocs]])
Expand Down
32 changes: 32 additions & 0 deletions test/fixtures/link_to_moduledoc_false.ex
@@ -0,0 +1,32 @@
defmodule LinkToModuledocFalse do
@moduledoc """
Links to the following modules/functions:
- `ModuledocFalse`
- `ModuledocFalse.foo/0`
- `t:ModuledocFalse.t/0`
- `Kernel.ParallelCompiler.require/2`
- `Kernel.Doesnotexist`
- `String`
- `String.foo/0`
- `t:String.t/0`
- `String.Foo`
- `Makeup`
- `Doc.False.hello/0`
- `Doc.Exist.hello/0`
"""

@doc """
Hello world.
## Examples
iex> LinkToModuledocFalse.hello()
:world
"""
def hello do
:world
end
end
12 changes: 12 additions & 0 deletions test/fixtures/moduledoc_false.ex
@@ -0,0 +1,12 @@
defmodule ModuledocFalse do
@moduledoc false

@type t :: term

@doc """
Foo is the new bar
"""
def foo do
:foo
end
end

0 comments on commit 05732c2

Please sign in to comment.