@@ -1015,6 +1015,8 @@ end
10151015# `#= ... =#` comments are reported as whitespace by JuliaSyntax, so block
10161016# handlers that skip whitespace would otherwise drop them. Append the comment
10171017# (keeping it on the current line when it trails code) instead of losing it.
1018+ #
1019+ # Returns true if the comment was added, false otherwise.
10181020function add_hasheq_comment! (t:: FST , n:: FST , s:: State )
10191021 n. typ === HASHEQCOMMENT || return false
10201022 tnodes = t. nodes:: Vector{FST}
@@ -3698,6 +3700,7 @@ function p_hcat(
36983700 # to decide whether to place boundary newlines. In other words, we can safely insert
36993701 # Placeholder nodes at these positions.
37003702
3703+ prev_comment_was_dropped = false
37013704 for (i, a) in enumerate (childs)
37023705 n = pretty (style, a, s, ctx, lineage)
37033706 if kind (a) === K " ["
@@ -3728,7 +3731,7 @@ function p_hcat(
37283731 add_node! (t, n, s; join_lines = true )
37293732 elseif JuliaSyntax. is_whitespace (a)
37303733 if kind (a) === K " Comment"
3731- add_node! (t, n, s; join_lines = true )
3734+ prev_comment_was_dropped = ! add_hasheq_comment! (t, n, s)
37323735 elseif is_newline_after_2semicolons (cst, i)
37333736 # See above: we cannot convert ';;\n' to ';;'
37343737 add_node! (t, Newline (; nest_behavior = AlwaysNest), s)
@@ -3738,13 +3741,36 @@ function p_hcat(
37383741 # later on, `n_tuple!` will insert newlines after the `[` and before the
37393742 # `].`
37403743 t. nest_behavior = AlwaysNest
3741- elseif ! (kind (cst[i+ 1 ]) in KSet " ; ]" ) && ! (kind (cst[i- 1 ]) in KSet " ; [" )
3744+ prev_comment_was_dropped = false
3745+ elseif ! (kind (cst[i+ 1 ]) in KSet " ; ] Comment" ) && ! (kind (cst[i- 1 ]) in KSet " ; [" )
37423746 # Whitespace is generally important to retain, because it can be a separator
37433747 # -- but we should omit it in a few cases:
37443748 # 1. If it's followed by / before a ';;' separator, since it's not needed.
37453749 # 2. Directly after the opening bracket.
37463750 # 3. Directly before the closing bracket.
3747- add_node! (t, Whitespace (1 ), s)
3751+ #
3752+ # There's also some special logic for comments, because the current way that
3753+ # JuliaFormatter deals with comments is crazily hacky.
3754+ if ! isnothing (first_arg_idx) &&
3755+ i < first_arg_idx &&
3756+ prev_comment_was_dropped
3757+ # Before the first argument, after a dropped regular # comment.
3758+ # Suppress whitespace so NOTCODE gap detection can reconstruct
3759+ # the comment at the parent level.
3760+ elseif prev_comment_was_dropped
3761+ # After a dropped regular # comment, past the first argument.
3762+ # Remove the preceding forced NEWLINE (e.g. from ;;) so that
3763+ # add_node!'s gap detection is not short-circuited by
3764+ # is_prev_newline, and can insert NOTCODE for the comment.
3765+ if is_prev_newline (t)
3766+ remove_prev_newline! (t)
3767+ end
3768+ else
3769+ add_node! (t, Whitespace (1 ), s)
3770+ end
3771+ prev_comment_was_dropped = false
3772+ else
3773+ prev_comment_was_dropped = false
37483774 end
37493775 elseif i == 1 && kind (a) != = K " ["
37503776 # Type preceding the `[`, e.g. `T` in `T[1 2 3]`.
@@ -3862,6 +3888,24 @@ function is_semantically_important_newline(
38623888 n = length (children (row_cst))
38633889 # Start of the row - not important
38643890 i == 1 && return false
3891+ # A newline is not important if it's adjacent to a comment and all the children
3892+ # between the comment and the boundary of the row (start or end) are whitespace.
3893+ #
3894+ # Trailing comment case: all children after this newline are whitespace, and at least
3895+ # one is a comment. Example: `3 4\n # bar\n` — the newline before `# bar` is not a row
3896+ # separator. We don't need to include it.
3897+ if all (j -> JuliaSyntax. is_whitespace (row_cst[j]), (i+ 1 ): n) &&
3898+ any (j -> kind (row_cst[j]) === K " Comment" , (i+ 1 ): n)
3899+ return false
3900+ end
3901+ # Leading comment case: all children before this newline are whitespace, and at least
3902+ # one is a comment. Example: `\n # foo\n 1 2` — the newline after `# foo` is not a row
3903+ # separator. We can drop all newlines after the comment, because the insertion of the
3904+ # newline after the comment is handled by the NOTCODE mechanism later on.
3905+ if all (j -> JuliaSyntax. is_whitespace (row_cst[j]), 1 : (i- 1 )) &&
3906+ any (j -> kind (row_cst[j]) === K " Comment" , 1 : (i- 1 ))
3907+ return false
3908+ end
38653909 # End of the row -- might be important
38663910 i == n && return (! is_last_arg_of_parent && kind (row_cst[i- 1 ]) != = K " ;" )
38673911 # Otherwise it's important
0 commit comments