runner.ex (3069B)
1 defmodule Credo.Check.Runner do 2 @moduledoc false 3 4 # This module is responsible for running checks based on the context represented 5 # by the current `Credo.Execution`. 6 7 alias Credo.Check.Params 8 alias Credo.CLI.Output.UI 9 alias Credo.Execution 10 alias Credo.Execution.ExecutionTiming 11 12 @doc """ 13 Runs all checks on all source files (according to the config). 14 """ 15 def run(source_files, exec) when is_list(source_files) do 16 check_tuples = 17 exec 18 |> Execution.checks() 19 |> warn_about_ineffective_patterns(exec) 20 |> fix_deprecated_notation_for_checks_without_params() 21 22 Credo.Check.Worker.run(check_tuples, exec.max_concurrent_check_runs, fn check_tuple -> 23 run_check(exec, check_tuple) 24 end) 25 26 :ok 27 end 28 29 defp run_check(%Execution{debug: true} = exec, {check, params}) do 30 ExecutionTiming.run(&do_run_check/2, [exec, {check, params}]) 31 |> ExecutionTiming.append(exec, task: exec.current_task, check: check) 32 end 33 34 defp run_check(exec, {check, params}) do 35 do_run_check(exec, {check, params}) 36 end 37 38 defp do_run_check(exec, {check, params}) do 39 rerun_files_that_changed = Params.get_rerun_files_that_changed(params) 40 41 files_included = Params.files_included(params, check) 42 files_excluded = Params.files_excluded(params, check) 43 44 found_relevant_files = 45 if files_included == [] and files_excluded == [] do 46 [] 47 else 48 exec 49 |> Execution.working_dir() 50 |> Credo.Sources.find_in_dir(files_included, files_excluded) 51 end 52 53 source_files = 54 exec 55 |> Execution.get_source_files() 56 |> filter_source_files(rerun_files_that_changed) 57 |> filter_source_files(found_relevant_files) 58 59 try do 60 check.run_on_all_source_files(exec, source_files, params) 61 rescue 62 error -> 63 warn_about_failed_run(check, source_files) 64 65 if exec.crash_on_error do 66 reraise error, __STACKTRACE__ 67 else 68 [] 69 end 70 end 71 end 72 73 defp filter_source_files(source_files, []) do 74 source_files 75 end 76 77 defp filter_source_files(source_files, files_included) do 78 Enum.filter(source_files, fn source_file -> 79 Enum.member?(files_included, Path.expand(source_file.filename)) 80 end) 81 end 82 83 defp warn_about_failed_run(check, %Credo.SourceFile{} = source_file) do 84 UI.warn("Error while running #{check} on #{source_file.filename}") 85 end 86 87 defp warn_about_failed_run(check, _) do 88 UI.warn("Error while running #{check}") 89 end 90 91 defp fix_deprecated_notation_for_checks_without_params(checks) do 92 Enum.map(checks, fn 93 {check} -> {check, []} 94 {check, params} -> {check, params} 95 end) 96 end 97 98 defp warn_about_ineffective_patterns( 99 {checks, _included_checks, []}, 100 %Execution{ignore_checks: [_ | _] = ignore_checks} 101 ) do 102 UI.warn([ 103 :red, 104 "A pattern was given to ignore checks, but it did not match any: ", 105 inspect(ignore_checks) 106 ]) 107 108 checks 109 end 110 111 defp warn_about_ineffective_patterns({checks, _, _}, _) do 112 checks 113 end 114 end