Skip to content

Commit a4d687f

Browse files
committed
Update the document after cancelling the completion request to unblock sourcekitd
1 parent cd2faf1 commit a4d687f

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

Sources/SourceKitLSP/Swift/SwiftLanguageServer.swift

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -383,12 +383,16 @@ extension SwiftLanguageServer {
383383
// Sleep for a little bit until triggering the diagnostic generation. This effectively de-bounces diagnostic
384384
// generation since any later edit will cancel the previous in-flight task, which will thus never go on to send
385385
// the `DocumentDiagnosticsRequest`.
386-
try await Task.sleep(nanoseconds: UInt64(sourceKitServer.options.swiftPublishDiagnosticsDebounceDuration * 1_000_000_000))
386+
try await Task.sleep(
387+
nanoseconds: UInt64(sourceKitServer.options.swiftPublishDiagnosticsDebounceDuration * 1_000_000_000)
388+
)
387389
} catch {
388390
return
389391
}
390392
do {
391-
let diagnosticReport = try await self.fullDocumentDiagnosticReport(DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(document)))
393+
let diagnosticReport = try await self.fullDocumentDiagnosticReport(
394+
DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(document))
395+
)
392396

393397
await sourceKitServer.sendNotificationToClient(
394398
PublishDiagnosticsNotification(
@@ -397,10 +401,16 @@ extension SwiftLanguageServer {
397401
)
398402
)
399403
} catch {
400-
logger.fault("""
401-
Failed to get diagnostics
402-
\(error.forLogging)
403-
""")
404+
if error as? ResponseError == ResponseError.cancelled {
405+
logger.info("Cancelled diagnostics request")
406+
} else {
407+
logger.fault(
408+
"""
409+
Failed to get diagnostics
410+
\(error.forLogging)
411+
"""
412+
)
413+
}
404414
}
405415
}
406416
}
@@ -1171,7 +1181,9 @@ extension SwiftLanguageServer {
11711181
return try await .full(fullDocumentDiagnosticReport(req))
11721182
}
11731183

1174-
private func fullDocumentDiagnosticReport(_ req: DocumentDiagnosticsRequest) async throws -> RelatedFullDocumentDiagnosticReport {
1184+
private func fullDocumentDiagnosticReport(
1185+
_ req: DocumentDiagnosticsRequest
1186+
) async throws -> RelatedFullDocumentDiagnosticReport {
11751187
guard let snapshot = documentManager.latestSnapshot(req.textDocument.uri) else {
11761188
throw ResponseError.unknown("failed to find snapshot for url \(req.textDocument.uri.forLogging)")
11771189
}

Tests/SourceKitLSPTests/SourceKitTests.swift

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -424,15 +424,15 @@ final class SKTests: XCTestCase {
424424
"""
425425
class Foo {
426426
func slow(x: Invalid1, y: Invalid2) {
427-
x / y / x / y / x / y / x / y . 1️⃣
427+
1️⃣ x / y / x / y / x / y / x / y . 2️⃣
428428
}
429429
430430
struct Foo {
431-
let fooMember: String
431+
let 3️⃣fooMember: String
432432
}
433433
434434
func fast(a: Foo) {
435-
a.2️⃣
435+
a.4️⃣
436436
}
437437
}
438438
""",
@@ -443,7 +443,7 @@ final class SKTests: XCTestCase {
443443

444444
let requestID = RequestID.string("cancellation-test")
445445
testClient.server.handle(
446-
CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"]),
446+
CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["2️⃣"]),
447447
id: requestID,
448448
from: ObjectIdentifier(self)
449449
) { reply in
@@ -461,9 +461,26 @@ final class SKTests: XCTestCase {
461461

462462
let fastStartDate = Date()
463463
let fastReply = try await testClient.send(
464-
CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["2️⃣"])
464+
CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["4️⃣"])
465465
)
466466
XCTAssert(!fastReply.items.isEmpty)
467467
XCTAssertLessThan(Date().timeIntervalSince(fastStartDate), 2, "Fast request wasn't actually fast")
468+
469+
// Remove the slow-to-typecheck line. This causes the implicit diagnostics request for the push diagnostics
470+
// notification to get cancelled, which unblocks sourcekitd for later tests.
471+
testClient.send(
472+
DidChangeTextDocumentNotification(
473+
textDocument: VersionedTextDocumentIdentifier(uri, version: 2),
474+
contentChanges: [
475+
TextDocumentContentChangeEvent(range: positions["1️⃣"]..<positions["2️⃣"], text: "")
476+
]
477+
)
478+
)
479+
480+
// Check that semantic functionality based on the AST is working again.
481+
let symbolInfo = try await testClient.send(
482+
SymbolInfoRequest(textDocument: TextDocumentIdentifier(uri), position: positions["3️⃣"])
483+
)
484+
XCTAssertGreaterThan(symbolInfo.count, 0)
468485
}
469486
}

0 commit comments

Comments
 (0)