@@ -236,20 +236,16 @@ public final class UseShorthandTypeNames: SyntaxFormatRule {
236236 ) -> TypeSyntax {
237237 var wrappedType = wrappedType
238238
239- if let functionType = wrappedType. as ( FunctionTypeSyntax . self) {
240- // Function types must be wrapped as a tuple before using shorthand optional syntax,
241- // otherwise the "?" applies to the return type instead of the function type. Attach the
242- // leading trivia to the left-paren that we're adding in this case.
243- let tupleTypeElement = TupleTypeElementSyntax (
244- inoutKeyword: nil , firstName: nil , secondName: nil , colon: nil , type: TypeSyntax ( functionType) ,
245- ellipsis: nil , trailingComma: nil )
246- let tupleTypeElementList = TupleTypeElementListSyntax ( [ tupleTypeElement] )
247- let tupleType = TupleTypeSyntax (
248- leftParen: TokenSyntax . leftParenToken ( leadingTrivia: leadingTrivia) ,
249- elements: tupleTypeElementList,
250- rightParen: TokenSyntax . rightParenToken ( ) )
251- wrappedType = TypeSyntax ( tupleType)
252- } else {
239+ // Function types and some-or-any types must be wrapped in parentheses before using shorthand
240+ // optional syntax, otherwise the "?" will bind incorrectly (in the function case it binds to
241+ // only the result, and in the some-or-any case it only binds to the child protocol). Attach the
242+ // leading trivia to the left-paren that we're adding in these cases.
243+ switch Syntax ( wrappedType) . as ( SyntaxEnum . self) {
244+ case . functionType( let functionType) :
245+ wrappedType = parenthesizedType ( functionType, leadingTrivia: leadingTrivia)
246+ case . someOrAnyType( let someOrAnyType) :
247+ wrappedType = parenthesizedType ( someOrAnyType, leadingTrivia: leadingTrivia)
248+ default :
253249 // Otherwise, the argument type can safely become an optional by simply appending a "?", but
254250 // we need to transfer the leading trivia from the original `Optional` token over to it.
255251 // By doing so, something like `/* comment */ Optional<Foo>` will become `/* comment */ Foo?`
@@ -316,38 +312,58 @@ public final class UseShorthandTypeNames: SyntaxFormatRule {
316312 /// key type or value type does not have a valid expression representation.
317313 private func makeOptionalTypeExpression(
318314 wrapping wrappedType: TypeSyntax ,
319- leadingTrivia: Trivia ? = nil ,
315+ leadingTrivia: Trivia = [ ] ,
320316 questionMark: TokenSyntax
321317 ) -> OptionalChainingExprSyntax ? {
322318 guard var wrappedTypeExpr = expressionRepresentation ( of: wrappedType) else { return nil }
323319
324- if wrappedType. is ( FunctionTypeSyntax . self) {
325- // Function types must be wrapped as a tuple before using shorthand optional syntax,
326- // otherwise the "?" applies to the return type instead of the function type. Attach the
327- // leading trivia to the left-paren that we're adding in this case.
328- let tupleExprElement =
329- LabeledExprSyntax (
330- label: nil , colon: nil , expression: wrappedTypeExpr, trailingComma: nil )
331- let tupleExprElementList = LabeledExprListSyntax ( [ tupleExprElement] )
332- let tupleExpr = TupleExprSyntax (
333- leftParen: TokenSyntax . leftParenToken ( leadingTrivia: leadingTrivia ?? [ ] ) ,
334- elements: tupleExprElementList,
335- rightParen: TokenSyntax . rightParenToken ( ) )
336- wrappedTypeExpr = ExprSyntax ( tupleExpr)
337- } else {
320+ // Function types and some-or-any types must be wrapped in parentheses before using shorthand
321+ // optional syntax, otherwise the "?" will bind incorrectly (in the function case it binds to
322+ // only the result, and in the some-or-any case it only binds to the child protocol). Attach the
323+ // leading trivia to the left-paren that we're adding in these cases.
324+ switch Syntax ( wrappedType) . as ( SyntaxEnum . self) {
325+ case . functionType, . someOrAnyType:
326+ wrappedTypeExpr = parenthesizedExpr ( wrappedTypeExpr, leadingTrivia: leadingTrivia)
327+ default :
338328 // Otherwise, the argument type can safely become an optional by simply appending a "?". If
339329 // we were given leading trivia from another node (for example, from `Optional` when
340330 // converting a long-form to short-form), we need to transfer it over. By doing so, something
341331 // like `/* comment */ Optional<Foo>` will become `/* comment */ Foo?` instead of discarding
342332 // the comment.
343- wrappedTypeExpr. leadingTrivia = leadingTrivia ?? [ ]
333+ wrappedTypeExpr. leadingTrivia = leadingTrivia
344334 }
345335
346336 return OptionalChainingExprSyntax (
347337 expression: wrappedTypeExpr,
348338 questionMark: questionMark)
349339 }
350340
341+ /// Returns the given type wrapped in parentheses.
342+ private func parenthesizedType< TypeNode: TypeSyntaxProtocol > (
343+ _ typeToWrap: TypeNode ,
344+ leadingTrivia: Trivia
345+ ) -> TypeSyntax {
346+ let tupleTypeElement = TupleTypeElementSyntax ( type: TypeSyntax ( typeToWrap) )
347+ let tupleType = TupleTypeSyntax (
348+ leftParen: . leftParenToken( leadingTrivia: leadingTrivia) ,
349+ elements: TupleTypeElementListSyntax ( [ tupleTypeElement] ) ,
350+ rightParen: . rightParenToken( ) )
351+ return TypeSyntax ( tupleType)
352+ }
353+
354+ /// Returns the given expression wrapped in parentheses.
355+ private func parenthesizedExpr< ExprNode: ExprSyntaxProtocol > (
356+ _ exprToWrap: ExprNode ,
357+ leadingTrivia: Trivia
358+ ) -> ExprSyntax {
359+ let tupleExprElement = LabeledExprSyntax ( expression: exprToWrap)
360+ let tupleExpr = TupleExprSyntax (
361+ leftParen: . leftParenToken( leadingTrivia: leadingTrivia) ,
362+ elements: LabeledExprListSyntax ( [ tupleExprElement] ) ,
363+ rightParen: . rightParenToken( ) )
364+ return ExprSyntax ( tupleExpr)
365+ }
366+
351367 /// Returns an `ExprSyntax` that is syntactically equivalent to the given `TypeSyntax`, or nil if
352368 /// it wouldn't be valid.
353369 ///
@@ -404,7 +420,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule {
404420 case . optionalType( let optionalType) :
405421 let result = makeOptionalTypeExpression (
406422 wrapping: optionalType. wrappedType,
407- leadingTrivia: optionalType. firstToken ( viewMode: . sourceAccurate) ? . leadingTrivia,
423+ leadingTrivia: optionalType. firstToken ( viewMode: . sourceAccurate) ? . leadingTrivia ?? [ ] ,
408424 questionMark: optionalType. questionMark)
409425 return ExprSyntax ( result)
410426
@@ -427,6 +443,9 @@ public final class UseShorthandTypeNames: SyntaxFormatRule {
427443 rightParen: tupleType. rightParen)
428444 return ExprSyntax ( result)
429445
446+ case . someOrAnyType( let someOrAnyType) :
447+ return ExprSyntax ( TypeExprSyntax ( type: someOrAnyType) )
448+
430449 default :
431450 return nil
432451 }
0 commit comments