Setup Dialyxir and Credo code analyzers:

- Refactor codebase according to analyzers
This commit is contained in:
mitchell 2019-12-30 21:50:39 -05:00
parent 593f29d271
commit b699e661e2
15 changed files with 74 additions and 44 deletions

15
.credo.exs Normal file
View File

@ -0,0 +1,15 @@
%{
configs: [
%{
name: "default",
files: %{
included: ["lib/", "test/", "config/"],
excluded: []
},
checks: [
{Credo.Check.Refactor.MapInto, false},
{Credo.Check.Warning.LazyLogging, false}
]
}
]
}

View File

@ -1,16 +1,17 @@
.PHONY: all build clean install start test .PHONY: all build clean install lint start test
build: install test clean build: install lint test clean
docker build -t shortnr:latest . docker build -t shortnr:latest .
clean: clean:
mix clean --deps mix clean
install: install:
mix deps.get mix deps.get
install-prod: lint:
mix deps.get --only prod mix dialyzer
mix credo --strict
start: start:
iex -S mix run --no-halt iex -S mix run --no-halt

View File

@ -16,3 +16,9 @@ config :logger, :console,
:prod -> :info :prod -> :info
_ -> :debug _ -> :debug
end).(Mix.env()) end).(Mix.env())
config :credo,
checks: [
{Credo.Check.Refactor.MapInto, false},
{Credo.Check.Warning.LazyLogging, false}
]

View File

@ -1,10 +1,14 @@
defmodule Shortnr.Router do defmodule Shortnr.Router do
@moduledoc """
This module contains the Router for the Shortnr application. Do not import, other than
Application entry.
"""
use Plug.ErrorHandler use Plug.ErrorHandler
use Plug.Router use Plug.Router
require Logger require Logger
alias Shortnr.Transport.{Text, HTTP} alias Shortnr.Transport.{HTTP, Text}
alias Shortnr.URL alias Shortnr.URL
plug(Plug.Logger, log: :debug) plug(Plug.Logger, log: :debug)

View File

@ -1,6 +1,6 @@
defmodule Shortnr do defmodule Shortnr do
@moduledoc """ @moduledoc """
Documentation for Shortnr. The Shortnr application entry point. Check README for usage documenation.
""" """
use Application use Application

View File

@ -1,8 +1,13 @@
defmodule Shortnr.Transport.HTTP do defmodule Shortnr.Transport.HTTP do
@moduledoc """
This module contains functions that can be used to handle HTTP requests and send responses, by
manipulating Plug.Conn.
"""
import Plug.Conn import Plug.Conn
@type ok_error :: {:ok, term(), Plug.Conn.t()} | error()
@type error :: {:error, {atom(), String.t()}, Plug.Conn.t()} @type error :: {:error, {atom(), String.t()}, Plug.Conn.t()}
@type ok_error :: {:ok, term(), Plug.Conn.t()} | error()
@spec handle(ok_error(), (... -> ok_error())) :: ok_error() @spec handle(ok_error(), (... -> ok_error())) :: ok_error()
def handle(error = {:error, _sub_error, _conn}, _func), do: error def handle(error = {:error, _sub_error, _conn}, _func), do: error

View File

@ -1,28 +0,0 @@
defmodule Shortnr.Transport.Json do
import Plug.Conn
alias Shortnr.Transport.HTTP
@spec decode_request(Plug.Conn.t(), module()) :: HTTP.ok_error()
def decode_request(conn, struct_module) do
{:ok, body, conn} = read_body(conn)
{:ok, params} = Jason.decode(body)
params_list =
params
|> Map.to_list()
|> Enum.map(fn {key, value} -> {String.to_atom(key), value} end)
{:ok, struct(struct_module, params_list), conn}
end
@spec encode_response(HTTP.ok_error()) :: HTTP.ok_error()
def encode_response({:error, {status, response}, conn}) do
{:ok, json_body} = Jason.encode(%{data: response})
{:error, {status, json_body}, conn}
end
def encode_response({:ok, response, conn}) do
{:ok, json_body} = Jason.encode(%{data: response})
{:ok, json_body, conn}
end
end

View File

@ -1,4 +1,8 @@
defmodule Shortnr.Transport.Text do defmodule Shortnr.Transport.Text do
@moduledoc """
This modules contains functions to decode and encode text formatted http requests and responses.
"""
import Plug.Conn import Plug.Conn
alias Shortnr.Transport.HTTP alias Shortnr.Transport.HTTP
alias Shortnr.URL alias Shortnr.URL

View File

@ -1,4 +1,7 @@
defmodule Shortnr.Transport do defmodule Shortnr.Transport do
@moduledoc """
This module houses generic Transport types.
"""
@type error :: {:error, {atom(), String.t()}} @type error :: {:error, {atom(), String.t()}}
@type ok_error :: {:ok, term()} | error() @type ok_error :: {:ok, term()} | error()
end end

View File

@ -1,4 +1,8 @@
defmodule Shortnr.URL.Repo.ETS do defmodule Shortnr.URL.Repo.ETS do
@moduledoc """
This module is an implemention of the Repo behaviour using the Erlang ETS library.
"""
@behaviour Shortnr.URL.Repo @behaviour Shortnr.URL.Repo
@impl true @impl true
@ -16,7 +20,7 @@ defmodule Shortnr.URL.Repo.ETS do
end end
@impl true @impl true
def list() do def list do
resp = ets().select(:urls, [{:"$1", [], [:"$1"]}]) resp = ets().select(:urls, [{:"$1", [], [:"$1"]}])
{:ok, resp |> Enum.map(&elem(&1, 1))} {:ok, resp |> Enum.map(&elem(&1, 1))}
end end

View File

@ -1,6 +1,11 @@
defmodule Shortnr.URL.Repo do defmodule Shortnr.URL.Repo do
alias Shortnr.URL @moduledoc """
This module defines the Repo behaviour for the URL service. All Repos must implement this
entire behaviour.
"""
alias Shortnr.Transport alias Shortnr.Transport
alias Shortnr.URL
@callback put(URL.t()) :: :ok | Transport.error() @callback put(URL.t()) :: :ok | Transport.error()
@callback get(String.t()) :: {:ok, URL.t()} | Transport.error() @callback get(String.t()) :: {:ok, URL.t()} | Transport.error()

View File

@ -1,6 +1,9 @@
defmodule Shortnr.URL do defmodule Shortnr.URL do
@moduledoc """
This module represents both the URL data object, in the form of a struct, and the URL business
domain service.
"""
alias Shortnr.Transport alias Shortnr.Transport
alias Shortnr.URL
alias Shortnr.URL.Util alias Shortnr.URL.Util
defstruct id: "", defstruct id: "",
@ -17,7 +20,7 @@ defmodule Shortnr.URL do
@spec create(String.t(), module()) :: {:ok, String.t()} | Transport.error() @spec create(String.t(), module()) :: {:ok, String.t()} | Transport.error()
def create(url, repo) do def create(url, repo) do
url_struct = %URL{id: Util.gen_id(), url: URI.parse(url)} url_struct = %__MODULE__{id: Util.gen_id(), url: URI.parse(url)}
{:ok, extant_url} = repo.get(url_struct.id) {:ok, extant_url} = repo.get(url_struct.id)
@ -29,17 +32,17 @@ defmodule Shortnr.URL do
end end
end end
@spec get(String.t(), module()) :: {:ok, URL.t()} | Transport.error() @spec get(String.t(), module()) :: {:ok, t()} | Transport.error()
def get(key, repo) do def get(key, repo) do
{:ok, _} = repo.get(key) {:ok, _} = repo.get(key)
end end
@spec list(module()) :: {:ok, list(URL.t())} | Transport.error() @spec list(module()) :: {:ok, list(t())} | Transport.error()
def list(repo) do def list(repo) do
{:ok, _} = repo.list {:ok, _} = repo.list
end end
@spec delete(String.t(), module()) :: {:ok, :ignore} | Tranpsport.error() @spec delete(String.t(), module()) :: {:ok, String.t()} | Transport.error()
def delete(key, repo) do def delete(key, repo) do
:ok = repo.delete(key) :ok = repo.delete(key)
{:ok, "Success"} {:ok, "Success"}

View File

@ -1,4 +1,7 @@
defmodule Shortnr.URL.Util do defmodule Shortnr.URL.Util do
@moduledoc """
URL module utility functions.
"""
@id_chars String.codepoints("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXWYZ0123456789") @id_chars String.codepoints("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXWYZ0123456789")
@spec gen_id() :: String.t() @spec gen_id() :: String.t()
def gen_id do def gen_id do

View File

@ -24,7 +24,9 @@ defmodule Shortnr.MixProject do
[ [
{:plug_cowboy, "~> 2.0"}, {:plug_cowboy, "~> 2.0"},
{:elixir_uuid, "~> 1.2"}, {:elixir_uuid, "~> 1.2"},
{:jason, "~> 1.1"} {:jason, "~> 1.1"},
{:dialyxir, "~> 0.5.1", only: [:dev], runtime: false},
{:credo, "~> 1.1.5", only: [:dev, :test], runtime: false}
# {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
] ]

View File

@ -1,6 +1,9 @@
%{ %{
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
"cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"}, "cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm"}, "cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm"},
"credo": {:hex, :credo, "1.1.5", "caec7a3cadd2e58609d7ee25b3931b129e739e070539ad1a0cd7efeeb47014f4", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
"dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm"},
"elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm"},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"}, "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},