Skip to content

Commit 7899568

Browse files
authored
Fixes #1295: No LSP workspace/didChangeConfiguration notifications after language server restart (#1298)
1 parent 7792b0b commit 7899568

13 files changed

+38
-34
lines changed

client/src/common/client.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1434,9 +1434,9 @@ export abstract class BaseLanguageClient implements FeatureClient<Middleware, La
14341434
if (this._syncedDocuments) {
14351435
this._syncedDocuments.clear();
14361436
}
1437-
// Dispose features in reverse order;
1437+
// Clear features in reverse order;
14381438
for (const feature of Array.from(this._features.entries()).map(entry => entry[1]).reverse()) {
1439-
feature.dispose();
1439+
feature.clear();
14401440
}
14411441
if (mode === 'stop' && this._diagnostics !== undefined) {
14421442
this._diagnostics.dispose();

client/src/common/configuration.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export class ConfigurationFeature implements StaticFeature {
8787
return result;
8888
}
8989

90-
public dispose(): void {
90+
public clear(): void {
9191
}
9292
}
9393

@@ -149,11 +149,11 @@ export type $ConfigurationOptions = {
149149

150150
export class SyncConfigurationFeature implements DynamicFeature<DidChangeConfigurationRegistrationOptions> {
151151

152-
private isDisposed: boolean;
152+
private isCleared: boolean;
153153
private readonly _listeners: Map<string, Disposable>;
154154

155155
constructor(private _client: FeatureClient<DidChangeConfigurationWorkspaceMiddleware, $ConfigurationOptions>) {
156-
this.isDisposed = false;
156+
this.isCleared = false;
157157
this._listeners = new Map();
158158
}
159159

@@ -170,6 +170,7 @@ export class SyncConfigurationFeature implements DynamicFeature<DidChangeConfigu
170170
}
171171

172172
public initialize(): void {
173+
this.isCleared = false;
173174
let section = this._client.clientOptions.synchronize?.configurationSection;
174175
if (section !== undefined) {
175176
this.register({
@@ -199,16 +200,16 @@ export class SyncConfigurationFeature implements DynamicFeature<DidChangeConfigu
199200
}
200201
}
201202

202-
public dispose(): void {
203+
public clear(): void {
203204
for (const disposable of this._listeners.values()) {
204205
disposable.dispose();
205206
}
206207
this._listeners.clear();
207-
this.isDisposed = true;
208+
this.isCleared = true;
208209
}
209210

210211
private onDidChangeConfiguration(configurationSection: string | string[] | undefined, event: ConfigurationChangeEvent | undefined): void {
211-
if (this.isDisposed) {
212+
if (this.isCleared) {
212213
return;
213214
}
214215
let sections: string[] | undefined;

client/src/common/diagnostic.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1056,12 +1056,12 @@ export class DiagnosticFeature extends TextDocumentLanguageFeature<DiagnosticOpt
10561056
this.register({ id: id, registerOptions: options });
10571057
}
10581058

1059-
public dispose(): void {
1059+
public clear(): void {
10601060
if (this.tabs !== undefined) {
10611061
this.tabs.dispose();
10621062
this.tabs = undefined;
10631063
}
1064-
super.dispose();
1064+
super.clear();
10651065
}
10661066

10671067
protected registerLanguageProvider(options: DiagnosticRegistrationOptions): [Disposable, DiagnosticProviderShape] {

client/src/common/executeCommand.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export class ExecuteCommandFeature implements DynamicFeature<ExecuteCommandRegis
9292
}
9393
}
9494

95-
public dispose(): void {
95+
public clear(): void {
9696
this._commands.forEach((value) => {
9797
value.forEach(disposable => disposable.dispose());
9898
});

client/src/common/features.ts

+14-12
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,18 @@ export interface StaticFeature {
155155
getState(): FeatureState;
156156

157157
/**
158-
* Called when the client is stopped to dispose this feature. Usually a feature
159-
* un-registers listeners registered hooked up with the VS Code extension host.
158+
* Called when the client is stopped or re-started to clear this feature.
159+
* Usually a feature un-registers listeners registered hooked up with the
160+
* VS Code extension host.
160161
*/
161-
dispose(): void;
162+
clear(): void;
162163
}
163164

164165
export namespace StaticFeature {
165166
export function is (value: any): value is StaticFeature {
166167
const candidate: StaticFeature = value;
167168
return candidate !== undefined && candidate !== null &&
168-
Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.dispose) &&
169+
Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.clear) &&
169170
(candidate.fillInitializeParams === undefined || Is.func(candidate.fillInitializeParams));
170171
}
171172
}
@@ -237,17 +238,18 @@ export interface DynamicFeature<RO> {
237238
unregister(id: string): void;
238239

239240
/**
240-
* Called when the client is stopped to dispose this feature. Usually a feature
241-
* un-registers listeners registered hooked up with the VS Code extension host.
241+
* Called when the client is stopped or re-started to clear this feature.
242+
* Usually a feature un-registers listeners registered hooked up with the
243+
* VS Code extension host.
242244
*/
243-
dispose(): void;
245+
clear(): void;
244246
}
245247

246248
export namespace DynamicFeature {
247249
export function is<T>(value: any): value is DynamicFeature<T> {
248250
const candidate: DynamicFeature<T> = value;
249251
return candidate !== undefined && candidate !== null &&
250-
Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.dispose) &&
252+
Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.clear) &&
251253
(candidate.fillInitializeParams === undefined || Is.func(candidate.fillInitializeParams)) && Is.func(candidate.register) &&
252254
Is.func(candidate.unregister) && candidate.registrationType !== undefined;
253255
}
@@ -285,7 +287,7 @@ export abstract class DynamicDocumentFeature<RO, MW, CO = object> implements Dyn
285287
public abstract registrationType: RegistrationType<RO>;
286288
public abstract register(data: RegistrationData<RO>): void;
287289
public abstract unregister(id: string): void;
288-
public abstract dispose(): void;
290+
public abstract clear(): void;
289291

290292
/**
291293
* Returns the state the feature is in.
@@ -424,7 +426,7 @@ export abstract class TextDocumentEventFeature<P extends { textDocument: TextDoc
424426
}
425427
}
426428

427-
public dispose(): void {
429+
public clear(): void {
428430
this._selectors.clear();
429431
this._onNotificationSent.dispose();
430432
if (this._listener) {
@@ -518,7 +520,7 @@ export abstract class TextDocumentLanguageFeature<PO, RO extends TextDocumentReg
518520
}
519521
}
520522

521-
public dispose(): void {
523+
public clear(): void {
522524
this._registrations.forEach((value) => {
523525
value.disposable.dispose();
524526
});
@@ -618,7 +620,7 @@ export abstract class WorkspaceFeature<RO, PR, M> implements DynamicFeature<RO>
618620
}
619621
}
620622

621-
public dispose(): void {
623+
public clear(): void {
622624
this._registrations.forEach((registration) => {
623625
registration.disposable.dispose();
624626
});

client/src/common/fileOperations.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ abstract class FileOperationFeature<I, E extends Event<I>> implements DynamicFea
130130
}
131131
}
132132

133-
public dispose(): void {
133+
public clear(): void {
134134
this._filters.clear();
135135
if (this._listener) {
136136
this._listener.dispose();
@@ -276,8 +276,8 @@ abstract class CachingNotificationFileOperationFeature<I, E extends { readonly f
276276
}
277277
}
278278

279-
public dispose(): void {
280-
super.dispose();
279+
public clear(): void {
280+
super.clear();
281281
if (this._willListener) {
282282
this._willListener.dispose();
283283
this._willListener = undefined;

client/src/common/fileSystemWatcher.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export class FileSystemWatcherFeature implements DynamicFeature<DidChangeWatched
112112
}
113113
}
114114

115-
public dispose(): void {
115+
public clear(): void {
116116
this._watchers.forEach((disposables) => {
117117
for (let disposable of disposables) {
118118
disposable.dispose();

client/src/common/notebook.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,7 @@ export class NotebookDocumentSyncFeature implements DynamicFeature<proto.Noteboo
964964
provider && provider.dispose();
965965
}
966966

967-
public dispose(): void {
967+
public clear(): void {
968968
for (const provider of this.registrations.values()) {
969969
provider.dispose();
970970
}

client/src/common/progress.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class ProgressFeature implements StaticFeature {
4545
client.onRequest(WorkDoneProgressCreateRequest.type, createHandler);
4646
}
4747

48-
public dispose(): void {
48+
public clear(): void {
4949
for (const part of this.activeParts) {
5050
part.done();
5151
}

client/src/common/textSynchronization.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ export class DidChangeTextDocumentFeature extends DynamicDocumentFeature<TextDoc
319319
}
320320
}
321321

322-
public dispose(): void {
322+
public clear(): void {
323323
this._pendingTextDocumentChanges.clear();
324324
this._changeData.clear();
325325
this._syncKind = TextDocumentSyncKind.None;
@@ -484,7 +484,7 @@ export class WillSaveWaitUntilFeature extends DynamicDocumentFeature<TextDocumen
484484
}
485485
}
486486

487-
public dispose(): void {
487+
public clear(): void {
488488
this._selectors.clear();
489489
if (this._listener) {
490490
this._listener.dispose();

client/src/common/workspaceFolder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export class WorkspaceFoldersFeature implements DynamicFeature<void> {
160160
disposable.dispose();
161161
}
162162

163-
public dispose(): void {
163+
public clear(): void {
164164
for (let disposable of this._listeners.values()) {
165165
disposable.dispose();
166166
}

testbed/client/src/extension.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export async function activate(context: ExtensionContext) {
2727
{ scheme: 'file', pattern: '**/.vscode/test.txt' }
2828
],
2929
synchronize: {
30-
configurationSection: 'testbed'
30+
// configurationSection: 'testbed'
3131
// fileEvents: workspace.createFileSystemWatcher('**/*'),
3232
},
3333
diagnosticCollectionName: 'markers',

testbed/server/src/server.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
TextEdit, ProposedFeatures, DiagnosticTag, InsertTextFormat, SelectionRangeRequest, SelectionRange, InsertReplaceEdit,
1818
SemanticTokensClientCapabilities, SemanticTokensLegend, SemanticTokensBuilder, SemanticTokensRegistrationType,
1919
SemanticTokensRegistrationOptions, ProtocolNotificationType, ChangeAnnotation, WorkspaceChange, CompletionItemKind, DiagnosticSeverity,
20-
DocumentDiagnosticReportKind, WorkspaceDiagnosticReport, NotebookDocuments, CompletionList, DocumentLinkResolveRequest
20+
DocumentDiagnosticReportKind, WorkspaceDiagnosticReport, NotebookDocuments, CompletionList, DocumentLinkResolveRequest, DidChangeConfigurationNotification
2121
} from 'vscode-languageserver/node';
2222

2323
import {
@@ -187,6 +187,7 @@ connection.onInitialize((params, cancel, progress): Thenable<InitializeResult> |
187187
});
188188

189189
connection.onInitialized((params) => {
190+
void connection.client.register(DidChangeConfigurationNotification.type, undefined);
190191
connection.workspace.onDidChangeWorkspaceFolders((event) => {
191192
connection.console.log('Workspace folder changed received');
192193
});

0 commit comments

Comments
 (0)