@@ -181,6 +181,36 @@ public final class SourceKitServer: LanguageServer {
181
181
return nil
182
182
}
183
183
184
+ func reopenDocuments( for languageService: ToolchainLanguageServer ) {
185
+ queue. async {
186
+ guard let workspace = self . workspace else {
187
+ return
188
+ }
189
+
190
+ for documentUri in workspace. documentManager. openDocuments where workspace. documentService [ documentUri] === languageService {
191
+ guard let snapshot = workspace. documentManager. latestSnapshot ( documentUri) else {
192
+ // The document has been closed since we retrieved its URI. We don't care about it anymore.
193
+ continue
194
+ }
195
+
196
+ do {
197
+ // Close the document in the document manager so we can reopen it. If the document has been
198
+ // closed since, the try will fail and we won't try to reopen it.
199
+ try workspace. documentManager. close ( documentUri)
200
+ let textDocument = TextDocumentItem ( uri: documentUri,
201
+ language: snapshot. document. language,
202
+ version: snapshot. version,
203
+ text: snapshot. text)
204
+ // Re-open the document but don't register for build system notifications again since
205
+ // the document is still open in the build system server from before the sourcektid crash.
206
+ self . openDocument ( DidOpenTextDocumentNotification ( textDocument: textDocument) , workspace: workspace, registerForBuildSystemNotifications: false )
207
+ } catch {
208
+ // The document was no longer open. Ignore it
209
+ }
210
+ }
211
+ }
212
+ }
213
+
184
214
func languageService( for toolchain: Toolchain , _ language: Language ) -> ToolchainLanguageServer ? {
185
215
let key = LanguageServiceKey ( toolchain: toolchain. identifier, language: language)
186
216
if let service = languageService [ key] {
@@ -189,7 +219,7 @@ public final class SourceKitServer: LanguageServer {
189
219
190
220
// Start a new service.
191
221
return orLog ( " failed to start language service " , level: . error) {
192
- guard let service = try SourceKit . languageService ( for: toolchain, language, options: options, client: self ) else {
222
+ guard let service = try SourceKit . languageService ( for: toolchain, language, options: options, client: self , reopenDocuments : reopenDocuments ) else {
193
223
return nil
194
224
}
195
225
@@ -216,7 +246,8 @@ public final class SourceKitServer: LanguageServer {
216
246
}
217
247
}
218
248
219
- func languageService( for uri: DocumentURI , _ language: Language , in workspace: Workspace ) -> ToolchainLanguageServer ? {
249
+ /// **Public for testing purposes only**
250
+ public func languageService( for uri: DocumentURI , _ language: Language , in workspace: Workspace ) -> ToolchainLanguageServer ? {
220
251
if let service = workspace. documentService [ uri] {
221
252
return service
222
253
}
@@ -424,14 +455,21 @@ extension SourceKitServer {
424
455
// MARK: - Text synchronization
425
456
426
457
func openDocument( _ note: Notification < DidOpenTextDocumentNotification > , workspace: Workspace ) {
427
- workspace. documentManager. open ( note. params)
458
+ openDocument ( note. params, workspace: workspace)
459
+ }
460
+
461
+ private func openDocument( _ note: DidOpenTextDocumentNotification , workspace: Workspace , registerForBuildSystemNotifications: Bool = true ) {
462
+ workspace. documentManager. open ( note)
428
463
429
- let textDocument = note. params. textDocument
430
- workspace. buildSettings. registerForChangeNotifications (
431
- for: textDocument. uri, language: textDocument. language)
464
+ let textDocument = note. textDocument
465
+
466
+ if registerForBuildSystemNotifications {
467
+ workspace. buildSettings. registerForChangeNotifications (
468
+ for: textDocument. uri, language: textDocument. language)
469
+ }
432
470
433
471
if let service = languageService ( for: textDocument. uri, textDocument. language, in: workspace) {
434
- service. openDocument ( note. params )
472
+ service. openDocument ( note)
435
473
}
436
474
}
437
475
@@ -771,17 +809,18 @@ public func languageService(
771
809
for toolchain: Toolchain ,
772
810
_ language: Language ,
773
811
options: SourceKitServer . Options ,
774
- client: MessageHandler ) throws -> ToolchainLanguageServer ?
812
+ client: MessageHandler ,
813
+ reopenDocuments: @escaping ( ToolchainLanguageServer ) -> Void ) throws -> ToolchainLanguageServer ?
775
814
{
776
815
switch language {
777
816
778
817
case . c, . cpp, . objective_c, . objective_cpp:
779
818
guard toolchain. clangd != nil else { return nil }
780
- return try makeJSONRPCClangServer ( client: client, toolchain: toolchain, buildSettings: ( client as? SourceKitServer ) ? . workspace? . buildSettings, clangdOptions: options. clangdOptions)
819
+ return try makeJSONRPCClangServer ( client: client, toolchain: toolchain, buildSettings: ( client as? SourceKitServer ) ? . workspace? . buildSettings, clangdOptions: options. clangdOptions, reopenDocuments : reopenDocuments )
781
820
782
821
case . swift:
783
822
guard let sourcekitd = toolchain. sourcekitd else { return nil }
784
- return try makeLocalSwiftServer ( client: client, sourcekitd: sourcekitd, buildSettings: ( client as? SourceKitServer ) ? . workspace? . buildSettings, clientCapabilities: ( client as? SourceKitServer ) ? . workspace? . clientCapabilities)
823
+ return try makeLocalSwiftServer ( client: client, sourcekitd: sourcekitd, buildSettings: ( client as? SourceKitServer ) ? . workspace? . buildSettings, clientCapabilities: ( client as? SourceKitServer ) ? . workspace? . clientCapabilities, reopenDocuments : reopenDocuments )
785
824
786
825
default :
787
826
return nil
0 commit comments