Skip to content

Commit 71e3360

Browse files
committed
Fix automatic restart of language server upon changes in configuration
1 parent 6dba5d5 commit 71e3360

File tree

6 files changed

+75
-77
lines changed

6 files changed

+75
-77
lines changed

src/commands/registration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as implementations from './implementations';
22

33
import { commands, ExtensionContext, languages, Uri, ViewColumn, window, workspace } from 'vscode';
4-
import { ImandraxLanguageClient } from '../imandrax_language_client/imandrax_language_client';
4+
import { ImandraXLanguageClient } from '../imandrax_language_client/imandrax_language_client';
55

6-
export function register(context: ExtensionContext, imandraxLanguageClient: ImandraxLanguageClient) {
6+
export function register(context: ExtensionContext, imandraxLanguageClient: ImandraXLanguageClient) {
77
const getClient = () => { return imandraxLanguageClient.getClient(); };
88

99
const restart_cmd = "imandrax.restart_language_server";

src/extension.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as commands from './commands/commands';
22
import * as decorations from './decorations';
33
import * as formatter from './formatter';
4+
import * as ImandraXLanguageClientConfiguration from './imandrax_language_client/configuration';
45
import * as imandraxLanguageClient from './imandrax_language_client/imandrax_language_client';
56
import * as installer from './installer';
67
import * as listeners from './listeners';
@@ -11,8 +12,7 @@ import {
1112
ExtensionMode,
1213
Uri,
1314
window,
14-
workspace,
15-
TextEditorDecorationType
15+
workspace
1616
} from "vscode";
1717

1818
import {
@@ -21,10 +21,10 @@ import {
2121

2222

2323
export async function activate(context: ExtensionContext) {
24-
const languageClientConfig = imandraxLanguageClient.configuration.get();
24+
const languageClientConfig = ImandraXLanguageClientConfiguration.get();
2525

26-
if (imandraxLanguageClient.configuration.isFoundPath(languageClientConfig)) {
27-
const languageClientWrapper_ = new imandraxLanguageClient.ImandraxLanguageClient(languageClientConfig);
26+
if (ImandraXLanguageClientConfiguration.isFoundPath(languageClientConfig)) {
27+
const languageClientWrapper_ = new imandraxLanguageClient.ImandraXLanguageClient();
2828
const getClient: () => LanguageClient = () => { return languageClientWrapper_.getClient(); };
2929

3030
formatter.register();
@@ -39,8 +39,8 @@ export async function activate(context: ExtensionContext) {
3939
(global as any).testListeners = listenersInstance;
4040
}
4141

42-
workspace.onDidChangeConfiguration(event => {
43-
languageClientWrapper_.update_configuration(context.extensionUri, event);
42+
workspace.onDidChangeConfiguration(async event => {
43+
await languageClientWrapper_.update_configuration(context.extensionUri, event);
4444
});
4545

4646
await languageClientWrapper_.start({ extensionUri: context.extensionUri });

src/imandrax_language_client/configuration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ type BinPathAvailability =
2424
}
2525

2626
export interface ImandraXLanguageClientConfiguration {
27-
serverArgs: any,
28-
mergedEnv: any,
27+
serverArgs: string[],
28+
mergedEnv: object,
2929
binPathAvailability: BinPathAvailability,
3030
}
3131

src/imandrax_language_client/imandrax_language_client.ts

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
11
import * as commands from '../commands/commands';
22
import * as decorations from '../decorations';
33
import * as vfsProvider from '../vfs_provider';
4-
5-
import { FoundPathConfig } from './configuration';
4+
import * as configuration from './configuration';
65

76
import { ConfigurationChangeEvent, ExtensionContext, ExtensionMode, Uri, window, workspace, WorkspaceConfiguration } from 'vscode';
87
import { Executable, LanguageClient, LanguageClientOptions } from 'vscode-languageclient/node';
98

109

11-
export * as configuration from './configuration';
12-
13-
1410
const MAX_RESTARTS = 10;
1511

1612
export interface RestartParams {
1713
extensionUri: Uri
1814
}
1915

20-
export class ImandraxLanguageClient {
21-
private readonly serverOptions: Executable;
16+
export class ImandraXLanguageClient {
2217
private client!: LanguageClient;
2318
private readonly vfsProvider_: vfsProvider.VFSContentProvider;
2419
private restartCount = 0;
@@ -38,22 +33,30 @@ export class ImandraxLanguageClient {
3833
return this.vfsProvider_;
3934
}
4035

41-
constructor(languageClientConfig: FoundPathConfig) {
42-
this.serverOptions = {
43-
command: languageClientConfig.binPathAvailability.path,
44-
args: languageClientConfig.serverArgs,
45-
options: { env: languageClientConfig.mergedEnv }
46-
};
36+
constructor() {
4737
this.vfsProvider_ = new vfsProvider.VFSContentProvider(() => { return this.getClient(); });
4838
}
4939

5040
// Start language server
5141
async start(params: { extensionUri: Uri }): Promise<void> {
42+
const config = configuration.get();
43+
44+
if (!configuration.isFoundPath(config)) {
45+
console.log("ImandraX binary not found, cannot start language server.");
46+
return;
47+
}
48+
5249
const was_initial = this.isInitial();
5350
if (was_initial) {
5451
console.log("Starting ImandraX LSP server");
5552
}
5653

54+
const serverOptions : Executable = {
55+
command: config.binPathAvailability.path,
56+
args: config.serverArgs,
57+
options: { env: config.mergedEnv }
58+
};
59+
5760
// Options to control the language client
5861
const clientOptions: LanguageClientOptions = {
5962
// Register the server for plain text documents
@@ -71,7 +74,7 @@ export class ImandraxLanguageClient {
7174
this.client = new LanguageClient(
7275
"imandrax_lsp",
7376
"ImandraX LSP",
74-
this.serverOptions,
77+
serverOptions,
7578
clientOptions
7679
);
7780

@@ -86,7 +89,7 @@ export class ImandraxLanguageClient {
8689
(params) => { commands.visualize_decomp(extensionUri, params); });
8790
this.client.onNotification("$imandrax/vfs-file-changed",
8891
(params) => {
89-
const uri = Uri.parse(params["uri"]);
92+
const uri = Uri.parse(params.uri);
9093
this.vfsProvider_.onDidChangeEmitter.fire(uri);
9194
});
9295
}
@@ -131,9 +134,9 @@ export class ImandraxLanguageClient {
131134
if (event === undefined || event.affectsConfiguration('imandrax')) {
132135
const client = this.client;
133136
if (event && (
134-
event.affectsConfiguration('imandrax.lsp.binary') ||
135-
event.affectsConfiguration('imandrax.lsp.arguments') ||
136-
event.affectsConfiguration('imandrax.lsp.environment'))) {
137+
event.affectsConfiguration("imandrax.lsp.binary") ||
138+
event.affectsConfiguration("imandrax.lsp.arguments") ||
139+
event.affectsConfiguration("imandrax.lsp.environment"))) {
137140
await this.restart({ extensionUri: extensionUri });
138141
}
139142

src/listeners.ts

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as decorations from './decorations';
22

3-
import { commands, DecorationOptions, DiagnosticSeverity, ExtensionContext, languages, StatusBarAlignment, StatusBarItem, TextEditor, ThemeColor, Uri, window } from 'vscode';
3+
import { commands, DecorationOptions, DiagnosticSeverity, ExtensionContext, languages, StatusBarAlignment, StatusBarItem, TextEditor, ThemeColor, Uri, window, DiagnosticChangeEvent } from 'vscode';
44
import { LanguageClient } from 'vscode-languageclient/node';
55

66

@@ -39,21 +39,20 @@ export class Listeners {
3939
}
4040

4141
diagnostics_for_editor(editor: TextEditor) {
42-
let all_good: DecorationOptions[] = [];
43-
const all_bad: DecorationOptions[] = [];
44-
const doc = editor.document;
45-
if (doc !== undefined) {
46-
languages.getDiagnostics(doc.uri).forEach(d => {
42+
if (editor) {
43+
const uri = editor.document.uri;
44+
let all_good: DecorationOptions[] = [];
45+
const all_bad: DecorationOptions[] = [];
46+
const diags = languages.getDiagnostics(uri);
47+
diags.forEach(d => {
4748
if (d.source === "lsp") {
48-
if (editor) {
49-
const good = d.severity === DiagnosticSeverity.Information || d.severity === DiagnosticSeverity.Hint;
50-
const range = d.range.with(d.range.start, d.range.start);
51-
const decoration_options: DecorationOptions = { range: range };
52-
if (good) {
53-
all_good.push(decoration_options);
54-
} else {
55-
all_bad.push(decoration_options);
56-
}
49+
const good = d.severity === DiagnosticSeverity.Information || d.severity === DiagnosticSeverity.Hint;
50+
const range = d.range.with(d.range.start, d.range.start);
51+
const decoration_options: DecorationOptions = { range: range };
52+
if (good) {
53+
all_good.push(decoration_options);
54+
} else {
55+
all_bad.push(decoration_options);
5756
}
5857
}
5958
}
@@ -99,51 +98,47 @@ export class Listeners {
9998
}
10099
}
101100

102-
async diagnostic_listener() {
103-
const editor = window.activeTextEditor;
104-
if (editor !== undefined) {
105-
const doc = editor.document;
106-
if (doc !== undefined) {
107-
if (doc.languageId === "imandrax") {
101+
async diagnostic_listener(e: DiagnosticChangeEvent) {
102+
await Promise.all(e.uris.map(async uri => {
103+
const editor = window.visibleTextEditors.find(e => e.document.uri.path == uri.path)
104+
if (editor) {
105+
const doc = editor.document;
106+
if (doc && doc.languageId === "imandrax") {
108107
this.diagnostics_for_editor(editor);
109-
const file_uri = editor.document.uri;
110-
if (file_uri.scheme === "file") {
111-
await this.req_file_progress(file_uri);
108+
if (doc.uri.scheme === "file") {
109+
await this.req_file_progress(doc.uri);
112110
} else {
113111
this.file_progress_sbi.hide();
114112
}
115113
}
116114
}
117115
}
116+
));
118117
}
119118

120-
async active_editor_listener() {
121-
const editor = window.activeTextEditor;
122-
if (editor !== undefined) {
119+
async active_editor_listener(editor: TextEditor | undefined) {
120+
if (editor) {
123121
const doc = editor.document;
124-
if (doc !== undefined) {
125-
if (doc.languageId === "imandrax") {
126-
this.diagnostics_for_editor(editor);
127-
const file_uri = doc.uri;
128-
if (file_uri.scheme === "file") {
129-
if (this.getClient()?.isRunning()) {
130-
await this.getClient().sendNotification("$imandrax/active-document", { "uri": file_uri.path });
131-
}
132-
await this.req_file_progress(file_uri);
133-
}
134-
else {
135-
this.file_progress_sbi.hide();
122+
if (doc && doc.languageId === "imandrax") {
123+
this.diagnostics_for_editor(editor);
124+
if (doc.uri.scheme === "file") {
125+
if (this.getClient()?.isRunning()) {
126+
await this.getClient().sendNotification("$imandrax/active-document", { "uri": doc.uri.path });
136127
}
128+
await this.req_file_progress(doc.uri);
137129
}
138130
else {
139131
this.file_progress_sbi.hide();
140132
}
141133
}
134+
else {
135+
this.file_progress_sbi.hide();
136+
}
142137
}
143138
}
144139

145140
public register() {
146-
languages.onDidChangeDiagnostics(async () => { await this.diagnostic_listener(); }, undefined, []);
147-
window.onDidChangeActiveTextEditor(async () => { await this.active_editor_listener(); }, undefined, []);
141+
languages.onDidChangeDiagnostics(async (e: DiagnosticChangeEvent) => { await this.diagnostic_listener(e); });
142+
window.onDidChangeActiveTextEditor(async (e: TextEditor | undefined) => { await this.active_editor_listener(e); });
148143
}
149144
}

src/test/commands.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
/*
2-
eslint-disable
1+
/*
2+
eslint-disable
33
@typescript-eslint/no-unsafe-assignment,
4-
@typescript-eslint/no-explicit-any,
5-
@typescript-eslint/no-unsafe-member-access
4+
@typescript-eslint/no-explicit-any,
5+
@typescript-eslint/no-unsafe-member-access
66
*/
77

88
import * as assert from 'assert';
@@ -11,7 +11,7 @@ import * as os from 'os';
1111
import * as path from 'path';
1212
import * as util from './util';
1313
import * as vscode from 'vscode';
14-
import { ImandraxLanguageClient } from '../imandrax_language_client/imandrax_language_client';
14+
import { ImandraXLanguageClient } from '../imandrax_language_client/imandrax_language_client';
1515

1616

1717
suite('Commands Test Suite', () => {
@@ -20,7 +20,7 @@ suite('Commands Test Suite', () => {
2020
});
2121

2222
let extensionContext: vscode.ExtensionContext | undefined;
23-
let imandraxLanguageClient_: ImandraxLanguageClient | undefined;
23+
let imandraxLanguageClient_: ImandraXLanguageClient | undefined;
2424
suiteSetup(async () => {
2525
console.log("suite setup")
2626
const ext = vscode.extensions.getExtension('imandra.imandrax');
@@ -38,7 +38,7 @@ suite('Commands Test Suite', () => {
3838
'create terminal should increase',
3939
'the window.terminals.length by 1'
4040
].join(' '), async () => {
41-
// arrange
41+
// arrange
4242
console.log("get term count");
4343
const term_count = vscode.window.terminals.length;
4444

0 commit comments

Comments
 (0)