@@ -47,6 +47,18 @@ def _contains_macro(nodes: Node | list[Node]) -> bool:
4747 return _contains_macro (nodes .children )
4848
4949
50+ def _contains_list_with_comment (nodes : Node | list [Node ]) -> bool :
51+ """Check if a node (or list) contains a list with a comment child.
52+
53+ A `#` comment extends to end of line, so a list containing one cannot
54+ be rendered on a single line — every such list must be split."""
55+ if isinstance (nodes , list ):
56+ return any (_contains_list_with_comment (node ) for node in nodes )
57+ if nodes .type == "list" and any (c .type == "comment" for c in nodes .children ):
58+ return True
59+ return _contains_list_with_comment (nodes .children )
60+
61+
5062def format_json_file (filename : str , check : bool ) -> int :
5163 """Reformat a JSON file in place using cfbs pretty-printer.
5264
@@ -254,7 +266,8 @@ def maybe_split_generic_list(
254266 nodes : list [Node ], indent : int , line_length : int , trailing_comma : bool = True
255267) -> list [str ]:
256268 """Try a single-line rendering; fall back to split_generic_list if too long."""
257- if not _contains_macro (nodes ):
269+ has_comment = any (n .type == "comment" for n in nodes )
270+ if not _contains_macro (nodes ) and not has_comment :
258271 string = " " * indent + stringify_single_line_nodes (nodes )
259272 if len (string ) < line_length :
260273 return [string ]
@@ -299,7 +312,7 @@ def maybe_split_rval(
299312 node : Node , indent : int , offset : int , line_length : int
300313) -> list [str ]:
301314 """Return single-line rval if it fits at offset, otherwise split it."""
302- if _contains_macro (node ):
315+ if _contains_macro (node ) or _contains_list_with_comment ( node ) :
303316 return split_rval (node , indent , line_length )
304317 line = stringify_single_line_node (node )
305318 if len (line ) + offset < line_length :
@@ -371,8 +384,11 @@ def _attempt_split_attribute(node: Node, indent: int, line_length: int) -> list[
371384def _stringify (node : Node , indent : int , line_length : int ) -> list [str ]:
372385 """Return a node as pre-indented line(s), splitting if it exceeds line_length."""
373386 # Attributes containing macros must always be split — macros cannot
374- # appear inline on a single line.
375- if node .type == "attribute" and _contains_macro (node ):
387+ # appear inline on a single line. Same for lists with comments inside,
388+ # since `#` extends to end of line.
389+ if node .type == "attribute" and (
390+ _contains_macro (node ) or _contains_list_with_comment (node )
391+ ):
376392 return _attempt_split_attribute (node , indent , line_length - 1 )
377393 single_line = " " * indent + stringify_single_line_node (node )
378394 # Reserve 1 char for trailing ; or , after attributes
@@ -518,6 +534,8 @@ def _can_single_line_promise(node: Node, indent: int, line_length: int) -> bool:
518534 children = node .children
519535 if _contains_macro (children ):
520536 return False
537+ if _contains_list_with_comment (children ):
538+ return False
521539 attrs = [c for c in children if c .type == "attribute" ]
522540 next_sib = node .next_named_sibling
523541 while next_sib and next_sib .type == "macro" :
0 commit comments