mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-06-16 10:34:34 +00:00
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:
committed by
Cal Stephens
parent
282f2bc1cb
commit
b88aeefdac
@@ -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>
|
||||
|
||||
@@ -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]? {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user