Repository: rrrene/credo
Pull request #640 (2019-03-07 12:06:45)

Add UnnecessaryAliasExpansion check
I noticed we don’t have a check for this kind of code : 

```elixir
alias Foo.{Bar}
```

Alias expansion with braces is great but I think it affects the code readability when it’s used with a list containing a single item; it should be written : 

```elixir
alias Foo.Bar
```

This new `UnnecessaryAliasExpansion` check makes sure this rule is followed 😄


Patch:
diff --git a/.credo.exs b/.credo.exs
index 11a35546..97d79093 100644
--- a/.credo.exs
+++ b/.credo.exs
@@ -93,6 +93,7 @@
         {Credo.Check.Readability.StringSigils, []},
         {Credo.Check.Readability.TrailingBlankLine, []},
         {Credo.Check.Readability.TrailingWhiteSpace, []},
+        {Credo.Check.Readability.UnnecessaryAliasExpansion, []},
         {Credo.Check.Readability.VariableNames, []},
 
         #
diff --git a/lib/credo/check/readability/unnecessary_alias_expansion.ex b/lib/credo/check/readability/unnecessary_alias_expansion.ex
new file mode 100644
index 00000000..f0887742
--- /dev/null
+++ b/lib/credo/check/readability/unnecessary_alias_expansion.ex
@@ -0,0 +1,48 @@
+defmodule Credo.Check.Readability.UnnecessaryAliasExpansion do
+  @moduledoc false
+
+  @checkdoc """
+  Alias expansion is useful but when aliasing a single module,
+  it can be harder to read with unnecessary braces.
+
+      # preferred
+
+      alias ModuleA.Foo
+      alias ModuleA.{Foo, Bar}
+
+      # NOT preferred
+
+      alias ModuleA.{Foo}
+
+  Like all `Readability` issues, this one is not a technical concern.
+  But you can improve the odds of others reading and liking your code by making
+  it easier to follow.
+  """
+  @explanation [check: @checkdoc]
+
+  use Credo.Check, base_priority: :low
+
+  alias Credo.Code
+
+  @doc false
+  def run(source_file, params \\ []) do
+    issue_meta = IssueMeta.for(source_file, params)
+
+    Code.prewalk(source_file, &traverse(&1, &2, issue_meta))
+  end
+
+  defp traverse({:alias, _, [{_, _, [{:__aliases__, opts, [child]}]}]} = ast, issues, issue_meta) do
+    {ast, issues ++ [issue_for(issue_meta, Keyword.get(opts, :line), child)]}
+  end
+
+  defp traverse(ast, issues, _issue_meta), do: {ast, issues}
+
+  defp issue_for(issue_meta, line_no, trigger) do
+    format_issue(
+      issue_meta,
+      message: "Unnecessary alias expansion for #{trigger}, consider removing braces.",
+      trigger: trigger,
+      line_no: line_no
+    )
+  end
+end


Test patch:
diff --git a/test/credo/check/readability/unnecessary_alias_expansion_test.exs b/test/credo/check/readability/unnecessary_alias_expansion_test.exs
new file mode 100644
index 00000000..019dfe4a
--- /dev/null
+++ b/test/credo/check/readability/unnecessary_alias_expansion_test.exs
@@ -0,0 +1,46 @@
+defmodule Credo.Check.Readability.UnnecessaryAliasExpansionTest do
+  use Credo.TestHelper
+
+  @described_check Credo.Check.Readability.UnnecessaryAliasExpansion
+
+  #
+  # cases NOT raising issues
+  #
+
+  test "it should NOT report violation" do
+    """
+    defmodule Test do
+      alias App.Module1
+      alias App.{Module2, Module3}
+    end
+    """
+    |> to_source_file
+    |> refute_issues(@described_check)
+  end
+
+  #
+  # cases raising issues
+  #
+
+  test "it should report a violation" do
+    """
+    defmodule CredoSampleModule do
+      alias App.Module1
+      alias App.Module2.{Module3}
+    end
+    """
+    |> to_source_file
+    |> assert_issue(@described_check)
+  end
+
+  test "it should report a violation for double expansion" do
+    """
+    defmodule CredoSampleModule do
+      alias App.Module1
+      alias App.{Module2}.{Module3}
+    end
+    """
+    |> to_source_file
+    |> assert_issue(@described_check)
+  end
+end