Skip to content

Commit

Permalink
Merge pull request #7 from infinitered/try-credo
Browse files Browse the repository at this point in the history
Add Credo for linting
  • Loading branch information
danielberkompas authored Jul 18, 2016
2 parents 238583d + c70b16f commit d3fe0e9
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 40 deletions.
2 changes: 2 additions & 0 deletions apps/example/web/controllers/admin/post_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ defmodule Example.Admin.PostController do
plug :put_layout, {Example.LayoutView, "admin.html"}
plug :scrub_params, "post" when action in [:create, :update]
plug :assign_categories

plug :assign_authors

@filtrex [
%Config{type: :boolean, keys: ~w(draft)},
%Config{type: :date, keys: ~w(inserted_at updated_at), options: %{format: "{YYYY}-{0M}-{0D}"}},
%Config{type: :text, keys: ~w(title body)},
%Config{type: :number, keys: ~w(author_id)},
%Config{type: :number, keys: ~w(category_id)}
]

Expand Down
2 changes: 2 additions & 0 deletions apps/example/web/templates/admin/post/index.html.eex
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<thead>
<tr>
<th><%= table_link(@conn, "Title", :title) %></th>
<th><%= table_link(@conn, "Body", :body) %></th>
<th><%= table_link(@conn, "Draft", :draft) %></th>
<th><%= table_link(@conn, "Category", :category_id) %></th>
<th><%= table_link(@conn, "Author", :author_id) %></th>
Expand All @@ -23,6 +24,7 @@
<%= for post <- @posts do %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= post.draft %></td>
<td><%= table_assoc_display_name(post, :category_id, @categories) %>
<td><%= table_assoc_display_name(post, :author_id, @authors) %>
Expand Down
89 changes: 60 additions & 29 deletions apps/torch/lib/mix/tasks/torch.gen.ex
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ defmodule Mix.Tasks.Torch.Gen do
## Example
mix torch.gen eex Admin Post posts category_id:references:category,categories:id,name title:string body:text inserted_at:date
mix torch.gen eex Admin Post posts category_id:references:category,categories:id,name title:string body:text
"""

use Mix.Task
Expand All @@ -100,20 +100,32 @@ defmodule Mix.Tasks.Torch.Gen do
assoc_plugs: assoc_plugs(attrs),
assoc_plug_definitions: assoc_plug_definitions(binding, attrs)]

binding
|> copy_templates(format, path)
|> copy_elixir(path)
|> print_message(format)
end

defp copy_templates(binding, format, path) do
Mix.Torch.copy_from [:torch], "priv/templates/#{format}", "", binding, [
{:eex, "index.#{format}.eex", "web/templates/#{path}/index.html.#{format}"},
{:eex, "edit.#{format}.eex", "web/templates/#{path}/edit.html.#{format}"},
{:eex, "new.#{format}.eex", "web/templates/#{path}/new.html.#{format}"},
{:eex, "_form.#{format}.eex", "web/templates/#{path}/_form.html.#{format}"},
{:eex, "_filters.#{format}.eex", "web/templates/#{path}/_filters.html.#{format}"}
]
binding
end

defp copy_elixir(binding, path) do
Mix.Torch.copy_from [:torch], "priv/templates/elixir", "", binding, [
{:eex, "controller.ex", "web/controllers/#{path}_controller.ex"},
{:eex, "view.ex", "web/views/#{path}_view.ex"}
]
binding
end

defp print_message(binding, format) do
Mix.shell.info """
Success!
Expand All @@ -137,7 +149,7 @@ defmodule Mix.Tasks.Torch.Gen do
<nav>
<h1>Torch Admin</h1>
<ul>
#{IO.ANSI.green}<li><%= Torch.NavigationView.nav_link @conn, "#{String.capitalize(binding[:plural])}", #{ binding[:namespace_underscore]}_#{binding[:singular]}_path(@conn, :index) %></li>#{IO.ANSI.reset}
#{IO.ANSI.green}<li><%= #{nav_link(binding)} %></li>#{IO.ANSI.reset}
</ul>
</nav>
</header>
Expand All @@ -150,10 +162,15 @@ defmodule Mix.Tasks.Torch.Gen do
nav
h1 Torch Admin
ul
#{IO.ANSI.green}li= Torch.NavigationView.nav_link @conn, "#{String.capitalize(binding[:plural])}", #{ binding[:namespace_underscore]}_#{binding[:singular]}_path(@conn, :index)#{IO.ANSI.reset}
#{IO.ANSI.green}li= #{nav_link(binding)}#{IO.ANSI.reset}
"""
end

@lint false
defp nav_link(binding) do
~s{Torch.NavigationView.nav_link @conn, "#{String.capitalize(binding[:plural])}", #{binding[:namespace_underscore]}_#{binding[:singular]}_path(@conn, :index)}
end

defp inputs("eex", attrs) do
inputs = inputs("slim", attrs)
for {label, input, error} <- inputs do
Expand All @@ -162,35 +179,49 @@ defmodule Mix.Tasks.Torch.Gen do
end

defp inputs("slim", attrs) do
attrs = Enum.reject(attrs, fn({key, _type}) -> key in [:inserted_at, :updated_at] end)
Enum.map attrs, fn
{_, {:array, _}} ->
{nil, nil, nil}
{key, {:references, data}} ->
{label(data[:assoc_singular]), ~s(= select f, #{inspect(key)}, @#{data[:assoc_plural]}, prompt: "Choose one"), error(key)}
{key, :file} ->
{label(key), ~s(= file_input f, #{inspect(key)}), error(key)}
{key, :integer} ->
{label(key), ~s(= number_input f, #{inspect(key)}), error(key)}
{key, :float} ->
{label(key), ~s(= number_input f, #{inspect(key)}, step: "any"), error(key)}
{key, :decimal} ->
{label(key), ~s(= number_input f, #{inspect(key)}, step: "any"), error(key)}
{key, :boolean} ->
{label(key), ~s(= select f, #{inspect(key)}, [{"True", true}, {"False", false}], prompt: "Choose one"), error(key)}
{key, :text} ->
{label(key), ~s(= textarea f, #{inspect(key)}), error(key)}
{key, :date} ->
{label(key), ~s(= date_select f, #{inspect(key)}), error(key)}
{key, :time} ->
{label(key), ~s(= time_select f, #{inspect(key)}), error(key)}
{key, :datetime} ->
{label(key), ~s(= datetime_select f, #{inspect(key)}), error(key)}
{key, _} ->
{label(key), ~s(= text_input f, #{inspect(key)}), error(key)}
for {key, _} = attr <- attrs, not key in [:inserted_at, :updated_at] do
do_input(attr)
end
end

@lint false
defp do_input({_, {:array, _}}) do
{nil, nil, nil}
end
defp do_input({key, {:references, data}}) do
{label(data[:assoc_singular]), ~s(= select f, #{inspect(key)}, @#{data[:assoc_plural]}, prompt: "Choose one"), error(key)}
end
defp do_input({key, :file}) do
{label(key), ~s(= file_input f, #{inspect(key)}), error(key)}
end
defp do_input({key, :integer}) do
{label(key), ~s(= number_input f, #{inspect(key)}), error(key)}
end
defp do_input({key, :float}) do
{label(key), ~s(= number_input f, #{inspect(key)}, step: "any"), error(key)}
end
defp do_input({key, :decimal}) do
{label(key), ~s(= number_input f, #{inspect(key)}, step: "any"), error(key)}
end
defp do_input({key, :boolean}) do
{label(key), ~s(= select f, #{inspect(key)}, [{"True", true}, {"False", false}], prompt: "Choose one"), error(key)}
end
defp do_input({key, :text}) do
{label(key), ~s(= textarea f, #{inspect(key)}), error(key)}
end
defp do_input({key, :date}) do
{label(key), ~s(= date_select f, #{inspect(key)}), error(key)}
end
defp do_input({key, :time}) do
{label(key), ~s(= time_select f, #{inspect(key)}), error(key)}
end
defp do_input({key, :datetime}) do
{label(key), ~s(= datetime_select f, #{inspect(key)}), error(key)}
end
defp do_input({key, _}) do
{label(key), ~s(= text_input f, #{inspect(key)}), error(key)}
end

defp assoc_plugs(attrs) do
for {_key, {:references, data}} <- attrs do
"plug :assign_#{data[:assoc_plural]}"
Expand Down
33 changes: 25 additions & 8 deletions apps/torch/lib/mix/torch.ex
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,22 @@ defmodule Mix.Torch do
path: "admin/super_user"]
"""
def inflect(namespace, singular) do
base = Mix.Torch.base
scoped = Phoenix.Naming.camelize(singular)
path = Phoenix.Naming.underscore(scoped)
singular = String.split(path, "/") |> List.last
module = base |> Module.concat(namespace) |> Module.concat(scoped) |> inspect
alias = String.split(module, ".") |> List.last
human = Phoenix.Naming.humanize(singular)
scoped = Phoenix.Naming.camelize(singular)
path = Phoenix.Naming.underscore(scoped)
singular =
path
|> String.split("/")
|> List.last
module =
base
|> Module.concat(namespace)
|> Module.concat(scoped)
|> inspect
alias =
module
|> String.split(".")
|> List.last
human = Phoenix.Naming.humanize(singular)

[alias: alias,
human: human,
Expand Down Expand Up @@ -106,7 +115,14 @@ defmodule Mix.Torch do
def uniques(attrs) do
attrs
|> Enum.filter(&String.ends_with?(&1, ":unique"))
|> Enum.map(& &1 |> String.split(":", parts: 2) |> hd |> String.to_atom)
|> Enum.map(&do_unique/1)
end

defp do_unique(attr) do
attr
|> String.split(":", parts: 2)
|> hd
|> String.to_atom
end

@doc """
Expand Down Expand Up @@ -193,6 +209,7 @@ defmodule Mix.Torch do
{String.to_atom(key), {String.to_atom(comp), String.to_atom(value)}}
end

@lint false
defp type_to_default(t) do
case t do
{:array, _} -> []
Expand Down
8 changes: 6 additions & 2 deletions apps/torch/lib/torch/views/filter_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,12 @@ defmodule Torch.FilterView do
def filter_date_input(prefix, field, params) do
prefix = to_string(prefix)
field = to_string(field)
{:safe, start} = date_input("#{prefix}[#{field}_between][start]", get_in(params, [prefix, "#{field}_between", "start"]))
{:safe, ending} = date_input("#{prefix}[#{field}_between][end]", get_in(params, [prefix, "#{field}_between", "end"]))
{:safe, start} =
date_input("#{prefix}[#{field}_between][start]",
get_in(params, [prefix, "#{field}_between", "start"]))
{:safe, ending} =
date_input("#{prefix}[#{field}_between][end]",
get_in(params, [prefix, "#{field}_between", "end"]))
raw(start <> ending)
end

Expand Down
1 change: 1 addition & 0 deletions apps/torch/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ defmodule Torch.Mixfile do
{:phoenix_html, "~> 2.6"},
{:ecto, ">= 1.0.0"},
{:scrivener_ecto, ">= 1.0.0"},
{:credo, "~> 0.4", only: [:dev, :test]},
{:ex_doc, "~> 0.13", only: :dev}]
end

Expand Down
1 change: 1 addition & 0 deletions bin/setup
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ cd apps/example && {
}

mix test
mix credo --strict
108 changes: 108 additions & 0 deletions config/.credo.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# This file contains the configuration for Credo and you are probably reading
# this after creating it with `mix credo.gen.config`.
#
# If you find anything wrong or unclear in this file, please report an
# issue on GitHub: https://github.com/rrrene/credo/issues
#
%{
#
# You can have as many configs as you like in the `configs:` field.
configs: [
%{
#
# Run any config using `mix credo -C <name>`. If no config name is given
# "default" is used.
name: "default",
#
# these are the files included in the analysis
files: %{
#
# you can give explicit globs or simply directories
# in the latter case `**/*.{ex,exs}` will be used
included: ["apps/torch/lib", "apps/torch/web"],
excluded: [~r"/_build/", ~r"/deps/"]
},
#
# If you create your own checks, you must specify the source files for
# them here, so they can be loaded by Credo before running the analysis.
requires: [],
#
# Credo automatically checks for updates, like e.g. Hex does.
# You can disable this behaviour below:
check_for_updates: true,
#
# You can customize the parameters of any check by adding a second element
# to the tuple.
#
# To disable a check put `false` as second element:
#
# {Credo.Check.Design.DuplicatedCode, false}
#
checks: [
{Credo.Check.Consistency.ExceptionNames},
{Credo.Check.Consistency.LineEndings},
{Credo.Check.Consistency.SpaceAroundOperators},
{Credo.Check.Consistency.SpaceInParentheses},
{Credo.Check.Consistency.TabsOrSpaces},

# For some checks, like AliasUsage, you can only customize the priority
# Priority values are: `low, normal, high, higher`
{Credo.Check.Design.AliasUsage, false},

# For others you can set parameters

# If you don't want the `setup` and `test` macro calls in ExUnit tests
# or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just
# set the `excluded_macros` parameter to `[:schema, :setup, :test]`.
{Credo.Check.Design.DuplicatedCode, excluded_macros: []},

# You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just
# set this value to 0 (zero).
{Credo.Check.Design.TagTODO, exit_status: 2},
{Credo.Check.Design.TagFIXME},

{Credo.Check.Readability.FunctionNames},
{Credo.Check.Readability.LargeNumbers},
{Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 120},
{Credo.Check.Readability.ModuleAttributeNames},
{Credo.Check.Readability.ModuleDoc},
{Credo.Check.Readability.ModuleNames},
{Credo.Check.Readability.ParenthesesInCondition},
{Credo.Check.Readability.PredicateFunctionNames},
{Credo.Check.Readability.TrailingBlankLine},
{Credo.Check.Readability.TrailingWhiteSpace},
{Credo.Check.Readability.VariableNames},

{Credo.Check.Refactor.ABCSize, max_size: 40},
{Credo.Check.Refactor.CondStatements},
{Credo.Check.Refactor.FunctionArity},
{Credo.Check.Refactor.MatchInCondition},
{Credo.Check.Refactor.PipeChainStart},
{Credo.Check.Refactor.CyclomaticComplexity},
{Credo.Check.Refactor.NegatedConditionsInUnless},
{Credo.Check.Refactor.NegatedConditionsWithElse},
{Credo.Check.Refactor.Nesting},
{Credo.Check.Refactor.UnlessWithElse},

{Credo.Check.Warning.IExPry},
{Credo.Check.Warning.IoInspect},
{Credo.Check.Warning.NameRedeclarationByAssignment},
{Credo.Check.Warning.NameRedeclarationByCase},
{Credo.Check.Warning.NameRedeclarationByDef},
{Credo.Check.Warning.NameRedeclarationByFn},
{Credo.Check.Warning.OperationOnSameValues},
{Credo.Check.Warning.BoolOperationOnSameValues},
{Credo.Check.Warning.UnusedEnumOperation},
{Credo.Check.Warning.UnusedKeywordOperation},
{Credo.Check.Warning.UnusedListOperation},
{Credo.Check.Warning.UnusedStringOperation},
{Credo.Check.Warning.UnusedTupleOperation},
{Credo.Check.Warning.OperationWithConstantResult},

# Custom checks can be created using `mix credo.gen.check`.
#
]
}
]
}
4 changes: 3 additions & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
%{"certifi": {:hex, :certifi, "0.4.0", "a7966efb868b179023618d29a407548f70c52466bf1849b9e8ebd0e34b7ea11f", [:rebar3], []},
%{"bunt": {:hex, :bunt, "0.1.6", "5d95a6882f73f3b9969fdfd1953798046664e6f77ec4e486e6fafc7caad97c6f", [:mix], []},
"certifi": {:hex, :certifi, "0.4.0", "a7966efb868b179023618d29a407548f70c52466bf1849b9e8ebd0e34b7ea11f", [:rebar3], []},
"combine": {:hex, :combine, "0.9.1", "5fd778ee77032ae593bf79aedb8519d9e36283e4f869abd98c2d6029ca476db8", [:mix], []},
"connection": {:hex, :connection, "1.0.3", "3145f7416be3df248a4935f24e3221dc467c1e3a158d62015b35bd54da365786", [:mix], []},
"cowboy": {:hex, :cowboy, "1.0.4", "a324a8df9f2316c833a470d918aaf73ae894278b8aa6226ce7a9bf699388f878", [:rebar, :make], [{:cowlib, "~> 1.0.0", [hex: :cowlib, optional: false]}, {:ranch, "~> 1.0", [hex: :ranch, optional: false]}]},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], []},
"credo": {:hex, :credo, "0.4.6", "30febde77446dfff48055f9ac3d8bfc9d9250e787c1ed75deab7073841ab7ad1", [:mix], [{:bunt, "~> 0.1.6", [hex: :bunt, optional: false]}]},
"db_connection": {:hex, :db_connection, "1.0.0-rc.3", "d9ceb670fe300271140af46d357b669983cd16bc0d01206d7d3222dde56cf038", [:mix], [{:sbroker, "~> 1.0.0-beta.3", [hex: :sbroker, optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: true]}, {:connection, "~> 1.0.2", [hex: :connection, optional: false]}]},
"decimal": {:hex, :decimal, "1.1.2", "79a769d4657b2d537b51ef3c02d29ab7141d2b486b516c109642d453ee08e00c", [:mix], []},
"earmark": {:hex, :earmark, "1.0.1", "2c2cd903bfdc3de3f189bd9a8d4569a075b88a8981ded9a0d95672f6e2b63141", [:mix], []},
Expand Down

0 comments on commit d3fe0e9

Please sign in to comment.