Skip to content
Closed
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
123 changes: 56 additions & 67 deletions lib/mix/tasks/docs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -239,30 +239,22 @@ defmodule Mix.Tasks.Docs do
@doc false
def run(args, config \\ Mix.Project.config(), generator \\ &ExDoc.generate_docs/3) do
Mix.Task.run("compile")

{cli_opts, args, _} = OptionParser.parse(args, aliases: @aliases, switches: @switches)

if args != [] do
Mix.raise("Extraneous arguments on the command line")
end
if args != [], do: Mix.raise("Extraneous arguments on the command line")

project = to_string(config[:name] || config[:app])
version = config[:version] || "dev"

options =
config
|> get_docs_opts()
|> Keyword.merge(cli_opts)
# accepted at root level config
|> normalize_source_url(config)
# accepted at root level config
|> normalize_homepage_url(config)
|> normalize_source_beam(config)
|> normalize_main()
|> normalize_deps()
options = get_docs_opts(config, cli_opts)
# def'd after `get_formatters/1`

for formatter <- get_formatters(options) do
index = generator.(project, version, Keyword.put(options, :formatter, formatter))
log(index)

Mix.shell().info([:green, "Docs successfully generated."])
Mix.shell().info([:green, "View them at #{inspect(index)}."])

index
end
end
Expand All @@ -274,89 +266,86 @@ defmodule Mix.Tasks.Docs do
end
end

defp get_docs_opts(config) do
# Table of Contents:
#
# config
# |> get_docs_opts()
# |> Keyword.merge(cli_opts)
# |> normalize_urls(config, [:source_url, :homepage_url]) # accepted at root level config
# |> normalize_source_beam(config)
# |> normalize_main()
# |> normalize_deps()
#
defp get_docs_opts(config, cli_opts) do
docs = config[:docs]

cond do
is_function(docs, 0) -> docs.()
is_nil(docs) -> []
true -> docs
end
|> Keyword.merge(cli_opts)
# accepted at root level config
|> normalize_urls(config, [:source_url, :homepage_url])
end

defp log(index) do
Mix.shell().info([:green, "Docs successfully generated."])
Mix.shell().info([:green, "View them at #{inspect(index)}."])
defp normalize_urls(options, config, keys) do
Enum.reduce(keys, options, fn key, options_ ->
case Keyword.get(config, key) do
nil -> options_
value -> Keyword.put(options_, key, value)
end
end)
|> normalize_source_beam(config)
end

defp normalize_source_url(options, config) do
if source_url = config[:source_url] do
Keyword.put(options, :source_url, source_url)
else
options
end
end
def normalize_source_beam(options, config) do
source_beam =
case Mix.Project.umbrella?(config) do
false ->
Mix.Project.compile_path()

defp normalize_homepage_url(options, config) do
if homepage_url = config[:homepage_url] do
Keyword.put(options, :homepage_url, homepage_url)
else
options
end
end
true ->
ignored_apps = Keyword.get(options, :ignore_apps, [])
build = Mix.Project.build_path()

defp normalize_source_beam(options, config) do
compile_path =
if Mix.Project.umbrella?(config) do
umbrella_compile_paths(Keyword.get(options, :ignore_apps, []))
else
Mix.Project.compile_path()
for {app, _} <- Mix.Project.apps_paths(),
app not in ignored_apps,
do: Path.join([build, "lib", Atom.to_string(app), "ebin"])
end

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

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

for {app, _} <- Mix.Project.apps_paths(),
app not in ignored_apps do
Path.join([build, "lib", Atom.to_string(app), "ebin"])
end
Keyword.put_new(options, :source_beam, source_beam)
|> normalize_main()
end

defp normalize_main(options) do
main = options[:main]

cond do
is_nil(main) ->
Keyword.delete(options, :main)

is_atom(main) ->
Keyword.put(options, :main, inspect(main))

is_binary(main) ->
options
is_nil(main) -> Keyword.delete(options, :main)
is_atom(main) -> Keyword.put(options, :main, inspect(main))
is_binary(main) -> options
end
|> normalize_deps()
end

defp normalize_deps(options) do
user_deps = Keyword.get(options, :deps, [])

deps =
for {app, doc} <- Keyword.merge(get_deps(), user_deps),
for {app, doc} <- Keyword.merge(get_deps(), Keyword.get(options, :deps, [])),
lib_dir = :code.lib_dir(app),
is_list(lib_dir),
do: {List.to_string(lib_dir), doc}

Keyword.put(options, :deps, deps)
# call stack returns to `run/1`
end

defp get_deps do
for {key, _} <- Mix.Project.deps_paths(),
defp get_deps,
do:
for(
{key, _} <- Mix.Project.deps_paths(),
_ = Application.load(key),
vsn = Application.spec(key, :vsn) do
{key, "https://hexdocs.pm/#{key}/#{vsn}/"}
end
end
vsn = Application.spec(key, :vsn),
do: {key, "https://hexdocs.pm/#{key}/#{vsn}/"}
)
end