zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

cond_statements.ex (2039B)


      1 defmodule Credo.Check.Refactor.CondStatements do
      2   use Credo.Check,
      3     explanations: [
      4       check: """
      5       Each cond statement should have 3 or more statements including the
      6       "always true" statement.
      7 
      8       Consider an `if`/`else` construct if there is only one condition and the
      9       "always true" statement, since it will more accessible to programmers
     10       new to the codebase (and possibly new to Elixir).
     11 
     12       Example:
     13 
     14           cond do
     15             x == y -> 0
     16             true -> 1
     17           end
     18 
     19           # should be written as
     20 
     21           if x == y do
     22             0
     23           else
     24             1
     25           end
     26 
     27       """
     28     ]
     29 
     30   @doc false
     31   @impl true
     32   def run(%SourceFile{} = source_file, params) do
     33     issue_meta = IssueMeta.for(source_file, params)
     34 
     35     Credo.Code.prewalk(source_file, &traverse(&1, &2, issue_meta))
     36   end
     37 
     38   # TODO: consider for experimental check front-loader (ast)
     39   defp traverse({:cond, meta, arguments} = ast, issues, issue_meta) do
     40     conditions =
     41       arguments
     42       |> Credo.Code.Block.do_block_for!()
     43       |> List.wrap()
     44 
     45     count = Enum.count(conditions)
     46 
     47     should_be_written_as_if_else_block? =
     48       count <= 2 && contains_always_matching_condition?(conditions)
     49 
     50     if should_be_written_as_if_else_block? do
     51       {ast, issues ++ [issue_for(issue_meta, meta[:line], :cond)]}
     52     else
     53       {ast, issues}
     54     end
     55   end
     56 
     57   defp traverse(ast, issues, _issue_meta) do
     58     {ast, issues}
     59   end
     60 
     61   defp contains_always_matching_condition?(conditions) do
     62     Enum.any?(conditions, fn
     63       {:->, _meta, [[{name, _meta2, nil}], _args]} when is_atom(name) ->
     64         name |> to_string |> String.starts_with?("_")
     65 
     66       {:->, _meta, [[true], _args]} ->
     67         true
     68 
     69       _ ->
     70         false
     71     end)
     72   end
     73 
     74   defp issue_for(issue_meta, line_no, trigger) do
     75     format_issue(
     76       issue_meta,
     77       message:
     78         "Cond statements should contain at least two conditions besides `true`, consider using `if` instead.",
     79       trigger: trigger,
     80       line_no: line_no
     81     )
     82   end
     83 end