Skip to content

Commit bebc06e

Browse files
authored
Merge pull request #36 from CodinGame/never-uninstall-services
Never uninstall service but reinitialize them instead
2 parents 37ba4b6 + 5056ac7 commit bebc06e

File tree

3 files changed

+71
-74
lines changed

3 files changed

+71
-74
lines changed

src/languageClient.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
CloseAction, ErrorAction, MonacoLanguageClient, Emitter, Event, TextDocument, Services, State, DisposableCollection, CancellationToken, RequestType, NotificationType, LogMessageNotification
44
} from 'monaco-languageclient'
55
import delay from 'delay'
6-
import { installServices } from './services'
6+
import { updateServices } from './services'
77
import createLanguageClient from './createLanguageClient'
88
import { WillShutdownParams } from './customRequests'
99
import { FileSystemFeature, InitializeTextDocumentFeature, WillDisposeFeature } from './extensions'
@@ -298,15 +298,9 @@ function createLanguageClientManager (
298298
}
299299
}
300300

301-
const serviceDisposable = installServices(infrastructure)
301+
updateServices(infrastructure)
302302

303-
const languageClientManager = new LanguageClientManager(id, languageServerOptions, infrastructure)
304-
305-
languageClientManager.onDidClose(() => {
306-
serviceDisposable.dispose()
307-
})
308-
309-
return languageClientManager
303+
return new LanguageClientManager(id, languageServerOptions, infrastructure)
310304
}
311305

312306
export {

src/services.ts

Lines changed: 17 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
import * as monaco from 'monaco-editor'
33
import {
4-
Services, MonacoToProtocolConverter, ProtocolToMonacoConverter, MonacoLanguages, TextDocumentSaveReason, MonacoCommands, DisposableCollection
4+
Services, MonacoToProtocolConverter, ProtocolToMonacoConverter, MonacoLanguages, MonacoCommands
55
} from 'monaco-languageclient'
66
import { RenameFile, CreateFile, WorkspaceEdit, Disposable } from 'vscode-languageserver-protocol'
77
import WatchableConsoleWindow from './services/WatchableConsoleWindow'
@@ -29,72 +29,31 @@ function installCommands (services: CgMonacoServices): Disposable {
2929
})
3030
}
3131

32-
function autoSaveModels (services: CgMonacoServices): Disposable {
33-
const disposableCollection = new DisposableCollection()
34-
const timeoutMap = new Map<string, number>()
35-
disposableCollection.push(services.workspace.onDidChangeTextDocument(e => {
36-
const timeout = timeoutMap.get(e.textDocument.uri)
37-
if (timeout != null) {
38-
window.clearTimeout(timeout)
39-
timeoutMap.delete(e.textDocument.uri)
40-
}
41-
timeoutMap.set(e.textDocument.uri, window.setTimeout(() => {
42-
timeoutMap.delete(e.textDocument.uri)
43-
services.workspace.saveDocument(e.textDocument, TextDocumentSaveReason.AfterDelay).catch((error: Error) => {
44-
monaco.errorHandler.onUnexpectedError(new Error(`[LSP] Unable to save the document ${e.textDocument.uri.toString()}`, {
45-
cause: error
46-
}))
47-
})
48-
}, 500))
49-
}))
50-
disposableCollection.push(Disposable.create(() => {
51-
for (const timeout of Array.from(timeoutMap.values())) {
52-
window.clearTimeout(timeout)
53-
}
54-
}))
55-
return disposableCollection
32+
const m2p = new MonacoToProtocolConverter(monaco)
33+
const p2m = new ProtocolToMonacoConverter(monaco)
34+
const services = {
35+
commands: new MonacoCommands(monaco),
36+
languages: new MonacoLanguages(monaco, p2m, m2p),
37+
workspace: new CodinGameMonacoWorkspace(p2m, m2p, 'file:///tmp/project'),
38+
window: new WatchableConsoleWindow()
5639
}
5740

58-
let serviceDisposable: Disposable | null = null
59-
let serviceReferenceCount = 0
60-
function installServices (infrastructure: Infrastructure): Disposable {
61-
if (serviceReferenceCount === 0) {
62-
const disposableCollection = new DisposableCollection()
63-
64-
const m2p = new MonacoToProtocolConverter(monaco)
65-
const p2m = new ProtocolToMonacoConverter(monaco)
66-
const services = {
67-
commands: new MonacoCommands(monaco),
68-
languages: new MonacoLanguages(monaco, p2m, m2p),
69-
workspace: new CodinGameMonacoWorkspace(p2m, m2p, infrastructure.rootUri, infrastructure.workspaceFolders),
70-
window: new WatchableConsoleWindow()
71-
}
72-
73-
disposableCollection.push(services.workspace)
74-
disposableCollection.push(installCommands(services))
75-
disposableCollection.push(Services.install(services))
41+
installCommands(services)
42+
Services.install(services)
7643

77-
if (!infrastructure.automaticTextDocumentUpdate) {
78-
disposableCollection.push(autoSaveModels(services))
79-
}
80-
serviceDisposable = disposableCollection
81-
}
82-
serviceReferenceCount++
83-
84-
return Disposable.create(() => {
85-
serviceReferenceCount--
86-
if (serviceReferenceCount <= 0) {
87-
serviceDisposable?.dispose()
88-
serviceDisposable = null
89-
}
90-
})
44+
function updateServices (infrastructure: Infrastructure): void {
45+
services.workspace.initialize(
46+
infrastructure.rootUri,
47+
infrastructure.workspaceFolders,
48+
!infrastructure.automaticTextDocumentUpdate
49+
)
9150
}
9251

9352
function getServices (): CgMonacoServices {
9453
return Services.get()! as CgMonacoServices
9554
}
9655

9756
export {
98-
installServices,
57+
updateServices,
9958
getServices
10059
}

src/services/CodinGameMonacoWorkspace.ts

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
MonacoWorkspace, TextDocument, TextDocumentSaveReason,
3-
ProtocolToMonacoConverter, MonacoToProtocolConverter, Emitter, Event, TextDocumentWillSaveEvent, Disposable
3+
ProtocolToMonacoConverter, MonacoToProtocolConverter, Emitter, Event, TextDocumentWillSaveEvent, Disposable, DisposableCollection
44
} from 'monaco-languageclient'
55
import * as monaco from 'monaco-editor'
66
import type * as vscode from 'vscode'
@@ -17,23 +17,40 @@ export default class CodinGameMonacoWorkspace extends MonacoWorkspace {
1717

1818
configurations = new Configuration()
1919

20+
private autoSaveModelDisposable: Disposable | undefined
21+
22+
public workspaceFolders: typeof vscode.workspace.workspaceFolders
23+
2024
constructor (
2125
p2m: ProtocolToMonacoConverter,
2226
m2p: MonacoToProtocolConverter,
23-
_rootUri: string | null = null,
24-
public workspaceFolders: typeof vscode.workspace.workspaceFolders
27+
rootUri: string | null = null
2528
) {
26-
super(monaco, p2m, m2p, _rootUri)
29+
super(monaco, p2m, m2p, rootUri)
30+
}
2731

28-
// "workaround" for https://github.com/TypeFox/monaco-languageclient/pull/199#issuecomment-593414330
29-
if (this.workspaceFolders == null && _rootUri != null) {
30-
const uri = monaco.Uri.parse(_rootUri)
32+
public initialize (
33+
rootUri: string | null = null,
34+
workspaceFolders: typeof vscode.workspace.workspaceFolders,
35+
autoSaveModels: boolean
36+
): void {
37+
this._rootUri = rootUri
38+
if (workspaceFolders != null) {
39+
this.workspaceFolders = workspaceFolders
40+
} else if (rootUri != null) {
41+
const uri = monaco.Uri.parse(rootUri)
3142
this.workspaceFolders = [{
3243
uri,
3344
index: 0,
3445
name: uri.toString()
3546
}]
3647
}
48+
if (autoSaveModels && this.autoSaveModelDisposable == null) {
49+
this.autoSaveModelDisposable = this.autoSaveModels()
50+
} else if (!autoSaveModels && this.autoSaveModelDisposable != null) {
51+
this.autoSaveModelDisposable.dispose()
52+
this.autoSaveModelDisposable = undefined
53+
}
3754
}
3855

3956
get onWillSaveTextDocument (): Event<TextDocumentWillSaveEvent> {
@@ -73,8 +90,35 @@ export default class CodinGameMonacoWorkspace extends MonacoWorkspace {
7390
}
7491
}
7592

93+
private autoSaveModels (): Disposable {
94+
const disposableCollection = new DisposableCollection()
95+
const timeoutMap = new Map<string, number>()
96+
disposableCollection.push(this.onDidChangeTextDocument(e => {
97+
const timeout = timeoutMap.get(e.textDocument.uri)
98+
if (timeout != null) {
99+
window.clearTimeout(timeout)
100+
timeoutMap.delete(e.textDocument.uri)
101+
}
102+
timeoutMap.set(e.textDocument.uri, window.setTimeout(() => {
103+
timeoutMap.delete(e.textDocument.uri)
104+
this.saveDocument(e.textDocument, TextDocumentSaveReason.AfterDelay).catch((error: Error) => {
105+
monaco.errorHandler.onUnexpectedError(new Error(`[LSP] Unable to save the document ${e.textDocument.uri.toString()}`, {
106+
cause: error
107+
}))
108+
})
109+
}, 500))
110+
}))
111+
disposableCollection.push(Disposable.create(() => {
112+
for (const timeout of Array.from(timeoutMap.values())) {
113+
window.clearTimeout(timeout)
114+
}
115+
}))
116+
return disposableCollection
117+
}
118+
76119
override dispose (): void {
77120
super.dispose()
121+
this.autoSaveModelDisposable?.dispose()
78122
this.configurations.dispose()
79123
this.onWillSaveTextDocumentEmitter.dispose()
80124
this.onDidSaveTextDocumentEmitter.dispose()

0 commit comments

Comments
 (0)