Skip to content

Commit e0c47ad

Browse files
authored
Merge pull request #80 from esl/allow-typecheck-erl-files
Support typechecking for erlang files from `src/` directory
2 parents 63ec628 + 87cc585 commit e0c47ad

File tree

6 files changed

+82
-2
lines changed

6 files changed

+82
-2
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ gradient-*.tar
2525
# Temporary files, for example, from tests.
2626
/tmp/
2727

28-
# Beam files compiled from examples
28+
# Elixir beam files compiled from examples
2929
test/examples/_build/
3030

31+
# Erlang beam files compiled from examples
32+
test/examples/erlang/_build/
33+
3134
# MacOS DS_Store
3235
.DS_Store

lib/gradient.ex

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ defmodule Gradient do
2323
def type_check_file(file, opts \\ []) do
2424
opts = Keyword.put(opts, :return_errors, true)
2525

26-
with {:ok, forms} <- ElixirFileUtils.get_forms(file) do
26+
with {:ok, forms} <- ElixirFileUtils.get_forms(file),
27+
{:elixir, _} <- wrap_language_name(forms) do
2728
forms = maybe_specify_forms(forms, opts)
2829

2930
case maybe_gradient_check(forms, opts) ++ maybe_gradualizer_check(forms, opts) do
@@ -36,6 +37,12 @@ defmodule Gradient do
3637
:error
3738
end
3839
else
40+
{:erlang, forms} ->
41+
opts = Keyword.put(opts, :return_errors, false)
42+
case maybe_gradualizer_check(forms, opts) do
43+
:nok -> :error
44+
_ -> :ok
45+
end
3946
error ->
4047
Logger.error("Can't load file - #{inspect(error)}")
4148
:error
@@ -74,6 +81,14 @@ defmodule Gradient do
7481
end
7582
end
7683

84+
defp wrap_language_name([{:attribute, _, :file, {file_name, _}} | _] = forms) do
85+
if :string.str(file_name, '.erl') > 0 do
86+
{:erlang, forms}
87+
else
88+
{:elixir, forms}
89+
end
90+
end
91+
7792
defp put_code_path(forms, opts) do
7893
case opts[:code_path] do
7994
nil ->

test/examples/erlang/test.erl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-module(test).
2+
3+
-export([positive/1]).
4+
5+
-spec positive(integer()) -> ok | error.
6+
positive(A) when A > 0 ->
7+
ok;
8+
positive(_) ->
9+
error.

test/examples/erlang/test_err.erl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-module(test_err).
2+
3+
-export([positive/1]).
4+
5+
-spec positive(integer()) -> integer().
6+
positive(A) when A > 0 ->
7+
ok;
8+
positive(_) ->
9+
error.

test/gradient_test.exs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,31 @@
11
defmodule GradientTest do
22
use ExUnit.Case
33
doctest Gradient
4+
5+
import Gradient.TestHelpers
6+
import ExUnit.CaptureIO
7+
8+
test "typecheck erlang beam" do
9+
# typecheck file with errors
10+
path = "test/examples/erlang/_build/test_err.beam"
11+
erl_path = "test/examples/erlang/test_err.erl"
12+
io_data = capture_io(fn -> assert :error = Gradient.type_check_file(path) end)
13+
assert String.contains?(io_data, erl_path)
14+
# typecheck correct file
15+
capture_io(fn ->
16+
assert :ok = Gradient.type_check_file("test/examples/erlang/_build/test.beam")
17+
end)
18+
end
19+
20+
test "typecheck elixir beam" do
21+
# typecheck file with errors
22+
path = "test/examples/_build/Elixir.WrongRet.beam"
23+
ex_path = "test/examples/type/wrong_ret.ex"
24+
io_data = capture_io(fn -> assert :error = Gradient.type_check_file(path) end)
25+
assert String.contains?(io_data, ex_path)
26+
# typecheck correct file
27+
capture_io(fn ->
28+
assert :ok = Gradient.type_check_file("test/examples/_build/Elixir.Basic.beam")
29+
end)
30+
end
431
end

test/test_helper.exs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
defmodule ExamplesCompiler do
22
@build_path "test/examples/_build/"
3+
@erl_build_path "test/examples/erlang/_build/"
34

45
@version_step 0.01
56

@@ -24,6 +25,20 @@ defmodule ExamplesCompiler do
2425
end
2526
end
2627

28+
def erl_compile(pattern) do
29+
case File.mkdir(@erl_build_path) do
30+
:ok ->
31+
pattern
32+
|> Path.wildcard()
33+
|> Enum.each(fn p ->
34+
:compile.file(to_charlist(p), [:debug_info, {:outdir, to_charlist(@erl_build_path)}])
35+
end)
36+
37+
_ ->
38+
:error
39+
end
40+
end
41+
2742
def excluded_version_tags do
2843
case @version do
2944
1.11 ->
@@ -58,4 +73,6 @@ end
5873
ExamplesCompiler.compile("test/examples/**/*.ex")
5974
exlcude = ExamplesCompiler.excluded_version_tags()
6075

76+
ExamplesCompiler.erl_compile("test/examples/erlang/**/*.erl")
77+
6178
ExUnit.start(exclude: exlcude)

0 commit comments

Comments
 (0)