defmodule Chaps.Settings do
strip_docs = fn subsection ->
update_in(
subsection,
[
Access.all(),
Access.elem(1),
Access.filter(fn {k, _v} -> k == :doc end)
],
fn {:doc, _doc} -> {:doc, false} end
)
end
@terminal_options [
print_files: [
doc: """
Whether or not to print a table of files with the coverage of each
file. If set to `false`, the table will not be printed but the overall
coverage will be printed.
""",
type: :boolean,
default: true
],
file_column_width: [
doc: """
The width of the column to fit in file names in the terminal output
table. Set this option to something larger like `80` or `100` if your
project has files with long path names.
""",
type: :integer,
default: 80
],
filter_fully_covered: [
doc: """
Wether to filter fully covered modules from the terminal table.
""",
type: :boolean,
default: true
]
]
@coverage_options [
treat_no_relevant_lines_as_covered: [
doc: """
Wether or not to treat files which have no significant lines of code
as covered (`true`) at 100% or or not covered (`false`) at 0%.
""",
type: :boolean,
default: true
],
output_dir: [
doc: """
The output directory to place the HTML report, if generating an HTML
report with `mix chaps.html`.
""",
type: :string,
default: "cover"
],
template_path: [
doc: """
A path to source a custom template for rendering HTML reports.
Defaults to the internal EEx template within the Chaps library.
""",
type: :string
],
xml_base_dir: [
doc: """
Where to output the XML report if generating an XML report.
""",
type: :string,
default: ""
],
minimum_coverage: [
doc: """
A percentage target for coverage. If the overall coverage falls below
this target, the `mix chaps` tasks will exit with status code 1.
Coverage is floored to the tenths place.
""",
type: :float,
default: 100.0
],
html_filter_fully_covered: [
doc: """
Wether or not to filter fully covered modules from the HTML source.
""",
type: :boolean,
default: true
]
]
@schema NimbleOptions.new!(
default_stop_words: [
doc: """
A default set of words for which coverage should be ignored. This option
should not be customized. Instead configure the `:custom_stop_words`
key.
""",
type: {:list, {:custom, __MODULE__, :validate_regex, []}},
default: [
~r/defmodule/,
~r/defrecord/,
~r/defimpl/,
~r/defexception/,
~r/defprotocol/,
~r/defstruct/,
~r/def.+(.+\\.+).+do/,
~r/^\s+use\s+/
]
],
custom_stop_words: [
doc: """
A customizable set of words for which coverage should be ignored. The
cover module has some difficulty discovering coverage on compile-time
constructs in Elixir, so it can be useful to fully ignore some words.
""",
type: {:list, {:custom, __MODULE__, :validate_regex, []}},
default: []
],
skip_files: [
doc: """
A list of regular expressions to use to ignore matching path names from
the coverage calculation.
""",
type: {:list, {:custom, __MODULE__, :validate_regex, []}},
default: [~r/^test/, ~r/deps/]
],
print_summary: [
doc: """
Whether or not to print the summary of the overall coverage to the
terminal.
""",
type: :boolean,
default: true
],
terminal_options: [
doc: """
A set of terminal-output specific configuration options. See
the Terminal Options section below for inner configuration.
""",
type: :keyword_list,
keys: strip_docs.(@terminal_options),
default: []
],
coverage_options: [
doc: """
A set of options that configure how Chaps calculates coverage.
See the Coverage Options section below for inner configuration.
""",
type: :keyword_list,
keys: strip_docs.(@coverage_options),
default: []
]
)
@moduledoc """
Configurable options used for calculating and displaying coverage status
## Schema
#{NimbleOptions.docs(@schema)}
### Terminal Options
#{NimbleOptions.docs(@terminal_options)}
### Coverage Options
#{NimbleOptions.docs(@coverage_options)}
"""
@doc false
def get_stop_words do
read_config(:default_stop_words) ++ read_config(:custom_stop_words)
end
@doc false
def get_coverage_options, do: read_config(:coverage_options)
@doc false
def default_coverage_value do
if get_coverage_options()[:treat_no_relevant_lines_as_covered],
do: 100.0,
else: 0.0
end
@doc false
def get_terminal_options, do: read_config(:terminal_options)
@doc false
def get_file_col_width do
get_terminal_options()[:file_column_width]
end
@doc false
def get_print_files do
get_terminal_options()[:print_files]
end
@doc false
def get_terminal_filter_fully_covered do
get_terminal_options()[:filter_fully_covered]
end
@doc false
def get_xml_base_dir do
get_coverage_options()[:xml_base_dir]
end
@doc false
def get_skip_files do
read_config(:skip_files)
end
@doc false
def get_print_summary do
read_config(:print_summary)
end
@doc false
def read_config(key) do
:chaps
|> Application.get_all_env()
|> NimbleOptions.validate!(@schema)
|> Keyword.fetch!(key)
end
@doc false
def validate_regex(%Regex{} = regex), do: {:ok, regex}
def validate_regex(binary) when is_binary(binary), do: Regex.compile(binary)
def validate_regex(other),
do: {:error, "must be a regular expression, got: #{inspect(other)}"}
end