diff --git a/spec/compiler/formatter/formatter_spec.cr b/spec/compiler/formatter/formatter_spec.cr index 2fa6e1d37e5a..b770c962cac8 100644 --- a/spec/compiler/formatter/formatter_spec.cr +++ b/spec/compiler/formatter/formatter_spec.cr @@ -1310,4 +1310,11 @@ describe Crystal::Formatter do " 2 \n" + "end" ) + + # #7443 + assert_format "long_variable_name = [{\n :foo => 1,\n}, {\n :bar => 2,\n}]" + assert_format "long_variable_name = [\n {\n :foo => 1,\n }, {\n :bar => 2,\n },\n]" + assert_format "long_variable_name = [\n {\n :foo => 1,\n },\n {\n :bar => 2,\n },\n]" + assert_format "long_variable_name = [1, 2, 3,\n 4, 5, 6]" + assert_format "long_variable_name = [1, 2, 3, # foo\n 4, 5, 6]" end diff --git a/src/compiler/crystal/tools/formatter.cr b/src/compiler/crystal/tools/formatter.cr index 0df6ca258e9e..9d00bcaf7723 100644 --- a/src/compiler/crystal/tools/formatter.cr +++ b/src/compiler/crystal/tools/formatter.cr @@ -787,6 +787,7 @@ module Crystal if found_comment || @token.type == :NEWLINE # add one level of indentation for contents if a newline is present offset = @indent + 2 + start_column = @indent + 2 if elements.empty? skip_space_or_newline @@ -802,7 +803,8 @@ module Crystal found_first_newline = true else # indent contents at the same column as starting token if no newline - offset = @column + offset = @indent + start_column = @column end elements.each_with_index do |element, i| @@ -819,17 +821,20 @@ module Crystal write_space_at_end = true end + start_line = @line if next_needs_indent write_indent(offset, element) else indent(offset, element) end + element_lines = @line - start_line + next_offset = element_lines == 0 ? start_column : offset has_heredoc_in_line = !@lexer.heredocs.empty? last = last?(i, elements) - found_comment = skip_space(offset, write_comma: (last || has_heredoc_in_line) && has_newlines) + found_comment = skip_space(next_offset, write_comma: (last || has_heredoc_in_line) && has_newlines) if @token.type == :"," if !found_comment && (!last || has_heredoc_in_line) @@ -839,7 +844,7 @@ module Crystal slash_is_regex! next_token - found_comment = skip_space(offset, write_comma: last && has_newlines) + found_comment = skip_space(element_lines == 0 ? start_column : offset, write_comma: last && has_newlines) if @token.type == :NEWLINE if last && !found_comment && !wrote_comma write "," @@ -849,12 +854,14 @@ module Crystal skip_space_or_newline next_needs_indent = true has_newlines = true + offset = next_offset if element_lines == 0 else if !last && !found_comment write " " next_needs_indent = false elsif found_comment next_needs_indent = true + offset = next_offset if element_lines == 0 end end end