redundant_blank_lines.ex (2396B)
1 defmodule Credo.Check.Readability.RedundantBlankLines do 2 use Credo.Check, 3 base_priority: :low, 4 tags: [:formatter], 5 param_defaults: [max_blank_lines: 1], 6 explanations: [ 7 check: """ 8 Files should not have two or more consecutive blank lines. 9 10 Like all `Readability` issues, this one is not a technical concern. 11 But you can improve the odds of others reading and liking your code by making 12 it easier to follow. 13 """, 14 params: [ 15 max_blank_lines: "The maximum number of tolerated consecutive blank lines." 16 ] 17 ] 18 19 alias Credo.Code.Charlists 20 alias Credo.Code.Heredocs 21 alias Credo.Code.Sigils 22 alias Credo.Code.Strings 23 24 @doc false 25 # TODO: consider for experimental check front-loader (text) 26 def run(%SourceFile{} = source_file, params) do 27 issue_meta = IssueMeta.for(source_file, params) 28 29 max_blank_lines = Params.get(params, :max_blank_lines, __MODULE__) 30 31 source_file 32 |> Charlists.replace_with_spaces("=") 33 |> Sigils.replace_with_spaces("=", "=", source_file.filename) 34 |> Strings.replace_with_spaces("=", "=", source_file.filename) 35 |> Heredocs.replace_with_spaces("=", "=", "=", source_file.filename) 36 |> Credo.Code.to_lines() 37 |> blank_lines() 38 |> consecutive_lines(max_blank_lines) 39 |> Enum.map(fn line -> issue_for(issue_meta, line, max_blank_lines) end) 40 end 41 42 defp issue_for(issue_meta, line, max_blank_lines) do 43 format_issue( 44 issue_meta, 45 message: "There should be no more than #{max_blank_lines} consecutive blank lines.", 46 line_no: line 47 ) 48 end 49 50 defp blank_lines(lines) do 51 lines 52 |> Enum.filter(fn {_, content} -> content == "" end) 53 |> Enum.map(fn {pos, _} -> pos end) 54 end 55 56 defp consecutive_lines([], _), do: [] 57 58 defp consecutive_lines([first_line | other_lines], max_blank_lines) do 59 reducer = consecutive_lines_reducer(max_blank_lines) 60 61 other_lines 62 |> Enum.reduce({first_line, 0, []}, reducer) 63 |> elem(2) 64 end 65 66 defp consecutive_lines_reducer(max_blank_lines) do 67 fn line, {last, consecutive, lines} -> 68 consecutive = 69 if last && line == last + 1 do 70 consecutive + 1 71 else 72 0 73 end 74 75 lines = 76 if consecutive >= max_blank_lines do 77 lines ++ [line] 78 else 79 lines 80 end 81 82 {line, consecutive, lines} 83 end 84 end 85 end