// // WrapArgumentsTests.swift // SwiftFormatTests // // Created by Nick Lockwood on 11/23/16. // Copyright © 2024 Nick Lockwood. All rights reserved. // import XCTest @testable import SwiftFormat final class WrapArgumentsTests: XCTestCase { func testIndentFirstElementWhenApplyingWrap() { let input = """ let foo = Set([ Thing(), Thing(), ]) """ let output = """ let foo = Set([ Thing(), Thing(), ]) """ testFormatting(for: input, output, rule: .wrapArguments, exclude: [.propertyTypes]) } func testWrapArgumentsDoesntIndentTrailingComment() { let input = """ foo( // foo bar: Int, baaz: Int ) """ let output = """ foo( // foo bar: Int, baaz: Int ) """ testFormatting(for: input, output, rule: .wrapArguments) } func testWrapArgumentsDoesntIndentClosingBracket() { let input = """ [ "foo": [ ], ] """ testFormatting(for: input, rule: .wrapArguments) } func testWrapParametersDoesNotAffectFunctionDeclaration() { let input = """ foo( bar _: Int, baz _: String ) """ let options = FormatOptions(wrapArguments: .preserve, wrapParameters: .afterFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapParametersClosureAfterParameterListDoesNotWrapClosureArguments() { let input = """ func foo() {} bar = (baz: 5, quux: 7, quuz: 10) """ let options = FormatOptions(wrapArguments: .preserve, wrapParameters: .beforeFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapParametersNotSetWrapArgumentsAfterFirstDefaultsToAfterFirst() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let output = """ func foo(bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapArguments: .afterFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersNotSetWrapArgumentsBeforeFirstDefaultsToBeforeFirst() { let input = """ func foo(bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapArguments: .beforeFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersNotSetWrapArgumentsPreserveDefaultsToPreserve() { let input = """ func foo( bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapArguments: .preserve) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersFunctionDeclarationClosingParenOnSameLine() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let output = """ func foo( bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapArguments: .beforeFirst, closingParenPosition: .sameLine) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersFunctionDeclarationClosingParenOnNextLine() { let input = """ func foo( bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapArguments: .beforeFirst, closingParenPosition: .balanced) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersFunctionDeclarationClosingParenOnSameLineAndForce() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let output = """ func foo( bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapArguments: .beforeFirst, closingParenPosition: .sameLine, callSiteClosingParenPosition: .sameLine) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersFunctionDeclarationClosingParenOnNextLineAndForce() { let input = """ func foo( bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapArguments: .beforeFirst, closingParenPosition: .balanced, callSiteClosingParenPosition: .sameLine) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersFunctionDeclarationClosingParenOnNextLineSingleArgument() { let input = """ func foo( bar _: Int) {} """ let output = """ func foo( bar _: Int ) {} """ let options = FormatOptions(wrapArguments: .beforeFirst, closingParenPosition: .balanced, maxWidth: 100) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersFunctionCallClosingParenOnNextLineAndForce() { let input = """ foo( bar: 42, baz: "foo" ) """ let output = """ foo( bar: 42, baz: "foo") """ let options = FormatOptions(wrapArguments: .beforeFirst, closingParenPosition: .balanced, callSiteClosingParenPosition: .sameLine) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersFunctionCallClosingParenBalancedAndForce() { let input = """ foo( bar: 42, baz: "foo") """ let output = """ foo( bar: 42, baz: "foo" ) """ let options = FormatOptions(wrapArguments: .beforeFirst, closingParenPosition: .sameLine, callSiteClosingParenPosition: .balanced) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersFunctionCallClosingParenBalancedSingleArgument() { let input = """ foo( bar: 42) """ let output = """ foo( bar: 42 ) """ let options = FormatOptions(wrapArguments: .beforeFirst, closingParenPosition: .sameLine, callSiteClosingParenPosition: .balanced, maxWidth: 100) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testIndentMultilineStringWhenWrappingArguments() { let input = """ foobar(foo: \"\"" baz \"\"", bar: \"\"" baz \"\"") """ let options = FormatOptions(wrapArguments: .afterFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } func testHandleXcodeTokenApplyingWrap() { let input = """ test(image: \u{003c}#T##UIImage#>, name: "Name") """ let output = """ test( image: \u{003c}#T##UIImage#>, name: "Name" ) """ let options = FormatOptions(wrapArguments: .beforeFirst, maxWidth: 20) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testIssue1530() { let input = """ extension DRAutoWeatherReadRequestResponse { static let mock = DRAutoWeatherReadRequestResponse( offlineFirstWeather: DRAutoWeatherReadRequestResponse.DROfflineFirstWeather( daily: .mockWeatherID, hourly: [] ) ) } """ let options = FormatOptions(wrapArguments: .beforeFirst) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.propertyTypes]) } // MARK: wrapParameters // MARK: preserve func testAfterFirstPreserved() { let input = """ func foo(bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapParameters: .preserve) testFormatting(for: input, rule: .wrapArguments, options: options) } func testAfterFirstPreservedIndentFixed() { let input = """ func foo(bar _: Int, baz _: String) {} """ let output = """ func foo(bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapParameters: .preserve) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testAfterFirstPreservedNewlineRemoved() { let input = """ func foo(bar _: Int, baz _: String ) {} """ let output = """ func foo(bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapParameters: .preserve) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testBeforeFirstPreserved() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapParameters: .preserve) testFormatting(for: input, rule: .wrapArguments, options: options) } func testBeforeFirstPreservedIndentFixed() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapParameters: .preserve) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testBeforeFirstPreservedNewlineAdded() { let input = """ func foo( bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapParameters: .preserve) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersAfterMultilineComment() { let input = """ /** Some function comment. */ func barFunc( _ firstParam: FirstParamType, secondParam: SecondParamType ) """ let options = FormatOptions(wrapParameters: .preserve) testFormatting(for: input, rule: .wrapArguments, options: options) } // MARK: afterFirst func testBeforeFirstConvertedToAfterFirst() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let output = """ func foo(bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapParameters: .afterFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testNoWrapInnerArguments() { let input = """ func foo( bar _: Int, baz _: foo(bar, baz) ) {} """ let output = """ func foo(bar _: Int, baz _: foo(bar, baz)) {} """ let options = FormatOptions(wrapParameters: .afterFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } // MARK: afterFirst, maxWidth func testWrapAfterFirstIfMaxLengthExceeded() { let input = """ func foo(bar: Int, baz: String) -> Bool {} """ let output = """ func foo(bar: Int, baz: String) -> Bool {} """ let options = FormatOptions(wrapParameters: .afterFirst, maxWidth: 20) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments, .wrap]) } func testWrapAfterFirstIfMaxLengthExceeded2() { let input = """ func foo(bar: Int, baz: String, quux: Bool) -> Bool {} """ let output = """ func foo(bar: Int, baz: String, quux: Bool) -> Bool {} """ let options = FormatOptions(wrapParameters: .afterFirst, maxWidth: 20) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments, .wrap]) } func testWrapAfterFirstIfMaxLengthExceeded3() { let input = """ func foo(bar: Int, baz: String, aVeryLongLastArgumentThatExceedsTheMaxWidthByItself: Bool) -> Bool {} """ let output = """ func foo(bar: Int, baz: String, aVeryLongLastArgumentThatExceedsTheMaxWidthByItself: Bool) -> Bool {} """ let options = FormatOptions(wrapParameters: .afterFirst, maxWidth: 32) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments, .wrap]) } func testWrapAfterFirstIfMaxLengthExceeded3WithWrap() { let input = """ func foo(bar: Int, baz: String, aVeryLongLastArgumentThatExceedsTheMaxWidthByItself: Bool) -> Bool {} """ let output = """ func foo(bar: Int, baz: String, aVeryLongLastArgumentThatExceedsTheMaxWidthByItself: Bool) -> Bool {} """ let output2 = """ func foo(bar: Int, baz: String, aVeryLongLastArgumentThatExceedsTheMaxWidthByItself: Bool) -> Bool {} """ let options = FormatOptions(wrapParameters: .afterFirst, maxWidth: 32) testFormatting(for: input, [output, output2], rules: [.wrapArguments, .wrap], options: options, exclude: [.unusedArguments]) } func testWrapAfterFirstIfMaxLengthExceeded4WithWrap() { let input = """ func foo(bar: String, baz: String, quux: Bool) -> Bool {} """ let output = """ func foo(bar: String, baz: String, quux: Bool) -> Bool {} """ let options = FormatOptions(wrapParameters: .afterFirst, maxWidth: 31) testFormatting(for: input, [output], rules: [.wrapArguments, .wrap], options: options, exclude: [.unusedArguments]) } func testWrapAfterFirstIfMaxLengthExceededInClassScopeWithWrap() { let input = """ class TestClass { func foo(bar: String, baz: String, quux: Bool) -> Bool {} } """ let output = """ class TestClass { func foo(bar: String, baz: String, quux: Bool) -> Bool {} } """ let output2 = """ class TestClass { func foo(bar: String, baz: String, quux: Bool) -> Bool {} } """ let options = FormatOptions(wrapParameters: .afterFirst, maxWidth: 31) testFormatting(for: input, [output, output2], rules: [.wrapArguments, .wrap], options: options, exclude: [.unusedArguments]) } func testWrapParametersListInClosureType() { let input = """ var mathFunction: (Int, Int, String) -> Int = { _, _, _ in 0 } """ let output = """ var mathFunction: (Int, Int, String) -> Int = { _, _, _ in 0 } """ let output2 = """ var mathFunction: (Int, Int, String) -> Int = { _, _, _ in 0 } """ let options = FormatOptions(wrapParameters: .afterFirst, maxWidth: 30) testFormatting(for: input, [output, output2], rules: [.wrapArguments], options: options) } func testWrapParametersAfterFirstIfMaxLengthExceededInReturnType() { let input = """ func foo(bar: Int, baz: String, quux: Bool) -> LongReturnType {} """ let output2 = """ func foo(bar: Int, baz: String, quux: Bool) -> LongReturnType {} """ let options = FormatOptions(wrapParameters: .afterFirst, maxWidth: 50) testFormatting(for: input, [input, output2], rules: [.wrapArguments], options: options, exclude: [.unusedArguments]) } func testWrapParametersAfterFirstWithSeparatedArgumentLabels() { let input = """ func foo(with bar: Int, and baz: String, and quux: Bool ) -> LongReturnType {} """ let output = """ func foo(with bar: Int, and baz: String, and quux: Bool) -> LongReturnType {} """ let options = FormatOptions(wrapParameters: .afterFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } // MARK: beforeFirst func testWrapAfterFirstConvertedToWrapBefore() { let input = """ func foo(bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testLinebreakInsertedAtEndOfWrappedFunction() { let input = """ func foo( bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testAfterFirstConvertedToBeforeFirst() { let input = """ func foo(bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapParametersListBeforeFirstInClosureType() { let input = """ var mathFunction: (Int, Int, String) -> Int = { _, _, _ in 0 } """ let output = """ var mathFunction: ( Int, Int, String ) -> Int = { _, _, _ in 0 } """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options) } func testWrapParametersListBeforeFirstInThrowingClosureType() { let input = """ var mathFunction: (Int, Int, String) throws -> Int = { _, _, _ in 0 } """ let output = """ var mathFunction: ( Int, Int, String ) throws -> Int = { _, _, _ in 0 } """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options) } func testWrapParametersListBeforeFirstInTypedThrowingClosureType() { let input = """ var mathFunction: (Int, Int, String) throws(Foo) -> Int = { _, _, _ in 0 } """ let output = """ var mathFunction: ( Int, Int, String ) throws(Foo) -> Int = { _, _, _ in 0 } """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options) } func testWrapParametersListBeforeFirstInRethrowingClosureType() { let input = """ var mathFunction: (Int, Int, String) rethrows -> Int = { _, _, _ in 0 } """ let output = """ var mathFunction: ( Int, Int, String ) rethrows -> Int = { _, _, _ in 0 } """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options) } func testWrapParametersListBeforeFirstInClosureTypeAsFunctionParameter() { let input = """ func foo(bar: (Int, Bool, String) -> Int) -> Int {} """ let output = """ func foo(bar: ( Int, Bool, String ) -> Int) -> Int {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options, exclude: [.unusedArguments]) } func testWrapParametersListBeforeFirstInClosureTypeAsFunctionParameterWithOtherParams() { let input = """ func foo(bar: Int, baz: (Int, Bool, String) -> Int) -> Int {} """ let output = """ func foo(bar: Int, baz: ( Int, Bool, String ) -> Int) -> Int {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options, exclude: [.unusedArguments]) } func testWrapParametersListBeforeFirstInClosureTypeAsFunctionParameterWithOtherParamsAfterWrappedClosure() { let input = """ func foo(bar: Int, baz: (Int, Bool, String) -> Int, quux: String) -> Int {} """ let output = """ func foo(bar: Int, baz: ( Int, Bool, String ) -> Int, quux: String) -> Int {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options, exclude: [.unusedArguments]) } func testWrapParametersListBeforeFirstInEscapingClosureTypeAsFunctionParameter() { let input = """ func foo(bar: @escaping (Int, Bool, String) -> Int) -> Int {} """ let output = """ func foo(bar: @escaping ( Int, Bool, String ) -> Int) -> Int {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options, exclude: [.unusedArguments]) } func testWrapParametersListBeforeFirstInNoEscapeClosureTypeAsFunctionParameter() { let input = """ func foo(bar: @noescape (Int, Bool, String) -> Int) -> Int {} """ let output = """ func foo(bar: @noescape ( Int, Bool, String ) -> Int) -> Int {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options, exclude: [.unusedArguments]) } func testWrapParametersListBeforeFirstInEscapingAutoclosureTypeAsFunctionParameter() { let input = """ func foo(bar: @escaping @autoclosure (Int, Bool, String) -> Int) -> Int {} """ let output = """ func foo(bar: @escaping @autoclosure ( Int, Bool, String ) -> Int) -> Int {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments], options: options, exclude: [.unusedArguments]) } // MARK: beforeFirst, maxWidth func testWrapBeforeFirstIfMaxLengthExceeded() { let input = """ func foo(bar: Int, baz: String) -> Bool {} """ let output = """ func foo( bar: Int, baz: String ) -> Bool {} """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 20) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } func testNoWrapBeforeFirstIfMaxLengthNotExceeded() { let input = """ func foo(bar: Int, baz: String) -> Bool {} """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 42) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } func testNoWrapGenericsIfClosingBracketWithinMaxWidth() { let input = """ func foo(bar: Int, baz: String) -> Bool {} """ let output = """ func foo( bar: Int, baz: String ) -> Bool {} """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 20) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } func testWrapAlreadyWrappedArgumentsIfMaxLengthExceeded() { let input = """ func foo( bar: Int, baz: String, quux: Bool ) -> Bool {} """ let output = """ func foo( bar: Int, baz: String, quux: Bool ) -> Bool {} """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 26) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } func testWrapParametersBeforeFirstIfMaxLengthExceededInReturnType() { let input = """ func foo(bar: Int, baz: String, quux: Bool) -> LongReturnType {} """ let output2 = """ func foo( bar: Int, baz: String, quux: Bool ) -> LongReturnType {} """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 50) testFormatting(for: input, [input, output2], rules: [.wrapArguments], options: options, exclude: [.unusedArguments]) } func testWrapParametersBeforeFirstWithSeparatedArgumentLabels() { let input = """ func foo(with bar: Int, and baz: String ) -> LongReturnType {} """ let output = """ func foo( with bar: Int, and baz: String ) -> LongReturnType {} """ let options = FormatOptions(wrapParameters: .beforeFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } func testWrapParametersListBeforeFirstInClosureTypeWithMaxWidth() { let input = """ var mathFunction: (Int, Int, String) -> Int = { _, _, _ in 0 } """ let output = """ var mathFunction: ( Int, Int, String ) -> Int = { _, _, _ in 0 } """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 30) testFormatting(for: input, [output], rules: [.wrapArguments], options: options) } func testNoWrapBeforeFirstMaxWidthNotExceededWithLineBreakSinceLastEndOfArgumentScope() { let input = """ class Foo { func foo() { bar() } func bar(foo: String, bar: Int) { quux() } } """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 37) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } func testNoWrapSubscriptWithSingleElement() { let input = """ guard let foo = bar[0] {} """ let output = """ guard let foo = bar[ 0 ] {} """ let options = FormatOptions(wrapCollections: .beforeFirst, maxWidth: 20) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.wrap]) } func testWrapArrayWithSingleElementIfOverMaxWidth() { let input = """ let foo = [0] """ let output = """ let foo = [ 0, ] """ let options = FormatOptions(wrapCollections: .beforeFirst, maxWidth: 11) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options, exclude: [.wrap]) } func testWrapPartiallyWrappedArrayWithSingleElement() { let input = """ let foo = [ 0] """ let output = """ let foo = [ 0, ] """ let options = FormatOptions(wrapCollections: .beforeFirst, maxWidth: 100) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options, exclude: [.wrap]) } func testWrapDictionaryWithSingleElementIfOverMaxWidth() { let input = """ let foo = [bar: baz] """ let output = """ let foo = [ bar: baz, ] """ let options = FormatOptions(wrapCollections: .beforeFirst, maxWidth: 15) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options, exclude: [.wrap]) } func testNoWrapImageLiteral() { let input = """ if let image = #imageLiteral(resourceName: \"abc.png\") {} """ let options = FormatOptions(wrapCollections: .beforeFirst, maxWidth: 30) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.wrap]) } func testNoWrapColorLiteral() { let input = """ if let color = #colorLiteral(red: 0.2392156863, green: 0.6470588235, blue: 0.3647058824, alpha: 1) {} """ let options = FormatOptions(wrapCollections: .beforeFirst, maxWidth: 30) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.wrap]) } func testWrapArgumentsNoIndentBlankLines() { let input = """ let foo = [ bar, ] """ let options = FormatOptions(wrapCollections: .beforeFirst) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.wrap, .blankLinesAtStartOfScope, .blankLinesAtEndOfScope]) } // MARK: closingParenPosition = true func testParenOnSameLineWhenWrapAfterFirstConvertedToWrapBefore() { let input = """ func foo(bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapParameters: .beforeFirst, closingParenPosition: .sameLine) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testParenOnSameLineWhenWrapBeforeFirstUnchanged() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let output = """ func foo( bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapParameters: .beforeFirst, closingParenPosition: .sameLine) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testParenOnSameLineWhenWrapBeforeFirstPreserved() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let output = """ func foo( bar _: Int, baz _: String) {} """ let options = FormatOptions(wrapParameters: .preserve, closingParenPosition: .sameLine) testFormatting(for: input, output, rule: .wrapArguments, options: options) } // MARK: indent with tabs func testTabIndentWrappedFunctionWithSmartTabs() { let input = """ func foo(bar: Int, baz: Int) {} """ let options = FormatOptions(indent: "\t", wrapParameters: .afterFirst, tabWidth: 2) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } func testTabIndentWrappedFunctionWithoutSmartTabs() { let input = """ func foo(bar: Int, baz: Int) {} """ let output = """ func foo(bar: Int, \t\t\t\t baz: Int) {} """ let options = FormatOptions(indent: "\t", wrapParameters: .afterFirst, tabWidth: 2, smartTabs: false) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments]) } // MARK: - wrapArguments --wrapArguments func testWrapArgumentsDoesNotAffectFunctionDeclaration() { let input = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapArguments: .afterFirst, wrapParameters: .preserve) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapArgumentsDoesNotAffectInit() { let input = """ init( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapArguments: .afterFirst, wrapParameters: .preserve) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapArgumentsDoesNotAffectSubscript() { let input = """ subscript( bar _: Int, baz _: String ) -> Int {} """ let options = FormatOptions(wrapArguments: .afterFirst, wrapParameters: .preserve) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapArgumentsDoesNotAffectAsyncFunctionDeclaration() { let input = """ func foo( bar _: Int, baz _: String ) async {} """ let options = FormatOptions(wrapArguments: .afterFirst, wrapParameters: .preserve) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapParametersUsedForAsyncFunctionDeclaration() { let input = """ func testAsync(first: String, second: String, third: String) async { debugPrint("") } """ let options = FormatOptions(wrapArguments: .beforeFirst, wrapParameters: .afterFirst) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.unusedArguments, .wrapMultilineStatementBraces]) } // MARK: afterFirst func testWrapArgumentsConvertBeforeFirstToAfterFirst() { let input = """ foo( bar _: Int, baz _: String ) """ let output = """ foo(bar _: Int, baz _: String) """ let options = FormatOptions(wrapArguments: .afterFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testCorrectWrapIndentForNestedArguments() { let input = """ foo( bar: ( x: 0, y: 0 ), baz: ( x: 0, y: 0 ) ) """ let output = """ foo(bar: (x: 0, y: 0), baz: (x: 0, y: 0)) """ let options = FormatOptions(wrapArguments: .afterFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testNoRemoveLinebreakAfterCommentInArguments() { let input = """ a(b // comment ) """ let options = FormatOptions(wrapArguments: .afterFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } func testNoRemoveLinebreakAfterCommentInArguments2() { let input = """ foo(bar: bar // , // baz: baz ) {} """ let options = FormatOptions(wrapArguments: .afterFirst) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.indent]) } func testConsecutiveCodeCommentsNotIndented() { let input = """ foo(bar: bar, // bar, // baz, quux) """ let options = FormatOptions(wrapArguments: .afterFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } // MARK: afterFirst maxWidth func testWrapArgumentsAfterFirst() { let input = """ foo(bar: Int, baz: String, quux: Bool) """ let output = """ foo(bar: Int, baz: String, quux: Bool) """ let options = FormatOptions(wrapArguments: .afterFirst, maxWidth: 20) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.unusedArguments, .wrap]) } // MARK: beforeFirst func testClosureInsideParensNotWrappedOntoNextLine() { let input = """ foo({ bar() }) """ let options = FormatOptions(wrapArguments: .beforeFirst) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.trailingClosures]) } func testNoMangleCommentedLinesWhenWrappingArguments() { let input = """ foo(bar: bar, quux: quux // , // baz: baz ) {} """ let output = """ foo( bar: bar, quux: quux // , // baz: baz ) {} """ let options = FormatOptions(wrapArguments: .beforeFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testNoMangleCommentedLinesWhenWrappingArgumentsWithNoCommas() { let input = """ foo(bar: bar, quux: quux // baz: baz ) {} """ let output = """ foo( bar: bar, quux: quux // baz: baz ) {} """ let options = FormatOptions(wrapArguments: .beforeFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } // MARK: preserve func testWrapArgumentsDoesNotAffectLessThanOperator() { let input = """ func foo() { guard foo < bar.count else { return nil } } """ let options = FormatOptions(wrapArguments: .preserve) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.wrapConditionalBodies]) } // MARK: - --wrapArguments, --wrapParameter // MARK: beforeFirst func testNoMistakeTernaryExpressionForArguments() { let input = """ (foo ? bar : baz) """ let options = FormatOptions(wrapArguments: .beforeFirst, wrapParameters: .beforeFirst) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.redundantParens]) } // MARK: beforeFirst, maxWidth : string interpolation func testNoWrapBeforeFirstArgumentInStringInterpolation() { let input = """ "a very long string literal with \\(interpolation) inside" """ let options = FormatOptions(wrapArguments: .beforeFirst, wrapParameters: .beforeFirst, maxWidth: 40) testFormatting(for: input, rule: .wrapArguments, options: options) } func testNoWrapBeforeFirstArgumentInStringInterpolation2() { let input = """ "a very long string literal with \\(interpolation) inside" """ let options = FormatOptions(wrapArguments: .beforeFirst, wrapParameters: .beforeFirst, maxWidth: 50) testFormatting(for: input, rule: .wrapArguments, options: options) } func testNoWrapBeforeFirstArgumentInStringInterpolation3() { let input = """ "a very long string literal with \\(interpolated, variables) inside" """ let options = FormatOptions(wrapArguments: .beforeFirst, wrapParameters: .beforeFirst, maxWidth: 40) testFormatting(for: input, rule: .wrapArguments, options: options) } func testNoWrapBeforeNestedFirstArgumentInStringInterpolation() { let input = """ "a very long string literal with \\(foo(interpolated)) inside" """ let options = FormatOptions(wrapArguments: .beforeFirst, wrapParameters: .beforeFirst, maxWidth: 45) testFormatting(for: input, rule: .wrapArguments, options: options) } func testNoWrapBeforeNestedFirstArgumentInStringInterpolation2() { let input = """ "a very long string literal with \\(foo(interpolated, variables)) inside" """ let options = FormatOptions(wrapArguments: .beforeFirst, wrapParameters: .beforeFirst, maxWidth: 45) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapProtocolFuncParametersBeforeFirst() { let input = """ public protocol Foo { public func stringify(_ value: T, label: String) -> (T, String) } """ let output = """ public protocol Foo { public func stringify( _ value: T, label: String ) -> (T, String) } """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 30) testFormatting(for: input, output, rule: .wrapArguments, options: options) } // MARK: afterFirst maxWidth : string interpolation func testNoWrapAfterFirstArgumentInStringInterpolation() { let input = """ "a very long string literal with \\(interpolated) inside" """ let options = FormatOptions(wrapArguments: .afterFirst, wrapParameters: .afterFirst, maxWidth: 46) testFormatting(for: input, rule: .wrapArguments, options: options) } func testNoWrapAfterFirstArgumentInStringInterpolation2() { let input = """ "a very long string literal with \\(interpolated, variables) inside" """ let options = FormatOptions(wrapArguments: .afterFirst, wrapParameters: .afterFirst, maxWidth: 50) testFormatting(for: input, rule: .wrapArguments, options: options) } func testNoWrapAfterNestedFirstArgumentInStringInterpolation() { let input = """ "a very long string literal with \\(foo(interpolated, variables)) inside" """ let options = FormatOptions(wrapArguments: .afterFirst, wrapParameters: .afterFirst, maxWidth: 55) testFormatting(for: input, rule: .wrapArguments, options: options) } // macros func testWrapMacroParametersBeforeFirst() { let input = """ @freestanding(expression) public macro stringify(_ value: T, label: String) -> (T, String) """ let output = """ @freestanding(expression) public macro stringify( _ value: T, label: String ) -> (T, String) """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 30) testFormatting(for: input, output, rule: .wrapArguments, options: options) } // MARK: - wrapArguments --wrapCollections // MARK: beforeFirst func testNoDoubleSpaceAddedToWrappedArray() { let input = """ [ foo, bar ] """ let output = """ [ foo, bar ] """ let options = FormatOptions(trailingCommas: .never, wrapCollections: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments, .spaceInsideBrackets], options: options) } func testTrailingCommasAddedToWrappedArray() { let input = """ [foo, bar] """ let output = """ [ foo, bar, ] """ let options = FormatOptions(trailingCommas: .always, wrapCollections: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options) } func testTrailingCommasAddedToWrappedNestedDictionary() { let input = """ [foo: [bar: baz, bar2: baz2]] """ let output = """ [foo: [ bar: baz, bar2: baz2, ]] """ let options = FormatOptions(trailingCommas: .always, wrapCollections: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options) } func testTrailingCommasAddedToSingleLineNestedDictionary() { let input = """ [ foo: [bar: baz, bar2: baz2]] """ let output = """ [ foo: [bar: baz, bar2: baz2], ] """ let options = FormatOptions(trailingCommas: .always, wrapCollections: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options) } func testTrailingCommasAddedToWrappedNestedDictionaries() { let input = """ [foo: [bar: baz, bar2: baz2], foo2: [bar: baz, bar2: baz2]] """ let output = """ [ foo: [ bar: baz, bar2: baz2, ], foo2: [ bar: baz, bar2: baz2, ], ] """ let options = FormatOptions(trailingCommas: .always, wrapCollections: .beforeFirst) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options) } func testSpaceAroundEnumValuesInArray() { let input = """ [ .foo, .bar, .baz, ] """ let options = FormatOptions(wrapCollections: .beforeFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } // MARK: beforeFirst maxWidth func testWrapCollectionOnOneLineBeforeFirstWidthExceededInChainedFunctionCallAfterCollection() { let input = """ let foo = ["bar", "baz"].quux(quuz) """ let output = """ let foo = ["bar", "baz"] .quux(quuz) """ let options = FormatOptions(wrapCollections: .beforeFirst, maxWidth: 26) testFormatting(for: input, [output], rules: [.wrap, .wrapArguments], options: options) } // MARK: afterFirst func testTrailingCommaRemovedInWrappedArray() { let input = """ [ .foo, .bar, .baz, ] """ let output = """ [.foo, .bar, .baz] """ let options = FormatOptions(wrapCollections: .afterFirst) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testNoRemoveLinebreakAfterCommentInElements() { let input = """ [a, // comment ] """ let options = FormatOptions(wrapCollections: .afterFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapCollectionsConsecutiveCodeCommentsNotIndented() { let input = """ let a = [foo, // bar, // baz, quux] """ let options = FormatOptions(wrapCollections: .afterFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapCollectionsConsecutiveCodeCommentsNotIndentedInWrapBeforeFirst() { let input = """ let a = [ foo, // bar, // baz, quux, ] """ let options = FormatOptions(wrapCollections: .beforeFirst) testFormatting(for: input, rule: .wrapArguments, options: options) } // MARK: preserve func testNoBeforeFirstPreservedAndTrailingCommaIgnoredInMultilineNestedDictionary() { let input = """ [foo: [bar: baz, bar2: baz2]] """ let output = """ [foo: [bar: baz, bar2: baz2]] """ let options = FormatOptions(trailingCommas: .always, wrapCollections: .preserve) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options) } func testBeforeFirstPreservedAndTrailingCommaAddedInSingleLineNestedDictionary() { let input = """ [ foo: [bar: baz, bar2: baz2]] """ let output = """ [ foo: [bar: baz, bar2: baz2], ] """ let options = FormatOptions(trailingCommas: .always, wrapCollections: .preserve) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options) } func testBeforeFirstPreservedAndTrailingCommaAddedInSingleLineNestedDictionaryWithOneNestedItem() { let input = """ [ foo: [bar: baz]] """ let output = """ [ foo: [bar: baz], ] """ let options = FormatOptions(trailingCommas: .always, wrapCollections: .preserve) testFormatting(for: input, [output], rules: [.wrapArguments, .trailingCommas], options: options) } // MARK: - wrapArguments --wrapCollections & --wrapArguments // MARK: beforeFirst maxWidth func testWrapArgumentsBeforeFirstWhenArgumentsExceedMaxWidthAndArgumentIsCollection() { let input = """ foo(bar: ["baz", "quux"], quuz: corge) """ let output = """ foo( bar: ["baz", "quux"], quuz: corge ) """ let options = FormatOptions(wrapArguments: .beforeFirst, wrapCollections: .beforeFirst, maxWidth: 26) testFormatting(for: input, [output], rules: [.wrapArguments], options: options) } // MARK: afterFirst maxWidth func testWrapArgumentsAfterFirstWhenArgumentsExceedMaxWidthAndArgumentIsCollection() { let input = """ foo(bar: ["baz", "quux"], quuz: corge) """ let output = """ foo(bar: ["baz", "quux"], quuz: corge) """ let options = FormatOptions(wrapArguments: .afterFirst, wrapCollections: .beforeFirst, maxWidth: 26) testFormatting(for: input, [output], rules: [.wrapArguments], options: options) } // MARK: - wrapArguments Multiple Wraps On Same Line func testWrapAfterFirstWhenChainedFunctionAndThenArgumentsExceedMaxWidth() { let input = """ foo.bar(baz: [qux, quux]).quuz([corge: grault], garply: waldo) """ let output = """ foo.bar(baz: [qux, quux]) .quuz([corge: grault], garply: waldo) """ let options = FormatOptions(wrapArguments: .afterFirst, wrapCollections: .afterFirst, maxWidth: 28) testFormatting(for: input, [output], rules: [.wrapArguments, .wrap], options: options) } func testWrapAfterFirstWrapCollectionsBeforeFirstWhenChainedFunctionAndThenArgumentsExceedMaxWidth() { let input = """ foo.bar(baz: [qux, quux]).quuz([corge: grault], garply: waldo) """ let output = """ foo.bar(baz: [qux, quux]) .quuz([corge: grault], garply: waldo) """ let options = FormatOptions(wrapArguments: .afterFirst, wrapCollections: .beforeFirst, maxWidth: 28) testFormatting(for: input, [output], rules: [.wrapArguments, .wrap], options: options) } func testNoMangleNestedFunctionCalls() { let input = """ points.append(.curve( quadraticBezier(p0.position.x, Double(p1.x), Double(p2.x), t), quadraticBezier(p0.position.y, Double(p1.y), Double(p2.y), t) )) """ let output = """ points.append(.curve( quadraticBezier( p0.position.x, Double(p1.x), Double(p2.x), t ), quadraticBezier( p0.position.y, Double(p1.y), Double(p2.y), t ) )) """ let options = FormatOptions(wrapArguments: .beforeFirst, maxWidth: 40) testFormatting(for: input, [output], rules: [.wrapArguments, .wrap], options: options) } func testWrapArguments_typealias_beforeFirst() { let input = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let output = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let options = FormatOptions(wrapTypealiases: .beforeFirst, maxWidth: 40) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_multipleTypealiases_beforeFirst() { let input = """ enum Namespace { typealias DependenciesA = FooProviding & BarProviding typealias DependenciesB = BaazProviding & QuuxProviding } """ let output = """ enum Namespace { typealias DependenciesA = FooProviding & BarProviding typealias DependenciesB = BaazProviding & QuuxProviding } """ let options = FormatOptions(wrapTypealiases: .beforeFirst, maxWidth: 45) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_afterFirst() { let input = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let output = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let options = FormatOptions(wrapTypealiases: .afterFirst, maxWidth: 40) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_multipleTypealiases_afterFirst() { let input = """ enum Namespace { typealias DependenciesA = FooProviding & BarProviding typealias DependenciesB = BaazProviding & QuuxProviding } """ let output = """ enum Namespace { typealias DependenciesA = FooProviding & BarProviding typealias DependenciesB = BaazProviding & QuuxProviding } """ let options = FormatOptions(wrapTypealiases: .afterFirst, maxWidth: 45) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_shorterThanMaxWidth() { let input = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding """ let options = FormatOptions(wrapTypealiases: .afterFirst, maxWidth: 100) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_shorterThanMaxWidth_butWrappedInconsistently() { let input = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let output = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let options = FormatOptions(wrapTypealiases: .afterFirst, maxWidth: 200) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_shorterThanMaxWidth_butWrappedInconsistently2() { let input = """ enum Namespace { typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding } """ let output = """ enum Namespace { typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding } """ let options = FormatOptions(wrapTypealiases: .beforeFirst, maxWidth: 200) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_shorterThanMaxWidth_butWrappedInconsistently3() { let input = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let output = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let options = FormatOptions(wrapTypealiases: .afterFirst, maxWidth: 200) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_shorterThanMaxWidth_butWrappedInconsistently4() { let input = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let output = """ typealias Dependencies = FooProviding & BarProviding & BaazProviding & QuuxProviding """ let options = FormatOptions(wrapTypealiases: .afterFirst, maxWidth: 200) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_shorterThanMaxWidth_butWrappedInconsistentlyWithComment() { let input = """ typealias Dependencies = FooProviding & BarProviding // trailing comment 1 // Inline Comment 1 & BaazProviding & QuuxProviding // trailing comment 2 """ let output = """ typealias Dependencies = FooProviding & BarProviding // trailing comment 1 // Inline Comment 1 & BaazProviding & QuuxProviding // trailing comment 2 """ let options = FormatOptions(wrapTypealiases: .beforeFirst, maxWidth: 200) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_singleTypePreserved() { let input = """ typealias Dependencies = FooProviding """ let options = FormatOptions(wrapTypealiases: .beforeFirst, maxWidth: 10) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.wrap]) } func testWrapArguments_typealias_preservesCommentsBetweenTypes() { let input = """ typealias Dependencies // We use `FooProviding` because `FooFeature` depends on `Foo` = FooProviding // We use `BarProviding` because `BarFeature` depends on `Bar` & BarProviding // We use `BaazProviding` because `BaazFeature` depends on `Baaz` & BaazProviding """ let options = FormatOptions(wrapTypealiases: .beforeFirst, maxWidth: 100) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_preservesCommentsAfterTypes() { let input = """ typealias Dependencies = FooProviding // We use `FooProviding` because `FooFeature` depends on `Foo` & BarProviding // We use `BarProviding` because `BarFeature` depends on `Bar` & BaazProviding // We use `BaazProviding` because `BaazFeature` depends on `Baaz` """ let options = FormatOptions(wrapTypealiases: .beforeFirst, maxWidth: 100) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } func testWrapArguments_typealias_withAssociatedType() { let input = """ typealias Collections = Collection & Collection & Collection & Collection """ let output = """ typealias Collections = Collection & Collection & Collection & Collection """ let options = FormatOptions(wrapTypealiases: .beforeFirst, maxWidth: 50) testFormatting(for: input, output, rule: .wrapArguments, options: options, exclude: [.sortTypealiases]) } // MARK: - -return wrap-if-multiline func testWrapReturnOnMultilineFunctionDeclaration() { let input = """ func multilineFunction( foo _: String, bar _: String) -> String {} """ let output = """ func multilineFunction( foo _: String, bar _: String) -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapReturnOnMultilineFunctionDeclarationInProtocol() { let input = """ protocol MyProtocol { func multilineFunction( foo _: String, bar _: String) -> String } """ let output = """ protocol MyProtocol { func multilineFunction( foo _: String, bar _: String) -> String } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapReturnAndEffectOnMultilineFunctionDeclaration() { let input = """ func multilineFunction( foo _: String, bar _: String) async -> String {} """ let output = """ func multilineFunction( foo _: String, bar _: String) async -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testDoesntWrapReturnAndEffectOnSingleLineFunctionDeclaration() { let input = """ func singleLineFunction() async throws -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting(for: input, rule: .wrapArguments, options: options) } func testDoesntWrapReturnAndTypedEffectOnSingleLineFunctionDeclaration() { let input = """ func singleLineFunction() async throws(Foo) -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapEffectOnMultilineFunctionDeclaration() { let input = """ func multilineFunction( foo _: String, bar _: String) async throws -> String {} """ let output = """ func multilineFunction( foo _: String, bar _: String) async throws -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testUnwrapEffectOnMultilineInit() { let input = """ init( foo: String, bar: String ) async throws { print(foo, bar) } """ let output = """ init( foo: String, bar: String ) async throws { print(foo, bar) } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, [output], rules: [.wrapArguments, .braces], options: options) } func testWrapEffectOnMultilineProtocolRequirement() { let input = """ protocol MyProtocol { func multilineFunction( foo _: String, bar _: String) async throws -> String } """ let output = """ protocol MyProtocol { func multilineFunction( foo _: String, bar _: String) async throws -> String } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testUnwrapEffectOnMultilineFunctionDeclaration() { let input = """ func multilineFunction( foo _: String, bar _: String) async throws -> String {} """ let output = """ func multilineFunction( foo _: String, bar _: String) async throws -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .never ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testUnwrapEffectAndReturnTypeOnMultilineFunctionDeclaration() { let input = """ func multilineFunction( foo _: String, bar _: String) async throws -> String {} """ let output = """ func multilineFunction( foo _: String, bar _: String ) async throws -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testFormatReturnTypeOnMultilineFunctionDeclarationWithLineComment() { let input = """ func multilineFunction( foo _: String, bar _: String) async throws -> String // this is a comment {} """ let output = """ func multilineFunction( foo _: String, bar _: String ) async throws -> String // this is a comment {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testUnwrapClosingBraceInVoidThrowingMethod() { let input = """ func multilineFunction( foo: String, bar: String) async throws { print(foo, bar) } """ let output = """ func multilineFunction( foo: String, bar: String ) async throws { print(foo, bar) } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, [output], rules: [.wrapArguments, .braces], options: options) } func testUnwrapClosingBraceInVoidNonThrowingMethod() { let input = """ func multilineFunction( foo: String, bar: String) { print(foo, bar) } """ let output = """ func multilineFunction( foo: String, bar: String ) { print(foo, bar) } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, [output], rules: [.wrapArguments, .braces], options: options) } func testWrapReturnIfMultilineOnClosureArgument() { let input = """ func multilineFunctionWithClosureArgument( closure: (( _ view: ChartContainerView, _ content: Content, _ traitCollection: UITraitCollection, _ state: ItemCellState) -> Void)? = nil) -> String { print(closure) } """ let output = """ func multilineFunctionWithClosureArgument( closure: (( _ view: ChartContainerView, _ content: Content, _ traitCollection: UITraitCollection, _ state: ItemCellState) -> Void)? = nil) -> String { print(closure) } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, maxWidth: 100 ) testFormatting(for: input, [output], rules: [.wrapArguments, .wrap, .indent], options: options) } func testPreservesReturnInClosure() { let input = """ public private(set) var foo: (( UIAccessibility.Notification, Any?, Bool, TimeInterval, String, Int, String) -> Void)? """ let output = """ public private(set) var foo: (( UIAccessibility.Notification, Any?, Bool, TimeInterval, String, Int, String) -> Void)? """ let options = FormatOptions( wrapArguments: .beforeFirst, wrapCollections: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, maxWidth: 100, wrapEffects: .ifMultiline ) testFormatting(for: input, [output], rules: [.wrapArguments, .wrap], options: options) } func testFormatReturnTypeOnMultilineFunctionDeclarationWithBlockComment() { let input = """ func multilineFunction( foo _: String, bar _: String) async throws -> String /* block comment */ {} """ let output = """ func multilineFunction( foo _: String, bar _: String ) async throws -> String /* block comment */ {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testUnwrapReturnTypeOnMultilineFunctionDeclaration() { let input = """ func multilineFunction( foo _: String, bar _: String) -> String {} """ let output = """ func multilineFunction( foo _: String, bar _: String ) -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testUnwrapReturnTypeOnMultilineSubscriptDeclaration() { let input = """ subscript( foo _: String, bar _: String) -> String {} """ let output = """ subscript( foo _: String, bar _: String ) -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testUnwrapBraceForReturnTypeOnMultilineFunctionDeclaration() { let input = """ func multilineFunction( foo _: String, bar _: String) -> String { print("hello") } """ let output = """ func multilineFunction( foo _: String, bar _: String ) -> String { print("hello") } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, wrapReturnType: .never, wrapEffects: .never ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testAllmanBraceWithWrapReturnTypeNever() { let input = """ func makeStuff( param1: String = "", param2: Int? = nil, param3: String = "" ) -> String { print(param1, param2, param3) return "return" } """ let output = """ func makeStuff( param1: String = "", param2: Int? = nil, param3: String = "" ) -> String { print(param1, param2, param3) return "return" } """ let options = FormatOptions(allmanBraces: true, wrapReturnType: .never) testFormatting(for: input, [output], rules: [.wrapArguments, .braces], options: options) } func testWrapArgumentsDoesntBreakFunctionDeclaration_issue_1776() { let input = """ struct OpenAPIController: RouteCollection { let info = InfoObject(title: "Swagger {{cookiecutter.service_name}} - OpenAPI", description: "{{cookiecutter.description}}", contact: .init(email: "{{cookiecutter.email}}"), version: Version(0, 0, 1)) func boot(routes: RoutesBuilder) throws { routes.get("swagger", "swagger.json") { $0.application.routes.openAPI(info: info) } .excludeFromOpenAPI() } } """ let options = FormatOptions(wrapEffects: .never) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.propertyTypes]) } func testWrapEffectsNeverPreservesComments() { let input = """ func multilineFunction( foo _: String, bar _: String) // Comment here between the parameters and effects async throws -> String {} """ let output = """ func multilineFunction( foo _: String, bar _: String) async throws -> String {} """ let options = FormatOptions(closingParenPosition: .sameLine, wrapEffects: .never) testFormatting( for: input, output, rule: .wrapArguments, options: options, exclude: [.indent] ) } func testWrapReturnOnMultilineFunctionDeclarationWithAfterFirst() { let input = """ func multilineFunction(foo _: String, bar _: String) -> String {} """ let output = """ func multilineFunction(foo _: String, bar _: String) -> String {} """ let options = FormatOptions( wrapArguments: .afterFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline ) testFormatting( for: input, output, rule: .wrapArguments, options: options, exclude: [.indent] ) } func testWrapReturnOnMultilineThrowingFunctionDeclarationWithAfterFirst() { let input = """ func multilineFunction(foo _: String, bar _: String) throws -> String {} """ let output = """ func multilineFunction(foo _: String, bar _: String) throws -> String {} """ let options = FormatOptions( wrapArguments: .afterFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline ) testFormatting( for: input, output, rule: .wrapArguments, options: options, exclude: [.indent] ) } func testWrapReturnAndEffectOnMultilineThrowingFunctionDeclarationWithAfterFirst() { let input = """ func multilineFunction(foo _: String, bar _: String) throws -> String {} """ let output = """ func multilineFunction(foo _: String, bar _: String) throws -> String {} """ let options = FormatOptions( wrapArguments: .afterFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting( for: input, output, rule: .wrapArguments, options: options, exclude: [.indent] ) } func testWrapEffectsNeverDoesntUnwrapAsyncLet() { let input = """ async let createdAd = createAd( subcategoryID: subcategory.id, shopID: shop?.id) async let locationCity = createEditAdWorker.loadNearestCity(coordinates: coordinates) """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapEffectsWrapsAsyncEffectBeforeLetProperty() { let input = """ @attached(body) macro GenerateBody() = #externalMacro(module: "...", type: "...") @GenerateBody // generates the body func foo( _ bar: Baaz, _ baaz: Baaz) async let quux: Quux """ let output = """ @attached(body) macro GenerateBody() = #externalMacro(module: "...", type: "...") @GenerateBody // generates the body func foo( _ bar: Baaz, _ baaz: Baaz) async let quux: Quux """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting(for: input, [output], rules: [.wrapArguments, .indent], options: options) } func testWrapsThrowsBeforeAsyncLet() { let input = """ @GenerateBody // generates the body func foo( _ bar: Baaz, _ baaz: Baaz) throws async let quux: Quux """ let output = """ @GenerateBody // generates the body func foo( _ bar: Baaz, _ baaz: Baaz) throws async let quux: Quux """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline, wrapEffects: .ifMultiline ) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testDoesntWrapReturnOnMultilineThrowingFunction() { let input = """ func multilineFunction(foo _: String, bar _: String) throws -> String {} """ let options = FormatOptions( wrapArguments: .afterFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline ) testFormatting( for: input, rule: .wrapArguments, options: options, exclude: [.indent] ) } func testDoesntWrapReturnOnSingleLineFunctionDeclaration() { let input = """ func multilineFunction(foo _: String, bar _: String) -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline ) testFormatting(for: input, rule: .wrapArguments, options: options) } func testDoesntWrapReturnOnSingleLineFunctionDeclarationAfterMultilineArray() { let input = """ final class Foo { private static let array = [ "one", ] private func singleLine() -> String {} } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline ) testFormatting(for: input, rule: .wrapArguments, options: options) } func testDoesntWrapReturnOnSingleLineFunctionDeclarationAfterMultilineMethodCall() { let input = """ public final class Foo { public var multiLineMethodCall = Foo.multiLineMethodCall( bar: bar, baz: baz) func singleLine() -> String { return "method body" } } """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine, wrapReturnType: .ifMultiline ) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.propertyTypes]) } func testPreserveReturnOnMultilineFunctionDeclarationByDefault() { let input = """ func multilineFunction( foo _: String, bar _: String) -> String {} """ let options = FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .sameLine ) testFormatting(for: input, rule: .wrapArguments, options: options) } // MARK: wrapConditions before-first func testWrapConditionsBeforeFirstPreservesMultilineStatements() { let input = """ if let unwrappedFoo = Foo( bar: bar, baz: baz), unwrappedFoo.elements .compactMap({ $0 }) .filter({ if $0.matchesCondition { return true } else { return false } }) .isEmpty, let bar = unwrappedFoo.bar, let baz = unwrappedFoo.bar? .first(where: { $0.isBaz }), let unwrappedFoo2 = Foo( bar: bar2, baz: baz2), let quux = baz.quux {} """ testFormatting( for: input, rules: [.wrapArguments, .indent], options: FormatOptions(closingParenPosition: .sameLine, wrapConditions: .beforeFirst), exclude: [.propertyTypes] ) } func testWrapConditionsBeforeFirst() { let input = """ if let foo = foo, let bar = bar, foo == bar {} else if foo != bar, let quux = quux {} if let baz = baz {} guard baz.filter({ $0 == foo }), let bar = bar else {} while let foo = foo, let bar = bar {} """ let output = """ if let foo = foo, let bar = bar, foo == bar {} else if foo != bar, let quux = quux {} if let baz = baz {} guard baz.filter({ $0 == foo }), let bar = bar else {} while let foo = foo, let bar = bar {} """ testFormatting( for: input, output, rule: .wrapArguments, options: FormatOptions(indent: " ", wrapConditions: .beforeFirst), exclude: [.wrapConditionalBodies] ) } func testWrapConditionsBeforeFirstWhereShouldPreserveExisting() { let input = """ else {} else {} if foo == bar {} guard let foo = bar else {} guard let foo = bar else {} """ testFormatting( for: input, rule: .wrapArguments, options: FormatOptions(indent: " ", wrapConditions: .beforeFirst), exclude: [.elseOnSameLine, .wrapConditionalBodies, .blankLinesAfterGuardStatements] ) } func testWrapConditionsAfterFirst() { let input = """ if let foo = foo, let bar = bar, foo == bar {} else if foo != bar, let quux = quux {} else {} if let baz = baz {} guard baz.filter({ $0 == foo }), let bar = bar else {} while let foo = foo, let bar = bar {} """ let output = """ if let foo = foo, let bar = bar, foo == bar {} else if foo != bar, let quux = quux {} else {} if let baz = baz {} guard baz.filter({ $0 == foo }), let bar = bar else {} while let foo = foo, let bar = bar {} """ testFormatting( for: input, output, rule: .wrapArguments, options: FormatOptions(indent: " ", wrapConditions: .afterFirst), exclude: [.wrapConditionalBodies] ) } func testWrapConditionsAfterFirstWhenFirstLineIsComment() { let input = """ guard // Apply this rule to any function-like declaration ["func", "init", "subscript"].contains(keyword.string), // Opaque generic parameter syntax is only supported in Swift 5.7+ formatter.options.swiftVersion >= "5.7", // Validate that this is a generic method using angle bracket syntax, // and find the indices for all of the key tokens let paramListStartIndex = formatter.index(of: .startOfScope("("), after: keywordIndex), let paramListEndIndex = formatter.endOfScope(at: paramListStartIndex), let genericSignatureStartIndex = formatter.index(of: .startOfScope("<"), after: keywordIndex), let genericSignatureEndIndex = formatter.endOfScope(at: genericSignatureStartIndex), genericSignatureStartIndex < paramListStartIndex, genericSignatureEndIndex < paramListStartIndex, let openBraceIndex = formatter.index(of: .startOfScope("{"), after: paramListEndIndex), let closeBraceIndex = formatter.endOfScope(at: openBraceIndex) else { return } """ let output = """ guard // Apply this rule to any function-like declaration ["func", "init", "subscript"].contains(keyword.string), // Opaque generic parameter syntax is only supported in Swift 5.7+ formatter.options.swiftVersion >= "5.7", // Validate that this is a generic method using angle bracket syntax, // and find the indices for all of the key tokens let paramListStartIndex = formatter.index(of: .startOfScope("("), after: keywordIndex), let paramListEndIndex = formatter.endOfScope(at: paramListStartIndex), let genericSignatureStartIndex = formatter.index(of: .startOfScope("<"), after: keywordIndex), let genericSignatureEndIndex = formatter.endOfScope(at: genericSignatureStartIndex), genericSignatureStartIndex < paramListStartIndex, genericSignatureEndIndex < paramListStartIndex, let openBraceIndex = formatter.index(of: .startOfScope("{"), after: paramListEndIndex), let closeBraceIndex = formatter.endOfScope(at: openBraceIndex) else { return } """ testFormatting( for: input, [output], rules: [.wrapArguments, .indent], options: FormatOptions(wrapConditions: .afterFirst), exclude: [.wrapConditionalBodies] ) } func testWrapConditionsAfterFirstGuardElseOnOwnLine() { let input = """ guard let something = complexCall(...), isOnline, shouldReallyRefresh else { return } """ testFormatting( for: input, rule: .wrapArguments, options: FormatOptions(wrapConditions: .afterFirst), exclude: [.wrapConditionalBodies] ) } func testWrapConditionsBeforeFirstGuardElseOnOwnLine() { let input = """ guard let something = complexCall(...), isOnline, shouldReallyRefresh else { return } """ testFormatting( for: input, rule: .wrapArguments, options: FormatOptions(wrapConditions: .beforeFirst), exclude: [.wrapConditionalBodies] ) } func testWrapConditionsAfterFirstGuardElseOnOwnLineIndented() { let input = """ func foo() { guard let something = complexCall(...), isOnline, shouldReallyRefresh else { return } } """ testFormatting( for: input, rule: .wrapArguments, options: FormatOptions(wrapConditions: .afterFirst), exclude: [.wrapConditionalBodies] ) } func testWrapConditionsAfterFirstIfBraceOnOwnLine() { let input = """ if let something = complexCall(...), isOnline, shouldReallyRefresh { print("True branch") } """ testFormatting( for: input, rule: .wrapArguments, options: FormatOptions(wrapConditions: .afterFirst) ) } func testWrapConditionsBeforeFirstIfBraceOnOwnLine() { let input = """ if let something = complexCall(...), isOnline, shouldReallyRefresh { print("True branch") } """ testFormatting( for: input, rule: .wrapArguments, options: FormatOptions(wrapConditions: .beforeFirst) ) } func testWrapPartiallyWrappedFunctionCall() { let input = """ func foo( bar: Bar, baaz: Baaz, quux: Quux, ) { print( bar, baaz, ) } """ let output = """ func foo( bar: Bar, baaz: Baaz, quux: Quux, ) { print( bar, baaz, ) } """ testFormatting(for: input, output, rule: .wrapArguments, options: FormatOptions(wrapArguments: .beforeFirst, allowPartialWrapping: false), exclude: [.unusedArguments, .trailingCommas]) } func testWrapPartiallyWrappedFunctionCallTwoLines() { let input = """ func foo( foo: Foo, bar: Bar, baaz: Baaz, quux: Quux ) { print( foo, bar, baaz, quux ) } """ let output = """ func foo( foo: Foo, bar: Bar, baaz: Baaz, quux: Quux ) { print( foo, bar, baaz, quux ) } """ testFormatting(for: input, output, rule: .wrapArguments, options: FormatOptions(wrapArguments: .beforeFirst, allowPartialWrapping: false)) } func testWrapPartiallyWrappedArray() { let input = """ let foo = [ foo, bar, baaz, quux, ] """ let output = """ let foo = [ foo, bar, baaz, quux, ] """ testFormatting(for: input, output, rule: .wrapArguments, options: FormatOptions(wrapArguments: .beforeFirst, allowPartialWrapping: false)) } func testArrayWithBlankLine() { let input = """ let foo = [ foo, bar, baaz, quux, ] """ testFormatting(for: input, rule: .wrapArguments, options: FormatOptions(wrapArguments: .beforeFirst, allowPartialWrapping: false)) } func testPartiallyWrappedArrayWithBlankLine() { let input = """ let foo = [ foo, bar, baaz, quux, ] """ let output = """ let foo = [ foo, bar, baaz, quux, ] """ testFormatting(for: input, output, rule: .wrapArguments, options: FormatOptions(wrapArguments: .beforeFirst, allowPartialWrapping: false)) } func testWrapArgumentsBeforeFirstDoesntWrapClosingParenIfFirstArgumentNotWrapped() { let input = """ return .tuple(string .split { $0.isNewline } .map { .string("\\($0)") }) """ testFormatting(for: input, rule: .wrapArguments, options: FormatOptions( wrapArguments: .beforeFirst, closingParenPosition: .balanced, maxWidth: 1000 )) } func testNoWrapEmptyFuncParensBeforeFirst() { let input = """ func aVeryLongFunctionNameThatExceedsTheMaxWidthLimit() { foo() } """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 40) testFormatting(for: input, rule: .wrapArguments, options: options) } func testNoWrapEmptyInitParensBeforeFirst() { let input = """ init() { foo() } """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 8) testFormatting(for: input, rule: .wrapArguments, options: options, exclude: [.wrap]) } func testUnwrapAlreadyWrappedEmptyFuncParensBeforeFirst() { let input = """ func aVeryLongFunctionNameThatExceedsTheMaxWidthLimit( ) { foo() } """ let output = """ func aVeryLongFunctionNameThatExceedsTheMaxWidthLimit() { foo() } """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 40) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapThresholdWrapsWhenExpressionExceedsThreshold() { let input = """ func foo(bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ // Line is 38 chars — under maxWidth (100) but over listWrapThreshold (20) let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 100, listWrapThreshold: 20) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapThresholdDoesNotWrapShortExpression() { let input = """ let result = max(a, b) """ // Line is 22 chars — under listWrapThreshold (40) let options = FormatOptions(wrapArguments: .beforeFirst, maxWidth: 100, listWrapThreshold: 40) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapThresholdZeroWrapsMultiArgumentCalls() { let input = """ let x = foo(a, b) """ let output = """ let x = foo( a, b ) """ // listWrapThreshold 0 — wraps multi-argument calls regardless of length let options = FormatOptions(wrapArguments: .beforeFirst, maxWidth: 200, listWrapThreshold: 0) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapThresholdWrapsSingleArgumentCall() { let input = """ let x = someVeryLongFunctionName(someVeryLongArgumentName: someVeryLongValue) """ let output = """ let x = someVeryLongFunctionName( someVeryLongArgumentName: someVeryLongValue ) """ // Single-argument call — listWrapThreshold wraps it when line exceeds threshold let options = FormatOptions(wrapArguments: .beforeFirst, maxWidth: 200, listWrapThreshold: 0) testFormatting(for: input, output, rule: .wrapArguments, options: options) } func testWrapThresholdDoesNotWrapZeroArgumentCall() { let input = """ let x = someVeryLongFunctionName() """ // Zero-argument call — listWrapThreshold should never wrap it let options = FormatOptions(wrapArguments: .beforeFirst, maxWidth: 200, listWrapThreshold: 0) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapThresholdDefaultPreservesExistingBehaviour() { let input = """ func foo(bar _: Int, baz _: String) {} """ // listWrapThreshold defaults to -1 (none), so only maxWidth triggers wrapping. // Line is 38 chars — under maxWidth 100, so nothing wraps. let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 100) testFormatting(for: input, rule: .wrapArguments, options: options) } func testWrapThresholdDoesNotAffectPartiallyWrappedExpressions() { // Expressions that are already partially wrapped should be handled by // completePartialWrapping, not influenced by listWrapThreshold. let input = """ func foo(bar _: Int, baz _: String) {} """ let output = """ func foo( bar _: Int, baz _: String ) {} """ let options = FormatOptions(wrapParameters: .beforeFirst, maxWidth: 100, listWrapThreshold: 200) testFormatting(for: input, output, rule: .wrapArguments, options: options) } }