Skip to content

Commit 2d504b0

Browse files
committed
cfengine format: Fixed issue with slists containing comments
Signed-off-by: Ole Herman Schumacher Elgesem <ole@northern.tech>
1 parent 63ef157 commit 2d504b0

1 file changed

Lines changed: 22 additions & 4 deletions

File tree

src/cfengine_cli/format.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
5062
def 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[
371384
def _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

Comments
 (0)