@@ -19,6 +19,7 @@ import SKOptions
1919import SKUtilities
2020import SourceKitD
2121import SourceKitLSP
22+ import SwiftBasicFormat
2223import SwiftExtensions
2324import SwiftParser
2425@_spi ( SourceKitLSP) import SwiftRefactor
@@ -396,15 +397,7 @@ class CodeCompletionSession {
396397 return nil
397398 }
398399
399- let strippedPrefix : String
400- let exprToExpand : String
401- if insertText. starts ( with: " ?. " ) {
402- strippedPrefix = " ?. "
403- exprToExpand = String ( insertText. dropFirst ( 2 ) )
404- } else {
405- strippedPrefix = " "
406- exprToExpand = insertText
407- }
400+ let ( strippedPrefix, exprToExpand) = extractExpressionToExpand ( from: insertText)
408401
409402 // Note we don't need special handling for macro expansions since
410403 // their insertion text doesn't include the '#', so are parsed as
@@ -439,6 +432,33 @@ class CodeCompletionSession {
439432 return String ( bytes: expandedBytes, encoding: . utf8)
440433 }
441434
435+ /// Extract the expression to expand by stripping optional chaining prefix if present.
436+ private func extractExpressionToExpand( from insertText: String ) -> ( strippedPrefix: String , exprToExpand: String ) {
437+ if insertText. starts ( with: " ?. " ) {
438+ return ( strippedPrefix: " ?. " , exprToExpand: String ( insertText. dropFirst ( 2 ) ) )
439+ } else {
440+ return ( strippedPrefix: " " , exprToExpand: insertText)
441+ }
442+ }
443+
444+ /// If the code completion text returned by sourcekitd, format it using SwiftBasicFormat. This is needed for
445+ /// completion items returned from sourcekitd that already have the trailing closure expanded.
446+ private func formatMultiLineCompletion( insertText: String ) -> String ? {
447+ // We only need to format the completion result if it's a multi-line completion that needs adjustment of
448+ // indentation.
449+ guard insertText. contains ( where: \. isNewline) else {
450+ return nil
451+ }
452+
453+ let ( strippedPrefix, exprToExpand) = extractExpressionToExpand ( from: insertText)
454+
455+ var parser = Parser ( exprToExpand)
456+ let expr = ExprSyntax . parse ( from: & parser)
457+ let formatted = expr. formatted ( using: ClosureCompletionFormat ( indentationWidth: indentationWidth) )
458+
459+ return strippedPrefix + formatted. description
460+ }
461+
442462 private func completionsFromSKDResponse(
443463 _ completions: SKDResponseArray ,
444464 in snapshot: DocumentSnapshot ,
@@ -462,6 +482,8 @@ class CodeCompletionSession {
462482
463483 if let closureExpanded = expandClosurePlaceholders ( insertText: insertText) {
464484 insertText = closureExpanded
485+ } else if let multilineFormatted = formatMultiLineCompletion ( insertText: insertText) {
486+ insertText = multilineFormatted
465487 }
466488
467489 let text = rewriteSourceKitPlaceholders ( in: insertText, clientSupportsSnippets: clientSupportsSnippets)
0 commit comments