Skip to content

Commit

Permalink
Keep internal / external parameter labels on the same line (nicklockw…
Browse files Browse the repository at this point in the history
  • Loading branch information
calda authored and nicklockwood committed Jul 12, 2020
1 parent 4fb5909 commit 177821c
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 1 deletion.
53 changes: 52 additions & 1 deletion Sources/ParsingHelpers.swift
Expand Up @@ -853,13 +853,58 @@ extension Formatter {
endOfScope -= 1
}
}

func keepArgumentParametersOnSameLine(
startOfScope i: Int,
endOfScope: inout Int
) {
// Remove existing linebreaks between two identifiers
// (This makes sure the internal and external argument labels stay on the same line)
var linebreakIndiciesToRemove = [Int]()
for index in i ..< endOfScope {
if tokens[index].is(.linebreak),
// Check if this linebreak sits between two identifiers (e.g. the external and internal argument labels)
let nextCommaOrClosingParen = self.index(of: .delimiter(","), after: index)
?? self.index(of: .endOfScope(")"), after: index),
let previousNonwhitespace = self.index(of: .nonSpaceOrCommentOrLinebreak, before: index),
tokens[previousNonwhitespace].is(.identifier),
let nextNonwhitespace = self.index(of: .nonSpaceOrCommentOrLinebreak, after: index),
tokens[nextNonwhitespace].is(.identifier),
nextNonwhitespace < nextCommaOrClosingParen {
linebreakIndiciesToRemove.append(index)
}
}

for linebreakIndexToRemove in linebreakIndiciesToRemove.reversed() {
removeToken(at: linebreakIndexToRemove)
endOfScope -= 1

// We also have to clean up any extra spaces that may sit
// between the two identifiers.
if tokens[linebreakIndexToRemove].is(.space) {
replaceToken(at: linebreakIndexToRemove, with: .space(" "))
}

// Insert a replacement linebreak after the next comma
if let nextComma = self.index(of: .delimiter(","), after: linebreakIndexToRemove - 1),
nextComma < endOfScope {
insertLinebreak(at: nextComma + 1)
endOfScope += 1
}
}
}

func wrapArgumentsBeforeFirst(startOfScope i: Int,
endOfScope: Int,
allowGrouping: Bool,
endOfScopeOnSameLine: Bool) {
// Get indent
let indent = indentForLine(at: i)
var endOfScope = endOfScope

keepArgumentParametersOnSameLine(startOfScope: i,
endOfScope: &endOfScope)

if endOfScopeOnSameLine {
removeLinebreakBeforeEndOfScope(at: &endOfScope)
} else {
Expand All @@ -872,6 +917,7 @@ extension Formatter {
}
}
}

// Insert linebreak after each comma
var index = self.index(of: .nonSpaceOrCommentOrLinebreak, before: endOfScope)!
if tokens[index] != .delimiter(",") {
Expand Down Expand Up @@ -913,9 +959,14 @@ extension Formatter {
guard var firstArgumentIndex = self.index(of: .nonSpaceOrLinebreak, in: i + 1 ..< endOfScope) else {
return
}

var endOfScope = endOfScope
keepArgumentParametersOnSameLine(startOfScope: i,
endOfScope: &endOfScope)

// Remove linebreak after opening paren
removeTokens(inRange: i + 1 ..< firstArgumentIndex)
var endOfScope = endOfScope - (firstArgumentIndex - (i + 1))
endOfScope -= (firstArgumentIndex - (i + 1))
firstArgumentIndex = i + 1
// Get indent
let start = startOfLine(at: i)
Expand Down
36 changes: 36 additions & 0 deletions Tests/RulesTests.swift
Expand Up @@ -8661,6 +8661,24 @@ class RulesTests: XCTestCase {
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: FormatRules.wrapArguments,
options: options, exclude: ["unusedArguments"])
}

// MARK: beforeFirst

func testWrapAfterFirstConvertedToWrapBefore() {
Expand Down Expand Up @@ -8938,6 +8956,24 @@ class RulesTests: XCTestCase {
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: FormatRules.wrapArguments,
options: options, exclude: ["unusedArguments"])
}

func testWrapParametersListBeforeFirstInClosureTypeWithMaxWidth() {
let input = """
var mathFunction: (Int, Int, String) -> Int = { _, _, _ in
Expand Down
2 changes: 2 additions & 0 deletions Tests/XCTestManifests.swift
Expand Up @@ -1796,7 +1796,9 @@ extension RulesTests {
("testWrapIfElseStatement", testWrapIfElseStatement),
("testWrapIfStatement", testWrapIfStatement),
("testWrapParametersAfterFirstIfMaxLengthExceededInReturnType", testWrapParametersAfterFirstIfMaxLengthExceededInReturnType),
("testWrapParametersAfterFirstWithSeparatedArgumentLabels", testWrapParametersAfterFirstWithSeparatedArgumentLabels),
("testWrapParametersBeforeFirstIfMaxLengthExceededInReturnType", testWrapParametersBeforeFirstIfMaxLengthExceededInReturnType),
("testWrapParametersBeforeFirstWithSeparatedArgumentLabels", testWrapParametersBeforeFirstWithSeparatedArgumentLabels),
("testWrapParametersClosureAfterParameterListDoesNotWrapClosureArguments", testWrapParametersClosureAfterParameterListDoesNotWrapClosureArguments),
("testWrapParametersDoesNotAffectFunctionDeclaration", testWrapParametersDoesNotAffectFunctionDeclaration),
("testWrapParametersListBeforeFirstInClosureType", testWrapParametersListBeforeFirstInClosureType),
Expand Down

0 comments on commit 177821c

Please sign in to comment.