Skip to content

Commit 08f9950

Browse files
authored
Merge pull request swiftlang#82 from dylansturg/optional_function_types
Wrap function types in tuples when converting to optional shorthand s…
2 parents e19ef9e + 94d8499 commit 08f9950

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

Sources/SwiftFormatRules/UseShorthandTypeNames.swift

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,25 @@ public final class UseShorthandTypeNames: SyntaxFormatRule {
120120
func shortenOptionalType(argument: GenericArgumentSyntax, trivia: (Trivia, Trivia))
121121
-> TypeSyntax
122122
{
123+
let argumentType: TypeSyntax
124+
if let functionType = argument.argumentType as? FunctionTypeSyntax {
125+
// Function types must be wrapped as a tuple before using shorthand optional syntax,
126+
// otherwise the "?" applies to the return type instead of the function type.
127+
let tupleTypeElement =
128+
SyntaxFactory.makeTupleTypeElement(type: functionType, trailingComma: nil)
129+
let tupleElementList = SyntaxFactory.makeTupleTypeElementList([tupleTypeElement])
130+
argumentType = SyntaxFactory.makeTupleType(
131+
leftParen: SyntaxFactory.makeLeftParenToken(),
132+
elements: tupleElementList,
133+
rightParen: SyntaxFactory.makeRightParenToken())
134+
} else {
135+
// Otherwise, the argument type can safely become an optional by simply appending a "?".
136+
argumentType = argument.argumentType
137+
}
123138
let (_, trailing) = trivia
124139
let questionMark = SyntaxFactory.makePostfixQuestionMarkToken(trailingTrivia: trailing)
125-
let newOptional = SyntaxFactory.makeOptionalType(
126-
wrappedType: argument.argumentType, questionMark: questionMark)
140+
let newOptional =
141+
SyntaxFactory.makeOptionalType(wrappedType: argumentType, questionMark: questionMark)
127142
return newOptional
128143
}
129144

Tests/SwiftFormatRulesTests/UseShorthandTypeNamesTests.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ public class UseShorthandTypeNamesTests: DiagnosingTestCase {
1111
input: """
1212
func enumeratedDictionary<Element>(
1313
from values: Array<Element>,
14-
start: Optional<Array<Element>.Index> = nil
14+
start: Optional<Array<Element>.Index> = nil,
15+
callback: Optional<(_ someArg: Optional<Bool>) -> Void> = nil
1516
) -> Dictionary<Int, Array<Element>> {
1617
// Specializer syntax
1718
Array<Array<Optional<Int>>.Index>.init()
1819
// More specializer syntax
1920
Array<[Int]>.init()
21+
let foo: Optional<() -> Void>? = nil
22+
let bar: Array<() -> Void> = []
23+
let baz: Dictionary<Int, Optional<(Any) -> Void>>? = nil
2024
}
2125
func nestedLongForms(
2226
x: Array<Dictionary<String, Int>>,
@@ -30,12 +34,16 @@ public class UseShorthandTypeNamesTests: DiagnosingTestCase {
3034
expected: """
3135
func enumeratedDictionary<Element>(
3236
from values: [Element],
33-
start: Array<Element>.Index? = nil
37+
start: Array<Element>.Index? = nil,
38+
callback: ((_ someArg: Bool?) -> Void)? = nil
3439
) -> [Int: [Element]] {
3540
// Specializer syntax
3641
[Array<Int?>.Index].init()
3742
// More specializer syntax
3843
[[Int]].init()
44+
let foo: (() -> Void)?? = nil
45+
let bar: [() -> Void] = []
46+
let baz: [Int: ((Any) -> Void)?]? = nil
3947
}
4048
func nestedLongForms(
4149
x: [[String: Int]],

0 commit comments

Comments
 (0)