Skip to content

Commit 6eb63e8

Browse files
committed
Better formatting for empty hashes and arrays with interior comments
1 parent 1f623a5 commit 6eb63e8

File tree

2 files changed

+80
-11
lines changed

2 files changed

+80
-11
lines changed

lib/syntax_tree/formatter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def format(node, stackable: true)
5050
# Print all comments that were found after the node.
5151
trailing.each do |comment|
5252
line_suffix(priority: COMMENT_PRIORITY) do
53-
text(" ")
53+
comment.inline? ? text(" ") : breakable
5454
comment.format(self)
5555
break_parent
5656
end

lib/syntax_tree/node.rb

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,29 @@ def format(q)
816816
end
817817
end
818818

819+
class EmptyWithCommentsFormatter
820+
# [LBracket] the opening bracket
821+
attr_reader :lbracket
822+
823+
def initialize(lbracket)
824+
@lbracket = lbracket
825+
end
826+
827+
def format(q)
828+
q.group do
829+
q.text("[")
830+
q.indent do
831+
lbracket.comments.each do |comment|
832+
q.breakable(force: true)
833+
comment.format(q)
834+
end
835+
end
836+
q.breakable(force: true)
837+
q.text("]")
838+
end
839+
end
840+
end
841+
819842
# [LBracket] the bracket that opens this array
820843
attr_reader :lbracket
821844

@@ -867,6 +890,11 @@ def format(q)
867890
return
868891
end
869892

893+
if empty_with_comments?
894+
EmptyWithCommentsFormatter.new(lbracket).format(q)
895+
return
896+
end
897+
870898
q.group do
871899
q.format(lbracket)
872900

@@ -919,6 +947,12 @@ def var_refs?(q)
919947
q.maxwidth * 2
920948
)
921949
end
950+
951+
# If we have an empty array that contains only comments, then we're going
952+
# to do some special printing to ensure they get indented correctly.
953+
def empty_with_comments?
954+
contents.nil? && lbracket.comments.any? && lbracket.comments.none?(&:inline?)
955+
end
922956
end
923957

924958
# AryPtn represents matching against an array pattern using the Ruby 2.7+
@@ -4311,6 +4345,29 @@ def format(q)
43114345
# { key => value }
43124346
#
43134347
class HashLiteral < Node
4348+
class EmptyWithCommentsFormatter
4349+
# [LBrace] the opening brace
4350+
attr_reader :lbrace
4351+
4352+
def initialize(lbrace)
4353+
@lbrace = lbrace
4354+
end
4355+
4356+
def format(q)
4357+
q.group do
4358+
q.text("{")
4359+
q.indent do
4360+
lbrace.comments.each do |comment|
4361+
q.breakable(force: true)
4362+
comment.format(q)
4363+
end
4364+
end
4365+
q.breakable(force: true)
4366+
q.text("}")
4367+
end
4368+
end
4369+
end
4370+
43144371
# [LBrace] the left brace that opens this hash
43154372
attr_reader :lbrace
43164373

@@ -4355,7 +4412,18 @@ def format_key(q, key)
43554412

43564413
private
43574414

4415+
# If we have an empty hash that contains only comments, then we're going
4416+
# to do some special printing to ensure they get indented correctly.
4417+
def empty_with_comments?
4418+
assocs.empty? && lbrace.comments.any? && lbrace.comments.none?(&:inline?)
4419+
end
4420+
43584421
def format_contents(q)
4422+
if empty_with_comments?
4423+
EmptyWithCommentsFormatter.new(lbrace).format(q)
4424+
return
4425+
end
4426+
43594427
q.format(lbrace)
43604428

43614429
if assocs.empty?
@@ -7584,19 +7652,20 @@ def attach_comments(start_char, end_char)
75847652
comment = parser_comments[comment_index]
75857653
location = comment.location
75867654

7587-
if !comment.inline? && (start_char <= location.start_char) &&
7588-
(end_char >= location.end_char) && !comment.ignore?
7589-
parser_comments.delete_at(comment_index)
7590-
7591-
while (node = body[body_index]) &&
7592-
(
7593-
node.is_a?(VoidStmt) ||
7594-
node.location.start_char < location.start_char
7595-
)
7655+
if !comment.inline? && (start_char <= location.start_char) && (end_char >= location.end_char) && !comment.ignore?
7656+
while (node = body[body_index]) && (node.is_a?(VoidStmt) || node.location.start_char < location.start_char)
75967657
body_index += 1
75977658
end
75987659

7599-
body.insert(body_index, comment)
7660+
if body_index != 0 && body[body_index - 1].location.start_char < location.start_char && body[body_index - 1].location.end_char > location.start_char
7661+
# The previous node entirely encapsules the comment, so we don't
7662+
# want to attach it here since it will get attached normally. This
7663+
# is mostly in the case of hash and array literals.
7664+
comment_index += 1
7665+
else
7666+
parser_comments.delete_at(comment_index)
7667+
body.insert(body_index, comment)
7668+
end
76007669
else
76017670
comment_index += 1
76027671
end

0 commit comments

Comments
 (0)