Summary
The wrapConditionalBodies rule's help text describes its scope as "inline conditional statements", but it currently also wraps Swift 5.9+ if expressions, which is unintended behavior.
Reproduction
// Input
.contains { if case .cancelled = $0 { true } else { false } }
let isX = if condition { true } else { false }
// Output (current — undesired)
.contains { if case .cancelled = $0 {
true
} else {
false
} }
let isX = if condition {
true
} else {
false
}
Verified with SwiftFormat 0.60.1:
swiftformat --rules wrapConditionalBodies --swift-version 6.0 <file>
Background
The rule was introduced in #989 (August 2021), before Swift 5.9 introduced if expressions (September 2023). This case was likely never considered.
SwiftLint's equivalent rule conditional_returns_on_newline naturally avoids this — it only triggers when the body contains a return statement, so if expressions are unaffected by design.
Suggested Fix
Skip wrapping when the if is used as an expression. Two cases to detect:
Case 1 — assignment context (let x = if ...):
Already detectable via the existing isConditionalAssignment(at:) helper.
Case 2 — closure/function body expression (.contains { if ... { true } else { false } }):
Harder to detect without type information. One possible heuristic is checking that all branches are exhaustive (else branch present) and no branch body starts with return, but this has edge cases. Open to suggestions on the right approach here.
Happy to submit a PR if this direction looks good.
Summary
The
wrapConditionalBodiesrule's help text describes its scope as "inline conditional statements", but it currently also wraps Swift 5.9+ if expressions, which is unintended behavior.Reproduction
Verified with SwiftFormat 0.60.1:
Background
The rule was introduced in #989 (August 2021), before Swift 5.9 introduced if expressions (September 2023). This case was likely never considered.
SwiftLint's equivalent rule
conditional_returns_on_newlinenaturally avoids this — it only triggers when the body contains areturnstatement, so if expressions are unaffected by design.Suggested Fix
Skip wrapping when the
ifis used as an expression. Two cases to detect:Case 1 — assignment context (
let x = if ...):Already detectable via the existing
isConditionalAssignment(at:)helper.Case 2 — closure/function body expression (
.contains { if ... { true } else { false } }):Harder to detect without type information. One possible heuristic is checking that all branches are exhaustive (else branch present) and no branch body starts with
return, but this has edge cases. Open to suggestions on the right approach here.Happy to submit a PR if this direction looks good.