Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #1295: No LSP workspace/didChangeConfiguration notifications after language server restart #1298

Merged
merged 1 commit into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/src/common/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1434,9 +1434,9 @@ export abstract class BaseLanguageClient implements FeatureClient<Middleware, La
if (this._syncedDocuments) {
this._syncedDocuments.clear();
}
// Dispose features in reverse order;
// Clear features in reverse order;
for (const feature of Array.from(this._features.entries()).map(entry => entry[1]).reverse()) {
feature.dispose();
feature.clear();
}
if (mode === 'stop' && this._diagnostics !== undefined) {
this._diagnostics.dispose();
Expand Down
13 changes: 7 additions & 6 deletions client/src/common/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class ConfigurationFeature implements StaticFeature {
return result;
}

public dispose(): void {
public clear(): void {
}
}

Expand Down Expand Up @@ -149,11 +149,11 @@ export type $ConfigurationOptions = {

export class SyncConfigurationFeature implements DynamicFeature<DidChangeConfigurationRegistrationOptions> {

private isDisposed: boolean;
private isCleared: boolean;
private readonly _listeners: Map<string, Disposable>;

constructor(private _client: FeatureClient<DidChangeConfigurationWorkspaceMiddleware, $ConfigurationOptions>) {
this.isDisposed = false;
this.isCleared = false;
this._listeners = new Map();
}

Expand All @@ -170,6 +170,7 @@ export class SyncConfigurationFeature implements DynamicFeature<DidChangeConfigu
}

public initialize(): void {
this.isCleared = false;
let section = this._client.clientOptions.synchronize?.configurationSection;
if (section !== undefined) {
this.register({
Expand Down Expand Up @@ -199,16 +200,16 @@ export class SyncConfigurationFeature implements DynamicFeature<DidChangeConfigu
}
}

public dispose(): void {
public clear(): void {
for (const disposable of this._listeners.values()) {
disposable.dispose();
}
this._listeners.clear();
this.isDisposed = true;
this.isCleared = true;
}

private onDidChangeConfiguration(configurationSection: string | string[] | undefined, event: ConfigurationChangeEvent | undefined): void {
if (this.isDisposed) {
if (this.isCleared) {
return;
}
let sections: string[] | undefined;
Expand Down
4 changes: 2 additions & 2 deletions client/src/common/diagnostic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1056,12 +1056,12 @@ export class DiagnosticFeature extends TextDocumentLanguageFeature<DiagnosticOpt
this.register({ id: id, registerOptions: options });
}

public dispose(): void {
public clear(): void {
if (this.tabs !== undefined) {
this.tabs.dispose();
this.tabs = undefined;
}
super.dispose();
super.clear();
}

protected registerLanguageProvider(options: DiagnosticRegistrationOptions): [Disposable, DiagnosticProviderShape] {
Expand Down
2 changes: 1 addition & 1 deletion client/src/common/executeCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class ExecuteCommandFeature implements DynamicFeature<ExecuteCommandRegis
}
}

public dispose(): void {
public clear(): void {
this._commands.forEach((value) => {
value.forEach(disposable => disposable.dispose());
});
Expand Down
26 changes: 14 additions & 12 deletions client/src/common/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,18 @@ export interface StaticFeature {
getState(): FeatureState;

/**
* Called when the client is stopped to dispose this feature. Usually a feature
* un-registers listeners registered hooked up with the VS Code extension host.
* Called when the client is stopped or re-started to clear this feature.
* Usually a feature un-registers listeners registered hooked up with the
* VS Code extension host.
*/
dispose(): void;
clear(): void;
}

export namespace StaticFeature {
export function is (value: any): value is StaticFeature {
const candidate: StaticFeature = value;
return candidate !== undefined && candidate !== null &&
Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.dispose) &&
Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.clear) &&
(candidate.fillInitializeParams === undefined || Is.func(candidate.fillInitializeParams));
}
}
Expand Down Expand Up @@ -237,17 +238,18 @@ export interface DynamicFeature<RO> {
unregister(id: string): void;

/**
* Called when the client is stopped to dispose this feature. Usually a feature
* un-registers listeners registered hooked up with the VS Code extension host.
* Called when the client is stopped or re-started to clear this feature.
* Usually a feature un-registers listeners registered hooked up with the
* VS Code extension host.
*/
dispose(): void;
clear(): void;
}

export namespace DynamicFeature {
export function is<T>(value: any): value is DynamicFeature<T> {
const candidate: DynamicFeature<T> = value;
return candidate !== undefined && candidate !== null &&
Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.dispose) &&
Is.func(candidate.fillClientCapabilities) && Is.func(candidate.initialize) && Is.func(candidate.getState) && Is.func(candidate.clear) &&
(candidate.fillInitializeParams === undefined || Is.func(candidate.fillInitializeParams)) && Is.func(candidate.register) &&
Is.func(candidate.unregister) && candidate.registrationType !== undefined;
}
Expand Down Expand Up @@ -285,7 +287,7 @@ export abstract class DynamicDocumentFeature<RO, MW, CO = object> implements Dyn
public abstract registrationType: RegistrationType<RO>;
public abstract register(data: RegistrationData<RO>): void;
public abstract unregister(id: string): void;
public abstract dispose(): void;
public abstract clear(): void;

/**
* Returns the state the feature is in.
Expand Down Expand Up @@ -424,7 +426,7 @@ export abstract class TextDocumentEventFeature<P extends { textDocument: TextDoc
}
}

public dispose(): void {
public clear(): void {
this._selectors.clear();
this._onNotificationSent.dispose();
if (this._listener) {
Expand Down Expand Up @@ -518,7 +520,7 @@ export abstract class TextDocumentLanguageFeature<PO, RO extends TextDocumentReg
}
}

public dispose(): void {
public clear(): void {
this._registrations.forEach((value) => {
value.disposable.dispose();
});
Expand Down Expand Up @@ -618,7 +620,7 @@ export abstract class WorkspaceFeature<RO, PR, M> implements DynamicFeature<RO>
}
}

public dispose(): void {
public clear(): void {
this._registrations.forEach((registration) => {
registration.disposable.dispose();
});
Expand Down
6 changes: 3 additions & 3 deletions client/src/common/fileOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ abstract class FileOperationFeature<I, E extends Event<I>> implements DynamicFea
}
}

public dispose(): void {
public clear(): void {
this._filters.clear();
if (this._listener) {
this._listener.dispose();
Expand Down Expand Up @@ -276,8 +276,8 @@ abstract class CachingNotificationFileOperationFeature<I, E extends { readonly f
}
}

public dispose(): void {
super.dispose();
public clear(): void {
super.clear();
if (this._willListener) {
this._willListener.dispose();
this._willListener = undefined;
Expand Down
2 changes: 1 addition & 1 deletion client/src/common/fileSystemWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export class FileSystemWatcherFeature implements DynamicFeature<DidChangeWatched
}
}

public dispose(): void {
public clear(): void {
this._watchers.forEach((disposables) => {
for (let disposable of disposables) {
disposable.dispose();
Expand Down
2 changes: 1 addition & 1 deletion client/src/common/notebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ export class NotebookDocumentSyncFeature implements DynamicFeature<proto.Noteboo
provider && provider.dispose();
}

public dispose(): void {
public clear(): void {
for (const provider of this.registrations.values()) {
provider.dispose();
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/common/progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class ProgressFeature implements StaticFeature {
client.onRequest(WorkDoneProgressCreateRequest.type, createHandler);
}

public dispose(): void {
public clear(): void {
for (const part of this.activeParts) {
part.done();
}
Expand Down
4 changes: 2 additions & 2 deletions client/src/common/textSynchronization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export class DidChangeTextDocumentFeature extends DynamicDocumentFeature<TextDoc
}
}

public dispose(): void {
public clear(): void {
this._pendingTextDocumentChanges.clear();
this._changeData.clear();
this._syncKind = TextDocumentSyncKind.None;
Expand Down Expand Up @@ -484,7 +484,7 @@ export class WillSaveWaitUntilFeature extends DynamicDocumentFeature<TextDocumen
}
}

public dispose(): void {
public clear(): void {
this._selectors.clear();
if (this._listener) {
this._listener.dispose();
Expand Down
2 changes: 1 addition & 1 deletion client/src/common/workspaceFolder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export class WorkspaceFoldersFeature implements DynamicFeature<void> {
disposable.dispose();
}

public dispose(): void {
public clear(): void {
for (let disposable of this._listeners.values()) {
disposable.dispose();
}
Expand Down
2 changes: 1 addition & 1 deletion testbed/client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function activate(context: ExtensionContext) {
{ scheme: 'file', pattern: '**/.vscode/test.txt' }
],
synchronize: {
configurationSection: 'testbed'
// configurationSection: 'testbed'
// fileEvents: workspace.createFileSystemWatcher('**/*'),
},
diagnosticCollectionName: 'markers',
Expand Down
3 changes: 2 additions & 1 deletion testbed/server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
TextEdit, ProposedFeatures, DiagnosticTag, InsertTextFormat, SelectionRangeRequest, SelectionRange, InsertReplaceEdit,
SemanticTokensClientCapabilities, SemanticTokensLegend, SemanticTokensBuilder, SemanticTokensRegistrationType,
SemanticTokensRegistrationOptions, ProtocolNotificationType, ChangeAnnotation, WorkspaceChange, CompletionItemKind, DiagnosticSeverity,
DocumentDiagnosticReportKind, WorkspaceDiagnosticReport, NotebookDocuments, CompletionList, DocumentLinkResolveRequest
DocumentDiagnosticReportKind, WorkspaceDiagnosticReport, NotebookDocuments, CompletionList, DocumentLinkResolveRequest, DidChangeConfigurationNotification
} from 'vscode-languageserver/node';

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

connection.onInitialized((params) => {
void connection.client.register(DidChangeConfigurationNotification.type, undefined);
connection.workspace.onDidChangeWorkspaceFolders((event) => {
connection.console.log('Workspace folder changed received');
});
Expand Down