diff --git a/Rules.md b/Rules.md
index 12cc82f1..9a5eda9d 100644
--- a/Rules.md
+++ b/Rules.md
@@ -136,6 +136,7 @@
* [unusedPrivateDeclarations](#unusedPrivateDeclarations)
* [urlMacro](#urlMacro)
* [validateTestCases](#validateTestCases)
+* [wrapCaseBodies](#wrapCaseBodies)
* [wrapConditionalBodies](#wrapConditionalBodies)
* [wrapEnumCases](#wrapEnumCases)
* [wrapMultilineConditionalAssignment](#wrapMultilineConditionalAssignment)
@@ -4338,6 +4339,22 @@ Option | Description
+## wrapCaseBodies
+
+Wrap the bodies of inline switch cases onto a new line.
+
+
+Examples
+
+```diff
+- case .foo: return bar
++ case .foo:
++ return bar
+```
+
+
+
+
## wrapConditionalBodies
Wrap the bodies of inline conditional statements onto a new line.
diff --git a/Sources/RuleRegistry.generated.swift b/Sources/RuleRegistry.generated.swift
index 5408455e..799b312a 100644
--- a/Sources/RuleRegistry.generated.swift
+++ b/Sources/RuleRegistry.generated.swift
@@ -141,6 +141,7 @@ let ruleRegistry: [String: FormatRule] = [
"wrap": .wrap,
"wrapArguments": .wrapArguments,
"wrapAttributes": .wrapAttributes,
+ "wrapCaseBodies": .wrapCaseBodies,
"wrapConditionalBodies": .wrapConditionalBodies,
"wrapEnumCases": .wrapEnumCases,
"wrapFunctionBodies": .wrapFunctionBodies,
diff --git a/Sources/Rules/WrapCaseBodies.swift b/Sources/Rules/WrapCaseBodies.swift
new file mode 100644
index 00000000..e50eebb1
--- /dev/null
+++ b/Sources/Rules/WrapCaseBodies.swift
@@ -0,0 +1,53 @@
+//
+// WrapCaseBodies.swift
+// SwiftFormat
+//
+// Created by Kim de Vos on 3/23/26.
+// Copyright © 2026 Nick Lockwood. All rights reserved.
+//
+
+import Foundation
+
+public extension FormatRule {
+ static let wrapCaseBodies = FormatRule(
+ help: "Wrap the bodies of inline switch cases onto a new line.",
+ disabledByDefault: true,
+ sharedOptions: ["linebreaks", "indent"]
+ ) { formatter in
+ formatter.forEach(.endOfScope("case")) { i, _ in
+ formatter.wrapCaseBody(at: i)
+ }
+ formatter.forEach(.endOfScope("default")) { i, _ in
+ formatter.wrapCaseBody(at: i)
+ }
+ } examples: {
+ """
+ ```diff
+ - case .foo: return bar
+ + case .foo:
+ + return bar
+ ```
+ """
+ }
+}
+
+extension Formatter {
+ func wrapCaseBody(at caseIndex: Int) {
+ guard let colonIndex = index(of: .startOfScope(":"), after: caseIndex),
+ var firstTokenIndex = index(of: .nonSpaceOrComment, after: colonIndex),
+ !tokens[firstTokenIndex].isLinebreak,
+ !tokens[firstTokenIndex].isEndOfScope
+ else { return }
+
+ insertLinebreak(at: firstTokenIndex)
+
+ if tokens[firstTokenIndex - 1].isSpace {
+ removeToken(at: firstTokenIndex - 1)
+ firstTokenIndex -= 1
+ }
+
+ let movedTokenIndex = firstTokenIndex + 1
+ let indent = currentIndentForLine(at: caseIndex) + options.indent
+ insertSpace(indent, at: movedTokenIndex)
+ }
+}
diff --git a/Tests/Rules/WrapCaseBodiesTests.swift b/Tests/Rules/WrapCaseBodiesTests.swift
new file mode 100644
index 00000000..cc00ce5e
--- /dev/null
+++ b/Tests/Rules/WrapCaseBodiesTests.swift
@@ -0,0 +1,241 @@
+//
+// WrapCaseBodiesTests.swift
+// SwiftFormatTests
+//
+// Created by Kim de Vos on 3/23/26.
+// Copyright © 2026 Nick Lockwood. All rights reserved.
+//
+
+import XCTest
+@testable import SwiftFormat
+
+final class WrapCaseBodiesTests: XCTestCase {
+ func testWrapSingleLineCaseBody() {
+ let input = """
+ switch foo {
+ case .bar: return bar
+ default: return baz
+ }
+ """
+ let output = """
+ switch foo {
+ case .bar:
+ return bar
+ default:
+ return baz
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies)
+ }
+
+ func testAlreadyWrappedCaseBodiesUnchanged() {
+ let input = """
+ switch foo {
+ case .bar:
+ return bar
+ default:
+ return baz
+ }
+ """
+ testFormatting(for: input, rule: .wrapCaseBodies)
+ }
+
+ func testWrapDefaultCaseBody() {
+ let input = """
+ switch foo {
+ case .bar: break
+ default: return baz
+ }
+ """
+ let output = """
+ switch foo {
+ case .bar:
+ break
+ default:
+ return baz
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies)
+ }
+
+ func testWrapMultiPatternCaseBody() {
+ let input = """
+ switch foo {
+ case .bar, .baz: return quux
+ default: break
+ }
+ """
+ let output = """
+ switch foo {
+ case .bar, .baz:
+ return quux
+ default:
+ break
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies,
+ exclude: [.wrapSwitchCases])
+ }
+
+ func testWrapCaseWithWhereClause() {
+ let input = """
+ switch foo {
+ case let x where x > 0: return x
+ default: return 0
+ }
+ """
+ let output = """
+ switch foo {
+ case let x where x > 0:
+ return x
+ default:
+ return 0
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies)
+ }
+
+ func testCaseWithCommentAfterColonUnchanged() {
+ let input = """
+ switch foo {
+ case .bar: // comment
+ return bar
+ default:
+ return baz
+ }
+ """
+ testFormatting(for: input, rule: .wrapCaseBodies,
+ exclude: [.blankLineAfterSwitchCase])
+ }
+
+ func testWrapUnknownDefaultCaseBody() {
+ let input = """
+ switch foo {
+ case .bar: return bar
+ @unknown default: return baz
+ }
+ """
+ let output = """
+ switch foo {
+ case .bar:
+ return bar
+ @unknown default:
+ return baz
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies)
+ }
+
+ func testWrapNestedSwitchCaseBodies() {
+ let input = """
+ switch foo {
+ case .bar:
+ switch baz {
+ case .a: return a
+ case .b: return b
+ default: return c
+ }
+ default: return other
+ }
+ """
+ let output = """
+ switch foo {
+ case .bar:
+ switch baz {
+ case .a:
+ return a
+ case .b:
+ return b
+ default:
+ return c
+ }
+ default:
+ return other
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies,
+ exclude: [.blankLineAfterSwitchCase])
+ }
+
+ func testWrapCaseBodiesFullExample() {
+ let input = """
+ extension Int {
+ var foo: String {
+ switch self {
+ case 0: return "zero"
+ case 1: return "one"
+ case 2: return "two"
+ default: return "other"
+ }
+ }
+ }
+ """
+ let output = """
+ extension Int {
+ var foo: String {
+ switch self {
+ case 0:
+ return "zero"
+ case 1:
+ return "one"
+ case 2:
+ return "two"
+ default:
+ return "other"
+ }
+ }
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies)
+ }
+
+ func testWrapCaseBodyWithAssignment() {
+ let input = """
+ switch foo {
+ case .bar: baz = true
+ default: baz = false
+ }
+ """
+ let output = """
+ switch foo {
+ case .bar:
+ baz = true
+ default:
+ baz = false
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies)
+ }
+
+ func testWrapSwitchExpressionCaseBodies() {
+ let input = """
+ extension Int {
+ var foo: String {
+ return switch self {
+ case 0: "zero"
+ case 1: "one"
+ case 2: "two"
+ default: "other"
+ }
+ }
+ }
+ """
+ let output = """
+ extension Int {
+ var foo: String {
+ return switch self {
+ case 0:
+ "zero"
+ case 1:
+ "one"
+ case 2:
+ "two"
+ default:
+ "other"
+ }
+ }
+ }
+ """
+ testFormatting(for: input, output, rule: .wrapCaseBodies)
+ }
+}
diff --git a/Tests/XCTestCase+testFormatting.swift b/Tests/XCTestCase+testFormatting.swift
index 4cf05e73..7d5c4de4 100644
--- a/Tests/XCTestCase+testFormatting.swift
+++ b/Tests/XCTestCase+testFormatting.swift
@@ -84,6 +84,7 @@ extension XCTestCase {
.unusedPrivateDeclarations,
.preferFinalClasses,
.preferExplicitFalse,
+ .wrapCaseBodies,
]
let exclude = exclude + defaultExclusions.filter { !rules.contains($0) }
let formatResult: (output: String, changes: [SwiftFormat.Formatter.Change])