Skip to content

Commit 7f59f6f

Browse files
authored
Merge pull request #1016 from ahoppen/ahoppen/ignore-trigger-from-incomplete-completions
Ignore `triggerFromIncompleteCompletions` when performing code completion
2 parents d55e2a2 + 53a07b3 commit 7f59f6f

File tree

3 files changed

+64
-32
lines changed

3 files changed

+64
-32
lines changed

Sources/SourceKitLSP/Swift/CodeCompletion.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ extension SwiftLanguageServer {
5555
compileCommand: buildSettings,
5656
options: options,
5757
clientSupportsSnippets: clientSupportsSnippets,
58-
filterText: filterText,
59-
mustReuse: req.context?.triggerKind == .triggerFromIncompleteCompletions
58+
filterText: filterText
6059
)
6160
}
6261

Sources/SourceKitLSP/Swift/CodeCompletionSession.swift

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,7 @@ class CodeCompletionSession {
9494
compileCommand: SwiftCompileCommand?,
9595
options: SKCompletionOptions,
9696
clientSupportsSnippets: Bool,
97-
filterText: String,
98-
mustReuse: Bool
97+
filterText: String
9998
) async throws -> CompletionList {
10099
let task = completionQueue.asyncThrowing {
101100
if let session = completionSessions[ObjectIdentifier(sourcekitd)], session.state == .open {
@@ -113,24 +112,10 @@ class CodeCompletionSession {
113112
)
114113
}
115114

116-
if mustReuse {
117-
logger.error(
118-
"""
119-
triggerFromIncompleteCompletions with incompatible completion session; expected \
120-
\(session.uri.forLogging)@\(session.utf8StartOffset), \
121-
but got \(snapshot.uri.forLogging)@\(completionUtf8Offset)
122-
"""
123-
)
124-
throw ResponseError.serverCancelled
125-
}
126115
// The sessions aren't compatible. Close the existing session and open
127116
// a new one below.
128117
await session.close()
129118
}
130-
if mustReuse {
131-
logger.error("triggerFromIncompleteCompletions with no existing completion session")
132-
throw ResponseError.serverCancelled
133-
}
134119
let session = CodeCompletionSession(
135120
sourcekitd: sourcekitd,
136121
snapshot: snapshot,

Tests/SourceKitLSPTests/SwiftCompletionTests.swift

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -602,18 +602,6 @@ final class SwiftCompletionTests: XCTestCase {
602602
)
603603
)
604604

605-
// Not valid for the current session.
606-
// We explicitly keep the session and fail any requests that don't match so that the editor
607-
// can rely on `.triggerFromIncompleteCompletions` always being fast.
608-
await assertThrowsError(
609-
try await testClient.send(
610-
CompletionRequest(
611-
textDocument: TextDocumentIdentifier(uri),
612-
position: Position(line: 7, utf16index: 0),
613-
context: CompletionContext(triggerKind: .triggerFromIncompleteCompletions)
614-
)
615-
)
616-
)
617605
assertEqual(
618606
1,
619607
countFs(
@@ -711,14 +699,15 @@ final class SwiftCompletionTests: XCTestCase {
711699
)
712700

713701
// 'fA '
714-
await assertThrowsError(
702+
assertEqual(
715703
try await testClient.send(
716704
CompletionRequest(
717705
textDocument: TextDocumentIdentifier(uri),
718706
position: Position(line: 7, utf16index: 12),
719707
context: CompletionContext(triggerKind: .triggerFromIncompleteCompletions)
720708
)
721-
)
709+
).items,
710+
[]
722711
)
723712

724713
testClient.send(
@@ -897,6 +886,65 @@ final class SwiftCompletionTests: XCTestCase {
897886
)
898887
}
899888

889+
func testTriggerFromIncompleteAfterStartingStringLiteral() async throws {
890+
let testClient = try await TestSourceKitLSPClient()
891+
let uri = DocumentURI.for(.swift)
892+
let positions = testClient.openDocument(
893+
"""
894+
func foo(_ x: String) {}
895+
896+
func test() {
897+
foo1️⃣
898+
}
899+
""",
900+
uri: uri
901+
)
902+
903+
// The following is a pattern that VS Code sends. Make sure we don't return an error.
904+
// - Insert `()``, changing the line to `foo()``
905+
// - Invoke code completion after `(`
906+
// - Insert `""`, changing the line to `foo("")`
907+
// - Insert `d` inside the string literal, changing the line to `foo("d")`
908+
// - Ask for completion with the `triggerFromIncompleteCompletions` flag set.
909+
// Since this isn't actually re-filtering but is a completely new code completion session. When we detect this, we
910+
// should just start a new session and return the results.
911+
var position = positions["1️⃣"]
912+
testClient.send(
913+
DidChangeTextDocumentNotification(
914+
textDocument: VersionedTextDocumentIdentifier(uri, version: position.utf16index),
915+
contentChanges: [TextDocumentContentChangeEvent(range: Range(position), text: "()")]
916+
)
917+
)
918+
position.utf16index += 1
919+
let initialCompletionResults = try await testClient.send(
920+
CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: position)
921+
)
922+
// Test that we get the "abc" result which makes VS Code think that we are still in the same completion session when doing hte second completion.
923+
XCTAssert(initialCompletionResults.items.contains(where: { $0.label == #""abc""# }))
924+
testClient.send(
925+
DidChangeTextDocumentNotification(
926+
textDocument: VersionedTextDocumentIdentifier(uri, version: position.utf16index),
927+
contentChanges: [TextDocumentContentChangeEvent(range: Range(position), text: "\"\"")]
928+
)
929+
)
930+
position.utf16index += 1
931+
testClient.send(
932+
DidChangeTextDocumentNotification(
933+
textDocument: VersionedTextDocumentIdentifier(uri, version: position.utf16index),
934+
contentChanges: [TextDocumentContentChangeEvent(range: Range(position), text: "d")]
935+
)
936+
)
937+
let secondCompletionResults = try await testClient.send(
938+
CompletionRequest(
939+
textDocument: TextDocumentIdentifier(uri),
940+
position: position,
941+
context: CompletionContext(triggerKind: .triggerFromIncompleteCompletions)
942+
)
943+
)
944+
// We shouldn't be getting code completion results for inside the string literal.
945+
XCTAssert(secondCompletionResults.items.isEmpty)
946+
}
947+
900948
}
901949

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

0 commit comments

Comments
 (0)