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