module_names.ex (1868B)
1 defmodule Credo.Check.Readability.ModuleNames do 2 use Credo.Check, 3 base_priority: :high, 4 explanations: [ 5 check: """ 6 Module names are always written in PascalCase in Elixir. 7 8 # PascalCase 9 10 defmodule MyApp.WebSearchController do 11 # ... 12 end 13 14 # not PascalCase 15 16 defmodule MyApp.Web_searchController do 17 # ... 18 end 19 20 Like all `Readability` issues, this one is not a technical concern. 21 But you can improve the odds of other reading and liking your code by making 22 it easier to follow. 23 """ 24 ] 25 26 alias Credo.Code.Name 27 28 @doc false 29 @impl true 30 def run(%SourceFile{} = source_file, params) do 31 issue_meta = IssueMeta.for(source_file, params) 32 33 Credo.Code.prewalk(source_file, &traverse(&1, &2, issue_meta)) 34 end 35 36 defp traverse({:defmodule, _meta, arguments} = ast, issues, issue_meta) do 37 {ast, issues_for_def(arguments, issues, issue_meta)} 38 end 39 40 defp traverse(ast, issues, _issue_meta) do 41 {ast, issues} 42 end 43 44 defp issues_for_def(body, issues, issue_meta) do 45 case Enum.at(body, 0) do 46 {:__aliases__, meta, names} -> 47 names 48 |> Enum.filter(&String.Chars.impl_for/1) 49 |> Enum.join(".") 50 |> issues_for_name(meta, issues, issue_meta) 51 52 _ -> 53 issues 54 end 55 end 56 57 defp issues_for_name(name, meta, issues, issue_meta) do 58 all_pascal_case? = 59 name 60 |> to_string 61 |> String.split(".") 62 |> Enum.all?(&Name.pascal_case?/1) 63 64 if all_pascal_case? do 65 issues 66 else 67 [issue_for(issue_meta, meta[:line], name) | issues] 68 end 69 end 70 71 defp issue_for(issue_meta, line_no, trigger) do 72 format_issue( 73 issue_meta, 74 message: "Module names should be written in PascalCase.", 75 trigger: trigger, 76 line_no: line_no 77 ) 78 end 79 end