Fix inconsistent indenting of wrapped lines in case condition

This commit is contained in:
Nick Lockwood
2024-12-22 15:55:19 +00:00
parent c40ef72928
commit bc98f342d2
3 changed files with 52 additions and 2 deletions
+11 -2
View File
@@ -716,10 +716,17 @@ extension Formatter {
/// If the token at the specified index is part of a conditional statement, returns the index of the first
/// token in the statement (e.g. `if`, `guard`, `while`, etc.), otherwise returns nil
func startOfConditionalStatement(at i: Int, excluding: Set<String> = []) -> Int? {
guard var index = indexOfLastSignificantKeyword(at: i, excluding: excluding.union(["else", "where"])) else {
guard var index = indexOfLastSignificantKeyword(at: i, excluding: excluding.union(["else"])) else {
return nil
}
if tokens[index] == .keyword("where") {
if self.index(of: .endOfScope("case"), before: index) != nil {
return nil
}
index = indexOfLastSignificantKeyword(at: index, excluding: ["where"]) ?? index
}
if tokens[index] == .keyword("case"), let i = self.index(
of: .nonSpaceOrCommentOrLinebreak,
before: index,
@@ -744,8 +751,10 @@ extension Formatter {
default:
return nil
}
case "if", "guard", "while", "for", "case", "switch":
case "if", "guard", "while", "for", "case":
return index
case "switch":
return next(.startOfScope, after: i) == .startOfScope(":") ? nil : index
default:
return nil
}
+22
View File
@@ -100,6 +100,11 @@ class ParsingHelpersTests: XCTestCase {
XCTAssertFalse(formatter.isStartOfClosure(at: 11))
}
func testIfTryAndCallBracesNotTreatedAsClosure() {
let formatter = Formatter(tokenize("if try true && explode() {}"))
XCTAssertFalse(formatter.isStartOfClosure(at: 12))
}
func testGuardElseBracesNotTreatedAsClosure() {
let formatter = Formatter(tokenize("guard foo else {}"))
XCTAssertFalse(formatter.isStartOfClosure(at: 6))
@@ -224,6 +229,23 @@ class ParsingHelpersTests: XCTestCase {
XCTAssertFalse(formatter.isStartOfClosure(at: 28))
}
func testClosureInForInWhereClauseNotTreatedAsClosure() {
let formatter = Formatter(tokenize("for foo in foos where foo.method() { print(foo) }"))
XCTAssertFalse(formatter.isStartOfClosure(at: 16))
}
func testClosureInCaseWhereClause() {
let formatter = Formatter(tokenize("""
switch foo {
case .bar
where testValues.map(String.init).compactMap { $0 }
.contains(baz):
continue
}
"""))
XCTAssertTrue(formatter.isStartOfClosure(at: 26))
}
func testInitBracesNotTreatedAsClosure() {
let formatter = Formatter(tokenize("init() { foo = 5 }"))
XCTAssertFalse(formatter.isStartOfClosure(at: 4))
+19
View File
@@ -4110,4 +4110,23 @@ class IndentTests: XCTestCase {
let options = FormatOptions(wrapTernaryOperators: .beforeOperators, maxWidth: 60)
testFormatting(for: input, rule: .indent, options: options)
}
func testIndentSwitchCaseWhere() {
let input = """
switch testKey {
case "organization"
where testValues.map(String.init).compactMap { try? Entity.ID($0, format: .number) }
.contains(Self.sessionInteractor.stage.value?.membership?.organization.id ?? .zero): // 2
continue
case "user"
where testValues.map(String.init).compactMap { try? Entity.ID($0, format: .number) }
.contains(Self.sessionInteractor.stage.value?.session?.user.id ?? .zero): // 3
continue
}
"""
let options = FormatOptions(indentCase: true)
testFormatting(for: input, rule: .indent, options: options, exclude: [.wrap])
}
}