@@ -453,7 +453,7 @@ defmodule Protocol do
453453 true
454454
455455 """
456- @ spec extract_protocols ( [ charlist | String . t ( ) ] ) :: [ atom ]
456+ @ spec extract_protocols ( [ charlist | String . t ( ) | { charlist , [ charlist ] } ] ) :: [ atom ]
457457 def extract_protocols ( paths ) do
458458 extract_matching_by_attribute ( paths , [ ?E , ?l , ?i , ?x , ?i , ?r , ?. ] , fn module , attributes ->
459459 case attributes [ :__protocol__ ] do
@@ -482,7 +482,7 @@ defmodule Protocol do
482482 true
483483
484484 """
485- @ spec extract_impls ( module , [ charlist | String . t ( ) ] ) :: [ atom ]
485+ @ spec extract_impls ( module , [ charlist | String . t ( ) | { charlist , [ charlist ] } ] ) :: [ atom ]
486486 def extract_impls ( protocol , paths ) when is_atom ( protocol ) do
487487 prefix = Atom . to_charlist ( protocol ) ++ [ ?. ]
488488
@@ -496,17 +496,25 @@ defmodule Protocol do
496496
497497 defp extract_matching_by_attribute ( paths , prefix , callback ) do
498498 for path <- paths ,
499- # Do not use protocols as they may be consolidating
500- path = if ( is_list ( path ) , do: path , else: String . to_charlist ( path ) ) ,
501- file <- list_dir ( path ) ,
499+ { path , files } = list_dir ( path ) ,
500+ file <- files ,
502501 mod = extract_from_file ( path , file , prefix , callback ) ,
503502 do: mod
504503 end
505504
505+ # Do not use protocols as they may be consolidating
506+ defp list_dir ( { path , files } ) when is_list ( path ) and is_list ( files ) do
507+ { path , files }
508+ end
509+
510+ defp list_dir ( path ) when is_binary ( path ) do
511+ list_dir ( String . to_charlist ( path ) )
512+ end
513+
506514 defp list_dir ( path ) when is_list ( path ) do
507515 case :file . list_dir ( path ) do
508- { :ok , files } -> files
509- _ -> [ ]
516+ { :ok , files } -> { path , files }
517+ _ -> { path , [ ] }
510518 end
511519 end
512520
@@ -633,7 +641,7 @@ defmodule Protocol do
633641 checker =
634642 if checker do
635643 update_in ( checker . exports , fn exports ->
636- signatures = new_signatures ( definitions , protocol_funs , protocol , types )
644+ signatures = new_signatures ( definitions , protocol_funs , protocol , types , structs )
637645
638646 for { fun , info } <- exports do
639647 if sig = Map . get ( signatures , fun ) do
@@ -652,14 +660,13 @@ defmodule Protocol do
652660 end
653661 end
654662
655- defp new_signatures ( definitions , protocol_funs , protocol , types ) do
663+ defp new_signatures ( definitions , protocol_funs , protocol , types , structs ) do
656664 alias Module.Types.Descr
665+ types_minus_any = List . delete ( types , Any )
657666
658667 clauses =
659- types
660- |> List . delete ( Any )
661- |> Enum . map ( fn impl ->
662- { [ Module.Types.Of . impl ( impl ) ] , Descr . atom ( [ __concat__ ( protocol , impl ) ] ) }
668+ Enum . map ( types_minus_any , fn impl ->
669+ { [ Module.Types.Of . impl ( impl , :open ) ] , Descr . atom ( [ __concat__ ( protocol , impl ) ] ) }
663670 end )
664671
665672 { domain , impl_for , impl_for! } =
@@ -674,10 +681,16 @@ defmodule Protocol do
674681 end
675682
676683 _ ->
684+ structs_domain =
685+ case structs do
686+ [ ] -> Descr . none ( )
687+ _ -> Descr . open_map ( __struct__: Descr . atom ( structs ) )
688+ end
689+
677690 domain =
678- clauses
679- |> Enum . map ( fn { [ domain ] , _ } -> domain end )
680- |> Enum . reduce ( & Descr . union / 2 )
691+ Enum . reduce ( types_minus_any -- structs , structs_domain , fn impl , acc ->
692+ Descr . union ( Module.Types.Of . impl ( impl , :open ) , acc )
693+ end )
681694
682695 not_domain = Descr . negation ( domain )
683696
0 commit comments