Skip to content

Commit

Permalink
Merge pull request #2 from sascha-wolf/fix/dialyzer-warnings
Browse files Browse the repository at this point in the history
Resolve dialyzer warnings
  • Loading branch information
alexocode committed Nov 16, 2022
2 parents 2c27121 + b70dfff commit 6d1d9a0
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 9 deletions.
85 changes: 81 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

check_all:
name: Check Formatting & Run Credo
check_formatting:
name: Check Formatting
runs-on: ubuntu-latest
container: hexpm/elixir:1.14.0-erlang-24.3.4.5-alpine-3.16.2
env:
Expand Down Expand Up @@ -146,5 +146,82 @@ jobs:
key: ${{ env.CACHE_PREFIX_BUILD }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ env.CACHE_PREFIX_BUILD }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-

- run: mix compile --warnings-as-errors
- run: mix check.all
- run: mix compile
- run: mix format --check-formatted

check_style:
name: Check Style with Credo
runs-on: ubuntu-latest
container: hexpm/elixir:1.14.0-erlang-24.3.4.5-alpine-3.16.2
env:
MIX_ENV: dev
VERSION_ALPINE: 3.16.2
VERSION_ELIXIR: 1.14.0
VERSION_OTP: 24.3.4.5
steps:
- uses: actions/checkout@v2

- name: Cache - deps/
uses: actions/cache@v1
with:
path: deps/
key: ${{ env.CACHE_PREFIX_DEPS }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ env.CACHE_PREFIX_DEPS }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-

- name: Install Dependencies
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get --only "$MIX_ENV"
- name: Cache - _build/
uses: actions/cache@v1
with:
path: _build/
key: ${{ env.CACHE_PREFIX_BUILD }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ env.CACHE_PREFIX_BUILD }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-

- run: mix compile
- run: mix credo

check_types:
name: Check Types with Dialyzer (including generated)
runs-on: ubuntu-latest
container: hexpm/elixir:1.14.0-erlang-24.3.4.5-alpine-3.16.2
env:
MIX_ENV: dev
VERSION_ALPINE: 3.16.2
VERSION_ELIXIR: 1.14.0
VERSION_OTP: 24.3.4.5
steps:
- uses: actions/checkout@v2

- name: Cache - deps/
uses: actions/cache@v1
with:
path: deps/
key: ${{ env.CACHE_PREFIX_DEPS }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ env.CACHE_PREFIX_DEPS }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-

- name: Install Dependencies
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get --only "$MIX_ENV"
- name: Cache - _build/
uses: actions/cache@v1
with:
path: _build/
key: ${{ env.CACHE_PREFIX_BUILD }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ env.CACHE_PREFIX_BUILD }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}-

- run: mix compile

- name: Cache - Dialyzer PLTs
uses: actions/cache@v1
with:
path: .dialyzer/
key: ${{ env.CACHE_PREFIX_DIALYZER }}-env:${{ env.MIX_ENV }}-alpine:${{ env.VERSION_ALPINE }}-elixir:${{ env.VERSION_ELIXIR }}-otp:${{ env.VERSION_OTP }}

- run: mix dialyzer
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ ex_union-*.tar

# Temporary files, for example, from tests.
/tmp/

# Dialyzer cache (contains the PLTs - persistent lookup tables)
/.dialyzer/
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
### Changed
- [#2](https://github.com/sascha-wolf/ex_union/pull/2): Resolve dialyzer warnings ([@sascha-wolf])

### Removed

## [v0.1.0] - 2022-10-16
Expand All @@ -20,4 +22,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Generate a guard whose name is inferred from the top-level module

[Unreleased]: https://github.com/sascha-wolf/ex_union/compare/v0.1.0...main
[v0.1.0]: https://github.com/sascha-wolf/ex_union/compare/744dd7dc078c5e9d2311f11a223f326665d9a38b...v0.1.0
[v0.1.0]: https://github.com/sascha-wolf/ex_union/compare/744dd7dc078c5e9d2311f11a223f326665d9a38b...v0.1.0

[@sascha-wolf]: https://github.com/sascha-wolf
9 changes: 9 additions & 0 deletions examples/color.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Color do
import ExUnion

defunion hex(string :: String.t)
| rgb(red :: 0..255, green :: 0..255, blue :: 0..255)
| rgba(red :: 0..255, green :: 0..255, blue :: 0..255, alpha :: float)
| hsl(hue :: 0..360, saturation :: float, lightness :: float)
| hsla(hue :: 0..360, saturation :: float, lightness :: float, alpha :: float)
end
6 changes: 6 additions & 0 deletions examples/integer_tree.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
defmodule IntegerTree do
import ExUnion

# You can also use `t` instead of `union` if you prefer
defunion leaf | node(integer :: integer, left :: union, right :: union)
end
5 changes: 5 additions & 0 deletions examples/maybe.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule Maybe do
import ExUnion

defunion some(value) | none
end
9 changes: 9 additions & 0 deletions examples/wrapped.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Wrapped do
import ExUnion

defunion tuple(value :: {:ok, union})
| map(value :: %{any => union})
| function(value :: (union_keyword -> union_map))
| list(value :: [union])
| keyword(value :: [{atom, union}])
end
2 changes: 1 addition & 1 deletion lib/ex_union/definition.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule ExUnion.Definition do
alias __MODULE__.{Block, Type}

@type t :: %__MODULE__{
name: atom,
name: String.t(),
module: module,
types: list(Type.t())
}
Expand Down
25 changes: 23 additions & 2 deletions lib/ex_union/definition/type.ex
Original file line number Diff line number Diff line change
Expand Up @@ -98,26 +98,47 @@ defmodule ExUnion.Definition.Type do
arguments_with_types = Enum.map(fields, &{:"::", [], [&1.var, &1.type]})
arguments_mapped_to_struct_fields = Enum.map(fields, &{&1.name, &1.var})

# When we only have a single field we can easily generate an "overloaded contract"
# where the "simple new/1" spec is a superset of the "matching new/1".
# While this isn't an issue it does produce an "Overloaded contract" warning from
# dialyzer, since dialyzer doesn't support this, but since nothing breaks we still
# generate the @spec and silence this specific dialyzer warning to retain the type
# information
maybe_ignore_dialyzer_warning =
if length(fields) == 1 do
quote do
@dialyzer {:no_contracts, new: 1}
end
end

quote do
unquote(maybe_ignore_dialyzer_warning)
@spec new(unquote_splicing(arguments_with_types)) :: t()
def new(unquote_splicing(arguments)) do
%__MODULE__{unquote_splicing(arguments_mapped_to_struct_fields)}
end
end
end

def to_shortcut_function(%__MODULE__{} = type) do
arguments = Enum.map(type.fields, & &1.var)
def to_shortcut_function(%__MODULE__{fields: fields} = type) do
arguments = Enum.map(fields, & &1.var)
arguments_with_types = Enum.map(fields, &{:"::", [], [&1.var, &1.type]})
field_types = Enum.map(fields, &{&1.name, &1.type})

arity_1_shortcut =
quote do
@spec unquote(type.name)(fields :: %{unquote_splicing(field_types)}) ::
unquote(type.module).t()
@spec unquote(type.name)(fields :: unquote(field_types)) :: unquote(type.module).t()
defdelegate unquote(type.name)(fields),
to: unquote(type.module),
as: :new
end

arity_n_shortcut =
quote do
@spec unquote(type.name)(unquote_splicing(arguments_with_types)) ::
unquote(type.module).t()
defdelegate unquote(type.name)(unquote_splicing(arguments)),
to: unquote(type.module),
as: :new
Expand Down
15 changes: 14 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule ExUnion.MixProject do
app: :ex_union,
version: version(),
elixir: "~> 1.10",
elixirc_paths: elixirc_paths(Mix.env()),
preferred_cli_env: [
coveralls: :test,
"coveralls.detail": :test,
Expand All @@ -18,6 +19,7 @@ defmodule ExUnion.MixProject do
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps(),
dialyzer: dialyzer(),

# Docs
name: "ExUnion",
Expand All @@ -32,6 +34,9 @@ defmodule ExUnion.MixProject do
]
end

defp elixirc_paths(:dev), do: ["examples", "lib"]
defp elixirc_paths(_), do: ["lib"]

# Run "mix help compile.app" to learn about applications.
def application do
[
Expand All @@ -43,7 +48,7 @@ defmodule ExUnion.MixProject do
# See the documentation for `Mix` for more info on aliases.
defp aliases do
[
"check.all": ["format --check-formatted", "credo"]
"check.all": ["format --check-formatted", "credo", "dialyzer"]
]
end

Expand All @@ -52,13 +57,21 @@ defmodule ExUnion.MixProject do
[
# No Runtime
{:credo, ">= 1.0.0", only: :dev, runtime: false},
{:dialyxir, "~> 1.0", only: :dev, runtime: false},
{:ex_doc, "~> 0.23", only: :dev, runtime: false},

# Test
{:excoveralls, "~> 0.13", only: :test}
]
end

defp dialyzer do
[
# ignore_warnings: "dialyzer/ignore.exs",
plt_file: {:no_warn, ".dialyzer/dialyzer.plt"}
]
end

#######
# Hex #
#######
Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
"credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"},
"dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"},
"earmark_parser": {:hex, :earmark_parser, "1.4.26", "f4291134583f373c7d8755566122908eb9662df4c4b63caa66a0eabe06569b0a", [:mix], [], "hexpm", "48d460899f8a0c52c5470676611c01f64f3337bad0b26ddab43648428d94aabc"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ex_doc": {:hex, :ex_doc, "0.28.5", "3e52a6d2130ce74d096859e477b97080c156d0926701c13870a4e1f752363279", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d2c4b07133113e9aa3e9ba27efb9088ba900e9e51caa383919676afdf09ab181"},
"excoveralls": {:hex, :excoveralls, "0.15.0", "ac941bf85f9f201a9626cc42b2232b251ad8738da993cf406a4290cacf562ea4", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9631912006b27eca30a2f3c93562bc7ae15980afb014ceb8147dc5cdd8f376f1"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
Expand Down

0 comments on commit 6d1d9a0

Please sign in to comment.