Skip to content

Commit d9c5f32

Browse files
authored
Merge pull request #1111 from ahoppen/ahoppen/infer-closure-indentation
Infer indentation of the current source file when expanding trailing closures 🚥 #1110
2 parents fb2826c + d51c92a commit d9c5f32

File tree

4 files changed

+67
-7
lines changed

4 files changed

+67
-7
lines changed

Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ let package = Package(
293293
"SKSwiftPMWorkspace",
294294
"SourceKitD",
295295
.product(name: "IndexStoreDB", package: "indexstore-db"),
296+
.product(name: "SwiftBasicFormat", package: "swift-syntax"),
296297
.product(name: "SwiftDiagnostics", package: "swift-syntax"),
297298
.product(name: "SwiftIDEUtils", package: "swift-syntax"),
298299
.product(name: "SwiftParser", package: "swift-syntax"),

Sources/SourceKitLSP/Swift/CodeCompletion.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Foundation
1414
import LSPLogging
1515
import LanguageServerProtocol
1616
import SourceKitD
17+
import SwiftBasicFormat
1718

1819
extension SwiftLanguageServer {
1920

@@ -43,10 +44,13 @@ extension SwiftLanguageServer {
4344
let clientSupportsSnippets =
4445
capabilityRegistry.clientCapabilities.textDocument?.completion?.completionItem?.snippetSupport ?? false
4546
let buildSettings = await buildSettings(for: snapshot.uri)
47+
48+
let inferredIndentationWidth = BasicFormat.inferIndentation(of: await syntaxTreeManager.syntaxTree(for: snapshot))
49+
4650
return try await CodeCompletionSession.completionList(
4751
sourcekitd: sourcekitd,
4852
snapshot: snapshot,
49-
syntaxTreeParseResult: syntaxTreeManager.incrementalParseResult(for: snapshot),
53+
indentationWidth: inferredIndentationWidth,
5054
completionPosition: completionPos,
5155
completionUtf8Offset: offset,
5256
cursorPosition: req.position,

Sources/SourceKitLSP/Swift/CodeCompletionSession.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class CodeCompletionSession {
9191
static func completionList(
9292
sourcekitd: any SourceKitD,
9393
snapshot: DocumentSnapshot,
94-
syntaxTreeParseResult: IncrementalParseResult,
94+
indentationWidth: Trivia?,
9595
completionPosition: Position,
9696
completionUtf8Offset: Int,
9797
cursorPosition: Position,
@@ -123,7 +123,7 @@ class CodeCompletionSession {
123123
let session = CodeCompletionSession(
124124
sourcekitd: sourcekitd,
125125
snapshot: snapshot,
126-
syntaxTreeParseResult: syntaxTreeParseResult,
126+
indentationWidth: indentationWidth,
127127
utf8Offset: completionUtf8Offset,
128128
position: completionPosition,
129129
compileCommand: compileCommand,
@@ -140,7 +140,8 @@ class CodeCompletionSession {
140140

141141
private let sourcekitd: any SourceKitD
142142
private let snapshot: DocumentSnapshot
143-
private let syntaxTreeParseResult: IncrementalParseResult
143+
/// The inferred indentation width of the source file the completion is being performed in
144+
private let indentationWidth: Trivia?
144145
private let utf8StartOffset: Int
145146
private let position: Position
146147
private let compileCommand: SwiftCompileCommand?
@@ -158,14 +159,14 @@ class CodeCompletionSession {
158159
private init(
159160
sourcekitd: any SourceKitD,
160161
snapshot: DocumentSnapshot,
161-
syntaxTreeParseResult: IncrementalParseResult,
162+
indentationWidth: Trivia?,
162163
utf8Offset: Int,
163164
position: Position,
164165
compileCommand: SwiftCompileCommand?,
165166
clientSupportsSnippets: Bool
166167
) {
167168
self.sourcekitd = sourcekitd
168-
self.syntaxTreeParseResult = syntaxTreeParseResult
169+
self.indentationWidth = indentationWidth
169170
self.snapshot = snapshot
170171
self.utf8StartOffset = utf8Offset
171172
self.position = position
@@ -308,7 +309,10 @@ class CodeCompletionSession {
308309
var parser = Parser(exprToExpand)
309310
let expr = ExprSyntax.parse(from: &parser)
310311
guard let call = OutermostFunctionCallFinder.findOutermostFunctionCall(in: expr),
311-
let expandedCall = ExpandEditorPlaceholdersToTrailingClosures.refactor(syntax: call)
312+
let expandedCall = ExpandEditorPlaceholdersToTrailingClosures.refactor(
313+
syntax: call,
314+
in: ExpandEditorPlaceholdersToTrailingClosures.Context(indentationWidth: indentationWidth)
315+
)
312316
else {
313317
return nil
314318
}

Tests/SourceKitLSPTests/SwiftCompletionTests.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,7 @@ final class SwiftCompletionTests: XCTestCase {
10251025
]
10261026
)
10271027
}
1028+
10281029
func testExpandClosurePlaceholderOnOptional() async throws {
10291030
let testClient = try await TestSourceKitLSPClient(capabilities: snippetCapabilities)
10301031
let uri = DocumentURI.for(.swift)
@@ -1176,6 +1177,56 @@ final class SwiftCompletionTests: XCTestCase {
11761177
]
11771178
)
11781179
}
1180+
1181+
func testInferIndentationWhenExpandingClosurePlaceholder() async throws {
1182+
let testClient = try await TestSourceKitLSPClient(capabilities: snippetCapabilities)
1183+
let uri = DocumentURI.for(.swift)
1184+
let positions = testClient.openDocument(
1185+
"""
1186+
struct MyArray {
1187+
func myMap(_ body: (Int) -> Bool) -> Int {
1188+
return 1
1189+
}
1190+
}
1191+
func test(x: MyArray) {
1192+
x.1️⃣
1193+
}
1194+
""",
1195+
uri: uri
1196+
)
1197+
let completions = try await testClient.send(
1198+
CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"])
1199+
)
1200+
XCTAssertEqual(
1201+
completions.items.filter { $0.label.contains("myMap") },
1202+
[
1203+
CompletionItem(
1204+
label: "myMap(body: (Int) -> Bool)",
1205+
kind: .method,
1206+
detail: "Int",
1207+
deprecated: false,
1208+
sortText: nil,
1209+
filterText: "myMap(:)",
1210+
insertText: """
1211+
myMap { ${1:Int} in
1212+
${2:Bool}
1213+
}
1214+
""",
1215+
insertTextFormat: .snippet,
1216+
textEdit: .textEdit(
1217+
TextEdit(
1218+
range: Range(positions["1️⃣"]),
1219+
newText: """
1220+
myMap { ${1:Int} in
1221+
${2:Bool}
1222+
}
1223+
"""
1224+
)
1225+
)
1226+
)
1227+
]
1228+
)
1229+
}
11791230
}
11801231

11811232
private func countFs(_ response: CompletionList) -> Int {

0 commit comments

Comments
 (0)