diff --git a/src/cfengine_cli/commands.py b/src/cfengine_cli/commands.py index 9e1149c..698203a 100644 --- a/src/cfengine_cli/commands.py +++ b/src/cfengine_cli/commands.py @@ -74,6 +74,7 @@ def _format_dirname(directory: str, line_length: int, check: bool) -> int: name.endswith(".x.cf") or name.endswith(".input.cf") or name.endswith(".output.cf") + or name.endswith(".expected.cf") ): continue # Test files skipped during directory traversal if name.endswith( diff --git a/src/cfengine_cli/format.py b/src/cfengine_cli/format.py index 2c1bc13..845a09f 100644 --- a/src/cfengine_cli/format.py +++ b/src/cfengine_cli/format.py @@ -733,6 +733,9 @@ def _needs_blank_line_before(child: Node, indent: int, line_length: int) -> bool ) return not both_single + if child.type == "class_guarded_promise_block_attributes": + return prev.type in {"attribute", "class_guarded_promise_block_attributes"} + if child.type in CLASS_GUARD_TYPES: return prev.type in {"promise", "half_promise", "class_guarded_promises"} @@ -740,9 +743,21 @@ def _needs_blank_line_before(child: Node, indent: int, line_length: int) -> bool if prev.type not in {"promise", "half_promise"} | CLASS_GUARD_TYPES: return False parent = child.parent - return bool( - parent and parent.type in {"bundle_section", "class_guarded_promises"} - ) + if parent and parent.type in {"bundle_section", "class_guarded_promises"}: + return True + # Inside a body/promise block, a comment between two class guards + # only gets a blank-line separator when the preceding class guard + # already has interior comments (i.e. the visual block is rich + # enough that running it together with the next would look dense). + if parent and parent.type in {"body_block_body", "promise_block_body"}: + if _skip_comments(child.next_named_sibling, "next") is None: + return False + if prev.type in CLASS_GUARD_TYPES and any( + c.type == "comment" for c in prev.children + ): + return True + return False + return False return False @@ -775,8 +790,13 @@ def _skip_comments(sibling: Node | None, direction: str = "next") -> Node | None def _comment_indent(node: Node, indent: int) -> int: """Compute indentation for a leaf comment based on its nearest non-comment neighbor.""" nearest = _skip_comments(node.next_named_sibling, "next") + # A trailing comment whose previous sibling is a class-guarded group + # lines up with that group's contents (one extra indent level), as if + # it were the last comment inside the class guard. if nearest is None: nearest = _skip_comments(node.prev_named_sibling, "prev") + if nearest and nearest.type in CLASS_GUARD_TYPES: + return indent + 4 if nearest and nearest.type in INDENTED_TYPES: return indent + 2 # No indented sibling found — if we're directly inside a block body, diff --git a/tests/format/002_basics.expected.cf b/tests/format/002_basics.expected.cf index 78f8a64..138e065 100644 --- a/tests/format/002_basics.expected.cf +++ b/tests/format/002_basics.expected.cf @@ -12,8 +12,11 @@ body common control promise agent example { interpreter => "/usr/bin/python3"; + linux:: + interpreter => "/usr/bin/python3"; path => "/var/cfengine/inputs/modules/promises/git.py"; + windows:: path => "C:\Program files\Cfengine\inputs\modules\promises\git.py"; } diff --git a/tests/format/002_basics.input.cf b/tests/format/002_basics.input.cf index 840b735..1c54a7c 100644 --- a/tests/format/002_basics.input.cf +++ b/tests/format/002_basics.input.cf @@ -12,6 +12,7 @@ inputs => {}; promise agent example{ interpreter => "/usr/bin/python3"; linux:: +interpreter => "/usr/bin/python3"; path => "/var/cfengine/inputs/modules/promises/git.py"; windows:: path => "C:\Program files\Cfengine\inputs\modules\promises\git.py"; diff --git a/tests/format/004_comments.expected.cf b/tests/format/004_comments.expected.cf index 446fa74..421abe4 100644 --- a/tests/format/004_comments.expected.cf +++ b/tests/format/004_comments.expected.cf @@ -74,3 +74,73 @@ bundle agent win_services # Windows Time }; } + +body package_method apt +{ + any:: + # ii acpi 0.09-3ubuntu1 + package_changes => "bulk"; + package_list_command => "/usr/bin/dpkg -l"; + package_list_name_regex => "ii\s+([^\s]+).*"; + package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*"; + # package_list_arch_regex => "none"; + package_installed_regex => ".*"; + # all reported are installed: + # package_name_convention => "$(name)_$(version)_$(arch)"; + package_name_convention => "$(name)"; + # Use these only if not using a separate version/arch string: + # package_version_regex => ""; + # package_name_regex => ""; + # package_arch_regex => ""; + package_add_command => "/usr/bin/apt-get --yes install"; + package_delete_command => "/usr/bin/apt-get --yes remove"; + package_update_command => "/usr/bin/apt-get --yes dist-upgrade"; + # package_verify_command => "/bin/rpm -V"; +} + +body package_method ca +{ + # foo + package_changes => "bulk"; +} + +body package_method ac +{ + package_changes => "bulk"; + # bar +} + +body package_method cac +{ + # foo + package_changes => "bulk"; + # bar +} + +body package_method ga +{ + linux:: + package_changes => "bulk"; +} + +body package_method cgcac +{ + # foo + linux:: + # bar + package_changes => "bulk"; + # baz +} + +body package_method cgcacgcac +{ + # foo + linux:: + # bar + package_changes => "bulk"; + + # baz + !linux:: + # bar + package_changes => "bulk"; +} diff --git a/tests/format/004_comments.input.cf b/tests/format/004_comments.input.cf index f357966..0d1f90a 100644 --- a/tests/format/004_comments.input.cf +++ b/tests/format/004_comments.input.cf @@ -64,3 +64,72 @@ bundle agent win_services # Windows Time }; } + +body package_method apt +{ +any:: +# ii acpi 0.09-3ubuntu1 +package_changes => "bulk"; +package_list_command => "/usr/bin/dpkg -l"; +package_list_name_regex => "ii\s+([^\s]+).*"; +package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*"; +# package_list_arch_regex => "none"; +package_installed_regex => ".*"; +# all reported are installed: +# package_name_convention => "$(name)_$(version)_$(arch)"; +package_name_convention => "$(name)"; +# Use these only if not using a separate version/arch string: +# package_version_regex => ""; +# package_name_regex => ""; +# package_arch_regex => ""; +package_add_command => "/usr/bin/apt-get --yes install"; +package_delete_command => "/usr/bin/apt-get --yes remove"; +package_update_command => "/usr/bin/apt-get --yes dist-upgrade"; +# package_verify_command => "/bin/rpm -V"; +} + +body package_method ca +{ +# foo +package_changes => "bulk"; +} + +body package_method ac +{ +package_changes => "bulk"; +# bar +} + +body package_method cac +{ +# foo +package_changes => "bulk"; +# bar +} + +body package_method ga +{ +linux:: +package_changes => "bulk"; +} + +body package_method cgcac +{ +# foo +linux:: +# bar +package_changes => "bulk"; +# baz +} + +body package_method cgcacgcac +{ +# foo +linux:: +# bar +package_changes => "bulk"; +# baz +!linux:: +# bar +package_changes => "bulk"; +}