defmodule Mix.Tasks.Arch.Explore do use Mix.Task @moduledoc """ Mix task to gather information about the project and store it into the database. It currently gathers information about: - Inventory of applications, modules, functions and macros. - Metrics related to them such as: size and complexity. - Information about test coverage. - Internal dependencies between modules. Usage: mix arch.explore [options] The following options are accepted: * `--no-coverage` avoid running tests and collecting coverage information * `--include-deps` wildcard glob style to filter dependencies """ @shortdoc "Explore current project and stores info into Archeometer DB" @impl Mix.Task def run(argv) do case validate_args(argv) do {:ok, _opts, _args} -> collect( argv -- ["--no-coverage", "coverage"], Enum.member?(argv, "--no-coverage") ) {:error, error} -> Mix.shell().error("Error: #{error}") print_help() {:error, error} end end defp collect(argv, skip_coverage) do if Mix.Task.run("arch.explore.static", argv) == :ok do Mix.Task.run("arch.explore.xrefs", argv) Mix.Task.run("arch.explore.apps", argv) Mix.Task.run("arch.explore.ecto", argv) explore_coverage(skip: skip_coverage) else Mix.shell().error("Error: Could not run static exploration") end end defp explore_coverage(skip: true), do: :ok defp explore_coverage(skip: false) do # Coverage needs to be called as a command in order to set the mix testing environment Mix.Shell.cmd("mix arch.explore.coverage", [env: %{"MIX_ENV" => "test"}], &IO.puts/1) end defp validate_args(argv) do {opts, args, invalid} = OptionParser.parse( argv, strict: [ coverage: :boolean, include_deps: :keep ] ) case invalid do [] -> {:ok, opts, args} _ -> {:error, :wrong_arguments} end end defp print_help() do Mix.shell().info(""" Usage: mix arch.explore [opts] opts: --include-deps 'deps_filter', --no-coverage Where `deps_filter` is a glob Unix-like pattern, matches dependencies name --include-deps can be used more than once. - `*` matches none or many tokens - `?` matches exactly one token - `[abc]` matches a set of tokens - `[a-z]` matches a range of tokens - `[!...]` matches anything but a set of tokens """) end end