SimplifyGenericConstraints: Add 40 character limit to protocol composition (#2254)

This commit is contained in:
Manny Lopez
2025-10-23 15:37:55 -07:00
committed by Cal Stephens
parent 2390292896
commit de1b130b43
2 changed files with 47 additions and 0 deletions
@@ -134,6 +134,16 @@ extension Formatter {
constraintsByType[item.genericType.name, default: []].append(item.conformance)
}
// Check if any combined protocol composition is over 40 characters
// If so, skip simplification for the entire declaration
for conformances in constraintsByType.values {
let protocolNames = conformances.map(\.name)
let combinedComposition = protocolNames.joined(separator: " & ")
if combinedComposition.count > 40 {
return
}
}
// We perform modifications in reverse order to avoid invalidating indices
// First, remove constraints from the where clause
@@ -326,6 +326,21 @@ final class SimplifyGenericConstraintsTests: XCTestCase {
testFormatting(for: input, output, rule: .simplifyGenericConstraints, exclude: [.unusedArguments, .indent])
}
func testDoesNotSimplifyWhenCombinedCompositionIsTooLong() {
// When multiple constraints for the same type are combined with &,
// don't simplify if the result is over 40 characters
let input = """
func transform<A, B, C, D>(_ a: A, _ b: B, _ c: C, _ d: D)
where A: VeryLongProtocolName,
A: AnotherVeryLongProtocolName,
B: Collection,
C: Comparable,
D: Sequence
{}
"""
testFormatting(for: input, rule: .simplifyGenericConstraints, exclude: [.unusedArguments, .indent])
}
// MARK: - Constraints on generics not in parameter list
func testPreserveConstraintsForGenericsNotInParameterList() {
@@ -398,4 +413,26 @@ final class SimplifyGenericConstraintsTests: XCTestCase {
"""
testFormatting(for: input, rule: .simplifyGenericConstraints, exclude: [.indent, .emptyBraces])
}
func testDoesNotSimplifyLongProtocolComposition() {
// Don't simplify when protocol composition is over 40 characters
// This prevents awkward line breaks when wrapArguments is applied
let input = """
enum Foo<T>: SomeProtocol where
T: ProtocolA & SomeModule.ProtocolB & ProtocolC
{
}
"""
testFormatting(for: input, rule: .simplifyGenericConstraints, exclude: [.indent, .emptyBraces])
}
func testDoesNotSimplifySingleLongProtocolName() {
// Don't simplify when a single protocol name is over 40 characters
let input = """
enum Foo<T>: SomeProtocol where T: VeryLongProtocolNameThatIsOverFortyCharacters
{
}
"""
testFormatting(for: input, rule: .simplifyGenericConstraints, exclude: [.indent, .emptyBraces, .braces])
}
}