Skip to content

Commit 1795842

Browse files
committed
Fix another bug with parsing guard case statements
1 parent 61a2b5e commit 1795842

4 files changed

Lines changed: 82 additions & 2 deletions

File tree

Sources/FormattingHelpers.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ extension Formatter {
3333
while let token = self.token(at: index) {
3434
switch token {
3535
case .identifier where
36-
last(.nonSpaceOrCommentOrLinebreak, before: index)?.isOperator(".") == false:
36+
last(.nonSpaceOrCommentOrLinebreak, before: index)?.isOperator(".") == false &&
37+
next(.nonSpaceOrCommentOrLinebreak, after: index)?.isOperator(".") == false:
3738
let name = token.unescaped()
3839
if name != "_", declarationIndex != nil || !isConditional {
3940
names.insert(name)

Sources/Rules.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2876,12 +2876,15 @@ public struct _FormatRules {
28762876
index = nextIndex
28772877
}
28782878
lastKeyword = ""
2879-
case "if", "while", "guard":
2879+
case "if", "while", "guard", "for":
28802880
assert(!isTypeRoot)
28812881
// Guard is included because it's an error to reference guard vars in body
28822882
var scopedNames = localNames
28832883
formatter.processDeclaredVariables(at: &index, names: &scopedNames,
28842884
removeSelf: explicitSelf != .insert)
2885+
if scopeStack.last == .startOfScope("(") {
2886+
scopeStack.removeLast()
2887+
}
28852888
guard let startIndex = formatter.index(of: .startOfScope("{"), after: index) else {
28862889
return formatter.fatalError("Expected {", at: index)
28872890
}
@@ -2890,6 +2893,8 @@ public struct _FormatRules {
28902893
membersByType: &membersByType, classMembersByType: &classMembersByType,
28912894
usingDynamicLookup: usingDynamicLookup, isTypeRoot: false, isInit: isInit)
28922895
lastKeyword = ""
2896+
case "case" where ["if", "while", "guard", "for"].contains(lastKeyword):
2897+
break
28932898
default:
28942899
lastKeyword = token.string
28952900
}

Tests/RulesTests+Redundancy.swift

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2711,6 +2711,77 @@ extension RulesTests {
27112711
testFormatting(for: input, rule: FormatRules.redundantSelf)
27122712
}
27132713

2714+
func testNoRemoveSelfAfterGuardCaseLetWithExplicitNamespace() {
2715+
let input = """
2716+
class Foo {
2717+
var name: String?
2718+
2719+
func bug(element: Something) {
2720+
guard case let Something.a(name) = element
2721+
else { return }
2722+
self.name = name
2723+
}
2724+
}
2725+
"""
2726+
testFormatting(for: input, rule: FormatRules.redundantSelf)
2727+
}
2728+
2729+
func testRedundantSelfParsingBug() {
2730+
let input = """
2731+
private class Foo {
2732+
mutating func bar() -> Statement? {
2733+
let start = self
2734+
guard case Token.identifier(let name)? = self.popFirst() else {
2735+
self = start
2736+
return nil
2737+
}
2738+
return Statement.declaration(name: name)
2739+
}
2740+
}
2741+
"""
2742+
let output = """
2743+
private class Foo {
2744+
mutating func bar() -> Statement? {
2745+
let start = self
2746+
guard case Token.identifier(let name)? = popFirst() else {
2747+
self = start
2748+
return nil
2749+
}
2750+
return Statement.declaration(name: name)
2751+
}
2752+
}
2753+
"""
2754+
testFormatting(for: input, output, rule: FormatRules.redundantSelf,
2755+
exclude: ["hoistPatternLet"])
2756+
}
2757+
2758+
func testRedundantSelfParsingBug2() {
2759+
let input = """
2760+
extension Foo {
2761+
private enum NonHashableEnum: RawRepresentable {
2762+
case foo
2763+
case bar
2764+
2765+
var rawValue: RuntimeTypeTests.TestStruct {
2766+
return TestStruct(foo: 0)
2767+
}
2768+
2769+
init?(rawValue: RuntimeTypeTests.TestStruct) {
2770+
switch rawValue.foo {
2771+
case 0:
2772+
self = .foo
2773+
case 1:
2774+
self = .bar
2775+
default:
2776+
return nil
2777+
}
2778+
}
2779+
}
2780+
}
2781+
"""
2782+
testFormatting(for: input, rule: FormatRules.redundantSelf)
2783+
}
2784+
27142785
// explicitSelf = .insert
27152786

27162787
func testInsertSelf() {

Tests/XCTestManifests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,7 @@ extension RulesTests {
13321332
("testNoRemoveReturnInSubscript", testNoRemoveReturnInSubscript),
13331333
("testNoRemoveReturnInTupleVarGetter", testNoRemoveReturnInTupleVarGetter),
13341334
("testNoRemoveSelfAfterGenericInit", testNoRemoveSelfAfterGenericInit),
1335+
("testNoRemoveSelfAfterGuardCaseLetWithExplicitNamespace", testNoRemoveSelfAfterGuardCaseLetWithExplicitNamespace),
13351336
("testNoRemoveSelfAfterGuardLetSelf", testNoRemoveSelfAfterGuardLetSelf),
13361337
("testNoRemoveSelfAfterOptionalReturn", testNoRemoveSelfAfterOptionalReturn),
13371338
("testNoRemoveSelfBeforeInit", testNoRemoveSelfBeforeInit),
@@ -1654,6 +1655,8 @@ extension RulesTests {
16541655
("testRedundantReturnInVoidFunction3", testRedundantReturnInVoidFunction3),
16551656
("testRedundantReturnInVoidFunction4", testRedundantReturnInVoidFunction4),
16561657
("testRedundantSelfDoesntGetStuckIfNoParensFound", testRedundantSelfDoesntGetStuckIfNoParensFound),
1658+
("testRedundantSelfParsingBug", testRedundantSelfParsingBug),
1659+
("testRedundantSelfParsingBug2", testRedundantSelfParsingBug2),
16571660
("testRedundantSelfRemovedInsideConditionalCase", testRedundantSelfRemovedInsideConditionalCase),
16581661
("testRedundantSelfRemovedWhenFollowedBySwitchContainingIfdef", testRedundantSelfRemovedWhenFollowedBySwitchContainingIfdef),
16591662
("testRedundantSelfRuleDoesntErrorForClassFuncInClassWithWhere", testRedundantSelfRuleDoesntErrorForClassFuncInClassWithWhere),

0 commit comments

Comments
 (0)