Skip to content

Commit 7364e91

Browse files
Fix automatic restart of language server upon changes in configuration (#63)
1 parent 6dba5d5 commit 7364e91

File tree

10 files changed

+89
-89
lines changed

10 files changed

+89
-89
lines changed

eslint.config.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export default tseslint.config(
2424
"@typescript-eslint/no-unsafe-member-access": "warn",
2525
"@typescript-eslint/dot-notation": "warn",
2626
"@typescript-eslint/no-explicit-any": "warn",
27-
"@typescript-eslint/no-floating-promises": "warn"
2827
}
2928
},
3029
{

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"theme": "dark"
1111
},
1212
"license": "MIT",
13-
"version": "0.0.39",
13+
"version": "0.0.40",
1414
"repository": {
1515
"type": "git",
1616
"url": "https://github.com/imandra-ai/imandrax-vscode"

src/commands/implementations.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,13 @@ ${body}
118118
panel.webview.html = html;
119119
}
120120

121-
export function checkAll(getClient: () => LanguageClient) {
121+
export async function checkAll(getClient: () => LanguageClient) {
122122
if (!getClient()) {
123123
return undefined;
124124
}
125125
const file_uri = window.activeTextEditor?.document.uri;
126126
if (getClient() && getClient().isRunning() && file_uri?.scheme === "file") {
127-
getClient().sendRequest("workspace/executeCommand", { "command": "check-all", "arguments": [file_uri.toString()] });
127+
await getClient().sendRequest("workspace/executeCommand", { "command": "check-all", "arguments": [file_uri.toString()] });
128128
}
129129
}
130130

@@ -157,9 +157,9 @@ export function terminal_eval_selection(): boolean {
157157
return true;
158158
}
159159

160-
export function clear_cache(getClient: () => LanguageClient) {
160+
export async function clear_cache(getClient: () => LanguageClient) {
161161
if (getClient()?.isRunning()) {
162-
getClient().sendRequest("workspace/executeCommand", { "command": "clear-cache", "arguments": [] });
162+
await getClient().sendRequest("workspace/executeCommand", { "command": "clear-cache", "arguments": [] });
163163
}
164164
return true;
165165
}

src/commands/registration.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
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";
10-
const restart_handler = () => {
11-
imandraxLanguageClient.restart({ extensionUri: context.extensionUri });
10+
const restart_handler = async () => {
11+
await imandraxLanguageClient.restart({ extensionUri: context.extensionUri });
1212
};
1313
context.subscriptions.push(commands.registerCommand(restart_cmd, restart_handler));
1414

1515
const check_all_cmd = "imandrax.check_all";
16-
const check_all_handler = () => { implementations.checkAll(getClient); };
16+
const check_all_handler = async () => { await implementations.checkAll(getClient); };
1717
context.subscriptions.push(commands.registerCommand(check_all_cmd, check_all_handler));
1818

1919
const browse_cmd = "imandrax.browse";
@@ -33,7 +33,7 @@ export function register(context: ExtensionContext, imandraxLanguageClient: Iman
3333
context.subscriptions.push(commands.registerCommand(terminal_eval_selection_cmd, terminal_eval_selection_handler));
3434

3535
const clear_cache_cmd = "imandrax.clear_cache";
36-
const clear_cache_handler = () => { implementations.clear_cache(getClient); };
36+
const clear_cache_handler = async () => { await implementations.clear_cache(getClient); };
3737
context.subscriptions.push(commands.registerCommand(clear_cache_cmd, clear_cache_handler));
3838

3939
const open_vfs_file_cmd = "imandrax.open_vfs_file";
@@ -60,10 +60,10 @@ export function register(context: ExtensionContext, imandraxLanguageClient: Iman
6060
context.subscriptions.push(commands.registerCommand(open_goal_state_cmd, open_goal_state_handler));
6161

6262
const reset_goal_state_cmd = "imandrax.reset_goal_state";
63-
const reset_goal_state_handler = () => {
63+
const reset_goal_state_handler = async () => {
6464
if (getClient()?.isRunning()) {
6565
try {
66-
getClient().sendRequest("workspace/executeCommand", { "command": "reset-goal-state", "arguments": [] });
66+
await getClient().sendRequest("workspace/executeCommand", { "command": "reset-goal-state", "arguments": [] });
6767
}
6868
catch (e) {
6969
console.log("caught something!");

src/extension.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import {
1111
ExtensionMode,
1212
Uri,
1313
window,
14-
workspace,
15-
TextEditorDecorationType
14+
workspace
1615
} from "vscode";
1716

1817
import {
@@ -21,10 +20,11 @@ import {
2120

2221

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

2626
if (imandraxLanguageClient.configuration.isFoundPath(languageClientConfig)) {
27-
const languageClientWrapper_ = new imandraxLanguageClient.ImandraxLanguageClient(languageClientConfig);
27+
const languageClientWrapper_ = new imandraxLanguageClient.ImandraXLanguageClient(getConfig);
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: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,25 @@
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

10-
119
export * as configuration from './configuration';
1210

13-
1411
const MAX_RESTARTS = 10;
1512

1613
export interface RestartParams {
1714
extensionUri: Uri
1815
}
1916

20-
export class ImandraxLanguageClient {
21-
private readonly serverOptions: Executable;
17+
export class ImandraXLanguageClient {
2218
private client!: LanguageClient;
2319
private readonly vfsProvider_: vfsProvider.VFSContentProvider;
2420
private restartCount = 0;
2521
private isInitial = () => { return this.client === undefined; };
22+
private readonly getConfig: () => configuration.ImandraXLanguageClientConfiguration;
2623

2724
getRestartCount(context: ExtensionContext) {
2825
if (context?.extensionMode === ExtensionMode.Test) {
@@ -38,22 +35,31 @@ export class ImandraxLanguageClient {
3835
return this.vfsProvider_;
3936
}
4037

41-
constructor(languageClientConfig: FoundPathConfig) {
42-
this.serverOptions = {
43-
command: languageClientConfig.binPathAvailability.path,
44-
args: languageClientConfig.serverArgs,
45-
options: { env: languageClientConfig.mergedEnv }
46-
};
38+
constructor(getConfig:()=>configuration.ImandraXLanguageClientConfiguration) {
39+
this.getConfig = getConfig;
4740
this.vfsProvider_ = new vfsProvider.VFSContentProvider(() => { return this.getClient(); });
4841
}
4942

5043
// Start language server
5144
async start(params: { extensionUri: Uri }): Promise<void> {
45+
const config = this.getConfig();
46+
47+
if (!configuration.isFoundPath(config)) {
48+
console.log("ImandraX binary not found, cannot start language server.");
49+
return;
50+
}
51+
5252
const was_initial = this.isInitial();
5353
if (was_initial) {
5454
console.log("Starting ImandraX LSP server");
5555
}
5656

57+
const serverOptions: Executable = {
58+
command: config.binPathAvailability.path,
59+
args: config.serverArgs,
60+
options: { env: config.mergedEnv }
61+
};
62+
5763
// Options to control the language client
5864
const clientOptions: LanguageClientOptions = {
5965
// Register the server for plain text documents
@@ -71,7 +77,7 @@ export class ImandraxLanguageClient {
7177
this.client = new LanguageClient(
7278
"imandrax_lsp",
7379
"ImandraX LSP",
74-
this.serverOptions,
80+
serverOptions,
7581
clientOptions
7682
);
7783

@@ -86,7 +92,7 @@ export class ImandraxLanguageClient {
8692
(params) => { commands.visualize_decomp(extensionUri, params); });
8793
this.client.onNotification("$imandrax/vfs-file-changed",
8894
(params) => {
89-
const uri = Uri.parse(params["uri"]);
95+
const uri = Uri.parse(params.uri);
9096
this.vfsProvider_.onDidChangeEmitter.fire(uri);
9197
});
9298
}
@@ -131,9 +137,9 @@ export class ImandraxLanguageClient {
131137
if (event === undefined || event.affectsConfiguration('imandrax')) {
132138
const client = this.client;
133139
if (event && (
134-
event.affectsConfiguration('imandrax.lsp.binary') ||
135-
event.affectsConfiguration('imandrax.lsp.arguments') ||
136-
event.affectsConfiguration('imandrax.lsp.environment'))) {
140+
event.affectsConfiguration("imandrax.lsp.binary") ||
141+
event.affectsConfiguration("imandrax.lsp.arguments") ||
142+
event.affectsConfiguration("imandrax.lsp.environment"))) {
137143
await this.restart({ extensionUri: extensionUri });
138144
}
139145

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
}

0 commit comments

Comments
 (0)