Skip to content

Commit

Permalink
Merge pull request #735 from TheFirstAvenger/mb-561-abc-size-ecto
Browse files Browse the repository at this point in the history
Ignore Ecto.Query functions in ABCSize when Ecto.Query is imported. Fixes #561.
  • Loading branch information
rrrene committed Jan 26, 2020
2 parents fa26d28 + 61e9083 commit d89c8cb
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
19 changes: 19 additions & 0 deletions lib/credo/check/refactor/abc_size.ex
Expand Up @@ -22,6 +22,7 @@ defmodule Credo.Check.Refactor.ABCSize do
max_size: 30,
excluded_functions: []
]
@ecto_functions ["where", "from", "select", "join"]
@def_ops [:def, :defp, :defmacro]
@branch_ops [:.]
@condition_ops [:if, :unless, :for, :try, :case, :cond, :and, :or, :&&, :||]
Expand All @@ -31,16 +32,34 @@ defmodule Credo.Check.Refactor.ABCSize do

@doc false
def run(source_file, params \\ []) do
ignore_ecto? = imports_ecto_query?(source_file)
issue_meta = IssueMeta.for(source_file, params)
max_abc_size = Params.get(params, :max_size, @default_params)
excluded_functions = Params.get(params, :excluded_functions, @default_params)

excluded_functions =
if ignore_ecto? do
@ecto_functions ++ excluded_functions
else
excluded_functions
end

Credo.Code.prewalk(
source_file,
&traverse(&1, &2, issue_meta, max_abc_size, excluded_functions)
)
end

defp imports_ecto_query?(source_file),
do: Credo.Code.prewalk(source_file, &traverse_for_ecto/2, false)

defp traverse_for_ecto(_, true), do: {nil, true}

defp traverse_for_ecto({:import, _, [{:__aliases__, _, [:Ecto, :Query]} | _]}, false),
do: {nil, true}

defp traverse_for_ecto(ast, false), do: {ast, false}

defp traverse(
{:defmacro, _, [{:__using__, _, _}, _]} = ast,
issues,
Expand Down
43 changes: 43 additions & 0 deletions test/credo/check/refactor/abc_size_test.exs
Expand Up @@ -264,4 +264,47 @@ defmodule Credo.Check.Refactor.ABCSizeTest do

assert rounded_abc_size(source, ["where", "join", "select", "distinct"]) == 1
end

test "it should NOT count ecto functions when Ecto.Query is imported" do
source = """
defmodule CredoEctoQueryModule do
import Ecto.Query
def fun() do
Favorite
|> where(user_id: ^user.id)
|> join(:left, [f], t in Template, f.entity_id == t.id and f.entity_type == "template")
|> join(:left, [f, t], d in Document, f.entity_id == d.id and f.entity_type == "document")
|> join(:left, [f, t, d], dt in Template, dt.id == d.template_id)
|> join(:left, [f, t, d, dt], c in Category, c.id == t.category_id or c.id == dt.category_id)
|> select([f, t, d, dt, c], c)
|> distinct(true)
|> Repo.all()
end
end
"""
|> to_source_file
|> refute_issues(@described_check, max_size: 3)
end

test "it SHOULD count ecto functions when Ecto.Query is NOT imported" do
source = """
defmodule CredoEctoQueryModule do
def fun() do
Favorite
|> where(user_id: ^user.id)
|> join(:left, [f], t in Template, f.entity_id == t.id and f.entity_type == "template")
|> join(:left, [f, t], d in Document, f.entity_id == d.id and f.entity_type == "document")
|> join(:left, [f, t, d], dt in Template, dt.id == d.template_id)
|> join(:left, [f, t, d, dt], c in Category, c.id == t.category_id or c.id == dt.category_id)
|> select([f, t, d, dt, c], c)
|> distinct(true)
|> Repo.all()
end
end
"""
|> to_source_file
|> assert_issue(@described_check, max_size: 3)
end
end

0 comments on commit d89c8cb

Please sign in to comment.