Fix redundantStaticSelf false positive inside closures and nested functions (#2518)

Co-authored-by: calda <1811727+calda@users.noreply.github.com>
This commit is contained in:
Copilot
2026-04-25 10:38:25 -07:00
committed by GitHub
parent c08ea75e6f
commit f69d629a1e
2 changed files with 41 additions and 12 deletions
+7 -2
View File
@@ -2553,11 +2553,14 @@ extension Formatter {
.keyword("func") where lastKeyword != "import":
lastKeyword = ""
let members = classOrStatic ? classMembers : members
// For the staticSelf (redundantStaticSelf) rule, nested functions are not
// within the static func scope, so Self. should be preserved inside them.
let effectiveClassOrStatic = staticSelf && !isTypeRoot ? false : classOrStatic
processFunction(at: &index, localNames: localNames, members: members,
typeStack: &typeStack, closureStack: &closureStack, membersByType: &membersByType,
classMembersByType: &classMembersByType,
usingDynamicLookup: usingDynamicLookup,
classOrStatic: classOrStatic)
classOrStatic: effectiveClassOrStatic)
classOrStatic = false
continue
case .keyword("static"):
@@ -2946,10 +2949,12 @@ extension Formatter {
closureStack.append((allowsImplicitSelf: closureAllowsImplicitSelf(), selfCapture: selfCapture))
index = (inIndex ?? index) + 1
// For the staticSelf (redundantStaticSelf) rule, closures are not within
// the static func scope, so Self. should be preserved inside them.
processBody(at: &index, localNames: closureLocalNames, members: members,
typeStack: &typeStack, closureStack: &closureStack,
membersByType: &membersByType, classMembersByType: &classMembersByType,
usingDynamicLookup: usingDynamicLookup, classOrStatic: classOrStatic,
usingDynamicLookup: usingDynamicLookup, classOrStatic: staticSelf ? false : classOrStatic,
isTypeRoot: false, isInit: isInit)
index -= 1
closureStack.removeLast()
+34 -10
View File
@@ -91,16 +91,7 @@ final class RedundantStaticSelfTests: XCTestCase {
}
}
"""
let output = """
enum E {
static func foo() {
func bar() {
foo()
}
}
}
"""
testFormatting(for: input, output, rule: .redundantStaticSelf)
testFormatting(for: input, rule: .redundantStaticSelf)
}
func testRedundantStaticSelfInNestedType() {
@@ -240,4 +231,37 @@ final class RedundantStaticSelfTests: XCTestCase {
"""
testFormatting(for: input, rule: .redundantStaticSelf, exclude: [.wrapFunctionBodies])
}
func testPreserveStaticSelfInClosureInsideStaticFunc() {
let input = """
enum XError: Error {
case error(String, cause: (any Error)? = nil)
static func error(_ message: String, cause: String?) -> Self {
.error(message, cause: cause.map { Self.error($0) })
}
}
"""
testFormatting(for: input, rule: .redundantStaticSelf)
}
func testRedundantStaticSelfRemovedOutsideClosureInsideStaticFunc() {
let input = """
enum E {
static func foo() {
Self.bar()
let x = { Self.bar() }
}
}
"""
let output = """
enum E {
static func foo() {
bar()
let x = { Self.bar() }
}
}
"""
testFormatting(for: input, output, rule: .redundantStaticSelf)
}
}