@@ -19,6 +19,7 @@ import SKOptions
19
19
import SKUtilities
20
20
import SourceKitD
21
21
import SourceKitLSP
22
+ import SwiftBasicFormat
22
23
import SwiftExtensions
23
24
import SwiftParser
24
25
@_spi ( SourceKitLSP) import SwiftRefactor
@@ -396,15 +397,7 @@ class CodeCompletionSession {
396
397
return nil
397
398
}
398
399
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)
408
401
409
402
// Note we don't need special handling for macro expansions since
410
403
// their insertion text doesn't include the '#', so are parsed as
@@ -439,6 +432,33 @@ class CodeCompletionSession {
439
432
return String ( bytes: expandedBytes, encoding: . utf8)
440
433
}
441
434
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
+
442
462
private func completionsFromSKDResponse(
443
463
_ completions: SKDResponseArray ,
444
464
in snapshot: DocumentSnapshot ,
@@ -462,6 +482,8 @@ class CodeCompletionSession {
462
482
463
483
if let closureExpanded = expandClosurePlaceholders ( insertText: insertText) {
464
484
insertText = closureExpanded
485
+ } else if let multilineFormatted = formatMultiLineCompletion ( insertText: insertText) {
486
+ insertText = multilineFormatted
465
487
}
466
488
467
489
let text = rewriteSourceKitPlaceholders ( in: insertText, clientSupportsSnippets: clientSupportsSnippets)
0 commit comments