Current section
Files
Jump to
Current section
Files
lib/ecto_schema_directories.ex
defmodule Nicene.EctoSchemaDirectories do
@moduledoc """
Ecto schemas should not be in directories with other types of files.
"""
@explanation [check: @moduledoc]
require Logger
use Credo.Check, base_priority: :high, category: :refactoring
@doc false
def run(source_file, params \\ []) do
run(source_file, params, other_files(source_file.filename))
end
def run(source_file, params, other_files) do
issue_meta = IssueMeta.for(source_file, params)
is_schema = Credo.Code.prewalk(source_file, &schema?/2, false)
if is_schema and not Enum.all?(other_files, &schema?/1) do
[issue_for(issue_meta, source_file.filename)]
else
[]
end
end
defp other_files(filename) do
case File.ls("#{Path.dirname(filename)}/*.ex") do
{:ok, files} ->
read_files(files)
{:error, error} ->
Logger.warn("Unable to get files in same directory - error: #{inspect(error)}")
[]
end
end
defp read_files(files) do
Enum.reduce(files, [], fn file, acc ->
case File.read(file) do
{:ok, binary} ->
[binary | acc]
{:error, error} ->
Logger.warn("Unable to read file #{file} - #{inspect(error)}")
acc
end
end)
end
defp schema?(code) do
code
|> Code.string_to_quoted()
|> Credo.Code.prewalk(&schema?/2, false)
end
defp schema?({:schema, _, [schema, _]} = ast, _) when is_binary(schema) do
{ast, true}
end
defp schema?(ast, acc) do
{ast, acc}
end
defp issue_for(issue_meta, filename) do
format_issue(issue_meta,
message: "#{filename} is in a directory with files that are not Ecto schemas"
)
end
end