@@ -1369,75 +1369,201 @@ defmodule Gradient.AstSpecifierTest do
13691369 test "typespec" do
13701370 { tokens , ast } = load ( "/Elixir.Typespec.beam" , "/typespec.ex" )
13711371
1372- [ atoms_type2 , atoms_type , named_type , missing_type_arg , missing_type | _ ] =
1372+ result =
13731373 AstSpecifier . run_mappers ( ast , tokens )
13741374 |> filter_attributes ( :spec )
1375- |> Enum . reverse ( )
1375+ |> make_spec_map ( )
1376+
1377+ assert { :attribute , 6 , :spec ,
1378+ { { :spec_remote_type , 0 } ,
1379+ [
1380+ { :type , 6 , :fun ,
1381+ [
1382+ { :type , 6 , :product , [ ] } ,
1383+ { :remote_type , 6 , [ { :atom , 6 , Unknown } , { :atom , 6 , :atom } , [ ] ] }
1384+ ] }
1385+ ] } } = result . spec_remote_type
1386+
1387+ assert { :attribute , 9 , :spec ,
1388+ { { :spec_user_type , 0 } ,
1389+ [
1390+ { :type , 9 , :fun ,
1391+ [
1392+ { :type , 9 , :product , [ ] } ,
1393+ { :user_type , 9 , :mylist ,
1394+ [ { :type , 9 , :union , [ { :atom , 9 , :ok } , { :type , 9 , :atom , [ ] } ] } ] }
1395+ ] }
1396+ ] } } = result . spec_user_type
1397+
1398+ assert { :attribute , 12 , :spec ,
1399+ { { :spec_map_and_named_type , 1 } ,
1400+ [
1401+ { :type , 12 , :fun ,
1402+ [
1403+ { :type , 12 , :product ,
1404+ [
1405+ { :ann_type , 12 ,
1406+ [
1407+ { :var , 12 , :type } ,
1408+ { :remote_type , 12 , [ { :atom , 12 , Unknown } , { :atom , 12 , :atom } , [ ] ] }
1409+ ] }
1410+ ] } ,
1411+ { :type , 12 , :map ,
1412+ [
1413+ { :type , 13 , :map_field_assoc ,
1414+ [ { :atom , 13 , :value } , { :type , 13 , :integer , [ ] } ] } ,
1415+ { :type , 14 , :map_field_exact ,
1416+ [
1417+ { :atom , 14 , :type } ,
1418+ { :remote_type , 14 , [ { :atom , 14 , Unknown } , { :atom , 14 , :atom } , [ ] ] }
1419+ ] }
1420+ ] }
1421+ ] }
1422+ ] } } = result . spec_map_and_named_type
1423+
1424+ assert { :attribute , 18 , :spec ,
1425+ { { :spec_atom , 1 } ,
1426+ [
1427+ { :type , 18 , :fun ,
1428+ [
1429+ { :type , 18 , :product ,
1430+ [
1431+ { :type , 18 , :union ,
1432+ [ { :atom , 18 , :ok } , { :atom , 18 , nil } , { :atom , 18 , true } , { :atom , 18 , false } ] }
1433+ ] } ,
1434+ { :remote_type , 18 ,
1435+ [
1436+ { :atom , 18 , Unknown } ,
1437+ { :atom , 18 , :atom } ,
1438+ [
1439+ { :type , 18 , :union ,
1440+ [
1441+ { :atom , 18 , :ok } ,
1442+ { :atom , 18 , nil } ,
1443+ { :atom , 18 , true } ,
1444+ { :atom , 18 , false }
1445+ ] }
1446+ ]
1447+ ] }
1448+ ] }
1449+ ] } } = result . spec_atom
1450+
1451+ assert { :attribute , 21 , :spec ,
1452+ { { :spec_function , 0 } ,
1453+ [
1454+ { :type , 21 , :fun ,
1455+ [
1456+ { :type , 21 , :product , [ ] } ,
1457+ { :type , 21 , :fun ,
1458+ [
1459+ { :type , 21 , :product ,
1460+ [
1461+ { :type , 21 , :atom , [ ] } ,
1462+ { :type , 21 , :map ,
1463+ [
1464+ { :type , 21 , :map_field_exact ,
1465+ [
1466+ { :atom , 21 , :name } ,
1467+ { :remote_type , 21 , [ { :atom , 21 , String } , { :atom , 21 , :t } , [ ] ] }
1468+ ] }
1469+ ] }
1470+ ] } ,
1471+ { :type , 21 , :map , :any }
1472+ ] }
1473+ ] }
1474+ ] } } = result . spec_function
13761475
1377- assert { :attribute , 17 , :spec ,
1378- { { :atoms_type2 , 1 } ,
1476+ assert { :attribute , 24 , :spec ,
1477+ { { :spec_struct , 1 } ,
13791478 [
1380- { :type , 17 , :fun ,
1479+ { :type , 24 , :fun ,
13811480 [
1382- { :type , 17 , :product ,
1383- [ { :type , 17 , :union , [ { :atom , 17 , :ok } , { :atom , 17 , :error } ] } ] } ,
1384- { :remote_type , 17 ,
1481+ { :type , 24 , :product ,
13851482 [
1386- { :atom , 17 , Unknown } ,
1387- { :atom , 17 , :atom } ,
1388- [ { :type , 17 , :union , [ { :atom , 17 , :ok } , { :atom , 17 , :error } ] } ]
1483+ { :type , 24 , :map ,
1484+ [
1485+ { :type , 24 , :map_field_exact ,
1486+ [ { :atom , 24 , :__struct__ } , { :atom , 24 , Typespec } ] } ,
1487+ { :type , 24 , :map_field_exact ,
1488+ [ { :atom , 24 , :age } , { :type , 24 , :term , [ ] } ] } ,
1489+ { :type , 24 , :map_field_exact ,
1490+ [ { :atom , 24 , :name } , { :type , 24 , :term , [ ] } ] }
1491+ ] }
1492+ ] } ,
1493+ { :type , 24 , :map ,
1494+ [
1495+ { :type , 24 , :map_field_exact ,
1496+ [ { :atom , 24 , :__struct__ } , { :atom , 24 , Typespec } ] } ,
1497+ { :type , 24 , :map_field_exact , [ { :atom , 24 , :age } , { :type , 24 , :term , [ ] } ] } ,
1498+ { :type , 24 , :map_field_exact , [ { :atom , 24 , :name } , { :type , 24 , :term , [ ] } ] }
13891499 ] }
13901500 ] }
1391- ] } } = atoms_type2
1501+ ] } } = result . spec_struct
1502+
1503+ assert { :attribute , 27 , :spec ,
1504+ { { :spec_list , 1 } ,
1505+ [
1506+ { :type , 27 , :fun ,
1507+ [
1508+ { :type , 27 , :product ,
1509+ [ { :type , 27 , :nonempty_list , [ { :type , 27 , :integer , [ ] } ] } ] } ,
1510+ { :type , 27 , :nonempty_list , [ ] }
1511+ ] }
1512+ ] } } = result . spec_list
13921513
1393- assert { :attribute , 14 , :spec ,
1394- { { :atoms_type , 1 } ,
1514+ assert { :attribute , 30 , :spec ,
1515+ { { :spec_range , 1 } ,
13951516 [
1396- { :type , 14 , :fun ,
1517+ { :type , 30 , :fun ,
13971518 [
1398- { :type , 14 , :product ,
1399- [ { :type , 14 , :union , [ { :atom , 14 , :ok } , { :atom , 14 , :error } ] } ] } ,
1400- { :type , 14 , :union , [ { :atom , 14 , :ok } , { :atom , 14 , :error } ] }
1519+ { :type , 30 , :product ,
1520+ [ { :type , 30 , :range , [ { :integer , 30 , 1 } , { :integer , 30 , 10 } ] } ] } ,
1521+ { :type , 30 , :list ,
1522+ [ { :type , 30 , :range , [ { :integer , 30 , 1 } , { :integer , 30 , 10 } ] } ] }
14011523 ] }
1402- ] } } = atoms_type
1524+ ] } } = result . spec_range
14031525
1404- assert { :attribute , 11 , :spec ,
1405- { { :named_type , 1 } ,
1526+ assert { :attribute , 33 , :spec ,
1527+ { { :spec_keyword , 1 } ,
14061528 [
1407- { :type , 11 , :fun ,
1529+ { :type , 33 , :fun ,
14081530 [
1409- { :type , 11 , :product ,
1531+ { :type , 33 , :product ,
14101532 [
1411- { :ann_type , 11 ,
1533+ { :type , 33 , :list ,
14121534 [
1413- { :var , 11 , :name } ,
1414- { :remote_type , 11 , [ { :atom , 11 , Unknown } , { :atom , 11 , :atom } , [ ] ] }
1535+ { :type , 33 , :union ,
1536+ [
1537+ { :type , 33 , :tuple , [ { :atom , 33 , :a } , { :type , 33 , :integer , [ ] } ] } ,
1538+ { :type , 33 , :tuple , [ { :atom , 33 , :b } , { :type , 33 , :integer , [ ] } ] }
1539+ ] }
14151540 ] }
14161541 ] } ,
1417- { :type , 11 , :atom , [ ] }
1542+ { :type , 33 , :integer , [ ] }
14181543 ] }
1419- ] } } = named_type
1544+ ] } } = result . spec_keyword
14201545
1421- assert { :attribute , 8 , :spec ,
1422- { { :missing_type_arg , 0 } ,
1546+ assert { :attribute , 36 , :spec ,
1547+ { { :spec_tuple , 1 } ,
14231548 [
1424- { :type , 8 , :fun ,
1549+ { :type , 36 , :fun ,
14251550 [
1426- { :type , 8 , :product , [ ] } ,
1427- { :user_type , 8 , :mylist ,
1428- [ { :remote_type , 8 , [ { :atom , 8 , Unknown } , { :atom , 8 , :atom } , [ ] ] } ] }
1551+ { :type , 36 , :product ,
1552+ [ { :type , 36 , :tuple , [ { :atom , 36 , :ok } , { :type , 36 , :integer , [ ] } ] } ] } ,
1553+ { :type , 36 , :tuple , :any }
14291554 ] }
1430- ] } } = missing_type_arg
1555+ ] } } = result . spec_tuple
14311556
1432- assert { :attribute , 5 , :spec ,
1433- { { :missing_type , 0 } ,
1557+ assert { :attribute , 39 , :spec ,
1558+ { { :spec_bitstring , 1 } ,
14341559 [
1435- { :type , 5 , :fun ,
1560+ { :type , 39 , :fun ,
14361561 [
1437- { :type , 5 , :product , [ ] } ,
1438- { :remote_type , 5 , [ { :atom , 5 , Unknown } , { :atom , 5 , :atom } , [ ] ] }
1562+ { :type , 39 , :product ,
1563+ [ { :type , 39 , :binary , [ { :integer , 39 , 48 } , { :integer , 39 , 8 } ] } ] } ,
1564+ { :type , 39 , :binary , [ { :integer , 39 , 0 } , { :integer , 39 , 0 } ] }
14391565 ] }
1440- ] } } = missing_type
1566+ ] } } = result . spec_bitstring
14411567 end
14421568
14431569 test "clauses without a line" do
@@ -1458,4 +1584,10 @@ defmodule Gradient.AstSpecifierTest do
14581584 def filter_attributes ( ast , type ) do
14591585 Enum . filter ( ast , & match? ( { :attribute , _ , ^ type , _ } , & 1 ) )
14601586 end
1587+
1588+ def make_spec_map ( specs ) do
1589+ specs
1590+ |> Enum . map ( fn { :attribute , _ , _ , { { name , _arity } , _ } } = attr -> { name , attr } end )
1591+ |> Enum . into ( % { } )
1592+ end
14611593end
0 commit comments