block_pipe.ex (2427B)
1 defmodule Credo.Check.Readability.BlockPipe do 2 use Credo.Check, 3 tags: [:controversial], 4 param_defaults: [ 5 exclude: [] 6 ], 7 explanations: [ 8 check: """ 9 Pipes (`|>`) should not be used with blocks. 10 11 The code in this example ... 12 13 list 14 |> Enum.take(5) 15 |> Enum.sort() 16 |> case do 17 [[_h | _t] | _] -> true 18 _ -> false 19 end 20 21 ... should be refactored to look like this: 22 23 maybe_nested_lists = 24 list 25 |> Enum.take(5) 26 |> Enum.sort() 27 28 case maybe_nested_lists do 29 [[_h | _t] | _] -> true 30 _ -> false 31 end 32 33 ... or create a new function: 34 35 list 36 |> Enum.take(5) 37 |> Enum.sort() 38 |> contains_nested_list?() 39 40 Piping to blocks may be harder to read because it can be said that it obscures intentions 41 and increases cognitive load on the reader. Instead, prefer introducing variables to your code or 42 new functions when it may be a sign that your function is getting too complicated and/or has too many concerns. 43 44 Like all `Readability` issues, this one is not a technical concern, but you can improve the odds of others reading 45 and understanding the intent of your code by making it easier to follow. 46 """, 47 params: [ 48 exclude: "Do not raise an issue for these macros and functions." 49 ] 50 ] 51 52 @doc false 53 @impl true 54 def run(%SourceFile{} = source_file, params) do 55 excluded_functions = Params.get(params, :exclude, __MODULE__) 56 57 issue_meta = IssueMeta.for(source_file, params) 58 59 Credo.Code.prewalk( 60 source_file, 61 &traverse(&1, &2, excluded_functions, issue_meta) 62 ) 63 end 64 65 defp traverse( 66 {:|>, meta, [_, {function, _, [[{:do, _} | _]]}]} = ast, 67 issues, 68 excluded_functions, 69 issue_meta 70 ) do 71 if Enum.member?(excluded_functions, function) do 72 {ast, issues} 73 else 74 {nil, issues ++ [issue_for(issue_meta, meta[:line], "|>")]} 75 end 76 end 77 78 defp traverse(ast, issues, _excluded_functions, _issue_meta) do 79 {ast, issues} 80 end 81 82 defp issue_for(issue_meta, line_no, trigger) do 83 format_issue( 84 issue_meta, 85 message: "Use a variable or create a new function instead of piping to a block", 86 trigger: trigger, 87 line_no: line_no 88 ) 89 end 90 end