Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
13 changes: 9 additions & 4 deletions lib/mix/tasks/docs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ defmodule Mix.Tasks.Docs do

* `:output` - Output directory for the generated docs; default: "doc".
May be overridden by command line argument.

*`:ignore_apps` - Apps to be ignored when generating documentation in an umbrella project.
Receives a list of atoms. Example: `[:first_app, :second_app]`.

## Groups

Expand Down Expand Up @@ -158,7 +161,8 @@ defmodule Mix.Tasks.Docs do
## Umbrella project

ExDoc can be used in an umbrella project and generates a single documentation
for all child apps.
for all child apps. You can use the `:ignore_apps` configuration to exclude
certain projects in the umbrella from documentation.

Generating documentation per each child app can be achieved by running:

Expand Down Expand Up @@ -249,18 +253,19 @@ defmodule Mix.Tasks.Docs do
defp normalize_source_beam(options, config) do
compile_path =
if Mix.Project.umbrella?(config) do
umbrella_compile_paths()
umbrella_compile_paths(Keyword.get(options, :ignore_apps, []))
else
Mix.Project.compile_path()
end

Keyword.put_new(options, :source_beam, compile_path)
end

defp umbrella_compile_paths do
defp umbrella_compile_paths(ignored_apps) do
build = Mix.Project.build_path()

for {app, _} <- Mix.Project.apps_paths() do
for {app, _} <- Mix.Project.apps_paths(),
app not in ignored_apps do
Path.join([build, "lib", Atom.to_string(app), "ebin"])
end
end
Expand Down
101 changes: 69 additions & 32 deletions test/mix/tasks/docs_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,80 +11,117 @@ defmodule Mix.Tasks.DocsTest do

test "inflects values from app and version" do
assert [{"ex_doc", "0.1.0", [formatter: "html", deps: _, source_beam: _]}] =
run([], [app: :ex_doc, version: "0.1.0"])
run([], app: :ex_doc, version: "0.1.0")
end

test "accepts multiple formatters from CLI" do
assert [{"ex_doc", "0.1.0", [formatter: "html", deps: _, source_beam: _]},
{"ex_doc", "0.1.0", [formatter: "epub", deps: _, source_beam: _]}] =
run(["-f", "html", "-f", "epub"], [app: :ex_doc, version: "0.1.0"])
assert [
{"ex_doc", "0.1.0", [formatter: "html", deps: _, source_beam: _]},
{"ex_doc", "0.1.0", [formatter: "epub", deps: _, source_beam: _]}
] = run(["-f", "html", "-f", "epub"], app: :ex_doc, version: "0.1.0")
end

test "accepts multiple formatters from config" do
assert [{"ex_doc", "0.1.0", [formatter: "html", deps: _, source_beam: _, formatters: _]},
{"ex_doc", "0.1.0", [formatter: "epub", deps: _, source_beam: _, formatters: _]}] =
run([], [app: :ex_doc, version: "0.1.0", docs: [formatters: ["html", "epub"]]])
assert [
{"ex_doc", "0.1.0", [formatter: "html", deps: _, source_beam: _, formatters: _]},
{"ex_doc", "0.1.0", [formatter: "epub", deps: _, source_beam: _, formatters: _]}
] = run([], app: :ex_doc, version: "0.1.0", docs: [formatters: ["html", "epub"]])
end

test "uses the given name" do
assert [{"ExDoc", "0.1.0", [formatter: "html", deps: _, source_beam: _]}] =
run([], [app: :ex_doc, version: "0.1.0", name: "ExDoc"])
run([], app: :ex_doc, version: "0.1.0", name: "ExDoc")
end

test "accepts modules in :main" do
assert [{"ex_doc", "dev", [formatter: "html", deps: _, main: "Sample", source_beam: _, ]}] =
run([], [app: :ex_doc, docs: [main: Sample]])
assert [{"ex_doc", "dev", [formatter: "html", deps: _, main: "Sample", source_beam: _]}] =
run([], app: :ex_doc, docs: [main: Sample])
end

test "accepts files in :main" do
assert [{"ex_doc", "dev", [formatter: "html", deps: _, source_beam: _, main: "another"]}] =
run([], [app: :ex_doc, docs: [main: "another"]])
run([], app: :ex_doc, docs: [main: "another"])
end

test "accepts output in :output" do
assert [{"ex_doc", "dev", [formatter: "html", deps: _, source_beam: _, output: "hello"]}] =
run([], [app: :ex_doc, docs: [output: "hello"]])
run([], app: :ex_doc, docs: [output: "hello"])
end

test "parses output with lower preference than options" do
assert [{"ex_doc", "dev", [formatter: "html", deps: _, source_beam: _, output: "world"]}] =
run(~w(-o world), [app: :ex_doc, docs: [output: "world"]])
run(~w(-o world), app: :ex_doc, docs: [output: "world"])
end

test "includes dependencies" do
assert [{"ex_doc", "dev", [formatter: "html", deps: deps, source_beam: _]}] =
run([], [app: :ex_doc, docs: []])
run([], app: :ex_doc, docs: [])

assert List.keyfind(deps, Application.app_dir(:earmark), 0) ==
{Application.app_dir(:earmark), "https://hexdocs.pm/earmark/#{Application.spec(:earmark, :vsn)}/"}
{Application.app_dir(:earmark),
"https://hexdocs.pm/earmark/#{Application.spec(:earmark, :vsn)}/"}
end

test "allows custom dependency paths" do
assert [{"ex_doc", "dev", [formatter: "html", deps: deps, source_beam: _]}] =
run([], [app: :ex_doc, docs: [deps: [earmark: "foo"]]])
run([], app: :ex_doc, docs: [deps: [earmark: "foo"]])

assert List.keyfind(deps, Application.app_dir(:earmark), 0) ==
{Application.app_dir(:earmark), "foo"}
{Application.app_dir(:earmark), "foo"}
end

test "accepts lazy docs" do
assert [{"ex_doc", "dev", [formatter: "html", deps: _, source_beam: _, main: "another"]}] =
run([], [app: :ex_doc, docs: fn -> [main: "another"] end])
run([], app: :ex_doc, docs: fn -> [main: "another"] end)
end

test "accepts options from root" do
# accepted options are: `app`, `name`, `source_url`, `homepage_url`, `version`
assert [{"ExDoc", "1.2.3-dev",
[formatter: "html",
deps: _, source_beam: _,
homepage_url: "http://elixir-lang.org",
source_url: "https://github.com/elixir-lang/ex_doc",
]}] =
run([], [app: :ex_doc,
name: "ExDoc",
source_url: "https://github.com/elixir-lang/ex_doc",
homepage_url: "http://elixir-lang.org",
version: "1.2.3-dev",
])

assert [{"ex_doc", "dev", _}] = run([], [app: :ex_doc])
assert [
{"ExDoc", "1.2.3-dev",
[
formatter: "html",
deps: _,
source_beam: _,
homepage_url: "http://elixir-lang.org",
source_url: "https://github.com/elixir-lang/ex_doc"
]}
] =
run([],
app: :ex_doc,
name: "ExDoc",
source_url: "https://github.com/elixir-lang/ex_doc",
homepage_url: "http://elixir-lang.org",
version: "1.2.3-dev"
)

assert [{"ex_doc", "dev", _}] = run([], app: :ex_doc)
end

test "supports umbrella project" do
Mix.Project.in_project(:umbrella, "test/fixtures/umbrella", fn _mod ->
[
{"umbrella", "dev",
[
formatter: "html",
deps: _,
source_beam: _
]}
] = run([], app: :umbrella, apps_path: "apps/", docs: [])
end)
end

test "supports umbrella project with ignore_apps" do
Mix.Project.in_project(:umbrella, "test/fixtures/umbrella", fn _mod ->
[
{"umbrella", "dev",
[
formatter: "html",
deps: _,
source_beam: _,
ignore_apps: [:foo]
]}
] = run([], app: :umbrella, apps_path: "apps/", docs: [ignore_apps: [:foo]])
end)
end
end