@@ -638,8 +638,21 @@ defmodule Code.Formatter do
638638 paren_fun_to_algebra ( paren_fun , min_line , max_line , state )
639639 end
640640
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
643656 end
644657
645658 defp block_to_algebra ( { :__block__ , _ , [ _ , _ | _ ] = args } , min_line , max_line , state ) do
@@ -1822,7 +1835,12 @@ defmodule Code.Formatter do
18221835 end
18231836
18241837 { 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
18261844
18271845 cond do
18281846 args_docs == [ ] ->
@@ -2084,85 +2102,81 @@ defmodule Code.Formatter do
20842102 end
20852103
20862104 ## 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 )
21002107
21012108 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 }
21032111 end
21042112
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 }
21072115 end
21082116
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
21102118 { 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
21142119
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
21192120
2120- defp each_quoted_to_algebra_with_comments ( [ arg | args ] , acc , max_line , state , comments? , fun ) do
21212121 case traverse_line ( arg , { @ max_line , @ min_line } ) do
21222122 { @ max_line , @ min_line } ->
2123- { doc_triplet , state } = fun . ( arg , args , state )
21242123 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? )
21262125
21272126 { 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
21302142
2131- { doc_triplet , state } = fun . ( arg , args , % { state | comments: comments } )
2143+ comments? = leading_comments != [ ] or trailing_comments != [ ]
21322144
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 )
21352147
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? )
21392153 end
21402154 end
21412155
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
21472157
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 )
21502166 end
21512167
21522168 defp add_previous_to_acc ( [ { doc , next_line , newlines } | acc ] , previous ) when newlines < previous ,
21532169 do: [ { doc , next_line , previous } | acc ]
21542170
21552171 defp add_previous_to_acc ( acc , _previous ) ,
21562172 do: acc
2173+ defp build_trailing_comments ( acc , [ ] ) , do: acc
21572174
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 )
21662180 end
21672181
21682182 # If the document is immediately followed by comment which is followed by newlines,
@@ -2174,6 +2188,7 @@ defmodule Code.Formatter do
21742188
21752189 defp adjust_trailing_newlines ( doc_triplet , _ , _ ) , do: doc_triplet
21762190
2191+
21772192 defp traverse_line ( { expr , meta , args } , { min , max } ) do
21782193 # This is a hot path, so use :lists.keyfind/3 instead Keyword.fetch!/2
21792194 acc =
0 commit comments