Update trailingCommas rule to support more case from SE-0439, including if statements, guard statements, subscripts, capture lists, generic arguments

This commit is contained in:
Cal Stephens
2025-05-12 20:18:43 -07:00
committed by Cal Stephens
parent 282f2bc1cb
commit b88aeefdac
8 changed files with 727 additions and 231 deletions
+22 -29
View File
@@ -3087,47 +3087,40 @@ Option | Description
foo,
bar,
- baz
]
let array = [
foo,
bar,
+ baz,
]
```
```diff
func foo(
- bar _: Int
) {}
func foo(
+ bar _: Int,
) {}
func foo(
bar _: Int,
- baaz _: Int
+ baaz _: Int
) {}
```
```diff
let foo = (
bar: 0,
- baz: 1
)
let foo = (
bar: 0,
+ baz: 1,
)
let foo = (
bar: 0,
- baz: 1
+ baz: 1,
)
```
```diff
@Foo(
"bar",
- "baz"
)
if
let foo,
- let baaz
+ let baaz,
{ ... }
```
@Foo(
"bar",
+ "baz",
)
```diff
guard
let foo,
- let baaz
+ let baaz,
else { return }
```
</details>
+15 -1
View File
@@ -1374,7 +1374,7 @@ extension Formatter {
while let conditionalBranchIndex = nextConditionalBranchIndex,
conditionalBranchIndex == ifIndex || tokens[conditionalBranchIndex] == .keyword("else"),
let startOfBody = index(of: .startOfScope("{"), after: conditionalBranchIndex),
let startOfBody = startOfConditionalBranchBody(after: conditionalBranchIndex),
let endOfBody = endOfScope(at: startOfBody)
{
branches.append((startOfBranch: startOfBody, endOfBranch: endOfBody))
@@ -1390,6 +1390,20 @@ extension Formatter {
return branches
}
/// Returns the `startOfScope("{")` token index for this conditional branch
func startOfConditionalBranchBody(after index: Int) -> Int? {
guard let startOfBody = self.index(of: .startOfScope("{"), after: index) else { return nil }
// If we find a closure, skip over it.
if isStartOfClosure(at: startOfBody),
let endOfClosure = endOfScope(at: startOfBody)
{
return startOfConditionalBranchBody(after: endOfClosure)
}
return startOfBody
}
/// Finds all of the branch bodies in a switch statement.
/// Returns the index of the `startOfScope` and `endOfScope` of each branch.
func switchStatementBranches(at switchIndex: Int) -> [ConditionalBranch]? {
+22 -3
View File
@@ -920,11 +920,30 @@ extension Formatter {
return true
}
case .delimiter(","):
guard let scope = scope ?? currentScope(at: i) else {
return false
// If this is the trailing comma in an if/guard/while condition list, then don't indent the following code (the condition body)
if isConditionalStatement(at: i),
let startOfBranchBody = startOfConditionalBranchBody(after: i),
let nextToken = index(of: .nonSpaceOrCommentOrLinebreak, after: i)
{
if nextToken == startOfBranchBody {
return true
}
// Handle guard statement lists ending with `else {` instead of just `{`
if tokens[nextToken] == .keyword("else"),
let followingToken = index(of: .nonSpaceOrCommentOrLinebreak, after: nextToken),
followingToken == startOfBranchBody
{
return true
}
}
// For arrays or argument lists, we already indent
return ["<", "[", "(", "case", "default"].contains(scope.string)
if let scope = scope ?? currentScope(at: i) {
return ["<", "[", "(", "case", "default"].contains(scope.string)
}
return false
case .delimiter(":"):
guard let scope = scope ?? currentScope(at: i) else {
return false
@@ -225,6 +225,10 @@ public extension FormatRule {
[type.definitionSourceRange] + type.conformances.map(\.sourceRange)
})
if genericsEligibleToRemove.isEmpty {
return
}
// We perform modifications to the function signature in reverse order
// so we don't invalidate any of the indices we've recorded. So first
// we remove components of the where clause.
+95 -99
View File
@@ -15,85 +15,54 @@ public extension FormatRule {
help: "Add or remove trailing commas where applicable.",
options: ["commas"]
) { formatter in
formatter.forEach(.endOfScope("]")) { i, _ in
guard let prevTokenIndex = formatter.index(of: .nonSpaceOrComment, before: i),
let scopeType = formatter.scopeType(at: i)
else {
return
}
switch scopeType {
case .array, .dictionary:
switch formatter.tokens[prevTokenIndex] {
case .linebreak:
guard let prevTokenIndex = formatter.index(
of: .nonSpaceOrCommentOrLinebreak, before: prevTokenIndex + 1
) else {
break
}
switch formatter.tokens[prevTokenIndex] {
case .startOfScope("["), .delimiter(":"):
break // do nothing
case .delimiter(","):
if !formatter.options.trailingCommas {
formatter.removeToken(at: prevTokenIndex)
}
default:
if formatter.options.trailingCommas {
formatter.insert(.delimiter(","), at: prevTokenIndex + 1)
}
}
case .delimiter(","):
formatter.removeToken(at: prevTokenIndex)
formatter.forEachToken { i, token in
switch token {
case .endOfScope("]"):
switch formatter.scopeType(at: i) {
case .array, .dictionary:
formatter.addOrRemoveTrailingComma(before: i, trailingCommaSupported: true)
case .subscript, .captureList:
formatter.addOrRemoveTrailingComma(before: i, trailingCommaSupported: formatter.options.swiftVersion >= "6.1")
default:
break
return
}
default:
return
}
}
guard formatter.options.swiftVersion >= "6.1" else { return }
case .endOfScope(")"), .endOfScope(">"):
formatter.addOrRemoveTrailingComma(before: i, trailingCommaSupported: formatter.options.swiftVersion >= "6.1")
formatter.forEach(.endOfScope(")")) { i, _ in
guard let startIndex = formatter.startOfScope(at: i),
formatter.tokens[startIndex] == .startOfScope("(")
else {
return
}
case .keyword("if"):
guard let startOfConditions = formatter.index(of: .nonSpaceOrCommentOrLinebreak, after: i),
let startOfBody = formatter.startOfConditionalBranchBody(after: startOfConditions)
else { return }
guard let prevToStartTokenIndex = formatter.index(of: .nonSpaceOrComment, before: startIndex) else {
return
}
formatter.addOrRemoveTrailingComma(before: startOfBody, trailingCommaSupported: formatter.options.swiftVersion >= "6.1")
guard formatter.tokens[prevToStartTokenIndex] != .delimiter(":") else {
return
}
case .keyword("guard"):
guard let startOfConditions = formatter.index(of: .nonSpaceOrCommentOrLinebreak, after: i),
let startOfBody = formatter.startOfConditionalBranchBody(after: startOfConditions),
let elseKeyword = formatter.index(of: .nonSpaceOrCommentOrLinebreak, before: startOfBody),
formatter.tokens[elseKeyword] == .keyword("else")
else { return }
guard let prevToEndTokenIndex = formatter.index(of: .nonSpaceOrComment, before: i) else {
return
}
formatter.addOrRemoveTrailingComma(before: elseKeyword, trailingCommaSupported: formatter.options.swiftVersion >= "6.1")
switch formatter.tokens[prevToEndTokenIndex] {
case .linebreak:
guard let lastArgIndex = formatter.index(
of: .nonSpaceOrCommentOrLinebreak, before: prevToEndTokenIndex + 1
) else {
break
case .keyword("while"):
guard let startOfConditions = formatter.index(of: .nonSpaceOrCommentOrLinebreak, after: i),
let startOfBody = formatter.startOfConditionalBranchBody(after: startOfConditions)
else { return }
// Ensure this isn't a `repeat { ... } while ...` condition where any `{` token after the while keyword would be unrelated
if let previousToken = formatter.index(of: .nonSpaceOrCommentOrLinebreak, before: i),
formatter.tokens[previousToken] == .endOfScope("}"),
let startOfScope = formatter.startOfScope(at: previousToken),
let tokenBeforeStartOfScope = formatter.index(of: .nonSpaceOrCommentOrLinebreak, before: startOfScope),
formatter.tokens[tokenBeforeStartOfScope] == .keyword("repeat")
{
return
}
switch formatter.tokens[lastArgIndex] {
case .delimiter(","):
if !formatter.options.trailingCommas {
formatter.removeToken(at: lastArgIndex)
}
case .startOfScope("("):
break
default:
if formatter.options.trailingCommas {
formatter.insert(.delimiter(","), at: lastArgIndex + 1)
}
}
case .delimiter(","):
formatter.removeToken(at: prevToEndTokenIndex)
formatter.addOrRemoveTrailingComma(before: startOfBody, trailingCommaSupported: formatter.options.swiftVersion >= "6.1")
default:
break
}
@@ -105,48 +74,75 @@ public extension FormatRule {
foo,
bar,
- baz
]
let array = [
foo,
bar,
+ baz,
]
```
```diff
func foo(
- bar _: Int
) {}
func foo(
+ bar _: Int,
) {}
func foo(
bar _: Int,
- baaz _: Int
+ baaz _: Int
) {}
```
```diff
let foo = (
bar: 0,
- baz: 1
)
let foo = (
bar: 0,
+ baz: 1,
)
let foo = (
bar: 0,
- baz: 1
+ baz: 1,
)
```
```diff
@Foo(
"bar",
- "baz"
)
if
let foo,
- let baaz
+ let baaz,
{ ... }
```
@Foo(
"bar",
+ "baz",
)
```diff
guard
let foo,
- let baaz
+ let baaz,
else { return }
```
"""
}
}
extension Formatter {
/// Adds or removes a trailing comma before the given index that marks the end of a comma-separated list.
/// Trailing commas can always be removed. `trailingCommaSupported` indicates whether or not a trailing
/// comma is allowed at this position.
func addOrRemoveTrailingComma(before endOfListIndex: Int, trailingCommaSupported: Bool) {
guard let prevTokenIndex = index(of: .nonSpaceOrComment, before: endOfListIndex) else { return }
switch tokens[prevTokenIndex] {
case .linebreak:
guard let prevTokenIndex = index(
of: .nonSpaceOrCommentOrLinebreak, before: prevTokenIndex + 1
) else {
break
}
switch tokens[prevTokenIndex] {
case .startOfScope("["), .delimiter(":"), .startOfScope("("):
break // do nothing
case .delimiter(","):
if !options.trailingCommas {
removeToken(at: prevTokenIndex)
}
default:
if options.trailingCommas, trailingCommaSupported {
insert(.delimiter(","), at: prevTokenIndex + 1)
}
}
case .delimiter(","):
removeToken(at: prevTokenIndex)
default:
break
}
}
}
+52
View File
@@ -4265,4 +4265,56 @@ class IndentTests: XCTestCase {
"""
testFormatting(for: input, rule: .indent)
}
func testNoIndentIfConditionBodyAfterTrailingCommaInClosure() {
let input = """
withTrailingClosure {
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz,
),
{
print("passed condition")
}
}
"""
testFormatting(for: input, rule: .indent)
}
func testNoIndentGuardConditionBodyAfterTrailingComma() {
let input = """
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz,
),
else {
return
}
"""
testFormatting(for: input, rule: .indent)
}
func testNoIndentGuardConditionBodyAfterTrailingCommaInClosure() {
let input = """
withTrailingClosure {
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz,
),
else {
return
}
}
"""
testFormatting(for: input, rule: .indent)
}
}
+24
View File
@@ -545,6 +545,30 @@ class RedundantReturnTests: XCTestCase {
options: options)
}
func testRedundantIfStatementWithClosureCondition() {
let input = """
func foo(condition: Bool) -> String {
if condition, { true }(), { false }() {
return "foo"
} else {
return "bar"
}
}
"""
let output = """
func foo(condition: Bool) -> String {
if condition, { true }(), { false }() {
"foo"
} else {
"bar"
}
}
"""
let options = FormatOptions(swiftVersion: "5.9")
testFormatting(for: input, [output], rules: [.redundantReturn, .conditionalAssignment], options: options, exclude: [.redundantClosure])
}
func testNonRedundantIfStatementReturnSwift5_9() {
let input = """
func foo(condition: Bool) -> String {
+493 -99
View File
@@ -288,6 +288,16 @@ class TrailingCommasTests: XCTestCase {
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasNotAddedToFunctionParametersBeforeSwift6_1() {
let input = """
func foo(
bar _: Int
) {}
"""
let options = FormatOptions(trailingCommas: true)
testFormatting(for: input, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromFunctionParameters() {
let input = """
func foo(
@@ -299,7 +309,41 @@ class TrailingCommasTests: XCTestCase {
bar _: Int
) {}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromFunctionParametersWithParenOnSameLine_trailingCommasDisabled() {
let input = """
func foo(
bar _: Int,
baaz _: Int,)
{}
"""
let output = """
func foo(
bar _: Int,
baaz _: Int)
{}
"""
let options = FormatOptions(trailingCommas: false, closingParenPosition: .sameLine)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromFunctionParametersWithParenOnSameLine_trailingCommasEnabled() {
let input = """
func foo(
bar _: Int,
baaz _: Int,)
{}
"""
let output = """
func foo(
bar _: Int,
baaz _: Int)
{}
"""
let options = FormatOptions(trailingCommas: true, closingParenPosition: .sameLine)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -329,7 +373,7 @@ class TrailingCommasTests: XCTestCase {
bar _: Int
) {}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -367,7 +411,7 @@ class TrailingCommasTests: XCTestCase {
)
}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -397,7 +441,7 @@ class TrailingCommasTests: XCTestCase {
1
)
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -431,7 +475,7 @@ class TrailingCommasTests: XCTestCase {
baz: 1
)
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -485,7 +529,7 @@ class TrailingCommasTests: XCTestCase {
)
}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -539,7 +583,7 @@ class TrailingCommasTests: XCTestCase {
)
}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -582,138 +626,314 @@ class TrailingCommasTests: XCTestCase {
func testTrailingCommasAddedToIf() {
let input = """
if (
true
) {}
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz)
{
print("passed condition")
}
"""
let output = """
if (
true,
) {}
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
{
print("passed condition")
}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas,
options: options, exclude: [.redundantParens])
let options = FormatOptions(trailingCommas: true, closingParenPosition: .sameLine, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasAddedToIfWithClosureCondition() {
let input = """
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
{ true }()
{
print("passed condition")
}
"""
let output = """
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
{ true }(),
{
print("passed condition")
}
"""
let options = FormatOptions(trailingCommas: true, closingParenPosition: .sameLine, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options, exclude: [.redundantClosure])
}
func testTrailingCommasNotAddedToIfBeforeSwift6_1() {
let input = """
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz)
{
print("passed condition")
}
"""
let options = FormatOptions(trailingCommas: true, closingParenPosition: .sameLine)
testFormatting(for: input, rule: .trailingCommas, options: options, exclude: [.redundantParens])
}
func testTrailingCommasRemovedFromIf() {
let input = """
if (
true,
) {}
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
{
print("passed condition")
}
"""
let output = """
if (
true
) {}
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz)
{
print("passed condition")
}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas,
options: options, exclude: [.redundantParens])
let options = FormatOptions(trailingCommas: false, closingParenPosition: .sameLine)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromIfWithClosureArgument() {
let input = """
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
{ true }(),
{
print("passed condition")
}
"""
let output = """
if
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
{ true }()
{
print("passed condition")
}
"""
let options = FormatOptions(trailingCommas: false, closingParenPosition: .sameLine)
testFormatting(for: input, output, rule: .trailingCommas, options: options, exclude: [.redundantClosure])
}
func testTrailingCommasRemovedFromSingleLineIf() {
let input = """
if foo.bar, foo.baaz(), {
print("passed condition")
}
"""
let output = """
if foo.bar, foo.baaz() {
print("passed condition")
}
"""
let options = FormatOptions(trailingCommas: true)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasAddedToGuard() {
let input = """
guard (
true
) else {
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz)
else {
return
}
"""
let output = """
guard (
true,
) else {
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
else {
return
}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas,
options: options, exclude: [.redundantParens])
let options = FormatOptions(trailingCommas: true, closingParenPosition: .sameLine, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasNotAddedToGuardBeforeSwift6_1() {
let input = """
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz)
else {
return
}
"""
let options = FormatOptions(trailingCommas: true, closingParenPosition: .sameLine)
testFormatting(for: input, rule: .trailingCommas, options: options, exclude: [.redundantParens])
}
func testTrailingCommasRemovedFromGuard() {
let input = """
guard (
true,
) else {
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
else {
return
}
"""
let output = """
guard (
true
) else {
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz)
else {
return
}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas,
options: options, exclude: [.redundantParens])
let options = FormatOptions(trailingCommas: false, closingParenPosition: .sameLine)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromGuardWithClosureArgument() {
let input = """
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
{ true }(),
else {
return
}
"""
let output = """
guard
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz),
{ true }()
else {
return
}
"""
let options = FormatOptions(trailingCommas: false, closingParenPosition: .sameLine)
testFormatting(for: input, output, rule: .trailingCommas, options: options, exclude: [.redundantClosure])
}
func testTrailingCommasRemovedFromSingleLineGuard() {
let input = """
guard foo.bar, foo.baaz(), else {
return
}
"""
let output = """
guard foo.bar, foo.baaz() else {
return
}
"""
let options = FormatOptions(trailingCommas: true)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasAddedToWhile() {
let input = """
while (
true
) {}
while
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz
)
{
break
}
"""
let output = """
while (
true,
) {}
while
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz,
),
{
break
}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas,
options: options, exclude: [.redundantParens])
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasNotAddedToRepeatWhile() {
let input = """
repeat
{
print(foo)
} while foo
// Ensure we don't confuse this trailing closure for a condition in the while statement:
trailingClosure
{
print("foo")
}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, rule: .trailingCommas, options: options, exclude: [.redundantParens, .braces, .indent])
}
func testTrailingCommasRemovedFromWhile() {
let input = """
while (
true,
) {}
while
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz,
),
{
break
}
"""
let output = """
while (
true
) {}
while
foo.bar,
foo.baaz(
bar: foo.bar,
baaz: foo.baaz
)
{
break
}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas,
options: options, exclude: [.redundantParens])
}
func testTrailingCommasAddedToBool() {
let input = """
let foo: Bool = (
true && true
)
"""
let output = """
let foo: Bool = (
true && true,
)
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas,
options: options, exclude: [.redundantParens])
}
func testTrailingCommasRemovedFromBool() {
let input = """
let foo: Bool = (
true && true,
)
"""
let output = """
let foo: Bool = (
true && true
)
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas,
options: options, exclude: [.redundantParens])
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasNotAddedToTypeAnnotation() {
@@ -723,7 +943,7 @@ class TrailingCommasTests: XCTestCase {
baz: Int
)
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, rule: .trailingCommas, options: options)
}
@@ -769,7 +989,7 @@ class TrailingCommasTests: XCTestCase {
): break
}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -803,7 +1023,7 @@ class TrailingCommasTests: XCTestCase {
bar
) = (0, 1)
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -813,7 +1033,7 @@ class TrailingCommasTests: XCTestCase {
)
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, rule: .trailingCommas,
options: options, exclude: [
.blankLinesAtEndOfScope,
@@ -859,7 +1079,7 @@ class TrailingCommasTests: XCTestCase {
)
\"""
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -897,7 +1117,7 @@ class TrailingCommasTests: XCTestCase {
)
struct Qux {}
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
@@ -931,7 +1151,181 @@ class TrailingCommasTests: XCTestCase {
"baz"
)
"""
let options = FormatOptions(trailingCommas: false, swiftVersion: "6.1")
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasAddedToGenericList() {
let input = """
struct S<
T1,
T2,
T3
> {}
"""
let output = """
struct S<
T1,
T2,
T3,
> {}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromGenericList() {
let input = """
struct S<
T1,
T2,
T3,
> {}
"""
let output = """
struct S<
T1,
T2,
T3
> {}
"""
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromSingleLineGenericList() {
let input = """
struct S<T1, T2, T3,> {}
"""
let output = """
struct S<T1, T2, T3> {}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasAddedToCaptureList() {
let input = """
{ [
capturedValue1,
capturedValue2
] in
}
"""
let output = """
{ [
capturedValue1,
capturedValue2,
] in
}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromCaptureList() {
let input = """
{ [
capturedValue1,
capturedValue2,
] in
}
"""
let output = """
{ [
capturedValue1,
capturedValue2
] in
}
"""
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromSingleLineCaptureList() {
let input = """
{ [capturedValue1, capturedValue2,] in
print(capturedValue1, capturedValue2)
}
"""
let output = """
{ [capturedValue1, capturedValue2] in
print(capturedValue1, capturedValue2)
}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasAddedToSubscript() {
let input = """
let value = m[
x,
y
]
"""
let output = """
let value = m[
x,
y,
]
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromSubscript() {
let input = """
let value = m[
x,
y,
]
"""
let output = """
let value = m[
x,
y
]
"""
let options = FormatOptions(trailingCommas: false)
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testTrailingCommasRemovedFromSingleLineSubscript() {
let input = """
let value = m[x, y,]
"""
let output = """
let value = m[x, y]
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
func testAddingTrailingCommaDoesntConflictWithOpaqueGenericParametersRule() {
let input = """
private func foo<
Foo: Bar,
Bar: Baaz
>(a: Foo, b: Foo)
where Foo == Bar
{
print(a, b)
}
"""
let output = """
private func foo<
Foo: Bar,
Bar: Baaz,
>(a: Foo, b: Foo)
where Foo == Bar
{
print(a, b)
}
"""
let options = FormatOptions(trailingCommas: true, swiftVersion: "6.1")
testFormatting(for: input, output, rule: .trailingCommas, options: options)
}
}