@@ -20,16 +20,14 @@ defmodule Mix.Tasks.Test do
2020 Mix . shell ( ) . info ( "\n Generating cover results ...\n " )
2121 { :result , ok , _fail } = :cover . analyse ( :coverage , :line )
2222
23- results =
24- ok
25- |> gather_coverage ( :cover . modules ( ) )
26- |> Enum . sort_by ( & percentage ( elem ( & 1 , 1 ) ) , & >= / 2 )
23+ { module_results , totals } = gather_coverage ( ok , :cover . modules ( ) )
24+ module_results = Enum . sort_by ( module_results , & percentage ( elem ( & 1 , 1 ) ) , & >= / 2 )
2725
2826 if summary_opts = Keyword . get ( opts , :summary , true ) do
29- console ( results , summary_opts )
27+ console ( module_results , totals , summary_opts )
3028 end
3129
32- html ( results , opts )
30+ html ( module_results , opts )
3331 end
3432 end
3533
@@ -40,50 +38,44 @@ defmodule Mix.Tasks.Test do
4038 # We may also have multiple entries on the same line.
4139 # Each line is only considered once.
4240 #
43- # We use the process dictionary for performance, to avoid
44- # working with nested maps, but we clean it up afterwards.
45- modules =
46- Enum . reduce ( results , MapSet . new ( ) , fn
47- { { module , 0 } , _ } , acc ->
48- MapSet . put ( acc , module )
49-
50- { { module , line } , { 1 , 0 } } , acc ->
51- coverage = Process . get ( module ) || % { }
52- Process . put ( module , Map . put ( coverage , line , true ) )
53- MapSet . put ( acc , module )
54-
55- { { module , line } , { 0 , 1 } } , acc ->
56- coverage = Process . get ( module ) || % { }
57- Process . put ( module , Map . put_new ( coverage , line , false ) )
58- MapSet . put ( acc , module )
41+ # We use ets for performance, to avoid working with nested maps
42+ table = :ets . new ( __MODULE__ , [ :set , :private ] )
43+
44+ try do
45+ Enum . each ( results , fn
46+ { { module , 0 } , _ } -> :ets . insert ( table , { { module , 0 } , :dummy } )
47+ { { module , line } , { 1 , 0 } } -> :ets . insert ( table , { { module , line } , true } )
48+ { { module , line } , { 0 , 1 } } -> :ets . insert_new ( table , { { module , line } , false } )
5949 end )
6050
61- for module <- modules , results = Process . delete ( module ) || % { } , module in keep do
62- result =
63- Enum . reduce ( results , { 0 , 0 } , fn
64- { _line , true } , { covered , not_covered } -> { covered + 1 , not_covered }
65- { _line , false } , { covered , not_covered } -> { covered , not_covered + 1 }
66- end )
51+ module_results =
52+ for module <- keep ,
53+ results = read_module_cover_results ( table , module ) ,
54+ do: { module , results }
6755
68- { module , result }
56+ total_covered = :ets . select_count ( table , [ { { :_ , true } , [ ] , [ true ] } ] )
57+ total_not_covered = :ets . select_count ( table , [ { { :_ , false } , [ ] , [ true ] } ] )
58+
59+ { module_results , { total_covered , total_not_covered } }
60+ after
61+ :ets . delete ( table )
6962 end
7063 end
7164
72- defp console ( results , true ) , do: console ( results , [ ] )
65+ defp read_module_cover_results ( table , module ) do
66+ covered = :ets . select_count ( table , [ { { { module , :_ } , true } , [ ] , [ true ] } ] )
67+ not_covered = :ets . select_count ( table , [ { { { module , :_ } , false } , [ ] , [ true ] } ] )
68+ { covered , not_covered }
69+ end
70+
71+ defp console ( results , totals , true ) , do: console ( results , totals , [ ] )
7372
74- defp console ( results , opts ) when is_list ( opts ) do
73+ defp console ( results , totals , opts ) when is_list ( opts ) do
7574 Mix . shell ( ) . info ( "Percentage | Module" )
7675 Mix . shell ( ) . info ( "-----------|--------------------------" )
7776 Enum . each ( results , & display ( & 1 , opts ) )
7877 Mix . shell ( ) . info ( "-----------|--------------------------" )
79-
80- total =
81- Enum . reduce ( results , { 0 , 0 } , fn { _ , { covered , not_covered } } ,
82- { total_covered , total_not_covered } ->
83- { total_covered + covered , total_not_covered + not_covered }
84- end )
85-
86- display ( { "Total" , total } , opts )
78+ display ( { "Total" , totals } , opts )
8779 Mix . shell ( ) . info ( "" )
8880 end
8981
@@ -121,14 +113,10 @@ defmodule Mix.Tasks.Test do
121113 ] )
122114 end
123115
124- defp percentage ( { 0 , 0 } ) , do: 100
116+ defp percentage ( { 0 , 0 } ) , do: 100.0
125117 defp percentage ( { covered , not_covered } ) , do: covered / ( covered + not_covered ) * 100
126118
127- defp format ( number , length ) when is_integer ( number ) ,
128- do: :io_lib . format ( "~#{ length } b" , [ number ] )
129-
130- defp format ( number , length ) when is_float ( number ) ,
131- do: :io_lib . format ( "~#{ length } .2f" , [ number ] )
119+ defp format ( number , length ) , do: :io_lib . format ( "~#{ length } .2f" , [ number ] )
132120
133121 defp format_name ( name ) when is_binary ( name ) , do: name
134122 defp format_name ( mod ) when is_atom ( mod ) , do: inspect ( mod )
0 commit comments