From 7cdf6142f88018d29ae1988637e566d60f52df17 Mon Sep 17 00:00:00 2001 From: Leonardo Bork Date: Fri, 13 Jul 2018 11:31:51 -0300 Subject: [PATCH 1/4] Allow apps to be excluded from umbrella app docs --- lib/ex_doc/config.ex | 6 ++- lib/mix/tasks/docs.ex | 22 ++++++-- test/mix/tasks/docs_test.exs | 101 ++++++++++++++++++++++++----------- 3 files changed, 92 insertions(+), 37 deletions(-) diff --git a/lib/ex_doc/config.ex b/lib/ex_doc/config.ex index f4d405f04..0988d9a67 100644 --- a/lib/ex_doc/config.ex +++ b/lib/ex_doc/config.ex @@ -40,7 +40,8 @@ defmodule ExDoc.Config do source_url: nil, source_url_pattern: nil, title: nil, - version: nil + version: nil, + ignored_apps: [] @type t :: %__MODULE__{ assets: nil | String.t(), @@ -68,6 +69,7 @@ defmodule ExDoc.Config do source_url: nil | String.t(), source_url_pattern: nil | String.t(), title: nil | String.t(), - version: nil | String.t() + version: nil | String.t(), + ignored_apps: list() } end diff --git a/lib/mix/tasks/docs.ex b/lib/mix/tasks/docs.ex index 29992a3f6..c39a29cc4 100644 --- a/lib/mix/tasks/docs.ex +++ b/lib/mix/tasks/docs.ex @@ -249,7 +249,7 @@ 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(get_ignored_apps(options)) else Mix.Project.compile_path() end @@ -257,11 +257,15 @@ defmodule Mix.Tasks.Docs do 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 - Path.join([build, "lib", Atom.to_string(app), "ebin"]) + app_name = Atom.to_string(app) + + unless(Enum.member?(ignored_apps, app_name)) do + Path.join([build, "lib", app_name, "ebin"]) + end end end @@ -280,6 +284,18 @@ defmodule Mix.Tasks.Docs do end end + defp get_ignored_apps(options) do + ignored_apps = options[:ignored_apps] + + cond do + is_nil(ignored_apps) -> + Keyword.put(options, :ignored_apps, []) + + is_list(ignored_apps) -> + ignored_apps + end + end + defp normalize_deps(options) do user_deps = Keyword.get(options, :deps, []) diff --git a/test/mix/tasks/docs_test.exs b/test/mix/tasks/docs_test.exs index c2b084e1f..6e223d76c 100644 --- a/test/mix/tasks/docs_test.exs +++ b/test/mix/tasks/docs_test.exs @@ -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 ignored_apps" do + Mix.Project.in_project(:umbrella, "test/fixtures/umbrella", fn _mod -> + [ + {"umbrella", "dev", + [ + formatter: "html", + deps: _, + source_beam: _, + ignored_apps: ["foo"] + ]} + ] = run([], app: :umbrella, apps_path: "apps/", docs: [ignored_apps: ["foo"]]) + end) end end From 8d259b22f8e18884508f31e0fde54827b29cf273 Mon Sep 17 00:00:00 2001 From: Leonardo Bork Date: Fri, 13 Jul 2018 20:44:56 -0300 Subject: [PATCH 2/4] Change to :ignore_apps, document and simplify --- lib/ex_doc/config.ex | 6 ++---- lib/mix/tasks/docs.ex | 25 ++++++++----------------- test/mix/tasks/docs_test.exs | 6 +++--- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/lib/ex_doc/config.ex b/lib/ex_doc/config.ex index 0988d9a67..f4d405f04 100644 --- a/lib/ex_doc/config.ex +++ b/lib/ex_doc/config.ex @@ -40,8 +40,7 @@ defmodule ExDoc.Config do source_url: nil, source_url_pattern: nil, title: nil, - version: nil, - ignored_apps: [] + version: nil @type t :: %__MODULE__{ assets: nil | String.t(), @@ -69,7 +68,6 @@ defmodule ExDoc.Config do source_url: nil | String.t(), source_url_pattern: nil | String.t(), title: nil | String.t(), - version: nil | String.t(), - ignored_apps: list() + version: nil | String.t() } end diff --git a/lib/mix/tasks/docs.ex b/lib/mix/tasks/docs.ex index c39a29cc4..0b2d5be7c 100644 --- a/lib/mix/tasks/docs.ex +++ b/lib/mix/tasks/docs.ex @@ -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 @@ -164,6 +167,8 @@ defmodule Mix.Tasks.Docs do mix cmd mix docs + As said, ignoring documentation for nested projects can be achieved by utilizing the `:ignore_apps` configuration. + See `mix help cmd` for more information. """ @@ -249,7 +254,7 @@ defmodule Mix.Tasks.Docs do defp normalize_source_beam(options, config) do compile_path = if Mix.Project.umbrella?(config) do - umbrella_compile_paths(get_ignored_apps(options)) + umbrella_compile_paths(Keyword.get(options, :ignore_apps, [])) else Mix.Project.compile_path() end @@ -261,10 +266,8 @@ defmodule Mix.Tasks.Docs do build = Mix.Project.build_path() for {app, _} <- Mix.Project.apps_paths() do - app_name = Atom.to_string(app) - - unless(Enum.member?(ignored_apps, app_name)) do - Path.join([build, "lib", app_name, "ebin"]) + unless(Enum.member?(ignored_apps, app)) do + Path.join([build, "lib", Atom.to_string(app), "ebin"]) end end end @@ -284,18 +287,6 @@ defmodule Mix.Tasks.Docs do end end - defp get_ignored_apps(options) do - ignored_apps = options[:ignored_apps] - - cond do - is_nil(ignored_apps) -> - Keyword.put(options, :ignored_apps, []) - - is_list(ignored_apps) -> - ignored_apps - end - end - defp normalize_deps(options) do user_deps = Keyword.get(options, :deps, []) diff --git a/test/mix/tasks/docs_test.exs b/test/mix/tasks/docs_test.exs index 6e223d76c..da99ad857 100644 --- a/test/mix/tasks/docs_test.exs +++ b/test/mix/tasks/docs_test.exs @@ -111,7 +111,7 @@ defmodule Mix.Tasks.DocsTest do end) end - test "supports umbrella project with ignored_apps" do + test "supports umbrella project with ignore_apps" do Mix.Project.in_project(:umbrella, "test/fixtures/umbrella", fn _mod -> [ {"umbrella", "dev", @@ -119,9 +119,9 @@ defmodule Mix.Tasks.DocsTest do formatter: "html", deps: _, source_beam: _, - ignored_apps: ["foo"] + ignore_apps: [:foo] ]} - ] = run([], app: :umbrella, apps_path: "apps/", docs: [ignored_apps: ["foo"]]) + ] = run([], app: :umbrella, apps_path: "apps/", docs: [ignore_apps: [:foo]]) end) end end From 3da2b3166e285664d2ec669b5dc392288cf33d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 14 Jul 2018 08:38:24 +0200 Subject: [PATCH 3/4] Update docs.ex --- lib/mix/tasks/docs.ex | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/mix/tasks/docs.ex b/lib/mix/tasks/docs.ex index 0b2d5be7c..8952c9138 100644 --- a/lib/mix/tasks/docs.ex +++ b/lib/mix/tasks/docs.ex @@ -161,14 +161,13 @@ 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: mix cmd mix docs - As said, ignoring documentation for nested projects can be achieved by utilizing the `:ignore_apps` configuration. - See `mix help cmd` for more information. """ From 30150d22c217348dac813bdebc3021e79e5a113a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 14 Jul 2018 08:39:16 +0200 Subject: [PATCH 4/4] Update docs.ex --- lib/mix/tasks/docs.ex | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/mix/tasks/docs.ex b/lib/mix/tasks/docs.ex index 8952c9138..f89971224 100644 --- a/lib/mix/tasks/docs.ex +++ b/lib/mix/tasks/docs.ex @@ -264,10 +264,9 @@ defmodule Mix.Tasks.Docs do defp umbrella_compile_paths(ignored_apps) do build = Mix.Project.build_path() - for {app, _} <- Mix.Project.apps_paths() do - unless(Enum.member?(ignored_apps, app)) do - Path.join([build, "lib", Atom.to_string(app), "ebin"]) - end + for {app, _} <- Mix.Project.apps_paths(), + app not in ignored_apps do + Path.join([build, "lib", Atom.to_string(app), "ebin"]) end end