lean4monaco 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/dist/vscode-lean4/vscode-lean4/src/utils/depInstaller.d.ts +81 -0
- package/dist/vscode-lean4/vscode-lean4/src/utils/depInstaller.js +372 -0
- package/package.json +1 -1
- package/dist/JuliaMono-Regular.ttf +0 -0
- package/dist/lean4-infoview/codicon.ttf +0 -0
- package/dist/lean4-infoview/esm-shims/react-dom.d.ts +0 -5
- package/dist/lean4-infoview/esm-shims/react-jsx-runtime.d.ts +0 -5
- package/dist/lean4-infoview/esm-shims/react.d.ts +0 -5
- package/dist/lean4-infoview/index.css +0 -4161
- package/dist/lean4-infoview/index.d.ts +0 -16
- package/dist/lean4-infoview/index.development.js +0 -37312
- package/dist/lean4-infoview/index.production.min.js +0 -1528
- package/dist/lean4-infoview/infoview/collapsing.d.ts +0 -12
- package/dist/lean4-infoview/infoview/contexts.d.ts +0 -10
- package/dist/lean4-infoview/infoview/editorConnection.d.ts +0 -22
- package/dist/lean4-infoview/infoview/errors.d.ts +0 -14
- package/dist/lean4-infoview/infoview/event.d.ts +0 -33
- package/dist/lean4-infoview/infoview/goalLocation.d.ts +0 -61
- package/dist/lean4-infoview/infoview/goals.d.ts +0 -46
- package/dist/lean4-infoview/infoview/info.d.ts +0 -18
- package/dist/lean4-infoview/infoview/infos.d.ts +0 -2
- package/dist/lean4-infoview/infoview/interactiveCode.d.ts +0 -19
- package/dist/lean4-infoview/infoview/main.d.ts +0 -13
- package/dist/lean4-infoview/infoview/messages.d.ts +0 -19
- package/dist/lean4-infoview/infoview/rpcSessions.d.ts +0 -11
- package/dist/lean4-infoview/infoview/serverVersion.d.ts +0 -10
- package/dist/lean4-infoview/infoview/tooltips.d.ts +0 -32
- package/dist/lean4-infoview/infoview/traceExplorer.d.ts +0 -11
- package/dist/lean4-infoview/infoview/userWidget.d.ts +0 -39
- package/dist/lean4-infoview/infoview/util.d.ts +0 -144
- package/dist/lean4-infoview/loader.d.ts +0 -20
- package/dist/lean4-infoview/loader.development.js +0 -1006
- package/dist/lean4-infoview/loader.production.min.js +0 -1
- package/dist/lean4-infoview/react-dom.development.js +0 -30537
- package/dist/lean4-infoview/react-dom.production.min.js +0 -21
- package/dist/lean4-infoview/react-jsx-runtime.development.js +0 -1362
- package/dist/lean4-infoview/react-jsx-runtime.production.min.js +0 -1
- package/dist/lean4-infoview/react.development.js +0 -2823
- package/dist/lean4-infoview/react.production.min.js +0 -1
- package/dist/monaco-lean4/vscode-lean4/package.json +0 -944
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationFeature.d.ts +0 -9
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationFeature.js +0 -20
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationHoverProvider.d.ts +0 -12
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationHoverProvider.js +0 -40
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationRewriterFeature.d.ts +0 -20
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationRewriterFeature.js +0 -79
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/VSCodeAbbreviationConfig.d.ts +0 -13
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/VSCodeAbbreviationConfig.js +0 -29
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/VSCodeAbbreviationRewriter.d.ts +0 -28
- package/dist/monaco-lean4/vscode-lean4/src/abbreviation/VSCodeAbbreviationRewriter.js +0 -124
- package/dist/monaco-lean4/vscode-lean4/src/config.d.ts +0 -33
- package/dist/monaco-lean4/vscode-lean4/src/config.js +0 -119
- package/dist/monaco-lean4/vscode-lean4/src/diagnostics/setupNotifs.d.ts +0 -27
- package/dist/monaco-lean4/vscode-lean4/src/diagnostics/setupNotifs.js +0 -133
- package/dist/monaco-lean4/vscode-lean4/src/infoview.d.ts +0 -69
- package/dist/monaco-lean4/vscode-lean4/src/infoview.js +0 -711
- package/dist/monaco-lean4/vscode-lean4/src/leanclient.d.ts +0 -67
- package/dist/monaco-lean4/vscode-lean4/src/leanclient.js +0 -443
- package/dist/monaco-lean4/vscode-lean4/src/rpc.d.ts +0 -16
- package/dist/monaco-lean4/vscode-lean4/src/rpc.js +0 -102
- package/dist/monaco-lean4/vscode-lean4/src/taskgutter.d.ts +0 -11
- package/dist/monaco-lean4/vscode-lean4/src/taskgutter.js +0 -130
- package/dist/monaco-lean4/vscode-lean4/src/utils/batch.d.ts +0 -37
- package/dist/monaco-lean4/vscode-lean4/src/utils/batch.js +0 -203
- package/dist/monaco-lean4/vscode-lean4/src/utils/clientProvider.d.ts +0 -41
- package/dist/monaco-lean4/vscode-lean4/src/utils/clientProvider.js +0 -205
- package/dist/monaco-lean4/vscode-lean4/src/utils/converters.d.ts +0 -16
- package/dist/monaco-lean4/vscode-lean4/src/utils/converters.js +0 -129
- package/dist/monaco-lean4/vscode-lean4/src/utils/elan.d.ts +0 -3
- package/dist/monaco-lean4/vscode-lean4/src/utils/elan.js +0 -4
- package/dist/monaco-lean4/vscode-lean4/src/utils/envPath.d.ts +0 -21
- package/dist/monaco-lean4/vscode-lean4/src/utils/envPath.js +0 -53
- package/dist/monaco-lean4/vscode-lean4/src/utils/exturi.d.ts +0 -35
- package/dist/monaco-lean4/vscode-lean4/src/utils/exturi.js +0 -136
- package/dist/monaco-lean4/vscode-lean4/src/utils/fsHelper.d.ts +0 -17
- package/dist/monaco-lean4/vscode-lean4/src/utils/fsHelper.js +0 -36
- package/dist/monaco-lean4/vscode-lean4/src/utils/leanInstaller.d.ts +0 -37
- package/dist/monaco-lean4/vscode-lean4/src/utils/leanInstaller.js +0 -210
- package/dist/monaco-lean4/vscode-lean4/src/utils/logger.d.ts +0 -7
- package/dist/monaco-lean4/vscode-lean4/src/utils/logger.js +0 -20
- package/dist/monaco-lean4/vscode-lean4/src/utils/notifs.d.ts +0 -24
- package/dist/monaco-lean4/vscode-lean4/src/utils/notifs.js +0 -110
- package/dist/monaco-lean4/vscode-lean4/src/utils/projectInfo.d.ts +0 -9
- package/dist/monaco-lean4/vscode-lean4/src/utils/projectInfo.js +0 -125
- package/dist/useragent.d.ts +0 -1
- package/dist/useragent.js +0 -31
- package/dist/vscode.css +0 -7
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { DiagnosticCollection, Disposable, OutputChannel, TextDocument } from 'vscode';
|
|
2
|
-
import { BaseLanguageClient, DidChangeTextDocumentParams, DidCloseTextDocumentParams, InitializeResult, LanguageClientOptions, PublishDiagnosticsParams } from 'vscode-languageclient/node';
|
|
3
|
-
import { LeanFileProgressProcessingInfo, ServerStoppedReason } from '@leanprover/infoview-api';
|
|
4
|
-
import { ExtUri } from './utils/exturi';
|
|
5
|
-
export type ServerProgress = Map<ExtUri, LeanFileProgressProcessingInfo[]>;
|
|
6
|
-
export declare class LeanClient implements Disposable {
|
|
7
|
-
private setupClient;
|
|
8
|
-
private isOpenLeanDocument;
|
|
9
|
-
running: boolean;
|
|
10
|
-
private client;
|
|
11
|
-
private outputChannel;
|
|
12
|
-
folderUri: ExtUri;
|
|
13
|
-
private subscriptions;
|
|
14
|
-
private noPrompt;
|
|
15
|
-
private showingRestartMessage;
|
|
16
|
-
private elanDefaultToolchain;
|
|
17
|
-
private isRestarting;
|
|
18
|
-
private staleDepNotifier;
|
|
19
|
-
private openServerDocuments;
|
|
20
|
-
private didChangeEmitter;
|
|
21
|
-
didChange: import("vscode").Event<DidChangeTextDocumentParams>;
|
|
22
|
-
private diagnosticsEmitter;
|
|
23
|
-
diagnostics: import("vscode").Event<PublishDiagnosticsParams>;
|
|
24
|
-
private didSetLanguageEmitter;
|
|
25
|
-
didSetLanguage: import("vscode").Event<string>;
|
|
26
|
-
private didCloseEmitter;
|
|
27
|
-
didClose: import("vscode").Event<DidCloseTextDocumentParams>;
|
|
28
|
-
private customNotificationEmitter;
|
|
29
|
-
/** Fires whenever a custom notification (i.e. one not defined in LSP) is received. */
|
|
30
|
-
customNotification: import("vscode").Event<{
|
|
31
|
-
method: string;
|
|
32
|
-
params: any;
|
|
33
|
-
}>;
|
|
34
|
-
/** saved progress info in case infoview is opened, it needs to get all of it. */
|
|
35
|
-
progress: ServerProgress;
|
|
36
|
-
private progressChangedEmitter;
|
|
37
|
-
progressChanged: import("vscode").Event<[string, LeanFileProgressProcessingInfo[]]>;
|
|
38
|
-
private stoppedEmitter;
|
|
39
|
-
stopped: import("vscode").Event<ServerStoppedReason>;
|
|
40
|
-
private restartedEmitter;
|
|
41
|
-
restarted: import("vscode").Event<unknown>;
|
|
42
|
-
private restartingEmitter;
|
|
43
|
-
restarting: import("vscode").Event<unknown>;
|
|
44
|
-
private restartedWorkerEmitter;
|
|
45
|
-
restartedWorker: import("vscode").Event<string>;
|
|
46
|
-
private serverFailedEmitter;
|
|
47
|
-
serverFailed: import("vscode").Event<string>;
|
|
48
|
-
constructor(folderUri: ExtUri, outputChannel: OutputChannel, elanDefaultToolchain: string, setupClient: (clientOptions: LanguageClientOptions, folderUri: ExtUri, elanDefaultToolchain: string) => Promise<BaseLanguageClient>, isOpenLeanDocument: (docUri: ExtUri) => boolean);
|
|
49
|
-
dispose(): void;
|
|
50
|
-
showRestartMessage(restartFile?: boolean, uri?: ExtUri | undefined): void;
|
|
51
|
-
restart(): Promise<void>;
|
|
52
|
-
private startClient;
|
|
53
|
-
private checkForImportsOutdatedError;
|
|
54
|
-
withStoppedClient(action: () => Promise<void>): Promise<'Success' | 'IsRestarting'>;
|
|
55
|
-
isInFolderManagedByThisClient(uri: ExtUri): boolean;
|
|
56
|
-
getClientFolder(): ExtUri;
|
|
57
|
-
start(): Promise<void>;
|
|
58
|
-
isStarted(): boolean;
|
|
59
|
-
isRunning(): boolean;
|
|
60
|
-
stop(): Promise<void>;
|
|
61
|
-
restartFile(doc: TextDocument): Promise<void>;
|
|
62
|
-
sendRequest(method: string, params: any): Promise<any>;
|
|
63
|
-
sendNotification(method: string, params: any): Promise<void> | undefined;
|
|
64
|
-
getDiagnostics(): DiagnosticCollection | undefined;
|
|
65
|
-
get initializeResult(): InitializeResult | undefined;
|
|
66
|
-
private obtainClientOptions;
|
|
67
|
-
}
|
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
import { Disposable, DocumentHighlightKind, EventEmitter, ProgressLocation, Range, window, workspace, } from 'vscode';
|
|
2
|
-
import { DiagnosticSeverity, RevealOutputChannelOn, State, } from 'vscode-languageclient/node';
|
|
3
|
-
import { getElaborationDelay, getFallBackToStringOccurrenceHighlighting, shouldAutofocusOutput, } from './config';
|
|
4
|
-
import { logger } from './utils/logger';
|
|
5
|
-
// @ts-ignore
|
|
6
|
-
import { SemVer } from 'semver';
|
|
7
|
-
import { c2pConverter, p2cConverter, patchConverters, setDependencyBuildMode } from './utils/converters';
|
|
8
|
-
import { parseExtUri, toExtUri } from './utils/exturi';
|
|
9
|
-
import { displayError, displayErrorWithOptionalInput, displayErrorWithOutput, displayInformationWithOptionalInput, } from './utils/notifs';
|
|
10
|
-
import path from 'path';
|
|
11
|
-
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
12
|
-
export class LeanClient {
|
|
13
|
-
setupClient;
|
|
14
|
-
isOpenLeanDocument;
|
|
15
|
-
running;
|
|
16
|
-
client;
|
|
17
|
-
outputChannel;
|
|
18
|
-
folderUri;
|
|
19
|
-
subscriptions = [];
|
|
20
|
-
noPrompt = false;
|
|
21
|
-
showingRestartMessage = false;
|
|
22
|
-
elanDefaultToolchain;
|
|
23
|
-
isRestarting = false;
|
|
24
|
-
staleDepNotifier;
|
|
25
|
-
openServerDocuments = new Set();
|
|
26
|
-
didChangeEmitter = new EventEmitter();
|
|
27
|
-
didChange = this.didChangeEmitter.event;
|
|
28
|
-
diagnosticsEmitter = new EventEmitter();
|
|
29
|
-
diagnostics = this.diagnosticsEmitter.event;
|
|
30
|
-
didSetLanguageEmitter = new EventEmitter();
|
|
31
|
-
didSetLanguage = this.didSetLanguageEmitter.event;
|
|
32
|
-
didCloseEmitter = new EventEmitter();
|
|
33
|
-
didClose = this.didCloseEmitter.event;
|
|
34
|
-
customNotificationEmitter = new EventEmitter();
|
|
35
|
-
/** Fires whenever a custom notification (i.e. one not defined in LSP) is received. */
|
|
36
|
-
customNotification = this.customNotificationEmitter.event;
|
|
37
|
-
/** saved progress info in case infoview is opened, it needs to get all of it. */
|
|
38
|
-
progress = new Map();
|
|
39
|
-
progressChangedEmitter = new EventEmitter();
|
|
40
|
-
progressChanged = this.progressChangedEmitter.event;
|
|
41
|
-
stoppedEmitter = new EventEmitter();
|
|
42
|
-
stopped = this.stoppedEmitter.event;
|
|
43
|
-
restartedEmitter = new EventEmitter();
|
|
44
|
-
restarted = this.restartedEmitter.event;
|
|
45
|
-
restartingEmitter = new EventEmitter();
|
|
46
|
-
restarting = this.restartingEmitter.event;
|
|
47
|
-
restartedWorkerEmitter = new EventEmitter();
|
|
48
|
-
restartedWorker = this.restartedWorkerEmitter.event;
|
|
49
|
-
serverFailedEmitter = new EventEmitter();
|
|
50
|
-
serverFailed = this.serverFailedEmitter.event;
|
|
51
|
-
constructor(folderUri, outputChannel, elanDefaultToolchain, setupClient, isOpenLeanDocument) {
|
|
52
|
-
this.setupClient = setupClient;
|
|
53
|
-
this.isOpenLeanDocument = isOpenLeanDocument;
|
|
54
|
-
this.outputChannel = outputChannel; // can be null when opening adhoc files.
|
|
55
|
-
this.folderUri = folderUri;
|
|
56
|
-
this.elanDefaultToolchain = elanDefaultToolchain;
|
|
57
|
-
this.subscriptions.push(new Disposable(() => {
|
|
58
|
-
if (this.staleDepNotifier) {
|
|
59
|
-
this.staleDepNotifier.dispose();
|
|
60
|
-
}
|
|
61
|
-
}));
|
|
62
|
-
}
|
|
63
|
-
dispose() {
|
|
64
|
-
this.subscriptions.forEach(s => s.dispose());
|
|
65
|
-
if (this.isStarted())
|
|
66
|
-
void this.stop();
|
|
67
|
-
}
|
|
68
|
-
showRestartMessage(restartFile = false, uri) {
|
|
69
|
-
if (this.showingRestartMessage) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
this.showingRestartMessage = true;
|
|
73
|
-
const finalizer = () => {
|
|
74
|
-
this.showingRestartMessage = false;
|
|
75
|
-
};
|
|
76
|
-
let restartItem;
|
|
77
|
-
let messageTitle;
|
|
78
|
-
if (!restartFile) {
|
|
79
|
-
restartItem = 'Restart Lean Server';
|
|
80
|
-
messageTitle = 'Lean Server has stopped unexpectedly.';
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
restartItem = 'Restart Lean Server on this file';
|
|
84
|
-
messageTitle = 'The Lean Server has stopped processing this file.';
|
|
85
|
-
}
|
|
86
|
-
displayErrorWithOptionalInput(messageTitle, restartItem, () => {
|
|
87
|
-
if (restartFile && uri !== undefined) {
|
|
88
|
-
const document = workspace.textDocuments.find(doc => uri.equalsUri(doc.uri));
|
|
89
|
-
if (document) {
|
|
90
|
-
void this.restartFile(document);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
void this.start();
|
|
95
|
-
}
|
|
96
|
-
}, finalizer);
|
|
97
|
-
}
|
|
98
|
-
async restart() {
|
|
99
|
-
if (this.isRestarting) {
|
|
100
|
-
displayError('Client is already being started.');
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
this.isRestarting = true;
|
|
104
|
-
try {
|
|
105
|
-
logger.log('[LeanClient] Restarting Lean Server');
|
|
106
|
-
if (this.isStarted()) {
|
|
107
|
-
await this.stop();
|
|
108
|
-
}
|
|
109
|
-
this.restartingEmitter.fire(undefined);
|
|
110
|
-
const progressOptions = {
|
|
111
|
-
location: ProgressLocation.Notification,
|
|
112
|
-
title: 'Starting Lean language client',
|
|
113
|
-
cancellable: false,
|
|
114
|
-
};
|
|
115
|
-
await window.withProgress(progressOptions, async (progress) => await this.startClient(progress));
|
|
116
|
-
}
|
|
117
|
-
finally {
|
|
118
|
-
this.isRestarting = false;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
async startClient(progress) {
|
|
122
|
-
// Should only be called from `restart`
|
|
123
|
-
const startTime = Date.now();
|
|
124
|
-
progress.report({ increment: 0 });
|
|
125
|
-
this.client = await this.setupClient(this.obtainClientOptions(), this.folderUri, this.elanDefaultToolchain);
|
|
126
|
-
patchConverters(this.client.protocol2CodeConverter, this.client.code2ProtocolConverter);
|
|
127
|
-
let insideRestart = true;
|
|
128
|
-
try {
|
|
129
|
-
this.client.onDidChangeState(async (s) => {
|
|
130
|
-
// see https://github.com/microsoft/vscode-languageserver-node/issues/825
|
|
131
|
-
if (s.newState === State.Starting) {
|
|
132
|
-
logger.log('[LeanClient] starting');
|
|
133
|
-
}
|
|
134
|
-
else if (s.newState === State.Running) {
|
|
135
|
-
const end = Date.now();
|
|
136
|
-
logger.log(`[LeanClient] running, started in ${end - startTime} ms`);
|
|
137
|
-
this.running = true; // may have been auto restarted after it failed.
|
|
138
|
-
if (!insideRestart) {
|
|
139
|
-
this.restartedEmitter.fire(undefined);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
else if (s.newState === State.Stopped) {
|
|
143
|
-
this.running = false;
|
|
144
|
-
logger.log('[LeanClient] has stopped or it failed to start');
|
|
145
|
-
if (!this.noPrompt) {
|
|
146
|
-
// only raise this event and show the message if we are not the ones
|
|
147
|
-
// who called the stop() method.
|
|
148
|
-
this.stoppedEmitter.fire({ message: 'Lean server has stopped.', reason: '' });
|
|
149
|
-
this.showRestartMessage();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
progress.report({ increment: 80 });
|
|
154
|
-
await this.client.start();
|
|
155
|
-
const version = this.client.initializeResult?.serverInfo?.version;
|
|
156
|
-
if (version && new SemVer(version).compare('0.2.0') < 0) {
|
|
157
|
-
if (this.staleDepNotifier) {
|
|
158
|
-
this.staleDepNotifier.dispose();
|
|
159
|
-
}
|
|
160
|
-
this.staleDepNotifier = this.diagnostics(params => this.checkForImportsOutdatedError(params));
|
|
161
|
-
}
|
|
162
|
-
// if we got this far then the client is happy so we are running!
|
|
163
|
-
this.running = true;
|
|
164
|
-
}
|
|
165
|
-
catch (error) {
|
|
166
|
-
const msg = '' + error;
|
|
167
|
-
logger.log(`[LeanClient] restart error ${msg}`);
|
|
168
|
-
this.outputChannel.appendLine(msg);
|
|
169
|
-
this.serverFailedEmitter.fire(msg);
|
|
170
|
-
insideRestart = false;
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
// HACK(WN): Register a default notification handler to fire on custom notifications.
|
|
174
|
-
// A mechanism to do this is provided in vscode-jsonrpc. One can register a `StarNotificationHandler`
|
|
175
|
-
// here: https://github.com/microsoft/vscode-languageserver-node/blob/b2fc85d28a1a44c22896559ee5f4d3ba37a02ef5/jsonrpc/src/common/connection.ts#L497
|
|
176
|
-
// which fires on any LSP notifications not in the standard, for example the `$/lean/..` ones.
|
|
177
|
-
// However this mechanism is not exposed in vscode-languageclient, so we hack around its implementation.
|
|
178
|
-
const starHandler = (method, params_) => {
|
|
179
|
-
if (method === '$/lean/fileProgress' && this.client) {
|
|
180
|
-
const params = params_;
|
|
181
|
-
const uri = toExtUri(p2cConverter.asUri(params.textDocument.uri));
|
|
182
|
-
if (uri !== undefined) {
|
|
183
|
-
this.progressChangedEmitter.fire([uri.toString(), params.processing]);
|
|
184
|
-
// save the latest progress on this Uri in case infoview needs it later.
|
|
185
|
-
this.progress.set(uri, params.processing);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
this.customNotificationEmitter.fire({ method, params: params_ });
|
|
189
|
-
};
|
|
190
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
191
|
-
this.client.onNotification(starHandler, () => { });
|
|
192
|
-
// Reveal the standard error output channel when the server prints something to stderr.
|
|
193
|
-
// The vscode-languageclient library already takes care of writing it to the output channel.
|
|
194
|
-
let stderrMsgBoxVisible = false;
|
|
195
|
-
this.client._serverProcess.stderr.on('data', async (chunk) => {
|
|
196
|
-
if (shouldAutofocusOutput()) {
|
|
197
|
-
this.client?.outputChannel.show(true);
|
|
198
|
-
}
|
|
199
|
-
else if (!stderrMsgBoxVisible) {
|
|
200
|
-
stderrMsgBoxVisible = true;
|
|
201
|
-
const finalizer = () => {
|
|
202
|
-
stderrMsgBoxVisible = false;
|
|
203
|
-
};
|
|
204
|
-
displayErrorWithOutput(`Lean server printed an error:\n${chunk.toString()}`, finalizer);
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
this.restartedEmitter.fire(undefined);
|
|
208
|
-
insideRestart = false;
|
|
209
|
-
}
|
|
210
|
-
checkForImportsOutdatedError(params) {
|
|
211
|
-
const fileUri = parseExtUri(params.uri);
|
|
212
|
-
if (fileUri === undefined) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
const fileName = fileUri.scheme === 'file' ? path.basename(fileUri.fsPath) : 'untitled';
|
|
216
|
-
const isImportsOutdatedError = params.diagnostics.some(d => d.severity === DiagnosticSeverity.Error &&
|
|
217
|
-
d.message.includes('Imports are out of date and must be rebuilt') &&
|
|
218
|
-
d.range.start.line === 0 &&
|
|
219
|
-
d.range.start.character === 0 &&
|
|
220
|
-
d.range.end.line === 0 &&
|
|
221
|
-
d.range.end.character === 0);
|
|
222
|
-
if (!isImportsOutdatedError) {
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
const message = `Imports of '${fileName}' are out of date and must be rebuilt. Restarting the file will rebuild them.`;
|
|
226
|
-
const input = 'Restart File';
|
|
227
|
-
displayInformationWithOptionalInput(message, input, () => {
|
|
228
|
-
const document = workspace.textDocuments.find(doc => fileUri.equalsUri(doc.uri));
|
|
229
|
-
if (!document || document.isClosed) {
|
|
230
|
-
displayError(`'${fileName}' was closed in the meantime. Imports will not be rebuilt.`);
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
void this.restartFile(document);
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
async withStoppedClient(action) {
|
|
237
|
-
if (this.isRestarting) {
|
|
238
|
-
return 'IsRestarting';
|
|
239
|
-
}
|
|
240
|
-
this.isRestarting = true; // Ensure that client cannot be restarted in the mean-time
|
|
241
|
-
if (this.isStarted()) {
|
|
242
|
-
await this.stop();
|
|
243
|
-
}
|
|
244
|
-
await action();
|
|
245
|
-
this.isRestarting = false;
|
|
246
|
-
await this.restart();
|
|
247
|
-
return 'Success';
|
|
248
|
-
}
|
|
249
|
-
isInFolderManagedByThisClient(uri) {
|
|
250
|
-
if (this.folderUri.scheme === 'untitled' && uri.scheme === 'untitled') {
|
|
251
|
-
return true;
|
|
252
|
-
}
|
|
253
|
-
if (this.folderUri.scheme === 'file' && uri.scheme === 'file') {
|
|
254
|
-
return uri.isInFolder(this.folderUri);
|
|
255
|
-
}
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
getClientFolder() {
|
|
259
|
-
return this.folderUri;
|
|
260
|
-
}
|
|
261
|
-
start() {
|
|
262
|
-
return this.restart();
|
|
263
|
-
}
|
|
264
|
-
isStarted() {
|
|
265
|
-
return this.client !== undefined;
|
|
266
|
-
}
|
|
267
|
-
isRunning() {
|
|
268
|
-
if (this.client) {
|
|
269
|
-
return this.running;
|
|
270
|
-
}
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
|
-
async stop() {
|
|
274
|
-
if (this.client && this.running) {
|
|
275
|
-
this.noPrompt = true;
|
|
276
|
-
try {
|
|
277
|
-
// some timing conditions can happen while running unit tests that cause
|
|
278
|
-
// this to throw an exception which then causes those tests to fail.
|
|
279
|
-
await this.client.stop();
|
|
280
|
-
}
|
|
281
|
-
catch (e) {
|
|
282
|
-
logger.log(`[LeanClient] Error stopping language client: ${e}`);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
this.noPrompt = false;
|
|
286
|
-
this.progress = new Map();
|
|
287
|
-
this.client = undefined;
|
|
288
|
-
this.openServerDocuments = new Set();
|
|
289
|
-
this.running = false;
|
|
290
|
-
}
|
|
291
|
-
async restartFile(doc) {
|
|
292
|
-
if (this.client === undefined || !this.running)
|
|
293
|
-
return; // there was a problem starting lean server.
|
|
294
|
-
const docUri = toExtUri(doc.uri);
|
|
295
|
-
if (docUri === undefined) {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
if (!this.isInFolderManagedByThisClient(docUri)) {
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
const uri = docUri.toString();
|
|
302
|
-
if (!this.openServerDocuments.delete(uri)) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
logger.log(`[LeanClient] Restarting File: ${uri}`);
|
|
306
|
-
await this.client.sendNotification('textDocument/didClose', this.client.code2ProtocolConverter.asCloseTextDocumentParams(doc));
|
|
307
|
-
if (this.openServerDocuments.has(uri)) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
this.openServerDocuments.add(uri);
|
|
311
|
-
await this.client.sendNotification('textDocument/didOpen', setDependencyBuildMode(this.client.code2ProtocolConverter.asOpenTextDocumentParams(doc), 'once'));
|
|
312
|
-
this.restartedWorkerEmitter.fire(uri);
|
|
313
|
-
}
|
|
314
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
315
|
-
sendRequest(method, params) {
|
|
316
|
-
return this.running && this.client
|
|
317
|
-
? this.client.sendRequest(method, params)
|
|
318
|
-
: new Promise((_, reject) => {
|
|
319
|
-
reject('Client is not running');
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
323
|
-
sendNotification(method, params) {
|
|
324
|
-
return this.running && this.client ? this.client.sendNotification(method, params) : undefined;
|
|
325
|
-
}
|
|
326
|
-
getDiagnostics() {
|
|
327
|
-
return this.running ? this.client?.diagnostics : undefined;
|
|
328
|
-
}
|
|
329
|
-
get initializeResult() {
|
|
330
|
-
return this.running ? this.client?.initializeResult : undefined;
|
|
331
|
-
}
|
|
332
|
-
obtainClientOptions() {
|
|
333
|
-
const documentSelector = {
|
|
334
|
-
language: 'lean4',
|
|
335
|
-
};
|
|
336
|
-
let workspaceFolder;
|
|
337
|
-
documentSelector.scheme = this.folderUri.scheme;
|
|
338
|
-
if (this.folderUri.scheme === 'file') {
|
|
339
|
-
documentSelector.pattern = `${this.folderUri.fsPath}/**/*`;
|
|
340
|
-
workspaceFolder = {
|
|
341
|
-
uri: this.folderUri.asUri(),
|
|
342
|
-
name: path.basename(this.folderUri.fsPath),
|
|
343
|
-
index: 0, // the language client library does not actually need this index
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
return {
|
|
347
|
-
outputChannel: this.outputChannel,
|
|
348
|
-
revealOutputChannelOn: RevealOutputChannelOn.Never, // contrary to the name, this disables the message boxes
|
|
349
|
-
documentSelector: [documentSelector],
|
|
350
|
-
workspaceFolder,
|
|
351
|
-
initializationOptions: {
|
|
352
|
-
editDelay: getElaborationDelay(),
|
|
353
|
-
hasWidgets: true,
|
|
354
|
-
},
|
|
355
|
-
connectionOptions: {
|
|
356
|
-
maxRestartCount: 0,
|
|
357
|
-
cancellationStrategy: undefined,
|
|
358
|
-
},
|
|
359
|
-
middleware: {
|
|
360
|
-
handleDiagnostics: (uri, diagnostics, next) => {
|
|
361
|
-
next(uri, diagnostics);
|
|
362
|
-
const uri_ = c2pConverter.asUri(uri);
|
|
363
|
-
const diagnostics_ = [];
|
|
364
|
-
for (const d of diagnostics) {
|
|
365
|
-
const d_ = {
|
|
366
|
-
...c2pConverter.asDiagnostic(d),
|
|
367
|
-
};
|
|
368
|
-
diagnostics_.push(d_);
|
|
369
|
-
}
|
|
370
|
-
this.diagnosticsEmitter.fire({ uri: uri_, diagnostics: diagnostics_ });
|
|
371
|
-
},
|
|
372
|
-
didOpen: async (doc, next) => {
|
|
373
|
-
const docUri = toExtUri(doc.uri);
|
|
374
|
-
if (!docUri) {
|
|
375
|
-
return; // This should never happen since the glob we launch the client for ensures that all uris are ext uris
|
|
376
|
-
}
|
|
377
|
-
const docIsOpen = this.isOpenLeanDocument(docUri);
|
|
378
|
-
if (!docIsOpen) {
|
|
379
|
-
// The language client library emits a `didOpen` notification when hovering over an identifier while holding `Ctrl` in order to provide a preview for the line that the definition is on.
|
|
380
|
-
// In Lean, this is very expensive and hence does not make much sense, so we filter these notification here.
|
|
381
|
-
// Should VS Code decide to send requests to a file that was filtered here, the language server will respond with an error, which VS Code will silently discard and interpret as having received an empty response.
|
|
382
|
-
// See https://github.com/microsoft/vscode/issues/78453 (the solution suggested in the thread is wrong, but `collectAllOpenLeanDocumentUris` works).
|
|
383
|
-
}
|
|
384
|
-
if (this.openServerDocuments.has(docUri.toString())) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
this.openServerDocuments.add(docUri.toString());
|
|
388
|
-
await next(doc);
|
|
389
|
-
// Opening the document may have set the language ID.
|
|
390
|
-
this.didSetLanguageEmitter.fire(doc.languageId);
|
|
391
|
-
},
|
|
392
|
-
didChange: async (data, next) => {
|
|
393
|
-
await next(data);
|
|
394
|
-
const params = c2pConverter.asChangeTextDocumentParams(data, data.document.uri, data.document.version);
|
|
395
|
-
this.didChangeEmitter.fire(params);
|
|
396
|
-
},
|
|
397
|
-
didClose: async (doc, next) => {
|
|
398
|
-
const docUri = toExtUri(doc.uri);
|
|
399
|
-
if (!docUri) {
|
|
400
|
-
return; // This should never happen since the glob we launch the client for ensures that all uris are ext uris
|
|
401
|
-
}
|
|
402
|
-
if (!this.openServerDocuments.delete(docUri.toString())) {
|
|
403
|
-
// Do not send `didClose` if we filtered the corresponding `didOpen` (see comment in the `didOpen` middleware).
|
|
404
|
-
// The language server is only resilient against requests for closed files, not the `didClose` notification itself.
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
await next(doc);
|
|
408
|
-
const params = c2pConverter.asCloseTextDocumentParams(doc);
|
|
409
|
-
this.didCloseEmitter.fire(params);
|
|
410
|
-
},
|
|
411
|
-
provideDocumentHighlights: async (doc, pos, ctok, next) => {
|
|
412
|
-
const leanHighlights = await next(doc, pos, ctok);
|
|
413
|
-
if (leanHighlights?.length)
|
|
414
|
-
return leanHighlights;
|
|
415
|
-
// vscode doesn't fall back to textual highlights, so we
|
|
416
|
-
// need to do that manually if the user asked for it
|
|
417
|
-
if (!getFallBackToStringOccurrenceHighlighting()) {
|
|
418
|
-
return [];
|
|
419
|
-
}
|
|
420
|
-
await new Promise(res => setTimeout(res, 250));
|
|
421
|
-
if (ctok.isCancellationRequested)
|
|
422
|
-
return;
|
|
423
|
-
const wordRange = doc.getWordRangeAtPosition(pos);
|
|
424
|
-
if (!wordRange)
|
|
425
|
-
return;
|
|
426
|
-
const word = doc.getText(wordRange);
|
|
427
|
-
const highlights = [];
|
|
428
|
-
const text = doc.getText();
|
|
429
|
-
const nonWordPattern = '[`~@$%^&*()-=+\\[{\\]}⟨⟩⦃⦄⟦⟧⟮⟯‹›\\\\|;:",./\\s]|^|$';
|
|
430
|
-
const regexp = new RegExp(`(?<=${nonWordPattern})${escapeRegExp(word)}(?=${nonWordPattern})`, 'g');
|
|
431
|
-
for (const match of text.matchAll(regexp)) {
|
|
432
|
-
const start = doc.positionAt(match.index ?? 0);
|
|
433
|
-
highlights.push({
|
|
434
|
-
range: new Range(start, start.translate(0, match[0].length)),
|
|
435
|
-
kind: DocumentHighlightKind.Text,
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
return highlights;
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export declare class Rpc {
|
|
2
|
-
readonly sendMessage: (msg: any) => void;
|
|
3
|
-
private seqNum;
|
|
4
|
-
private methods;
|
|
5
|
-
private pending;
|
|
6
|
-
/** Resolves when both sides of the channel are ready to receive procedure calls. */
|
|
7
|
-
private initPromise;
|
|
8
|
-
private resolveInit;
|
|
9
|
-
private initialized;
|
|
10
|
-
constructor(sendMessage: (msg: any) => void);
|
|
11
|
-
/** Register procedures that the other side of the channel can invoke. Must be called exactly once. */
|
|
12
|
-
register<T>(methods: T): void;
|
|
13
|
-
messageReceived(msg: any): void;
|
|
14
|
-
invoke(name: string, args: any[]): Promise<any>;
|
|
15
|
-
getApi<T>(): T;
|
|
16
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
export class Rpc {
|
|
2
|
-
sendMessage;
|
|
3
|
-
seqNum = 0;
|
|
4
|
-
methods = {};
|
|
5
|
-
pending = {};
|
|
6
|
-
/** Resolves when both sides of the channel are ready to receive procedure calls. */
|
|
7
|
-
initPromise;
|
|
8
|
-
resolveInit;
|
|
9
|
-
initialized = false;
|
|
10
|
-
constructor(sendMessage) {
|
|
11
|
-
this.sendMessage = sendMessage;
|
|
12
|
-
this.resolveInit = () => { }; // pacify the typechecker; the real initializer is below
|
|
13
|
-
this.initPromise = new Promise(resolve => {
|
|
14
|
-
this.resolveInit = resolve;
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
/** Register procedures that the other side of the channel can invoke. Must be called exactly once. */
|
|
18
|
-
register(methods) {
|
|
19
|
-
if (this.initialized)
|
|
20
|
-
throw new Error('RPC methods already registered');
|
|
21
|
-
this.methods = { ...methods };
|
|
22
|
-
const interval = setInterval(() => {
|
|
23
|
-
this.sendMessage({ kind: 'initialize' });
|
|
24
|
-
}, 50);
|
|
25
|
-
const prevResolveInit = this.resolveInit;
|
|
26
|
-
this.resolveInit = () => {
|
|
27
|
-
clearInterval(interval);
|
|
28
|
-
prevResolveInit();
|
|
29
|
-
};
|
|
30
|
-
this.initialized = true;
|
|
31
|
-
}
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
33
|
-
messageReceived(msg) {
|
|
34
|
-
if (msg.kind) {
|
|
35
|
-
if (msg.kind === 'initialize') {
|
|
36
|
-
this.sendMessage({ kind: 'initialized' });
|
|
37
|
-
}
|
|
38
|
-
else if (msg.kind === 'initialized' && this.initialized) {
|
|
39
|
-
this.resolveInit();
|
|
40
|
-
}
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
const { seqNum, name, args, result, exception } = msg;
|
|
44
|
-
if (seqNum === undefined)
|
|
45
|
-
return;
|
|
46
|
-
if (name !== undefined) {
|
|
47
|
-
// It's important that we wait on `initPromise` here. Otherwise we may try to invoke
|
|
48
|
-
// a method before `register` is called.
|
|
49
|
-
return void this.initPromise.then(async () => {
|
|
50
|
-
try {
|
|
51
|
-
const fn = this.methods[name];
|
|
52
|
-
if (fn === undefined)
|
|
53
|
-
throw new Error(`unknown RPC method ${name}`);
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
55
|
-
this.sendMessage({ seqNum, result: await fn(...args) });
|
|
56
|
-
}
|
|
57
|
-
catch (ex) {
|
|
58
|
-
this.sendMessage({ seqNum, exception: prepareExceptionForSerialization(ex) });
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
if (exception !== undefined) {
|
|
63
|
-
this.pending[seqNum].reject(exception);
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
this.pending[seqNum].resolve(result);
|
|
67
|
-
}
|
|
68
|
-
delete this.pending[seqNum];
|
|
69
|
-
}
|
|
70
|
-
async invoke(name, args) {
|
|
71
|
-
await this.initPromise;
|
|
72
|
-
this.seqNum += 1;
|
|
73
|
-
const seqNum = this.seqNum;
|
|
74
|
-
return new Promise((resolve, reject) => {
|
|
75
|
-
this.pending[seqNum] = { resolve, reject };
|
|
76
|
-
this.sendMessage({ seqNum, name, args });
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
getApi() {
|
|
80
|
-
return new Proxy({}, {
|
|
81
|
-
get: (_, prop) => (...args) => this.invoke(prop, args),
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function prepareExceptionForSerialization(ex) {
|
|
86
|
-
if (ex === undefined) {
|
|
87
|
-
return 'error';
|
|
88
|
-
}
|
|
89
|
-
else if (typeof ex === 'object' && !(ex instanceof Array)) {
|
|
90
|
-
/* Certain properties (such as `ex.message`) are not /enumerable/ per ECMAScript
|
|
91
|
-
* and disappear along the way through `Webview.postMessage`; we create a new object
|
|
92
|
-
* so that they make it through. */
|
|
93
|
-
const exOut = {};
|
|
94
|
-
for (const p of Object.getOwnPropertyNames(ex)) {
|
|
95
|
-
exOut[p] = ex[p];
|
|
96
|
-
}
|
|
97
|
-
return exOut;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
return ex;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Disposable, ExtensionContext } from 'vscode';
|
|
2
|
-
import { LeanClientProvider } from './utils/clientProvider';
|
|
3
|
-
export declare class LeanTaskGutter implements Disposable {
|
|
4
|
-
private decorations;
|
|
5
|
-
private status;
|
|
6
|
-
private gutters;
|
|
7
|
-
private subscriptions;
|
|
8
|
-
constructor(client: LeanClientProvider, context: ExtensionContext);
|
|
9
|
-
private updateDecos;
|
|
10
|
-
dispose(): void;
|
|
11
|
-
}
|