@@ -367,16 +367,21 @@ defmodule Module.Types.Descr do
367367
368368  @ doc  """ 
369369  Converts a descr to its quoted representation. 
370+ 
371+   ## Options 
372+ 
373+     * `:collapse_structs` - do not show struct fields that match 
374+       their default type 
370375  """ 
371-   def  to_quoted ( descr )  do 
376+   def  to_quoted ( descr ,   opts   \\   [ ] )  do 
372377    if  term_type? ( descr )  do 
373378      { :term ,  [ ] ,  [ ] } 
374379    else 
375380      # Dynamic always come first for visibility 
376381      { dynamic ,  descr }  = 
377382        case  :maps . take ( :dynamic ,  descr )  do 
378383          :error  ->  { [ ] ,  descr } 
379-           { dynamic ,  descr }  ->  { to_quoted ( :dynamic ,  dynamic ) ,  descr } 
384+           { dynamic ,  descr }  ->  { to_quoted ( :dynamic ,  dynamic ,   opts ) ,  descr } 
380385        end 
381386
382387      # Merge empty list and list together if they both exist 
@@ -385,7 +390,7 @@ defmodule Module.Types.Descr do
385390          % { list:  list ,  bitmap:  bitmap }  when  ( bitmap  &&&  @ bit_empty_list )  !=  0  -> 
386391            descr  =  descr  |>  Map . delete ( :list )  |>  Map . replace! ( :bitmap ,  bitmap  -  @ bit_empty_list ) 
387392
388-             case  list_to_quoted ( list ,  :list )  do 
393+             case  list_to_quoted ( list ,  :list ,   opts )  do 
389394              [ ]  ->  { [ { :empty_list ,  [ ] ,  [ ] } ] ,  descr } 
390395              unions  ->  { unions ,  descr } 
391396            end 
@@ -396,7 +401,9 @@ defmodule Module.Types.Descr do
396401
397402      unions  = 
398403        dynamic  ++ 
399-           Enum . sort ( extra  ++  Enum . flat_map ( descr ,  fn  { key ,  value }  ->  to_quoted ( key ,  value )  end ) ) 
404+           Enum . sort ( 
405+             extra  ++  Enum . flat_map ( descr ,  fn  { key ,  value }  ->  to_quoted ( key ,  value ,  opts )  end ) 
406+           ) 
400407
401408      case  unions  do 
402409        [ ]  ->  { :none ,  [ ] ,  [ ] } 
@@ -405,19 +412,19 @@ defmodule Module.Types.Descr do
405412    end 
406413  end 
407414
408-   defp  to_quoted ( :atom ,  val ) ,  do:  atom_to_quoted ( val ) 
409-   defp  to_quoted ( :bitmap ,  val ) ,  do:  bitmap_to_quoted ( val ) 
410-   defp  to_quoted ( :dynamic ,  descr ) ,  do:  dynamic_to_quoted ( descr ) 
411-   defp  to_quoted ( :map ,  dnf ) ,  do:  map_to_quoted ( dnf ) 
412-   defp  to_quoted ( :list ,  dnf ) ,  do:  list_to_quoted ( dnf ,  :non_empty_list ) 
413-   defp  to_quoted ( :tuple ,  dnf ) ,  do:  tuple_to_quoted ( dnf ) 
415+   defp  to_quoted ( :atom ,  val ,   _opts ) ,  do:  atom_to_quoted ( val ) 
416+   defp  to_quoted ( :bitmap ,  val ,   _opts ) ,  do:  bitmap_to_quoted ( val ) 
417+   defp  to_quoted ( :dynamic ,  descr ,   opts ) ,  do:  dynamic_to_quoted ( descr ,   opts ) 
418+   defp  to_quoted ( :map ,  dnf ,   opts ) ,  do:  map_to_quoted ( dnf ,   opts ) 
419+   defp  to_quoted ( :list ,  dnf ,   opts ) ,  do:  list_to_quoted ( dnf ,  :non_empty_list ,   opts ) 
420+   defp  to_quoted ( :tuple ,  dnf ,   opts ) ,  do:  tuple_to_quoted ( dnf ,   opts ) 
414421
415422  @ doc  """ 
416423  Converts a descr to its quoted string representation. 
417424  """ 
418-   def  to_quoted_string ( descr )  do 
425+   def  to_quoted_string ( descr ,   opts   \\   [ ] )  do 
419426    descr 
420-     |>  to_quoted ( ) 
427+     |>  to_quoted ( opts ) 
421428    |>  Code.Formatter . to_algebra ( ) 
422429    |>  Inspect.Algebra . format ( 98 ) 
423430    |>  IO . iodata_to_binary ( ) 
@@ -1045,16 +1052,16 @@ defmodule Module.Types.Descr do
10451052    end 
10461053  end 
10471054
1048-   defp  list_to_quoted ( dnf ,  name )  do 
1055+   defp  list_to_quoted ( dnf ,  name ,   opts )  do 
10491056    dnf  =  list_normalize ( dnf ) 
10501057
10511058    for  { list_type ,  last_type ,  negs }  <-  dnf ,  reduce:  [ ]  do 
10521059      acc  -> 
10531060        arguments  = 
10541061          if  subtype? ( last_type ,  @ empty_list )  do 
1055-             [ to_quoted ( list_type ) ] 
1062+             [ to_quoted ( list_type ,   opts ) ] 
10561063          else 
1057-             [ to_quoted ( list_type ) ,  to_quoted ( last_type ) ] 
1064+             [ to_quoted ( list_type ,   opts ) ,  to_quoted ( last_type ,   opts ) ] 
10581065          end 
10591066
10601067        if  negs  ==  [ ]  do 
@@ -1064,9 +1071,9 @@ defmodule Module.Types.Descr do
10641071          |>  Enum . map ( fn  { ty ,  lst }  -> 
10651072            args  = 
10661073              if  subtype? ( lst ,  @ empty_list )  do 
1067-                 [ to_quoted ( ty ) ] 
1074+                 [ to_quoted ( ty ,   opts ) ] 
10681075              else 
1069-                 [ to_quoted ( ty ) ,  to_quoted ( lst ) ] 
1076+                 [ to_quoted ( ty ,   opts ) ,  to_quoted ( lst ,   opts ) ] 
10701077              end 
10711078
10721079            { name ,  [ ] ,  args } 
@@ -1176,7 +1183,7 @@ defmodule Module.Types.Descr do
11761183    end 
11771184  end 
11781185
1179-   defp  dynamic_to_quoted ( descr )  do 
1186+   defp  dynamic_to_quoted ( descr ,   opts )  do 
11801187    cond  do 
11811188      term_type? ( descr )  -> 
11821189        [ { :dynamic ,  [ ] ,  [ ] } ] 
@@ -1185,7 +1192,7 @@ defmodule Module.Types.Descr do
11851192        [ single ] 
11861193
11871194      true  -> 
1188-         case  to_quoted ( descr )  do 
1195+         case  to_quoted ( descr ,   opts )  do 
11891196          { :none ,  _meta ,  [ ] }  =  none  ->  [ none ] 
11901197          descr  ->  [ { :dynamic ,  [ ] ,  [ descr ] } ] 
11911198        end 
@@ -1786,51 +1793,77 @@ defmodule Module.Types.Descr do
17861793         end ) ) 
17871794  end 
17881795
1789-   defp  map_to_quoted ( dnf )  do 
1796+   defp  map_to_quoted ( dnf ,   opts )  do 
17901797    dnf 
17911798    |>  map_normalize ( ) 
1792-     |>  Enum . map ( & map_each_to_quoted / 1 ) 
1799+     |>  Enum . map ( & map_each_to_quoted ( & 1 ,   opts ) ) 
17931800  end 
17941801
1795-   defp  map_each_to_quoted ( { tag ,  positive_map ,  negative_maps } )  do 
1802+   defp  map_each_to_quoted ( { tag ,  positive_map ,  negative_maps } ,   opts )  do 
17961803    case  negative_maps  do 
17971804      [ ]  -> 
1798-         map_literal_to_quoted ( { tag ,  positive_map } ) 
1805+         map_literal_to_quoted ( { tag ,  positive_map } ,   opts ) 
17991806
18001807      _  -> 
18011808        negative_maps 
1802-         |>  Enum . map ( & map_literal_to_quoted / 1 ) 
1809+         |>  Enum . map ( & map_literal_to_quoted ( & 1 ,   opts ) ) 
18031810        |>  Enum . reduce ( & { :or ,  [ ] ,  [ & 2 ,  & 1 ] } ) 
18041811        |>  Kernel . then ( 
1805-           & { :and ,  [ ] ,  [ map_literal_to_quoted ( { tag ,  positive_map } ) ,  { :not ,  [ ] ,  [ & 1 ] } ] } 
1812+           & { :and ,  [ ] ,  [ map_literal_to_quoted ( { tag ,  positive_map } ,   opts ) ,  { :not ,  [ ] ,  [ & 1 ] } ] } 
18061813        ) 
18071814    end 
18081815  end 
18091816
1810-   def  map_literal_to_quoted ( { :closed ,  fields } )  when  map_size ( fields )  ==  0  do 
1817+   def  map_literal_to_quoted ( { :closed ,  fields } ,   _opts )  when  map_size ( fields )  ==  0  do 
18111818    { :empty_map ,  [ ] ,  [ ] } 
18121819  end 
18131820
1814-   def  map_literal_to_quoted ( { tag ,  fields } )  do 
1821+   def  map_literal_to_quoted ( { tag ,  fields } ,   opts )  do 
18151822    case  tag  do 
18161823      :closed  -> 
18171824        with  % { __struct__:  struct_descr }  <-  fields , 
18181825             { _ ,  [ struct ] }  <-  atom_fetch ( struct_descr )  do 
1826+           fields  =  Map . delete ( fields ,  :__struct__ ) 
1827+ 
1828+           fields  = 
1829+             with  true  <-  Keyword . get ( opts ,  :collapse_structs ,  false ) , 
1830+                  [ _  |  _ ]  =  info  <-  maybe_struct ( struct ) , 
1831+                  true  <-  Enum . all? ( info ,  & is_map_key ( fields ,  & 1 . field ) )  do 
1832+               Enum . reduce ( info ,  fields ,  fn  % { field:  field } ,  acc  -> 
1833+                 # TODO: This should consider the struct default value 
1834+                 if  Map . fetch! ( acc ,  field )  ==  term ( )  do 
1835+                   Map . delete ( acc ,  field ) 
1836+                 else 
1837+                   acc 
1838+                 end 
1839+               end ) 
1840+             else 
1841+               _  ->  fields 
1842+             end 
1843+ 
18191844          { :% ,  [ ] , 
18201845           [ 
18211846             literal_to_quoted ( struct ) , 
1822-              { :%{} ,  [ ] ,  map_fields_to_quoted ( tag ,  Map . delete ( fields ,  :__struct__ ) ) } 
1847+              { :%{} ,  [ ] ,  map_fields_to_quoted ( tag ,  fields ,  opts ) } 
18231848           ] } 
18241849        else 
1825-           _  ->  { :%{} ,  [ ] ,  map_fields_to_quoted ( tag ,  fields ) } 
1850+           _  ->  { :%{} ,  [ ] ,  map_fields_to_quoted ( tag ,  fields ,   opts ) } 
18261851        end 
18271852
18281853      :open  -> 
1829-         { :%{} ,  [ ] ,  [ { :... ,  [ ] ,  nil }  |  map_fields_to_quoted ( tag ,  fields ) ] } 
1854+         { :%{} ,  [ ] ,  [ { :... ,  [ ] ,  nil }  |  map_fields_to_quoted ( tag ,  fields ,  opts ) ] } 
1855+     end 
1856+   end 
1857+ 
1858+   defp  maybe_struct ( struct )  do 
1859+     try  do 
1860+       struct . __info__ ( :struct ) 
1861+     rescue 
1862+       _  ->  nil 
18301863    end 
18311864  end 
18321865
1833-   defp  map_fields_to_quoted ( tag ,  map )  do 
1866+   defp  map_fields_to_quoted ( tag ,  map ,   opts )  do 
18341867    sorted  =  Enum . sort ( Map . to_list ( map ) ) 
18351868    keyword?  =  Inspect.List . keyword? ( sorted ) 
18361869
@@ -1846,9 +1879,9 @@ defmodule Module.Types.Descr do
18461879      { optional? ,  type }  =  pop_optional_static ( type ) 
18471880
18481881      cond  do 
1849-         not  optional?  ->  { key ,  to_quoted ( type ) } 
1882+         not  optional?  ->  { key ,  to_quoted ( type ,   opts ) } 
18501883        empty? ( type )  ->  { key ,  { :not_set ,  [ ] ,  [ ] } } 
1851-         true  ->  { key ,  { :if_set ,  [ ] ,  [ to_quoted ( type ) ] } } 
1884+         true  ->  { key ,  { :if_set ,  [ ] ,  [ to_quoted ( type ,   opts ) ] } } 
18521885      end 
18531886    end 
18541887  end 
@@ -1969,11 +2002,11 @@ defmodule Module.Types.Descr do
19692002  # This is a cheap optimization that relies on structural equality. 
19702003  defp  tuple_union ( left ,  right ) ,  do:  left  ++  ( right  --  left ) 
19712004
1972-   defp  tuple_to_quoted ( dnf )  do 
2005+   defp  tuple_to_quoted ( dnf ,   opts )  do 
19732006    dnf 
19742007    |>  tuple_simplify ( ) 
19752008    |>  tuple_fusion ( ) 
1976-     |>  Enum . map ( & tuple_each_to_quoted / 1 ) 
2009+     |>  Enum . map ( & tuple_each_to_quoted ( & 1 ,   opts ) ) 
19772010  end 
19782011
19792012  # Given a dnf of tuples, fuses the tuple unions when possible, 
@@ -2020,27 +2053,27 @@ defmodule Module.Types.Descr do
20202053    { tag ,  fused_elements ,  [ ] } 
20212054  end 
20222055
2023-   defp  tuple_each_to_quoted ( { tag ,  positive_tuple ,  negative_tuples } )  do 
2056+   defp  tuple_each_to_quoted ( { tag ,  positive_tuple ,  negative_tuples } ,   opts )  do 
20242057    case  negative_tuples  do 
20252058      [ ]  -> 
2026-         tuple_literal_to_quoted ( { tag ,  positive_tuple } ) 
2059+         tuple_literal_to_quoted ( { tag ,  positive_tuple } ,   opts ) 
20272060
20282061      _  -> 
20292062        negative_tuples 
2030-         |>  Enum . map ( & tuple_literal_to_quoted / 1 ) 
2063+         |>  Enum . map ( & tuple_literal_to_quoted ( & 1 ,   opts ) ) 
20312064        |>  Enum . reduce ( & { :or ,  [ ] ,  [ & 2 ,  & 1 ] } ) 
20322065        |>  Kernel . then ( 
2033-           & { :and ,  [ ] ,  [ tuple_literal_to_quoted ( { tag ,  positive_tuple } ) ,  { :not ,  [ ] ,  [ & 1 ] } ] } 
2066+           & { :and ,  [ ] ,  [ tuple_literal_to_quoted ( { tag ,  positive_tuple } ,   opts ) ,  { :not ,  [ ] ,  [ & 1 ] } ] } 
20342067        ) 
20352068    end 
20362069  end 
20372070
2038-   defp  tuple_literal_to_quoted ( { :closed ,  [ ] } ) ,  do:  { :{} ,  [ ] ,  [ ] } 
2071+   defp  tuple_literal_to_quoted ( { :closed ,  [ ] } ,   _opts ) ,  do:  { :{} ,  [ ] ,  [ ] } 
20392072
2040-   defp  tuple_literal_to_quoted ( { tag ,  elements } )  do 
2073+   defp  tuple_literal_to_quoted ( { tag ,  elements } ,   opts )  do 
20412074    case  tag  do 
2042-       :closed  ->  { :{} ,  [ ] ,  Enum . map ( elements ,  & to_quoted / 1 ) } 
2043-       :open  ->  { :{} ,  [ ] ,  Enum . map ( elements ,  & to_quoted / 1 )  ++  [ { :... ,  [ ] ,  nil } ] } 
2075+       :closed  ->  { :{} ,  [ ] ,  Enum . map ( elements ,  & to_quoted ( & 1 ,   opts ) ) } 
2076+       :open  ->  { :{} ,  [ ] ,  Enum . map ( elements ,  & to_quoted ( & 1 ,   opts ) )  ++  [ { :... ,  [ ] ,  nil } ] } 
20442077    end 
20452078  end 
20462079
0 commit comments