config_builder.ex (9029B)
1 defmodule Credo.ConfigBuilder do 2 alias Credo.CLI.Filename 3 alias Credo.CLI.Options 4 alias Credo.ConfigFile 5 alias Credo.Execution 6 7 @pattern_split_regex ~r/,\s*/ 8 9 def parse(exec) do 10 options = exec.cli_options 11 12 case get_config_file(exec, options) do 13 {:ok, config_file} -> 14 exec 15 |> add_config_file_to_exec(config_file) 16 |> add_strict_to_exec(config_file, options) 17 |> add_switches_to_exec(options.switches) 18 |> run_cli_switch_plugin_param_converters() 19 20 {:error, _} = error -> 21 error 22 end 23 end 24 25 defp get_config_file(exec, %Options{} = options) do 26 config_name = options.switches[:config_name] 27 config_filename = options.switches[:config_file] 28 dir = Filename.remove_line_no_and_column(options.path) 29 30 if is_binary(config_filename) do 31 filename = Path.expand(config_filename) 32 33 ConfigFile.read_from_file_path(exec, dir, filename, config_name) 34 else 35 ConfigFile.read_or_default(exec, dir, config_name) 36 end 37 end 38 39 defp add_config_file_to_exec(exec, %ConfigFile{} = config_file) do 40 %Execution{ 41 exec 42 | files: config_file.files, 43 color: config_file.color, 44 checks: config_file.checks, 45 requires: config_file.requires, 46 plugins: config_file.plugins, 47 parse_timeout: config_file.parse_timeout 48 } 49 end 50 51 defp add_strict_to_exec(exec, %ConfigFile{} = config_file, options) do 52 %Execution{ 53 exec 54 | strict: strict_via_args_or_config_file?(options.args, config_file) 55 } 56 end 57 58 defp strict_via_args_or_config_file?([], config_file) do 59 config_file.strict 60 end 61 62 defp strict_via_args_or_config_file?([potential_path | _], config_file) do 63 user_expecting_explain_command? = Filename.contains_line_no?(potential_path) 64 65 user_expecting_explain_command? || config_file.strict 66 end 67 68 defp add_switches_to_exec(%Execution{} = exec, switches) do 69 exec 70 |> add_switch_all(switches) 71 |> add_switch_color(switches) 72 |> add_switch_crash_on_error(switches) 73 |> add_switch_debug(switches) 74 |> add_switch_enable_disabled_checks(switches) 75 |> add_switch_files_excluded(switches) 76 |> add_switch_files_included(switches) 77 |> add_switch_checks_without_tag(switches) 78 |> add_switch_checks_with_tag(switches) 79 |> add_switch_format(switches) 80 |> add_switch_help(switches) 81 |> add_switch_ignore(switches) 82 |> add_switch_mute_exit_status(switches) 83 |> add_switch_only(switches) 84 |> add_switch_read_from_stdin(switches) 85 |> add_switch_strict(switches) 86 |> add_switch_min_priority(switches) 87 |> add_switch_verbose(switches) 88 |> add_switch_version(switches) 89 end 90 91 # add_switch_all 92 93 defp add_switch_all(exec, %{all: true}) do 94 %Execution{exec | all: true} 95 end 96 97 defp add_switch_all(exec, _), do: exec 98 99 # add_switch_files_included 100 101 defp add_switch_files_included(exec, %{files_included: [_head | _tail] = files_included}) do 102 %Execution{exec | files: %{exec.files | included: files_included}} 103 end 104 105 defp add_switch_files_included(exec, _), do: exec 106 107 # add_switch_files_excluded 108 109 defp add_switch_files_excluded(exec, %{files_excluded: [_head | _tail] = files_excluded}) do 110 %Execution{exec | files: %{exec.files | excluded: files_excluded}} 111 end 112 113 defp add_switch_files_excluded(exec, _), do: exec 114 115 # add_switch_checks_with_tag 116 117 defp add_switch_checks_with_tag(exec, %{ 118 checks_with_tag: [_head | _tail] = checks_with_tag 119 }) do 120 %Execution{exec | only_checks_tags: checks_with_tag} 121 end 122 123 defp add_switch_checks_with_tag(exec, _), do: exec 124 125 # add_switch_checks_without_tag 126 127 defp add_switch_checks_without_tag(exec, %{ 128 checks_without_tag: [_head | _tail] = checks_without_tag 129 }) do 130 %Execution{exec | ignore_checks_tags: checks_without_tag} 131 end 132 133 defp add_switch_checks_without_tag(exec, _), do: exec 134 135 # add_switch_color 136 137 defp add_switch_color(exec, %{color: color}) do 138 %Execution{exec | color: color} 139 end 140 141 defp add_switch_color(exec, _), do: exec 142 143 # add_switch_debug 144 145 defp add_switch_debug(exec, %{debug: debug}) do 146 %Execution{exec | debug: debug} 147 end 148 149 defp add_switch_debug(exec, _), do: exec 150 151 # add_switch_strict 152 153 defp add_switch_strict(exec, %{all_priorities: true}) do 154 add_switch_strict(exec, %{strict: true}) 155 end 156 157 defp add_switch_strict(exec, %{strict: true}) do 158 new_config = %Execution{exec | strict: true} 159 160 Execution.set_strict(new_config) 161 end 162 163 defp add_switch_strict(exec, %{strict: false}) do 164 new_config = %Execution{exec | strict: false} 165 166 Execution.set_strict(new_config) 167 end 168 169 defp add_switch_strict(exec, _), do: Execution.set_strict(exec) 170 171 defp add_switch_help(exec, %{help: true}) do 172 %Execution{exec | help: true} 173 end 174 175 defp add_switch_help(exec, _), do: exec 176 177 # add_switch_verbose 178 179 defp add_switch_verbose(exec, %{verbose: true}) do 180 %Execution{exec | verbose: true} 181 end 182 183 defp add_switch_verbose(exec, _), do: exec 184 185 # add_switch_crash_on_error 186 187 defp add_switch_crash_on_error(exec, %{crash_on_error: true}) do 188 %Execution{exec | crash_on_error: true} 189 end 190 191 defp add_switch_crash_on_error(exec, _), do: exec 192 193 # add_switch_mute_exit_status 194 195 defp add_switch_mute_exit_status(exec, %{mute_exit_status: true}) do 196 %Execution{exec | mute_exit_status: true} 197 end 198 199 defp add_switch_mute_exit_status(exec, _), do: exec 200 201 # add_switch_read_from_stdin 202 203 defp add_switch_read_from_stdin(exec, %{read_from_stdin: true}) do 204 %Execution{exec | read_from_stdin: true} 205 end 206 207 defp add_switch_read_from_stdin(exec, _), do: exec 208 209 # add_switch_version 210 211 defp add_switch_version(exec, %{version: true}) do 212 %Execution{exec | version: true} 213 end 214 215 defp add_switch_version(exec, _), do: exec 216 217 # add_switch_format 218 219 defp add_switch_format(exec, %{format: format}) do 220 %Execution{exec | format: format} 221 end 222 223 defp add_switch_format(exec, _), do: exec 224 225 # add_switch_min_priority 226 227 defp add_switch_min_priority(exec, %{min_priority: min_priority}) do 228 %Execution{exec | min_priority: min_priority} 229 end 230 231 defp add_switch_min_priority(exec, _), do: exec 232 233 # add_switch_enable_disabled_checks 234 235 defp add_switch_enable_disabled_checks(exec, %{enable_disabled_checks: check_pattern}) do 236 %Execution{exec | enable_disabled_checks: String.split(check_pattern, @pattern_split_regex)} 237 end 238 239 defp add_switch_enable_disabled_checks(exec, _), do: exec 240 241 # add_switch_only 242 243 # exclude/ignore certain checks 244 defp add_switch_only(exec, %{only: only}) do 245 add_switch_only(exec, %{checks: only}) 246 end 247 248 # this catches a `--checks/only` without an argument after it 249 defp add_switch_only(exec, %{checks: true}) do 250 exec 251 end 252 253 defp add_switch_only(exec, %{checks: check_pattern}) do 254 new_config = %Execution{ 255 exec 256 | strict: true, 257 only_checks: String.split(check_pattern, @pattern_split_regex) 258 } 259 260 Execution.set_strict(new_config) 261 end 262 263 defp add_switch_only(exec, _), do: exec 264 265 # add_switch_ignore 266 267 # exclude/ignore certain checks 268 defp add_switch_ignore(exec, %{ignore: ignore}) do 269 add_switch_ignore(exec, %{ignore_checks: ignore}) 270 end 271 272 # this catches a `--ignore-checks/ignore` without an argument after it 273 defp add_switch_ignore(exec, %{ignore_checks: true}) do 274 exec 275 end 276 277 defp add_switch_ignore(exec, %{ignore_checks: ignore_pattern}) do 278 %Execution{exec | ignore_checks: String.split(ignore_pattern, @pattern_split_regex)} 279 end 280 281 defp add_switch_ignore(exec, _), do: exec 282 283 defp run_cli_switch_plugin_param_converters(exec) do 284 Enum.reduce( 285 exec.cli_switch_plugin_param_converters, 286 exec, 287 &reduce_converters/2 288 ) 289 end 290 291 defp reduce_converters({_switch_name, _plugin_mod, false}, exec) do 292 exec 293 end 294 295 defp reduce_converters({switch_name, plugin_mod, true}, exec) do 296 reduce_converters({switch_name, plugin_mod, switch_name}, exec) 297 end 298 299 defp reduce_converters({switch_name, plugin_mod, param_name}, exec) when is_atom(param_name) do 300 converter_fun = fn switch_value -> {param_name, switch_value} end 301 302 reduce_converters({switch_name, plugin_mod, converter_fun}, exec) 303 end 304 305 defp reduce_converters({switch_name, plugin_mod, converter_fun}, exec) 306 when is_function(converter_fun) do 307 case Execution.get_given_cli_switch(exec, switch_name) do 308 {:ok, switch_value} -> 309 validate_converter_fun_result(exec, plugin_mod, switch_name, converter_fun.(switch_value)) 310 311 _ -> 312 exec 313 end 314 end 315 316 defp validate_converter_fun_result(exec, plugin_mod, _switch_name, {param_name, param_value}) do 317 Execution.put_plugin_param(exec, plugin_mod, param_name, param_value) 318 end 319 320 defp validate_converter_fun_result(_exec, plugin_mod, switch_name, value) do 321 raise "Expected CLI switch to plugin param converter function to return a two-element tuple of {param_name, param_value}, got #{inspect(value)} (plugin: #{inspect(plugin_mod)}, switch: #{inspect(switch_name)})" 322 end 323 end