Skip to content

Commit c40a786

Browse files
authored
Merge pull request #1994 from ahoppen/active-document-refinements
A couple refinements to the `window/didChangeActiveDocument` notification
2 parents 004f066 + baa3b70 commit c40a786

File tree

4 files changed

+42
-18
lines changed

4 files changed

+42
-18
lines changed

Contributor Documentation/LSP Extensions.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ export interface DocumentTestsParams {
438438
439439
New notification from the client to the server, telling SourceKit-LSP which document is the currently active primary document.
440440
441+
This notification should only be called for documents that the editor has opened in SourceKit-LSP using the `textDocument/didOpen` notification.
442+
441443
By default, SourceKit-LSP infers the currently active editor document from the last document that received a request.
442444
If the client supports active reporting of the currently active document, it should check for the
443445
`window/didChangeActiveDocument` experimental server capability. If that capability is present, it should respond with
@@ -449,9 +451,12 @@ active document changes.
449451
```ts
450452
export interface DidChangeActiveDocumentParams {
451453
/**
452-
* The document that is being displayed in the active editor.
454+
* The document that is being displayed in the active editor or `null` to indicate that either no document is active
455+
* or that the currently open document is not handled by SourceKit-LSP.
453456
*/
454-
textDocument: TextDocumentIdentifier;
457+
textDocument?: TextDocumentIdentifier;
458+
}
459+
```
455460
456461
## `window/logMessage`
457462

Sources/LanguageServerProtocol/Notifications/DidChangeActiveDocumentNotification.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
public struct DidChangeActiveDocumentNotification: NotificationType {
1414
public static let method: String = "window/didChangeActiveDocument"
1515

16-
/// The document that is being displayed in the active editor.
17-
public var textDocument: TextDocumentIdentifier
16+
/// The document that is being displayed in the active editor or `null` to indicate that either no document is active
17+
/// or that the currently open document is not handled by SourceKit-LSP.
18+
public var textDocument: TextDocumentIdentifier?
1819

19-
public init(textDocument: TextDocumentIdentifier) {
20+
public init(textDocument: TextDocumentIdentifier?) {
2021
self.textDocument = textDocument
2122
}
2223
}

Sources/SemanticIndex/SemanticIndexManager.swift

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -471,15 +471,8 @@ package final actor SemanticIndexManager {
471471
}
472472
}
473473
}
474-
if let inProgressPrepareForEditorTask {
475-
// Cancel the in progress prepare for editor task to indicate that we are no longer interested in it.
476-
// This will cancel the preparation of `inProgressPrepareForEditorTask`'s target if it hasn't started yet.
477-
// (see comment at the end of `SemanticIndexManager.prepare`).
478-
logger.debug(
479-
"Marking preparation of \(inProgressPrepareForEditorTask.document) as no longer relevant because \(uri) was opened"
480-
)
481-
inProgressPrepareForEditorTask.task.cancel()
482-
}
474+
475+
markPreparationForEditorFunctionalityTaskAsIrrelevant()
483476
inProgressPrepareForEditorTask = InProgressPrepareForEditorTask(
484477
id: id,
485478
document: uri,
@@ -488,6 +481,18 @@ package final actor SemanticIndexManager {
488481
self.indexProgressStatusDidChange()
489482
}
490483

484+
/// If there is an in-progress prepare for editor task, cancel it to indicate that we are no longer interested in it.
485+
/// This will cancel the preparation of `inProgressPrepareForEditorTask`'s target if it hasn't started yet. If the
486+
/// preparation has already started, we don't cancel it to guarantee forward progress (see comment at the end of
487+
/// `SemanticIndexManager.prepare`).
488+
package func markPreparationForEditorFunctionalityTaskAsIrrelevant() {
489+
guard let inProgressPrepareForEditorTask else {
490+
return
491+
}
492+
logger.debug("Marking preparation of \(inProgressPrepareForEditorTask.document) as no longer relevant")
493+
inProgressPrepareForEditorTask.task.cancel()
494+
}
495+
491496
/// Prepare the target that the given file is in, building all modules that the file depends on. Returns when
492497
/// preparation has finished.
493498
///

Sources/SourceKitLSP/SourceKitLSPServer.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,8 +1278,8 @@ extension SourceKitLSPServer {
12781278
)
12791279
return
12801280
}
1281-
await self.clientInteractedWithDocument(uri)
12821281
await openDocument(notification, workspace: workspace)
1282+
await self.clientInteractedWithDocument(uri)
12831283
}
12841284

12851285
private func openDocument(_ notification: DidOpenTextDocumentNotification, workspace: Workspace) async {
@@ -1403,9 +1403,22 @@ extension SourceKitLSPServer {
14031403
}
14041404

14051405
func didChangeActiveDocument(_ notification: DidChangeActiveDocumentNotification) async {
1406-
let workspace = await self.workspaceForDocument(uri: notification.textDocument.uri)
1407-
await workspace?.semanticIndexManager?
1408-
.schedulePreparationForEditorFunctionality(of: notification.textDocument.uri)
1406+
guard let activeDocument = notification.textDocument?.uri else {
1407+
// The client no longer has a SourceKit-LSP document open. Mark in-progress preparations as irrelevant to cancel
1408+
// them if they haven't started yet.
1409+
for workspace in workspaces {
1410+
await workspace.semanticIndexManager?.markPreparationForEditorFunctionalityTaskAsIrrelevant()
1411+
}
1412+
return
1413+
}
1414+
let documentWorkspace = await self.workspaceForDocument(uri: activeDocument)
1415+
for workspace in workspaces {
1416+
if workspace === documentWorkspace {
1417+
await workspace.semanticIndexManager?.schedulePreparationForEditorFunctionality(of: activeDocument)
1418+
} else {
1419+
await workspace.semanticIndexManager?.markPreparationForEditorFunctionalityTaskAsIrrelevant()
1420+
}
1421+
}
14091422
}
14101423

14111424
func willSaveDocument(

0 commit comments

Comments
 (0)