Packages
credo
1.7.15
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.7-rc.0
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.2-rc.4
1.7.2-rc.3
1.7.2-rc.2
1.7.2-rc.1
1.7.2-rc.0
1.7.1
1.7.0
1.7.0-rc.2
1.7.0-rc.1
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.5
1.5.0-rc.4
1.5.0-rc.3
1.5.0-rc.2
1.5.0-rc.1
1.4.1
1.4.0
1.4.0-rc.2
1.4.0-rc.1
1.3.2
1.3.1
1.3.0
1.3.0-rc3
1.3.0-rc2
1.3.0-rc1
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc4
1.2.0-rc3
1.2.0-rc2
1.2.0-rc1
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.1.0-rc3
1.1.0-rc2
1.1.0-rc1
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.1-rc1
1.0.0
1.0.0-rc1
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.9.0-rc8
0.9.0-rc7
0.9.0-rc6
0.9.0-rc5
0.9.0-rc4
0.9.0-rc3
0.9.0-rc2
0.9.0-rc1
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.8.0-rc7
0.8.0-rc6
0.8.0-rc5
0.8.0-rc4
0.8.0-rc3
0.8.0-rc2
0.8.0-rc1
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.6.0-rc2
0.6.0-rc1
0.5.3
0.5.2
0.5.1
0.5.0
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.10-dev
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.4.0-beta5
0.4.0-beta4
0.4.0-beta3
0.4.0-beta2
0.4.0-beta1
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.3.0-dev2
0.3.0-dev
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.1-dev
A static code analysis tool with a focus on code consistency and teaching.
Current section
Files
Jump to
Current section
Files
lib/credo/execution/task/validate_config.ex
defmodule Credo.Execution.Task.ValidateConfig do
@moduledoc false
use Credo.Execution.Task
alias Credo.Check
alias Credo.Check.Params
alias Credo.CLI.Output.UI
def call(exec, _opts) do
exec
|> validate_checks()
|> validate_only_checks()
|> validate_ignore_checks()
|> remove_missing_checks()
|> inspect_config_if_debug()
end
defp validate_only_checks(%Execution{only_checks: only_checks} = exec)
when is_list(only_checks) do
if Enum.any?(only_checks, &(&1 == "")) do
UI.warn([
:red,
"** (config) Including all checks, since an empty string was given as a pattern: #{inspect(only_checks)}"
])
end
exec
end
defp validate_only_checks(exec) do
exec
end
defp validate_ignore_checks(%Execution{ignore_checks: ignore_checks} = exec)
when is_list(ignore_checks) do
if Enum.any?(ignore_checks, &(&1 == "")) do
UI.warn([
:red,
"** (config) Ignoring all checks, since an empty string was given as a pattern: #{inspect(ignore_checks)}"
])
end
exec
end
defp validate_ignore_checks(exec) do
exec
end
defp validate_checks(%Execution{checks: %{enabled: checks}} = exec) do
Enum.each(checks, fn check_tuple ->
warn_if_check_missing(check_tuple)
warn_if_check_params_invalid(check_tuple)
end)
exec
end
defp warn_if_check_params_invalid({_check, false}), do: nil
defp warn_if_check_params_invalid({_check, []}), do: nil
defp warn_if_check_params_invalid({check, params}) do
if Check.defined?(check) do
do_warn_if_check_params_invalid({check, params})
end
end
defp do_warn_if_check_params_invalid({check, params}) do
valid_param_names = check.param_names() ++ Params.builtin_param_names()
check = check |> to_string |> String.to_existing_atom()
Enum.each(params, fn {param_name, _param_value} ->
unless Enum.member?(valid_param_names, param_name) do
candidate = find_best_match(valid_param_names, param_name)
warning = warning_message_for(check, param_name, candidate)
UI.warn([:red, warning])
end
end)
end
defp warning_message_for(check, param_name, candidate) do
if candidate do
"** (config) #{check_name(check)}: unknown param `#{param_name}`. Did you mean `#{candidate}`?"
else
"** (config) #{check_name(check)}: unknown param `#{param_name}`."
end
end
defp find_best_match(candidates, given, threshold \\ 0.8) do
given_string = to_string(given)
{jaro_distance, candidate} =
candidates
|> Enum.map(fn candidate_name ->
distance = String.jaro_distance(given_string, to_string(candidate_name))
{distance, candidate_name}
end)
|> Enum.sort()
|> List.last()
if jaro_distance > threshold do
candidate
end
end
defp warn_if_check_missing({check, _params}) do
unless Check.defined?(check) do
UI.warn([:red, "** (config) Ignoring an undefined check: #{check_name(check)}"])
end
end
defp check_name(atom) do
atom
|> to_string()
|> String.replace(~r/^Elixir\./, "")
end
defp inspect_config_if_debug(%Execution{debug: true} = exec) do
require Logger
Logger.debug(fn ->
"""
Execution struct after #{__MODULE__}:
#{inspect(exec, pretty: true)}
"""
end)
exec
end
defp inspect_config_if_debug(exec), do: exec
defp remove_missing_checks(
%Execution{checks: %{enabled: enabled_checks, disabled: disabled_checks}} = exec
) do
enabled_checks = Enum.filter(enabled_checks, &Check.defined?/1)
disabled_checks = Enum.filter(disabled_checks, &Check.defined?/1)
%{exec | checks: %{enabled: enabled_checks, disabled: disabled_checks}}
end
end