@@ -641,8 +641,21 @@ defmodule Code.Formatter do
641641 paren_fun_to_algebra ( paren_fun , min_line , max_line , state )
642642 end
643643
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
646659 end
647660
648661 defp block_to_algebra ( { :__block__ , _ , [ _ , _ | _ ] = args } , min_line , max_line , state ) do
@@ -1827,7 +1840,12 @@ defmodule Code.Formatter do
18271840 end
18281841
18291842 { 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
18311849
18321850 cond do
18331851 args_docs == [ ] ->
@@ -2089,85 +2107,81 @@ defmodule Code.Formatter do
20892107 end
20902108
20912109 ## 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 )
21052112
21062113 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 }
21082116 end
21092117
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 }
21122120 end
21132121
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
21152123 { 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
21192124
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
21242125
2125- defp each_quoted_to_algebra_with_comments ( [ arg | args ] , acc , max_line , state , comments? , fun ) do
21262126 case traverse_line ( arg , { @ max_line , @ min_line } ) do
21272127 { @ max_line , @ min_line } ->
2128- { doc_triplet , state } = fun . ( arg , args , state )
21292128 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? )
21312130
21322131 { 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
21352147
2136- { doc_triplet , state } = fun . ( arg , args , % { state | comments: comments } )
2148+ comments? = leading_comments != [ ] or trailing_comments != [ ]
21372149
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 )
21402152
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? )
21442158 end
21452159 end
21462160
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
21522162
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 )
21552171 end
21562172
21572173 defp add_previous_to_acc ( [ { doc , next_line , newlines } | acc ] , previous ) when newlines < previous ,
21582174 do: [ { doc , next_line , previous } | acc ]
21592175
21602176 defp add_previous_to_acc ( acc , _previous ) ,
21612177 do: acc
2178+ defp build_trailing_comments ( acc , [ ] ) , do: acc
21622179
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 )
21712185 end
21722186
21732187 # If the document is immediately followed by comment which is followed by newlines,
@@ -2179,6 +2193,7 @@ defmodule Code.Formatter do
21792193
21802194 defp adjust_trailing_newlines ( doc_triplet , _ , _ ) , do: doc_triplet
21812195
2196+
21822197 defp traverse_line ( { expr , meta , args } , { min , max } ) do
21832198 # This is a hot path, so use :lists.keyfind/3 instead Keyword.fetch!/2
21842199 acc =
0 commit comments