Skip to content

Commit 3be0342

Browse files
fix: SwiftLanguageService instead of ClangLanguageService
fix!: remove `documentManager` property fix!: remove `documentManager` in constructor fix: added documentManager as a computed Property fix: remove old documentmanager resetting step fix!: get throws instead of crashing server fix: throw ResponseError instead of NSError fix: adding try & orLog where necesary fix: refined orLog usage style: ran swift-format fix: document being opened twice fix(DocumentManager): remove unwanted comments lint: ran swift format
1 parent 607292a commit 3be0342

File tree

6 files changed

+70
-71
lines changed

6 files changed

+70
-71
lines changed

Sources/SourceKitLSP/Clang/ClangLanguageService.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import LanguageServerProtocolJSONRPC
1717
import SKCore
1818
import SKSupport
1919
import SwiftExtensions
20+
import SwiftSyntax
2021

2122
import struct TSCBasic.AbsolutePath
2223

@@ -443,7 +444,7 @@ extension ClangLanguageService {
443444

444445
// MARK: - Text synchronization
445446

446-
public func openDocument(_ notification: DidOpenTextDocumentNotification) async {
447+
public func openDocument(_ notification: DidOpenTextDocumentNotification, snapshot: DocumentSnapshot) async {
447448
openDocuments[notification.textDocument.uri] = notification.textDocument.language
448449
// Send clangd the build settings for the new file. We need to do this before
449450
// sending the open notification, so that the initial diagnostics already
@@ -459,7 +460,12 @@ extension ClangLanguageService {
459460

460461
func reopenDocument(_ notification: ReopenTextDocumentNotification) {}
461462

462-
public func changeDocument(_ notification: DidChangeTextDocumentNotification) {
463+
public func changeDocument(
464+
_ notification: DidChangeTextDocumentNotification,
465+
preEditSnapshot: DocumentSnapshot,
466+
postEditSnapshot: DocumentSnapshot,
467+
edits: [SourceEdit]
468+
) {
463469
clangd.send(notification)
464470
}
465471

Sources/SourceKitLSP/DocumentManager.swift

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -204,42 +204,6 @@ public final class DocumentManager: InMemoryDocumentManager, Sendable {
204204
}
205205
}
206206

207-
extension DocumentManager {
208-
209-
// MARK: - LSP notification handling
210-
211-
/// Convenience wrapper for `open(_:language:version:text:)` that logs on failure.
212-
@discardableResult
213-
func open(_ notification: DidOpenTextDocumentNotification) -> DocumentSnapshot? {
214-
let doc = notification.textDocument
215-
return orLog("failed to open document", level: .error) {
216-
try open(doc.uri, language: doc.language, version: doc.version, text: doc.text)
217-
}
218-
}
219-
220-
/// Convenience wrapper for `close(_:)` that logs on failure.
221-
func close(_ notification: DidCloseTextDocumentNotification) {
222-
orLog("failed to close document", level: .error) {
223-
try close(notification.textDocument.uri)
224-
}
225-
}
226-
227-
/// Convenience wrapper for `edit(_:newVersion:edits:updateDocumentTokens:)`
228-
/// that logs on failure.
229-
@discardableResult
230-
func edit(
231-
_ notification: DidChangeTextDocumentNotification
232-
) -> (preEditSnapshot: DocumentSnapshot, postEditSnapshot: DocumentSnapshot, edits: [SourceEdit])? {
233-
return orLog("failed to edit document", level: .error) {
234-
return try edit(
235-
notification.textDocument.uri,
236-
newVersion: notification.textDocument.version,
237-
edits: notification.contentChanges
238-
)
239-
}
240-
}
241-
}
242-
243207
fileprivate extension SourceEdit {
244208
/// Constructs a `SourceEdit` from the given `TextDocumentContentChangeEvent`.
245209
///

Sources/SourceKitLSP/LanguageService.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import Foundation
1414
import LanguageServerProtocol
1515
import SKCore
16+
import SwiftSyntax
1617

1718
/// The state of a `ToolchainLanguageServer`
1819
public enum LanguageServerState {
@@ -124,9 +125,9 @@ public protocol LanguageService: AnyObject, Sendable {
124125
// MARK: - Text synchronization
125126

126127
/// Sent to open up a document on the Language Server.
127-
/// This may be called before or after a corresponding
128-
/// `documentUpdatedBuildSettings` call for the same document.
129-
func openDocument(_ notification: DidOpenTextDocumentNotification) async
128+
///
129+
/// This may be called before or after a corresponding `documentUpdatedBuildSettings` call for the same document.
130+
func openDocument(_ notification: DidOpenTextDocumentNotification, snapshot: DocumentSnapshot) async
130131

131132
/// Sent to close a document on the Language Server.
132133
func closeDocument(_ notification: DidCloseTextDocumentNotification) async
@@ -138,7 +139,12 @@ public protocol LanguageService: AnyObject, Sendable {
138139
/// Only intended for `SwiftLanguageService`.
139140
func reopenDocument(_ notification: ReopenTextDocumentNotification) async
140141

141-
func changeDocument(_ notification: DidChangeTextDocumentNotification) async
142+
func changeDocument(
143+
_ notification: DidChangeTextDocumentNotification,
144+
preEditSnapshot: DocumentSnapshot,
145+
postEditSnapshot: DocumentSnapshot,
146+
edits: [SourceEdit]
147+
) async
142148
func willSaveDocument(_ notification: WillSaveTextDocumentNotification) async
143149
func didSaveDocument(_ notification: DidSaveTextDocumentNotification) async
144150

Sources/SourceKitLSP/Rename.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ extension SwiftLanguageService {
345345
in uri: DocumentURI,
346346
name: CompoundDeclName
347347
) async throws -> String {
348-
guard let snapshot = documentManager.latestSnapshotOrDisk(uri, language: .swift) else {
348+
guard let snapshot = try? documentManager.latestSnapshotOrDisk(uri, language: .swift) else {
349349
throw ResponseError.unknown("Failed to get contents of \(uri.forLogging) to translate Swift name to clang name")
350350
}
351351

Sources/SourceKitLSP/SourceKitLSPServer.swift

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,7 +1272,18 @@ extension SourceKitLSPServer {
12721272
private func openDocument(_ notification: DidOpenTextDocumentNotification, workspace: Workspace) async {
12731273
// Immediately open the document even if the build system isn't ready. This is important since
12741274
// we check that the document is open when we receive messages from the build system.
1275-
documentManager.open(notification)
1275+
let snapshot = orLog("Opening document") {
1276+
try documentManager.open(
1277+
notification.textDocument.uri,
1278+
language: notification.textDocument.language,
1279+
version: notification.textDocument.version,
1280+
text: notification.textDocument.text
1281+
)
1282+
}
1283+
guard let snapshot else {
1284+
// Already logged failure
1285+
return
1286+
}
12761287

12771288
let textDocument = notification.textDocument
12781289
let uri = textDocument.uri
@@ -1286,7 +1297,7 @@ extension SourceKitLSPServer {
12861297
await workspace.buildSystemManager.registerForChangeNotifications(for: uri, language: language)
12871298

12881299
// If the document is ready, we can immediately send the notification.
1289-
await service.openDocument(notification)
1300+
await service.openDocument(notification, snapshot: snapshot)
12901301
}
12911302

12921303
func closeDocument(_ notification: DidCloseTextDocumentNotification) async {
@@ -1314,7 +1325,9 @@ extension SourceKitLSPServer {
13141325
func closeDocument(_ notification: DidCloseTextDocumentNotification, workspace: Workspace) async {
13151326
// Immediately close the document. We need to be sure to clear our pending work queue in case
13161327
// the build system still isn't ready.
1317-
documentManager.close(notification)
1328+
orLog("failed to close document", level: .error) {
1329+
try documentManager.close(notification.textDocument.uri)
1330+
}
13181331

13191332
let uri = notification.textDocument.uri
13201333

@@ -1335,8 +1348,23 @@ extension SourceKitLSPServer {
13351348
await workspace.semanticIndexManager?.schedulePreparationForEditorFunctionality(of: uri)
13361349

13371350
// If the document is ready, we can handle the change right now.
1338-
documentManager.edit(notification)
1339-
await workspace.documentService.value[uri]?.changeDocument(notification)
1351+
let editResult = orLog("Editing document") {
1352+
try documentManager.edit(
1353+
notification.textDocument.uri,
1354+
newVersion: notification.textDocument.version,
1355+
edits: notification.contentChanges
1356+
)
1357+
}
1358+
guard let (preEditSnapshot, postEditSnapshot, edits) = editResult else {
1359+
// Already logged failure
1360+
return
1361+
}
1362+
await workspace.documentService.value[uri]?.changeDocument(
1363+
notification,
1364+
preEditSnapshot: preEditSnapshot,
1365+
postEditSnapshot: postEditSnapshot,
1366+
edits: edits
1367+
)
13401368
}
13411369

13421370
func willSaveDocument(

Sources/SourceKitLSP/Swift/SwiftLanguageService.swift

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public struct SwiftCompileCommand: Sendable, Equatable {
9393
}
9494

9595
public actor SwiftLanguageService: LanguageService, Sendable {
96-
/// The ``SourceKitLSPServer`` instance that created this `ClangLanguageService`.
96+
/// The ``SourceKitLSPServer`` instance that created this `SwiftLanguageService`.
9797
weak var sourceKitLSPServer: SourceKitLSPServer?
9898

9999
let sourcekitd: SourceKitD
@@ -121,9 +121,6 @@ public actor SwiftLanguageService: LanguageService, Sendable {
121121
options.generatedFilesAbsolutePath.asURL.appendingPathComponent("GeneratedMacroExpansions")
122122
}
123123

124-
// FIXME: ideally we wouldn't need separate management from a parent server in the same process.
125-
var documentManager: DocumentManager
126-
127124
/// For each edited document, the last task that was triggered to send a `PublishDiagnosticsNotification`.
128125
///
129126
/// This is used to cancel previous publish diagnostics tasks if an edit is made to a document.
@@ -148,6 +145,15 @@ public actor SwiftLanguageService: LanguageService, Sendable {
148145

149146
private var diagnosticReportManager: DiagnosticReportManager!
150147

148+
var documentManager: DocumentManager {
149+
get throws {
150+
guard let sourceKitLSPServer = self.sourceKitLSPServer else {
151+
throw ResponseError.unknown("Connection to the editor closed")
152+
}
153+
return sourceKitLSPServer.documentManager
154+
}
155+
}
156+
151157
/// Calling `scheduleCall` on `refreshDiagnosticsDebouncer` schedules a `DiagnosticsRefreshRequest` to be sent to
152158
/// to the client.
153159
///
@@ -183,7 +189,6 @@ public actor SwiftLanguageService: LanguageService, Sendable {
183189
self.capabilityRegistry = workspace.capabilityRegistry
184190
self.semanticIndexManager = workspace.semanticIndexManager
185191
self.testHooks = testHooks
186-
self.documentManager = DocumentManager()
187192
self.state = .connected
188193
self.diagnosticReportManager = nil // Needed to work around rdar://116221716
189194
self.options = options
@@ -203,7 +208,7 @@ public actor SwiftLanguageService: LanguageService, Sendable {
203208
sourcekitd: self.sourcekitd,
204209
options: options,
205210
syntaxTreeManager: syntaxTreeManager,
206-
documentManager: documentManager,
211+
documentManager: try documentManager,
207212
clientHasDiagnosticsCodeDescriptionSupport: await self.clientHasDiagnosticsCodeDescriptionSupport
208213
)
209214

@@ -439,15 +444,10 @@ extension SwiftLanguageService {
439444
])
440445
}
441446

442-
public func openDocument(_ notification: DidOpenTextDocumentNotification) async {
447+
public func openDocument(_ notification: DidOpenTextDocumentNotification, snapshot: DocumentSnapshot) async {
443448
cancelInFlightPublishDiagnosticsTask(for: notification.textDocument.uri)
444449
await diagnosticReportManager.removeItemsFromCache(with: notification.textDocument.uri)
445450

446-
guard let snapshot = self.documentManager.open(notification) else {
447-
// Already logged failure.
448-
return
449-
}
450-
451451
let buildSettings = await self.buildSettings(for: snapshot.uri)
452452

453453
let req = openDocumentSourcekitdRequest(snapshot: snapshot, compileCommand: buildSettings)
@@ -460,8 +460,6 @@ extension SwiftLanguageService {
460460
inFlightPublishDiagnosticsTasks[notification.textDocument.uri] = nil
461461
await diagnosticReportManager.removeItemsFromCache(with: notification.textDocument.uri)
462462

463-
self.documentManager.close(notification)
464-
465463
let req = closeDocumentSourcekitdRequest(uri: notification.textDocument.uri)
466464
_ = try? await self.sendSourcekitdRequest(req, fileContents: nil)
467465
}
@@ -542,7 +540,12 @@ extension SwiftLanguageService {
542540
}
543541
}
544542

545-
public func changeDocument(_ notification: DidChangeTextDocumentNotification) async {
543+
public func changeDocument(
544+
_ notification: DidChangeTextDocumentNotification,
545+
preEditSnapshot: DocumentSnapshot,
546+
postEditSnapshot: DocumentSnapshot,
547+
edits: [SourceEdit]
548+
) async {
546549
cancelInFlightPublishDiagnosticsTask(for: notification.textDocument.uri)
547550

548551
let keys = self.keys
@@ -552,10 +555,6 @@ extension SwiftLanguageService {
552555
let replacement: String
553556
}
554557

555-
guard let (preEditSnapshot, postEditSnapshot, edits) = self.documentManager.edit(notification) else {
556-
return
557-
}
558-
559558
for edit in edits {
560559
let req = sourcekitd.dictionary([
561560
keys.request: self.requests.editorReplaceText,
@@ -1006,10 +1005,6 @@ extension SwiftLanguageService: SKDNotificationHandler {
10061005

10071006
if notification.error == .connectionInterrupted {
10081007
await self.setState(.connectionInterrupted)
1009-
1010-
// We don't have any open documents anymore after sourcekitd crashed.
1011-
// Reset the document manager to reflect that.
1012-
self.documentManager = DocumentManager()
10131008
}
10141009
}
10151010
}

0 commit comments

Comments
 (0)