Skip to content

Commit dd48f95

Browse files
committed
Support when in typespec
1 parent a313549 commit dd48f95

File tree

4 files changed

+60
-0
lines changed

4 files changed

+60
-0
lines changed

lib/gradient/ast_specifier.ex

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,24 @@ defmodule Gradient.AstSpecifier do
478478
|> pass_tokens(tokens)
479479
end
480480

481+
def spec_mapper({:type, anno, :constraint, [subtype, vt]}, tokens, opts) do
482+
{:ok, _, anno, opts, _} = get_line(anno, opts)
483+
{subtype, _} = spec_mapper(subtype, tokens, opts)
484+
vt = context_mapper_map(vt, tokens, opts, &spec_mapper/3)
485+
486+
{:type, anno, :constraint, [subtype, vt]}
487+
|> pass_tokens(tokens)
488+
end
489+
490+
def spec_mapper({:type, anno, :bounded_fun, [fn_type, when_type]}, tokens, opts) do
491+
{:ok, _line, anno, opts, _} = get_line(anno, opts)
492+
{fn_type, _} = spec_mapper(fn_type, tokens, opts)
493+
when_type = context_mapper_map(when_type, tokens, opts, &spec_mapper/3)
494+
495+
{:type, anno, :bounded_fun, [fn_type, when_type]}
496+
|> pass_tokens(tokens)
497+
end
498+
481499
def spec_mapper({:type, anno, type_name, args}, tokens, opts) do
482500
{:ok, _line, anno, opts, _} = get_line(anno, opts)
483501
new_args = context_mapper_map(args, tokens, opts, &spec_mapper/3)
1.5 KB
Binary file not shown.

test/examples/typespec_when.ex

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
defmodule TypespecWhen do
2+
@spec foo({:a, x}) :: {:a, x} | {:b, x} when x: term()
3+
def foo({:a, x}) do
4+
case x do
5+
:foo ->
6+
{:a, x}
7+
8+
_ ->
9+
{:b, x}
10+
end
11+
end
12+
end

test/gradient/ast_specifier_test.exs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,36 @@ defmodule Gradient.AstSpecifierTest do
12941294
]} = recv
12951295
end
12961296

1297+
test "typespec when" do
1298+
{tokens, ast} = load("/Elixir.TypespecWhen.beam", "/typespec_when.ex")
1299+
1300+
[spec | _] =
1301+
AstSpecifier.run_mappers(ast, tokens)
1302+
|> filter_specs()
1303+
|> Enum.reverse()
1304+
1305+
assert {:attribute, 2, :spec,
1306+
{{:foo, 1},
1307+
[
1308+
{:type, 2, :bounded_fun,
1309+
[
1310+
{:type, 2, :fun,
1311+
[
1312+
{:type, 2, :product, [{:type, 2, :tuple, [{:atom, 2, :a}, {:var, 2, :x}]}]},
1313+
{:type, 2, :union,
1314+
[
1315+
{:type, 2, :tuple, [{:atom, 2, :a}, {:var, 2, :x}]},
1316+
{:type, 2, :tuple, [{:atom, 2, :b}, {:var, 2, :x}]}
1317+
]}
1318+
]},
1319+
[
1320+
{:type, 2, :constraint,
1321+
[{:atom, 2, :is_subtype}, [{:var, 2, :x}, {:type, 2, :term, []}]]}
1322+
]
1323+
]}
1324+
]}} = spec
1325+
end
1326+
12971327
test "typespec" do
12981328
{tokens, ast} = load("/Elixir.Typespec.beam", "/typespec.ex")
12991329

0 commit comments

Comments
 (0)