diff --git a/Sources/ParsingHelpers.swift b/Sources/ParsingHelpers.swift index 734bd297..5e5086c5 100644 --- a/Sources/ParsingHelpers.swift +++ b/Sources/ParsingHelpers.swift @@ -1299,7 +1299,7 @@ extension Formatter { /// - Any value can be preceded by `try`, `try?`, `try!`, or `await` /// - Any value can be followed by a postfix operator /// - Any value can be followed by an infix operator plus a right-hand-side expression. - /// - Any value can be followed by an arbitrary number of method calls `(...)` or subscripts `[...]`. + /// - Any value can be followed by an arbitrary number of method calls `(...)`, subscripts `[...]`, or generic arguments `<...>`. /// - Any value can be followed by a `.identifier` func parseExpressionRange(startingAt startIndex: Int) -> ClosedRange? { // Any expression can start with a prefix operator, or `await` @@ -1355,8 +1355,8 @@ extension Formatter { let nextToken = token(at: nextTokenIndex) { switch nextToken { - // Any expression can be followed by an arbitrary number of method calls `(...)` or subscripts `[...]`. - case .startOfScope("("), .startOfScope("["): + // Any expression can be followed by an arbitrary number of method calls `(...)`, subscripts `[...]`, or generic arguments `<...>`. + case .startOfScope("("), .startOfScope("["), .startOfScope("<"): // If there's a linebreak between an expression and a paren or subscript, // then it's not parsed as a method call and is actually a separate expression if tokens[endOfExpression ..< nextTokenIndex].contains(where: \.isLinebreak) { diff --git a/Tests/ParsingHelpersTests.swift b/Tests/ParsingHelpersTests.swift index fad9d131..2450c7d7 100644 --- a/Tests/ParsingHelpersTests.swift +++ b/Tests/ParsingHelpersTests.swift @@ -1879,6 +1879,8 @@ class ParsingHelpersTests: XCTestCase { XCTAssert(isSingleExpression(#"try? { try printThrows(foo) }()"#)) XCTAssert(isSingleExpression(#"await { await printAsync(foo) }()"#)) XCTAssert(isSingleExpression(#"try await { try await printAsyncThrows(foo) }()"#)) + XCTAssert(isSingleExpression(#"Foo()"#)) + XCTAssert(isSingleExpression(#"Foo(quux: quux)"#)) XCTAssert(isSingleExpression(""" foo diff --git a/Tests/RulesTests+Redundancy.swift b/Tests/RulesTests+Redundancy.swift index 567d1a7e..24cbad4c 100644 --- a/Tests/RulesTests+Redundancy.swift +++ b/Tests/RulesTests+Redundancy.swift @@ -8995,6 +8995,22 @@ class RedundancyTests: RulesTests { options: options, exclude: ["indent", "blankLinesBetweenScopes", "wrapMultilineConditionalAssignment"]) } + func testRemovesRedundantClosureWithGenericExistentialTypes() { + let input = """ + let foo: Foo = { DefaultFoo() }() + let foo: any Foo = { DefaultFoo() }() + let foo: any Foo = { DefaultFoo() }() + """ + + let output = """ + let foo: Foo = DefaultFoo() + let foo: any Foo = DefaultFoo() + let foo: any Foo = DefaultFoo() + """ + + testFormatting(for: input, output, rule: FormatRules.redundantClosure) + } + func testRedundantSwitchStatementReturnInFunctionWithMultipleWhereClauses() { // https://github.com/nicklockwood/SwiftFormat/issues/1554 let input = """