Skip to content

Commit 5b84923

Browse files
committed
fix: Dispose services as soon as no one is using them
1 parent 825c3d2 commit 5b84923

File tree

2 files changed

+33
-13
lines changed

2 files changed

+33
-13
lines changed

src/languageClient.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
import delay from 'delay'
66
import { Uri } from 'monaco-editor'
77
import { registerTextModelContentProvider } from '@codingame/monaco-editor-wrapper'
8-
import { installServices } from './services'
8+
import { getServices, installServices } from './services'
99
import createLanguageClient from './createLanguageClient'
1010
import { WillShutdownParams } from './customRequests'
1111
import { InitializeTextDocumentFeature, WillDisposeFeature } from './extensions'
@@ -277,10 +277,10 @@ function createLanguageClientManager (
277277
}
278278
}
279279

280-
const services = installServices(infrastructure)
281-
282280
const disposableCollection = new DisposableCollection()
283281

282+
disposableCollection.push(installServices(infrastructure))
283+
284284
const languageClientManager = new LanguageClientManager(id, languageServerOptions, infrastructure)
285285
languageClientManagerByLanguageId[id] = languageClientManager
286286
disposableCollection.push(Disposable.create(() => {
@@ -293,7 +293,7 @@ function createLanguageClientManager (
293293
return content != null ? monaco.editor.createModel(content, undefined, resource) : null
294294
}
295295
}))
296-
disposableCollection.push(services.workspace.registerSaveDocumentHandler({
296+
disposableCollection.push(getServices().workspace.registerSaveDocumentHandler({
297297
async saveTextContent (textDocument, reason) {
298298
await infrastructure.saveFileContent?.(textDocument, reason, languageClientManager)
299299
}

src/services.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,29 +54,49 @@ function autoSaveModels (services: CgMonacoServices): Disposable {
5454
}
5555

5656
let services: CgMonacoServices | null = null
57-
function installServices (infrastructure: Infrastructure): CgMonacoServices {
58-
const m2p = new MonacoToProtocolConverter(monaco)
59-
const p2m = new ProtocolToMonacoConverter(monaco)
60-
57+
let serviceDisposable: Disposable | null = null
58+
let serviceReferenceCount = 0
59+
function installServices (infrastructure: Infrastructure): Disposable {
6160
if (services == null) {
61+
// FIXME: we can't recreate services because MonacoWorkspace can't be disposed without memory leaks
62+
// fix me as soon as https://github.com/TypeFox/monaco-languageclient/pull/330/files is released
63+
const m2p = new MonacoToProtocolConverter(monaco)
64+
const p2m = new ProtocolToMonacoConverter(monaco)
6265
services = {
6366
commands: new MonacoCommands(monaco),
6467
languages: new MonacoLanguages(monaco, p2m, m2p),
6568
workspace: new CodinGameMonacoWorkspace(p2m, m2p, infrastructure.rootUri, infrastructure.workspaceFolders),
6669
window: new WatchableConsoleWindow()
6770
}
71+
}
6872

69-
Services.install(services)
73+
if (serviceReferenceCount === 0) {
74+
const disposableCollection = new DisposableCollection()
7075

71-
installCommands(services)
76+
disposableCollection.push(installCommands(services))
77+
disposableCollection.push(Services.install(services))
7278

7379
if (!infrastructure.automaticTextDocumentUpdate) {
74-
autoSaveModels(services)
80+
disposableCollection.push(autoSaveModels(services))
7581
}
82+
serviceDisposable = disposableCollection
7683
}
77-
return services
84+
serviceReferenceCount++
85+
86+
return Disposable.create(() => {
87+
serviceReferenceCount--
88+
if (serviceReferenceCount <= 0) {
89+
serviceDisposable?.dispose()
90+
serviceDisposable = null
91+
}
92+
})
93+
}
94+
95+
function getServices (): CgMonacoServices {
96+
return Services.get()! as CgMonacoServices
7897
}
7998

8099
export {
81-
installServices
100+
installServices,
101+
getServices
82102
}

0 commit comments

Comments
 (0)