@@ -641,8 +641,21 @@ defmodule Code.Formatter do
641
641
paren_fun_to_algebra ( paren_fun , min_line , max_line , state )
642
642
end
643
643
644
- defp block_to_algebra ( { :__block__ , _ , [ ] } , min_line , max_line , state ) do
645
- block_args_to_algebra ( [ ] , min_line , max_line , state )
644
+ defp block_to_algebra ( { :__block__ , meta , args } , _min_line , _max_line , state ) when args in [ [ ] , [ nil ] ] do
645
+ inner_comments = meta [ :inner_comments ] || [ ]
646
+ comments_docs =
647
+ Enum . map ( inner_comments , fn comment ->
648
+ comment = format_comment ( comment )
649
+ { comment . text , @ empty , 1 }
650
+ end )
651
+
652
+ docs = merge_algebra_with_comments ( comments_docs , @ empty )
653
+
654
+ case docs do
655
+ [ ] -> { @ empty , state }
656
+ [ line ] -> { line , state }
657
+ lines -> { lines |> Enum . reduce ( & line ( & 2 , & 1 ) ) |> force_unfit ( ) , state }
658
+ end
646
659
end
647
660
648
661
defp block_to_algebra ( { :__block__ , _ , [ _ , _ | _ ] = args } , min_line , max_line , state ) do
@@ -1827,7 +1840,12 @@ defmodule Code.Formatter do
1827
1840
end
1828
1841
1829
1842
{ args_docs , comments? , state } =
1830
- quoted_to_algebra_with_comments ( args , acc , min_line , max_line , state , arg_to_algebra )
1843
+ case args do
1844
+ [ ] ->
1845
+ quoted_to_algebra_with_comments ( args , acc , min_line , max_line , state , arg_to_algebra )
1846
+ _ ->
1847
+ quoted_to_algebra_with_comments ( args , acc , min_line , max_line , state , arg_to_algebra )
1848
+ end
1831
1849
1832
1850
cond do
1833
1851
args_docs == [ ] ->
@@ -2089,85 +2107,81 @@ defmodule Code.Formatter do
2089
2107
end
2090
2108
2091
2109
## Quoted helpers for comments
2092
-
2093
- defp quoted_to_algebra_with_comments ( args , acc , min_line , max_line , state , fun ) do
2094
- { pre_comments , state } =
2095
- get_and_update_in ( state . comments , fn comments ->
2096
- Enum . split_while ( comments , fn % { line: line } -> line <= min_line end )
2097
- end )
2098
-
2099
- { reverse_docs , comments? , state } =
2100
- if state . comments == [ ] do
2101
- each_quoted_to_algebra_without_comments ( args , acc , state , fun )
2102
- else
2103
- each_quoted_to_algebra_with_comments ( args , acc , max_line , state , false , fun )
2104
- end
2110
+ defp quoted_to_algebra_with_comments ( args , acc , _min_line , _max_line , state , fun ) do
2111
+ { reverse_docs , comments? , state } = each_quoted_to_algebra_with_comments ( args , acc , state , fun , false )
2105
2112
2106
2113
docs = merge_algebra_with_comments ( Enum . reverse ( reverse_docs ) , @ empty )
2107
- { docs , comments? , update_in ( state . comments , & ( pre_comments ++ & 1 ) ) }
2114
+
2115
+ { docs , comments? , state }
2108
2116
end
2109
2117
2110
- defp each_quoted_to_algebra_without_comments ( [ ] , acc , state , _fun ) do
2111
- { acc , false , state }
2118
+ defp each_quoted_to_algebra_with_comments ( [ ] , acc , state , _fun , comments? ) do
2119
+ { acc , comments? , state }
2112
2120
end
2113
2121
2114
- defp each_quoted_to_algebra_without_comments ( [ arg | args ] , acc , state , fun ) do
2122
+ defp each_quoted_to_algebra_with_comments ( [ arg | args ] , acc , state , fun , comments? ) do
2115
2123
{ doc_triplet , state } = fun . ( arg , args , state )
2116
- acc = [ doc_triplet | acc ]
2117
- each_quoted_to_algebra_without_comments ( args , acc , state , fun )
2118
- end
2119
2124
2120
- defp each_quoted_to_algebra_with_comments ( [ ] , acc , max_line , state , comments? , _fun ) do
2121
- { acc , comments , comments? } = extract_comments_before ( max_line , acc , state . comments , comments? )
2122
- { acc , comments? , % { state | comments: comments } }
2123
- end
2124
2125
2125
- defp each_quoted_to_algebra_with_comments ( [ arg | args ] , acc , max_line , state , comments? , fun ) do
2126
2126
case traverse_line ( arg , { @ max_line , @ min_line } ) do
2127
2127
{ @ max_line , @ min_line } ->
2128
- { doc_triplet , state } = fun . ( arg , args , state )
2129
2128
acc = [ doc_triplet | acc ]
2130
- each_quoted_to_algebra_with_comments ( args , acc , max_line , state , comments? , fun )
2129
+ each_quoted_to_algebra_with_comments ( args , acc , state , fun , comments? )
2131
2130
2132
2131
{ doc_start , doc_end } ->
2133
- { acc , comments , comments? } =
2134
- extract_comments_before ( doc_start , acc , state . comments , comments? )
2132
+ { leading_comments , trailing_comments } =
2133
+ case arg do
2134
+ { _ , meta , _ } ->
2135
+ leading_comments = meta [ :leading_comments ] || [ ]
2136
+ trailing_comments = meta [ :trailing_comments ] || [ ]
2137
+ { leading_comments , trailing_comments }
2138
+
2139
+ { { _ , left_meta , _ } , { _ , right_meta , _ } } ->
2140
+ leading_comments = left_meta [ :leading_comments ] || [ ]
2141
+ trailing_comments = right_meta [ :trailing_comments ] || [ ]
2142
+
2143
+ { leading_comments , trailing_comments }
2144
+ _ ->
2145
+ { [ ] , [ ] }
2146
+ end
2135
2147
2136
- { doc_triplet , state } = fun . ( arg , args , % { state | comments: comments } )
2148
+ comments? = leading_comments != [ ] or trailing_comments != [ ]
2137
2149
2138
- { acc , comments , comments? } =
2139
- extract_comments_trailing ( doc_start , doc_end , acc , state . comments , comments? )
2150
+ leading_docs = build_leading_comments ( [ ] , leading_comments , doc_start )
2151
+ trailing_docs = build_trailing_comments ( [ ] , trailing_comments )
2140
2152
2141
- acc = [ adjust_trailing_newlines ( doc_triplet , doc_end , comments ) | acc ]
2142
- state = % { state | comments: comments }
2143
- each_quoted_to_algebra_with_comments ( args , acc , max_line , state , comments? , fun )
2153
+ doc_triplet = adjust_trailing_newlines ( doc_triplet , doc_end , trailing_comments )
2154
+
2155
+ acc = Enum . concat ( [ trailing_docs , [ doc_triplet ] , leading_docs , acc ] )
2156
+
2157
+ each_quoted_to_algebra_with_comments ( args , acc , state , fun , comments? )
2144
2158
end
2145
2159
end
2146
2160
2147
- defp extract_comments_before ( max , acc , [ % { line: line } = comment | rest ] , _ ) when line < max do
2148
- % { previous_eol_count: previous , next_eol_count: next , text: doc } = comment
2149
- acc = [ { doc , @ empty , next } | add_previous_to_acc ( acc , previous ) ]
2150
- extract_comments_before ( max , acc , rest , true )
2151
- end
2161
+ defp build_leading_comments ( acc , [ ] , _ ) , do: acc
2152
2162
2153
- defp extract_comments_before ( _max , acc , rest , comments? ) do
2154
- { acc , rest , comments? }
2163
+ defp build_leading_comments ( acc , [ comment | rest ] , doc_start ) do
2164
+ comment = format_comment ( comment )
2165
+ % { previous_eol_count: previous , next_eol_count: next , text: doc , line: line } = comment
2166
+ # If the comment is on the same line as the document, we need to adjust the newlines
2167
+ # such that the comment is placed right above the document line.
2168
+ next = if line == doc_start , do: 1 , else: next
2169
+ acc = [ { doc , @ empty , next } | add_previous_to_acc ( acc , previous ) ]
2170
+ build_leading_comments ( acc , rest , doc_start )
2155
2171
end
2156
2172
2157
2173
defp add_previous_to_acc ( [ { doc , next_line , newlines } | acc ] , previous ) when newlines < previous ,
2158
2174
do: [ { doc , next_line , previous } | acc ]
2159
2175
2160
2176
defp add_previous_to_acc ( acc , _previous ) ,
2161
2177
do: acc
2178
+ defp build_trailing_comments ( acc , [ ] ) , do: acc
2162
2179
2163
- defp extract_comments_trailing ( min , max , acc , [ % { line: line , text: doc_comment } | rest ] , _ )
2164
- when line >= min and line <= max do
2165
- acc = [ { doc_comment , @ empty , 1 } | acc ]
2166
- extract_comments_trailing ( min , max , acc , rest , true )
2167
- end
2168
-
2169
- defp extract_comments_trailing ( _min , _max , acc , rest , comments? ) do
2170
- { acc , rest , comments? }
2180
+ defp build_trailing_comments ( acc , [ comment | rest ] ) do
2181
+ comment = format_comment ( comment )
2182
+ % { previous_eol_count: previous , next_eol_count: next , text: doc } = comment
2183
+ acc = [ { doc , @ empty , next } | acc ]
2184
+ build_trailing_comments ( acc , rest )
2171
2185
end
2172
2186
2173
2187
# If the document is immediately followed by comment which is followed by newlines,
@@ -2179,6 +2193,7 @@ defmodule Code.Formatter do
2179
2193
2180
2194
defp adjust_trailing_newlines ( doc_triplet , _ , _ ) , do: doc_triplet
2181
2195
2196
+
2182
2197
defp traverse_line ( { expr , meta , args } , { min , max } ) do
2183
2198
# This is a hot path, so use :lists.keyfind/3 instead Keyword.fetch!/2
2184
2199
acc =
0 commit comments