SR-14244: Tuple containing one or more closures is expanded incorrectly in source editor

I stumbled on a source parsing bug affecting Xcode's parameter expansion, and from my vetting of JIRA and the forums I don't think it's been reported yet, so I dropped a bug report into JIRA outlining this behavior.

Observed Behavior

When a function parameter is a tuple containing one or more closure signatures, pressing Return while its placeholder is highlighted in Xcode's source editor produces incorrect code template expansion. All other parameters in the tuple are ignored. If the closure signatures have an empty (()) input pattern, then only the first closure found is expanded. If the the closures expect an input value, then those input values are erroneously aggregated and applied to a single expanded closure.

Expected Behavior

The expansion should expand the tuple's signature completely, and for any closures it encounters it should produce fully labelled and parameterized closure structures.

Example 1

simple

func someMethod(closures: (closure1: () -> Void,
                           closure2: () -> Void)) { }

incorrectly expands as:

someMethod {
    <#code#>
}

but should expand as:

someMethod(closures: (closure1: {
    <#code#>
}, closure2: {
    <#code#>
}))

Example 2

complex

func someMethod(closures: (int: Int,
                           closure1: (Double) -> Data,
                           closure2: (String, Int) -> Float32)) { }

incorrectly expands as:

(notice the first int: Int parameter disappears and the closures become erroneously merged, with the return type taken from the 2nd closure)

someMethod { (<#Double#>, <#String#>, <#Int#>) -> Float32 in
    <#code#>
}

but should expand as:

someMethod(closures: (int: <#Int#>, closure1: { (<#Double#>) -> Data in
    <#code#>
}, closure2: { (<#String#>, <#Int#>) -> Float32 in
    <#code#>
}))
2 Likes