From 8cde497a29aa58e28bef4aa07e6bc6558aebb342 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:31:36 -0500 Subject: [PATCH 1/4] Adjust LSP Document Lifetimes --- .../Features/Editor/Views/CodeFileView.swift | 17 ++------ .../DocumentSync/LSPContentCoordinator.swift | 12 ++++-- .../SemanticTokenHighlightProvider.swift | 23 ++++++++--- .../LanguageServer+DocumentSync.swift | 8 ++-- .../LSP/LanguageServer/LanguageServer.swift | 20 +++++++--- .../LanguageServerFileMap.swift | 39 +------------------ .../Features/LSP/LanguageServerDocument.swift | 11 +++++- 7 files changed, 56 insertions(+), 74 deletions(-) diff --git a/CodeEdit/Features/Editor/Views/CodeFileView.swift b/CodeEdit/Features/Editor/Views/CodeFileView.swift index 6320a61272..2aa04497b6 100644 --- a/CodeEdit/Features/Editor/Views/CodeFileView.swift +++ b/CodeEdit/Features/Editor/Views/CodeFileView.swift @@ -21,8 +21,7 @@ struct CodeFileView: View { /// Any coordinators passed to the view. private var textViewCoordinators: [TextViewCoordinator] - - @State private var highlightProviders: [any HighlightProviding] = [] + private var highlightProviders: [any HighlightProviding] = [] @AppSettings(\.textEditing.defaultTabWidth) var defaultTabWidth @@ -86,7 +85,7 @@ struct CodeFileView: View { self.textViewCoordinators = textViewCoordinators + [editorInstance.rangeTranslator] + [codeFile.contentCoordinator] - + [codeFile.languageServerObjects.textCoordinator].compactMap({ $0 }) + + [codeFile.languageServerObjects.textCoordinator] self.isEditable = isEditable if let openOptions = codeFile.openOptions { @@ -94,7 +93,7 @@ struct CodeFileView: View { editorInstance.cursorPositions = openOptions.cursorPositions } - updateHighlightProviders() + highlightProviders = [codeFile.languageServerObjects.highlightProvider] + [treeSitterClient] codeFile .contentCoordinator @@ -186,10 +185,6 @@ struct CodeFileView: View { .onChange(of: settingsFont) { newFontSetting in font = newFontSetting.current } - .onReceive(codeFile.$languageServerObjects) { languageServerObjects in - // This will not be called in single-file views (for now) but is safe to listen to either way - updateHighlightProviders(lspHighlightProvider: languageServerObjects.highlightProvider) - } } /// Determines the style of bracket emphasis based on the `bracketEmphasis` setting and the current theme. @@ -212,12 +207,6 @@ struct CodeFileView: View { return .underline(color: color) } } - - /// Updates the highlight providers array. - /// - Parameter lspHighlightProvider: The language server provider, if available. - private func updateHighlightProviders(lspHighlightProvider: HighlightProviding? = nil) { - highlightProviders = [lspHighlightProvider].compactMap({ $0 }) + [treeSitterClient] - } } // This extension is kept here because it should not be used elsewhere in the app and may cause confusion diff --git a/CodeEdit/Features/LSP/Features/DocumentSync/LSPContentCoordinator.swift b/CodeEdit/Features/LSP/Features/DocumentSync/LSPContentCoordinator.swift index aed2a7adae..537d3b201b 100644 --- a/CodeEdit/Features/LSP/Features/DocumentSync/LSPContentCoordinator.swift +++ b/CodeEdit/Features/LSP/Features/DocumentSync/LSPContentCoordinator.swift @@ -32,16 +32,22 @@ class LSPContentCoordinator: TextViewCoord private var task: Task? weak var languageServer: LanguageServer? - var documentURI: String + var documentURI: String? /// Initializes a content coordinator, and begins an async stream of updates - init(documentURI: String, languageServer: LanguageServer) { + init(documentURI: String? = nil, languageServer: LanguageServer? = nil) { self.documentURI = documentURI self.languageServer = languageServer setUpUpdatesTask() } + func setUp(server: LanguageServer, document: DocumentType) { + languageServer = server + documentURI = document.languageServerURI + } + + func setUpUpdatesTask() { task?.cancel() // Create this stream here so it's always set up when the text view is set up, rather than only once on init. @@ -76,7 +82,7 @@ class LSPContentCoordinator: TextViewCoord } func textView(_ textView: TextView, didReplaceContentsIn range: NSRange, with string: String) { - guard let lspRange = editedRange else { + guard let lspRange = editedRange, let documentURI else { return } self.editedRange = nil diff --git a/CodeEdit/Features/LSP/Features/SemanticTokens/SemanticTokenHighlightProvider.swift b/CodeEdit/Features/LSP/Features/SemanticTokens/SemanticTokenHighlightProvider.swift index e74d51deaf..527e96b7fc 100644 --- a/CodeEdit/Features/LSP/Features/SemanticTokens/SemanticTokenHighlightProvider.swift +++ b/CodeEdit/Features/LSP/Features/SemanticTokens/SemanticTokenHighlightProvider.swift @@ -32,8 +32,8 @@ final class SemanticTokenHighlightProvider< typealias EditCallback = @MainActor (Result) -> Void typealias HighlightCallback = @MainActor (Result<[HighlightRange], any Error>) -> Void - private let tokenMap: SemanticTokenMap - private let documentURI: String + private var tokenMap: SemanticTokenMap? + private var documentURI: String? private weak var languageServer: LanguageServer? private weak var textView: TextView? @@ -45,13 +45,23 @@ final class SemanticTokenHighlightProvider< textView?.documentRange ?? .zero } - init(tokenMap: SemanticTokenMap, languageServer: LanguageServer, documentURI: String) { + init( + tokenMap: SemanticTokenMap? = nil, + languageServer: LanguageServer? = nil, + documentURI: String? = nil + ) { self.tokenMap = tokenMap self.languageServer = languageServer self.documentURI = documentURI self.storage = Storage() } + func setUp(server: LanguageServer, document: DocumentType) { + languageServer = server + documentURI = document.languageServerURI + tokenMap = server.highlightMap + } + // MARK: - Language Server Content Lifecycle /// Called when the language server finishes sending a document update. @@ -95,7 +105,8 @@ final class SemanticTokenHighlightProvider< textView: TextView, lastResultId: String ) async throws { - guard let response = try await languageServer.requestSemanticTokens( + guard let documentURI, + let response = try await languageServer.requestSemanticTokens( for: documentURI, previousResultId: lastResultId ) else { @@ -112,7 +123,7 @@ final class SemanticTokenHighlightProvider< /// Requests and applies tokens for an entire document. This does not require a previous response id, and should be /// used in place of `requestDeltaTokens` when that's the case. private func requestTokens(languageServer: LanguageServer, textView: TextView) async throws { - guard let response = try await languageServer.requestSemanticTokens(for: documentURI) else { + guard let documentURI, let response = try await languageServer.requestSemanticTokens(for: documentURI) else { return } await applyEntireResponse(response, callback: lastEditCallback) @@ -159,7 +170,7 @@ final class SemanticTokenHighlightProvider< return } - guard let lspRange = textView.lspRangeFrom(nsRange: range) else { + guard let lspRange = textView.lspRangeFrom(nsRange: range), let tokenMap else { completion(.failure(HighlightError.lspRangeFailure)) return } diff --git a/CodeEdit/Features/LSP/LanguageServer/Capabilities/LanguageServer+DocumentSync.swift b/CodeEdit/Features/LSP/LanguageServer/Capabilities/LanguageServer+DocumentSync.swift index be69c6647c..2c30e6935f 100644 --- a/CodeEdit/Features/LSP/LanguageServer/Capabilities/LanguageServer+DocumentSync.swift +++ b/CodeEdit/Features/LSP/LanguageServer/Capabilities/LanguageServer+DocumentSync.swift @@ -86,6 +86,7 @@ extension LanguageServer { switch resolveDocumentSyncKind() { case .full: guard let content = await getIsolatedDocumentContent(document) else { + logger.error("Failed to get isolated document content") return } let changeEvent = TextDocumentContentChangeEvent(range: nil, rangeLength: nil, text: content.string) @@ -107,7 +108,7 @@ extension LanguageServer { // Let the semantic token provider know about the update. // Note for future: If a related LSP object need notifying about document changes, do it here. - try await document.languageServerObjects.highlightProvider?.documentDidChange() + try await document.languageServerObjects.highlightProvider.documentDidChange() } catch { logger.warning("closeDocument: Error \(error)") throw error @@ -128,10 +129,7 @@ extension LanguageServer { @MainActor private func updateIsolatedDocument(_ document: DocumentType) { - document.languageServerObjects = LanguageServerDocumentObjects( - textCoordinator: openFiles.contentCoordinator(for: document), - highlightProvider: openFiles.semanticHighlighter(for: document) - ) + document.languageServerObjects.setUp(server: self, document: document) } @MainActor diff --git a/CodeEdit/Features/LSP/LanguageServer/LanguageServer.swift b/CodeEdit/Features/LSP/LanguageServer/LanguageServer.swift index 266cbbf6a0..d1c87f0eeb 100644 --- a/CodeEdit/Features/LSP/LanguageServer/LanguageServer.swift +++ b/CodeEdit/Features/LSP/LanguageServer/LanguageServer.swift @@ -51,7 +51,8 @@ class LanguageServer { lspInstance: InitializingServer, lspPid: pid_t, serverCapabilities: ServerCapabilities, - rootPath: URL + rootPath: URL, + logContainer: LanguageServerLogContainer ) { self.languageId = languageId self.binary = binary @@ -60,7 +61,7 @@ class LanguageServer { self.serverCapabilities = serverCapabilities self.rootPath = rootPath self.openFiles = LanguageServerFileMap() - self.logContainer = LanguageServerLogContainer(language: languageId) + self.logContainer = logContainer self.logger = Logger( subsystem: Bundle.main.bundleIdentifier ?? "", category: "LanguageServer.\(languageId.rawValue)" @@ -89,9 +90,11 @@ class LanguageServer { environment: binary.env ) + let logContainer = LanguageServerLogContainer(language: languageId) let (connection, process) = try makeLocalServerConnection( languageId: languageId, - executionParams: executionParams + executionParams: executionParams, + logContainer: logContainer ) let server = InitializingServer( server: connection, @@ -105,7 +108,8 @@ class LanguageServer { lspInstance: server, lspPid: process.processIdentifier, serverCapabilities: initializationResponse.capabilities, - rootPath: URL(filePath: workspacePath) + rootPath: URL(filePath: workspacePath), + logContainer: logContainer ) } @@ -118,13 +122,17 @@ class LanguageServer { /// - Returns: A new connection to the language server. static func makeLocalServerConnection( languageId: LanguageIdentifier, - executionParams: Process.ExecutionParameters + executionParams: Process.ExecutionParameters, + logContainer: LanguageServerLogContainer ) throws -> (connection: JSONRPCServerConnection, process: Process) { do { let (channel, process) = try DataChannel.localProcessChannel( parameters: executionParams, - terminationHandler: { + terminationHandler: { [weak logContainer] in logger.debug("Terminated data channel for \(languageId.rawValue)") + logContainer?.appendLog( + LogMessageParams(type: .error, message: "Data Channel Terminated Unexpectedly") + ) } ) return (JSONRPCServerConnection(dataChannel: channel), process) diff --git a/CodeEdit/Features/LSP/LanguageServer/LanguageServerFileMap.swift b/CodeEdit/Features/LSP/LanguageServer/LanguageServerFileMap.swift index fd71a06b7a..ac218acc20 100644 --- a/CodeEdit/Features/LSP/LanguageServer/LanguageServerFileMap.swift +++ b/CodeEdit/Features/LSP/LanguageServer/LanguageServerFileMap.swift @@ -16,8 +16,6 @@ class LanguageServerFileMap { private struct DocumentObject { let uri: String var documentVersion: Int - var contentCoordinator: LSPContentCoordinator - var semanticHighlighter: HighlightProviderType? } private var trackedDocuments: NSMapTable @@ -32,24 +30,7 @@ class LanguageServerFileMap { func addDocument(_ document: DocumentType, for server: LanguageServer) { guard let uri = document.languageServerURI else { return } trackedDocuments.setObject(document, forKey: uri as NSString) - var docData = DocumentObject( - uri: uri, - documentVersion: 0, - contentCoordinator: LSPContentCoordinator( - documentURI: uri, - languageServer: server - ), - semanticHighlighter: nil - ) - - if let tokenMap = server.highlightMap { - docData.semanticHighlighter = HighlightProviderType( - tokenMap: tokenMap, - languageServer: server, - documentURI: uri - ) - } - + let docData = DocumentObject(uri: uri, documentVersion: 0) trackedDocumentData[uri] = docData } @@ -87,22 +68,4 @@ class LanguageServerFileMap { func documentVersion(for uri: DocumentUri) -> Int? { return trackedDocumentData[uri]?.documentVersion } - - // MARK: - Content Coordinator - - func contentCoordinator(for document: DocumentType) -> LSPContentCoordinator? { - guard let uri = document.languageServerURI else { return nil } - return contentCoordinator(for: uri) - } - - func contentCoordinator(for uri: DocumentUri) -> LSPContentCoordinator? { - trackedDocumentData[uri]?.contentCoordinator - } - - // MARK: - Semantic Highlighter - - func semanticHighlighter(for document: DocumentType) -> HighlightProviderType? { - guard let uri = document.languageServerURI else { return nil } - return trackedDocumentData[uri]?.semanticHighlighter - } } diff --git a/CodeEdit/Features/LSP/LanguageServerDocument.swift b/CodeEdit/Features/LSP/LanguageServerDocument.swift index 8b4b09a47d..2953d08fc2 100644 --- a/CodeEdit/Features/LSP/LanguageServerDocument.swift +++ b/CodeEdit/Features/LSP/LanguageServerDocument.swift @@ -10,8 +10,15 @@ import CodeEditLanguages /// A set of properties a language server sets when a document is registered. struct LanguageServerDocumentObjects { - var textCoordinator: LSPContentCoordinator? - var highlightProvider: SemanticTokenHighlightProvider? + var textCoordinator: LSPContentCoordinator = LSPContentCoordinator() + // swiftlint:disable:next line_length + var highlightProvider: SemanticTokenHighlightProvider = SemanticTokenHighlightProvider() + + @MainActor + func setUp(server: LanguageServer, document: DocumentType) { + textCoordinator.setUp(server: server, document: document) + highlightProvider.setUp(server: server, document: document) + } } /// A protocol that allows a language server to register objects on a text document. From 492e61b3ceeb131d3a73636d5d619093d78d3503 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:34:11 -0500 Subject: [PATCH 2/4] Update CESE to v0.15.0 --- CodeEdit.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 28 +++++++++---------- .../StatusBarCursorPositionLabel.swift | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index 9bccd362c1..233f378ef3 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -1783,7 +1783,7 @@ repositoryURL = "https://github.com/CodeEditApp/CodeEditSourceEditor"; requirement = { kind = exactVersion; - version = 0.14.1; + version = 0.15.0; }; }; 6C85BB3E2C2105ED00EB5DEF /* XCRemoteSwiftPackageReference "CodeEditKit" */ = { diff --git a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 738864f7f4..32dd4e6728 100644 --- a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "ed7a5ce46da2e530a4b8ff23058a67ef7423fa2378b9588d66359f210b6365cb", + "originHash" : "01191ca9685501db65981a6fd21ab2d11c32196633d4cb776b5bb25908ed212f", "pins" : [ { "identity" : "aboutwindow", @@ -40,10 +40,10 @@ { "identity" : "codeeditsourceeditor", "kind" : "remoteSourceControl", - "location" : "https://github.com/CodeEditApp/CodeEditSourceEditor.git", + "location" : "https://github.com/CodeEditApp/CodeEditSourceEditor", "state" : { - "revision" : "afc57523b05c209496a221655c2171c0624b51d3", - "version" : "0.14.1" + "revision" : "c0d2c90aecca04ce2be2ff29c39a3add5951b539", + "version" : "0.15.0" } }, { @@ -60,8 +60,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/CodeEditApp/CodeEditTextView.git", "state" : { - "revision" : "d65c2a4b23a52f69d0b3a113124d7434c7af07fa", - "version" : "0.11.6" + "revision" : "d7ac3f11f22ec2e820187acce8f3a3fb7aa8ddec", + "version" : "0.12.1" } }, { @@ -290,21 +290,21 @@ } }, { - "identity" : "zipfoundation", + "identity" : "welcomewindow", "kind" : "remoteSourceControl", - "location" : "https://github.com/weichsel/ZIPFoundation", + "location" : "https://github.com/CodeEditApp/WelcomeWindow", "state" : { - "revision" : "02b6abe5f6eef7e3cbd5f247c5cc24e246efcfe0", - "version" : "0.9.19" + "revision" : "5168cf1ce9579b35ad00706fafef441418d8011f", + "version" : "1.0.0" } }, { - "identity" : "welcomewindow", + "identity" : "zipfoundation", "kind" : "remoteSourceControl", - "location" : "https://github.com/CodeEditApp/WelcomeWindow", + "location" : "https://github.com/weichsel/ZIPFoundation", "state" : { - "revision" : "5168cf1ce9579b35ad00706fafef441418d8011f", - "version" : "1.0.0" + "revision" : "02b6abe5f6eef7e3cbd5f247c5cc24e246efcfe0", + "version" : "0.9.19" } } ], diff --git a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarCursorPositionLabel.swift b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarCursorPositionLabel.swift index bdead53a57..6939fca4ec 100644 --- a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarCursorPositionLabel.swift +++ b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarCursorPositionLabel.swift @@ -115,7 +115,7 @@ struct StatusBarCursorPositionLabel: View { } // When there's a single cursor, display the line and column. - return "Line: \(cursorPositions[0].line) Col: \(cursorPositions[0].column)" + return "Line: \(cursorPositions[0].start.line) Col: \(cursorPositions[0].start.column)" } } } From 987ef9c790635dacbd75f4c8b825ff34f91b7788 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:34:33 -0500 Subject: [PATCH 3/4] fix:lint --- .../LSP/Features/DocumentSync/LSPContentCoordinator.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/CodeEdit/Features/LSP/Features/DocumentSync/LSPContentCoordinator.swift b/CodeEdit/Features/LSP/Features/DocumentSync/LSPContentCoordinator.swift index 537d3b201b..b2c2e75b7c 100644 --- a/CodeEdit/Features/LSP/Features/DocumentSync/LSPContentCoordinator.swift +++ b/CodeEdit/Features/LSP/Features/DocumentSync/LSPContentCoordinator.swift @@ -47,7 +47,6 @@ class LSPContentCoordinator: TextViewCoord documentURI = document.languageServerURI } - func setUpUpdatesTask() { task?.cancel() // Create this stream here so it's always set up when the text view is set up, rather than only once on init. From 1a3a7d5575db4e6559e20b6c9260469596dcfd8e Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:41:43 -0500 Subject: [PATCH 4/4] Adjust Tests --- .../SemanticTokenHighlightProvider.swift | 2 +- .../LSP/LanguageServer+CodeFileDocument.swift | 15 ++++++++------- .../LSP/LanguageServer+DocumentObjects.swift | 7 ++++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CodeEdit/Features/LSP/Features/SemanticTokens/SemanticTokenHighlightProvider.swift b/CodeEdit/Features/LSP/Features/SemanticTokens/SemanticTokenHighlightProvider.swift index 527e96b7fc..2fbfb8ea8a 100644 --- a/CodeEdit/Features/LSP/Features/SemanticTokens/SemanticTokenHighlightProvider.swift +++ b/CodeEdit/Features/LSP/Features/SemanticTokens/SemanticTokenHighlightProvider.swift @@ -34,7 +34,7 @@ final class SemanticTokenHighlightProvider< private var tokenMap: SemanticTokenMap? private var documentURI: String? - private weak var languageServer: LanguageServer? + weak var languageServer: LanguageServer? private weak var textView: TextView? private var lastEditCallback: EditCallback? diff --git a/CodeEditTests/Features/LSP/LanguageServer+CodeFileDocument.swift b/CodeEditTests/Features/LSP/LanguageServer+CodeFileDocument.swift index 4e632f2993..7112ccec8a 100644 --- a/CodeEditTests/Features/LSP/LanguageServer+CodeFileDocument.swift +++ b/CodeEditTests/Features/LSP/LanguageServer+CodeFileDocument.swift @@ -71,7 +71,8 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase { ), lspPid: -1, serverCapabilities: capabilities, - rootPath: tempTestDir + rootPath: tempTestDir, + logContainer: LanguageServerLogContainer(language: .swift) ) _ = try await server.lspInstance.initializeIfNeeded() return (connection: bufferingConnection, server: server) @@ -231,13 +232,13 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase { let (connection, server) = try await makeTestServer() // Create a CodeFileDocument to test with, attach it to the workspace and file let codeFile = try await openCodeFile(for: server, connection: connection, file: file, syncOption: option) - XCTAssertNotNil(server.openFiles.contentCoordinator(for: codeFile)) - server.openFiles.contentCoordinator(for: codeFile)?.setUpUpdatesTask() + XCTAssertNotNil(codeFile.languageServerObjects.textCoordinator.languageServer) + codeFile.languageServerObjects.textCoordinator.setUpUpdatesTask() codeFile.content?.replaceString(in: .zero, with: #"func testFunction() -> String { "Hello " }"#) let textView = TextView(string: "") textView.setTextStorage(codeFile.content!) - textView.delegate = server.openFiles.contentCoordinator(for: codeFile) + textView.delegate = codeFile.languageServerObjects.textCoordinator textView.replaceCharacters(in: NSRange(location: 39, length: 0), with: "Worlld") textView.replaceCharacters(in: NSRange(location: 39, length: 6), with: "") @@ -289,13 +290,13 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase { let (connection, server) = try await makeTestServer() let codeFile = try await openCodeFile(for: server, connection: connection, file: file, syncOption: option) - XCTAssertNotNil(server.openFiles.contentCoordinator(for: codeFile)) - server.openFiles.contentCoordinator(for: codeFile)?.setUpUpdatesTask() + XCTAssertNotNil(codeFile.languageServerObjects.textCoordinator.languageServer) + codeFile.languageServerObjects.textCoordinator.setUpUpdatesTask() codeFile.content?.replaceString(in: .zero, with: #"func testFunction() -> String { "Hello " }"#) let textView = TextView(string: "") textView.setTextStorage(codeFile.content!) - textView.delegate = server.openFiles.contentCoordinator(for: codeFile) + textView.delegate = codeFile.languageServerObjects.textCoordinator textView.replaceCharacters(in: NSRange(location: 39, length: 0), with: "Worlld") textView.replaceCharacters(in: NSRange(location: 39, length: 6), with: "") textView.replaceCharacters(in: NSRange(location: 39, length: 0), with: "World") diff --git a/CodeEditTests/Features/LSP/LanguageServer+DocumentObjects.swift b/CodeEditTests/Features/LSP/LanguageServer+DocumentObjects.swift index 9e405087c9..9b7738a7d8 100644 --- a/CodeEditTests/Features/LSP/LanguageServer+DocumentObjects.swift +++ b/CodeEditTests/Features/LSP/LanguageServer+DocumentObjects.swift @@ -51,7 +51,8 @@ final class LanguageServerDocumentObjectsTests: XCTestCase { ), lspPid: -1, serverCapabilities: capabilities, - rootPath: URL(fileURLWithPath: "") + rootPath: URL(fileURLWithPath: ""), + logContainer: LanguageServerLogContainer(language: .swift) ) _ = try await server.lspInstance.initializeIfNeeded() document = MockDocumentType() @@ -75,7 +76,7 @@ final class LanguageServerDocumentObjectsTests: XCTestCase { XCTAssertNotNil(server.openFiles.document(for: languageServerURI)) try await server.closeDocument(languageServerURI) - XCTAssertNil(document.languageServerObjects.highlightProvider) - XCTAssertNil(document.languageServerObjects.textCoordinator) + XCTAssertNil(document.languageServerObjects.highlightProvider.languageServer) + XCTAssertNil(document.languageServerObjects.textCoordinator.languageServer) } }