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.
Files changed (88) hide show
  1. package/README.md +2 -4
  2. package/dist/vscode-lean4/vscode-lean4/src/utils/depInstaller.d.ts +81 -0
  3. package/dist/vscode-lean4/vscode-lean4/src/utils/depInstaller.js +372 -0
  4. package/package.json +1 -1
  5. package/dist/JuliaMono-Regular.ttf +0 -0
  6. package/dist/lean4-infoview/codicon.ttf +0 -0
  7. package/dist/lean4-infoview/esm-shims/react-dom.d.ts +0 -5
  8. package/dist/lean4-infoview/esm-shims/react-jsx-runtime.d.ts +0 -5
  9. package/dist/lean4-infoview/esm-shims/react.d.ts +0 -5
  10. package/dist/lean4-infoview/index.css +0 -4161
  11. package/dist/lean4-infoview/index.d.ts +0 -16
  12. package/dist/lean4-infoview/index.development.js +0 -37312
  13. package/dist/lean4-infoview/index.production.min.js +0 -1528
  14. package/dist/lean4-infoview/infoview/collapsing.d.ts +0 -12
  15. package/dist/lean4-infoview/infoview/contexts.d.ts +0 -10
  16. package/dist/lean4-infoview/infoview/editorConnection.d.ts +0 -22
  17. package/dist/lean4-infoview/infoview/errors.d.ts +0 -14
  18. package/dist/lean4-infoview/infoview/event.d.ts +0 -33
  19. package/dist/lean4-infoview/infoview/goalLocation.d.ts +0 -61
  20. package/dist/lean4-infoview/infoview/goals.d.ts +0 -46
  21. package/dist/lean4-infoview/infoview/info.d.ts +0 -18
  22. package/dist/lean4-infoview/infoview/infos.d.ts +0 -2
  23. package/dist/lean4-infoview/infoview/interactiveCode.d.ts +0 -19
  24. package/dist/lean4-infoview/infoview/main.d.ts +0 -13
  25. package/dist/lean4-infoview/infoview/messages.d.ts +0 -19
  26. package/dist/lean4-infoview/infoview/rpcSessions.d.ts +0 -11
  27. package/dist/lean4-infoview/infoview/serverVersion.d.ts +0 -10
  28. package/dist/lean4-infoview/infoview/tooltips.d.ts +0 -32
  29. package/dist/lean4-infoview/infoview/traceExplorer.d.ts +0 -11
  30. package/dist/lean4-infoview/infoview/userWidget.d.ts +0 -39
  31. package/dist/lean4-infoview/infoview/util.d.ts +0 -144
  32. package/dist/lean4-infoview/loader.d.ts +0 -20
  33. package/dist/lean4-infoview/loader.development.js +0 -1006
  34. package/dist/lean4-infoview/loader.production.min.js +0 -1
  35. package/dist/lean4-infoview/react-dom.development.js +0 -30537
  36. package/dist/lean4-infoview/react-dom.production.min.js +0 -21
  37. package/dist/lean4-infoview/react-jsx-runtime.development.js +0 -1362
  38. package/dist/lean4-infoview/react-jsx-runtime.production.min.js +0 -1
  39. package/dist/lean4-infoview/react.development.js +0 -2823
  40. package/dist/lean4-infoview/react.production.min.js +0 -1
  41. package/dist/monaco-lean4/vscode-lean4/package.json +0 -944
  42. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationFeature.d.ts +0 -9
  43. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationFeature.js +0 -20
  44. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationHoverProvider.d.ts +0 -12
  45. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationHoverProvider.js +0 -40
  46. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationRewriterFeature.d.ts +0 -20
  47. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/AbbreviationRewriterFeature.js +0 -79
  48. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/VSCodeAbbreviationConfig.d.ts +0 -13
  49. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/VSCodeAbbreviationConfig.js +0 -29
  50. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/VSCodeAbbreviationRewriter.d.ts +0 -28
  51. package/dist/monaco-lean4/vscode-lean4/src/abbreviation/VSCodeAbbreviationRewriter.js +0 -124
  52. package/dist/monaco-lean4/vscode-lean4/src/config.d.ts +0 -33
  53. package/dist/monaco-lean4/vscode-lean4/src/config.js +0 -119
  54. package/dist/monaco-lean4/vscode-lean4/src/diagnostics/setupNotifs.d.ts +0 -27
  55. package/dist/monaco-lean4/vscode-lean4/src/diagnostics/setupNotifs.js +0 -133
  56. package/dist/monaco-lean4/vscode-lean4/src/infoview.d.ts +0 -69
  57. package/dist/monaco-lean4/vscode-lean4/src/infoview.js +0 -711
  58. package/dist/monaco-lean4/vscode-lean4/src/leanclient.d.ts +0 -67
  59. package/dist/monaco-lean4/vscode-lean4/src/leanclient.js +0 -443
  60. package/dist/monaco-lean4/vscode-lean4/src/rpc.d.ts +0 -16
  61. package/dist/monaco-lean4/vscode-lean4/src/rpc.js +0 -102
  62. package/dist/monaco-lean4/vscode-lean4/src/taskgutter.d.ts +0 -11
  63. package/dist/monaco-lean4/vscode-lean4/src/taskgutter.js +0 -130
  64. package/dist/monaco-lean4/vscode-lean4/src/utils/batch.d.ts +0 -37
  65. package/dist/monaco-lean4/vscode-lean4/src/utils/batch.js +0 -203
  66. package/dist/monaco-lean4/vscode-lean4/src/utils/clientProvider.d.ts +0 -41
  67. package/dist/monaco-lean4/vscode-lean4/src/utils/clientProvider.js +0 -205
  68. package/dist/monaco-lean4/vscode-lean4/src/utils/converters.d.ts +0 -16
  69. package/dist/monaco-lean4/vscode-lean4/src/utils/converters.js +0 -129
  70. package/dist/monaco-lean4/vscode-lean4/src/utils/elan.d.ts +0 -3
  71. package/dist/monaco-lean4/vscode-lean4/src/utils/elan.js +0 -4
  72. package/dist/monaco-lean4/vscode-lean4/src/utils/envPath.d.ts +0 -21
  73. package/dist/monaco-lean4/vscode-lean4/src/utils/envPath.js +0 -53
  74. package/dist/monaco-lean4/vscode-lean4/src/utils/exturi.d.ts +0 -35
  75. package/dist/monaco-lean4/vscode-lean4/src/utils/exturi.js +0 -136
  76. package/dist/monaco-lean4/vscode-lean4/src/utils/fsHelper.d.ts +0 -17
  77. package/dist/monaco-lean4/vscode-lean4/src/utils/fsHelper.js +0 -36
  78. package/dist/monaco-lean4/vscode-lean4/src/utils/leanInstaller.d.ts +0 -37
  79. package/dist/monaco-lean4/vscode-lean4/src/utils/leanInstaller.js +0 -210
  80. package/dist/monaco-lean4/vscode-lean4/src/utils/logger.d.ts +0 -7
  81. package/dist/monaco-lean4/vscode-lean4/src/utils/logger.js +0 -20
  82. package/dist/monaco-lean4/vscode-lean4/src/utils/notifs.d.ts +0 -24
  83. package/dist/monaco-lean4/vscode-lean4/src/utils/notifs.js +0 -110
  84. package/dist/monaco-lean4/vscode-lean4/src/utils/projectInfo.d.ts +0 -9
  85. package/dist/monaco-lean4/vscode-lean4/src/utils/projectInfo.js +0 -125
  86. package/dist/useragent.d.ts +0 -1
  87. package/dist/useragent.js +0 -31
  88. package/dist/vscode.css +0 -7
@@ -1,711 +0,0 @@
1
- import { RpcErrorCode, } from '@leanprover/infoview-api';
2
- import { commands, env, languages, Selection, TextEditorRevealType, ViewColumn, window, workspace, } from 'vscode';
3
- import { getEditorLineHeight, getInfoViewAllErrorsOnLine, getInfoViewAutoOpen, getInfoViewAutoOpenShowsGoal, getInfoViewDebounceTime, getInfoViewEmphasizeFirstGoal, getInfoViewReverseTacticState, getInfoViewShowExpectedType, getInfoViewShowGoalNames, getInfoViewShowTooltipOnHover, getInfoViewStyle, } from './config';
4
- import { c2pConverter, p2cConverter } from './utils/converters';
5
- import { parseExtUri, toExtUri } from './utils/exturi';
6
- import { logger } from './utils/logger';
7
- import { displayError, displayInformation } from './utils/notifs';
8
- const keepAlivePeriodMs = 10000;
9
- async function rpcConnect(client, uri) {
10
- const connParams = { uri };
11
- const result = await client.sendRequest('$/lean/rpc/connect', connParams);
12
- return result.sessionId;
13
- }
14
- class RpcSessionAtPos {
15
- sessionId;
16
- uri;
17
- keepAliveInterval;
18
- client;
19
- constructor(client, sessionId, uri) {
20
- this.sessionId = sessionId;
21
- this.uri = uri;
22
- this.client = client;
23
- this.keepAliveInterval = setInterval(async () => {
24
- const params = { uri, sessionId };
25
- try {
26
- await client.sendNotification('$/lean/rpc/keepAlive', params);
27
- }
28
- catch (e) {
29
- logger.log(`[InfoProvider] failed to send keepalive for ${uri}: ${e}`);
30
- if (this.keepAliveInterval)
31
- clearInterval(this.keepAliveInterval);
32
- }
33
- }, keepAlivePeriodMs);
34
- }
35
- dispose() {
36
- if (this.keepAliveInterval)
37
- clearInterval(this.keepAliveInterval);
38
- // TODO: at this point we could close the session
39
- }
40
- }
41
- export class InfoProvider {
42
- provider;
43
- leanDocs;
44
- context;
45
- infoWebviewFactory;
46
- /** Instance of the panel, if it is open. Otherwise `undefined`. */
47
- webviewPanel;
48
- subscriptions = [];
49
- clientSubscriptions = [];
50
- stylesheet = '';
51
- autoOpened = false;
52
- clientProvider;
53
- // Subscriptions are counted and only disposed of when count becomes 0.
54
- serverNotifSubscriptions = new Map();
55
- clientNotifSubscriptions = new Map();
56
- rpcSessions = new Map();
57
- // the key is the LeanClient.getClientFolder()
58
- clientsFailed = new Map();
59
- // the key is the uri of the file who's worker has failed.
60
- workersFailed = new Map();
61
- subscribeDidChangeNotification(client, method) {
62
- const h = client.didChange(params => {
63
- void this.webviewPanel?.api.sentClientNotification(method, params);
64
- });
65
- return h;
66
- }
67
- subscribeDidCloseNotification(client, method) {
68
- const h = client.didClose(params => {
69
- void this.webviewPanel?.api.sentClientNotification(method, params);
70
- });
71
- return h;
72
- }
73
- subscribeDiagnosticsNotification(client, method) {
74
- const h = client.diagnostics(params => {
75
- void this.webviewPanel?.api.gotServerNotification(method, params);
76
- });
77
- return h;
78
- }
79
- subscribeCustomNotification(client, method) {
80
- const h = client.customNotification(({ method: thisMethod, params }) => {
81
- if (thisMethod !== method)
82
- return;
83
- void this.webviewPanel?.api.gotServerNotification(method, params);
84
- });
85
- return h;
86
- }
87
- editorApi = {
88
- sendClientRequest: async (uri, method, params) => {
89
- const extUri = parseExtUri(uri);
90
- if (extUri === undefined) {
91
- return undefined;
92
- }
93
- const client = this.clientProvider.findClient(extUri);
94
- if (client) {
95
- try {
96
- const result = await client.sendRequest(method, params);
97
- return result;
98
- }
99
- catch (ex) {
100
- if (ex.code === RpcErrorCode.WorkerCrashed) {
101
- // ex codes related with worker exited or crashed
102
- logger.log(`[InfoProvider]The Lean Server has stopped processing this file: ${ex.message}`);
103
- await this.onWorkerStopped(uri, client, {
104
- message: 'The Lean Server has stopped processing this file: ',
105
- reason: ex.message,
106
- });
107
- }
108
- throw ex;
109
- }
110
- }
111
- return undefined;
112
- },
113
- sendClientNotification: async (uri, method, params) => {
114
- const extUri = parseExtUri(uri);
115
- if (extUri === undefined) {
116
- return;
117
- }
118
- const client = this.clientProvider.findClient(extUri);
119
- if (client) {
120
- await client.sendNotification(method, params);
121
- }
122
- },
123
- subscribeServerNotifications: async (method) => {
124
- const el = this.serverNotifSubscriptions.get(method);
125
- if (el) {
126
- const [count, h] = el;
127
- this.serverNotifSubscriptions.set(method, [count + 1, h]);
128
- return;
129
- }
130
- // NOTE(WN): For non-custom notifications we cannot call LanguageClient.onNotification
131
- // here because that *overwrites* the notification handler rather than registers an extra one.
132
- // So we have to add a bunch of event emitters to `LeanClient.`
133
- if (method === 'textDocument/publishDiagnostics') {
134
- const subscriptions = [];
135
- for (const client of this.clientProvider.getClients()) {
136
- subscriptions.push(this.subscribeDiagnosticsNotification(client, method));
137
- }
138
- this.serverNotifSubscriptions.set(method, [1, subscriptions]);
139
- }
140
- else if (method.startsWith('$')) {
141
- const subscriptions = [];
142
- for (const client of this.clientProvider.getClients()) {
143
- subscriptions.push(this.subscribeCustomNotification(client, method));
144
- }
145
- this.serverNotifSubscriptions.set(method, [1, subscriptions]);
146
- }
147
- else {
148
- throw new Error(`subscription to ${method} server notifications not implemented`);
149
- }
150
- },
151
- unsubscribeServerNotifications: async (method) => {
152
- const el = this.serverNotifSubscriptions.get(method);
153
- if (!el)
154
- throw new Error(`trying to unsubscribe from '${method}' with no active subscriptions`);
155
- const [count, subscriptions] = el;
156
- if (count === 1) {
157
- for (const h of subscriptions) {
158
- h.dispose();
159
- }
160
- this.serverNotifSubscriptions.delete(method);
161
- }
162
- else {
163
- this.serverNotifSubscriptions.set(method, [count - 1, subscriptions]);
164
- }
165
- },
166
- subscribeClientNotifications: async (method) => {
167
- const el = this.clientNotifSubscriptions.get(method);
168
- if (el) {
169
- const [count, d] = el;
170
- this.clientNotifSubscriptions.set(method, [count + 1, d]);
171
- return;
172
- }
173
- if (method === 'textDocument/didChange') {
174
- const subscriptions = [];
175
- for (const client of this.clientProvider.getClients()) {
176
- subscriptions.push(this.subscribeDidChangeNotification(client, method));
177
- }
178
- this.clientNotifSubscriptions.set(method, [1, subscriptions]);
179
- }
180
- else if (method === 'textDocument/didClose') {
181
- const subscriptions = [];
182
- for (const client of this.clientProvider.getClients()) {
183
- subscriptions.push(this.subscribeDidCloseNotification(client, method));
184
- }
185
- this.clientNotifSubscriptions.set(method, [1, subscriptions]);
186
- }
187
- else {
188
- throw new Error(`Subscription to '${method}' client notifications not implemented`);
189
- }
190
- },
191
- unsubscribeClientNotifications: async (method) => {
192
- const el = this.clientNotifSubscriptions.get(method);
193
- if (!el)
194
- throw new Error(`trying to unsubscribe from '${method}' with no active subscriptions`);
195
- const [count, subscriptions] = el;
196
- if (count === 1) {
197
- for (const d of subscriptions) {
198
- d.dispose();
199
- }
200
- this.clientNotifSubscriptions.delete(method);
201
- }
202
- else {
203
- this.clientNotifSubscriptions.set(method, [count - 1, subscriptions]);
204
- }
205
- },
206
- copyToClipboard: async (text) => {
207
- await env.clipboard.writeText(text);
208
- displayInformation(`Copied to clipboard: ${text}`);
209
- },
210
- insertText: async (text, kind, tdpp) => {
211
- let uri;
212
- let pos;
213
- if (tdpp) {
214
- uri = toExtUri(p2cConverter.asUri(tdpp.textDocument.uri));
215
- if (uri === undefined) {
216
- return;
217
- }
218
- pos = p2cConverter.asPosition(tdpp.position);
219
- }
220
- await this.handleInsertText(text, kind, uri, pos);
221
- },
222
- applyEdit: async (e) => {
223
- const we = await p2cConverter.asWorkspaceEdit(e);
224
- await workspace.applyEdit(we);
225
- },
226
- showDocument: async (show) => {
227
- const uri = parseExtUri(show.uri);
228
- if (uri === undefined) {
229
- return;
230
- }
231
- void this.revealEditorSelection(uri, p2cConverter.asRange(show.selection));
232
- },
233
- restartFile: async (uri) => {
234
- const extUri = parseExtUri(uri);
235
- if (extUri === undefined) {
236
- return;
237
- }
238
- const client = this.clientProvider.findClient(extUri);
239
- if (!client) {
240
- return;
241
- }
242
- const document = workspace.textDocuments.find(doc => extUri.equalsUri(doc.uri));
243
- if (!document || document.isClosed) {
244
- return;
245
- }
246
- await client.restartFile(document);
247
- },
248
- createRpcSession: async (uri) => {
249
- const extUri = parseExtUri(uri);
250
- if (extUri === undefined) {
251
- return '';
252
- }
253
- const client = this.clientProvider.findClient(extUri);
254
- if (!client)
255
- return '';
256
- const sessionId = await rpcConnect(client, uri);
257
- const session = new RpcSessionAtPos(client, sessionId, uri);
258
- if (!this.webviewPanel) {
259
- session.dispose();
260
- throw Error('infoview disconnect while connecting to RPC session');
261
- }
262
- else {
263
- this.rpcSessions.set(sessionId, session);
264
- return sessionId;
265
- }
266
- },
267
- closeRpcSession: async (sessionId) => {
268
- const session = this.rpcSessions.get(sessionId);
269
- if (session) {
270
- this.rpcSessions.delete(sessionId);
271
- session.dispose();
272
- }
273
- },
274
- };
275
- constructor(provider, leanDocs, context, infoWebviewFactory) {
276
- this.provider = provider;
277
- this.leanDocs = leanDocs;
278
- this.context = context;
279
- this.infoWebviewFactory = infoWebviewFactory;
280
- this.clientProvider = provider;
281
- this.updateStylesheet();
282
- provider.clientAdded(client => {
283
- void this.onClientAdded(client);
284
- });
285
- provider.clientRemoved(client => {
286
- void this.onClientRemoved(client);
287
- });
288
- provider.clientStopped(([client, activeClient, reason]) => {
289
- void this.onActiveClientStopped(client, activeClient, reason);
290
- });
291
- this.subscriptions.push(window.onDidChangeActiveTextEditor(() => this.sendPosition()), window.onDidChangeTextEditorSelection(() => this.sendPosition()), workspace.onDidChangeConfiguration(async (_e) => {
292
- // regression; changing the style needs a reload. :/
293
- this.updateStylesheet();
294
- await this.sendConfig();
295
- }), workspace.onDidChangeTextDocument(async () => {
296
- await this.sendPosition();
297
- }), commands.registerTextEditorCommand('lean4.displayGoal', editor => this.openPreview(editor)), commands.registerCommand('lean4.toggleInfoview', () => this.toggleInfoview()), commands.registerTextEditorCommand('lean4.displayList', async (editor) => {
298
- await this.openPreview(editor);
299
- await this.webviewPanel?.api.requestedAction({ kind: 'toggleAllMessages' });
300
- }), commands.registerTextEditorCommand('lean4.infoView.copyToComment', () => this.webviewPanel?.api.requestedAction({ kind: 'copyToComment' })), commands.registerCommand('lean4.infoView.toggleUpdating', () => this.webviewPanel?.api.requestedAction({ kind: 'togglePaused' })), commands.registerCommand('lean4.infoView.toggleExpectedType', () => this.webviewPanel?.api.requestedAction({ kind: 'toggleExpectedType' })), commands.registerTextEditorCommand('lean4.infoView.toggleStickyPosition', () => this.webviewPanel?.api.requestedAction({ kind: 'togglePin' })), commands.registerCommand('lean4.infoview.goToDefinition', args => this.webviewPanel?.api.goToDefinition(args.interactiveCodeTagId)));
301
- }
302
- async onClientRestarted(client) {
303
- // if we already have subscriptions for a previous client, we need to also
304
- // subscribe to the same things on this new client.
305
- for (const [method, [count, subscriptions]] of this.clientNotifSubscriptions) {
306
- if (method === 'textDocument/didChange') {
307
- subscriptions.push(this.subscribeDidChangeNotification(client, method));
308
- }
309
- else if (method === 'textDocument/didClose') {
310
- subscriptions.push(this.subscribeDidCloseNotification(client, method));
311
- }
312
- }
313
- for (const [method, [count, subscriptions]] of this.serverNotifSubscriptions) {
314
- if (method === 'textDocument/publishDiagnostics') {
315
- subscriptions.push(this.subscribeDiagnosticsNotification(client, method));
316
- }
317
- else if (method.startsWith('$')) {
318
- subscriptions.push(this.subscribeCustomNotification(client, method));
319
- }
320
- }
321
- await this.webviewPanel?.api.serverStopped(undefined); // clear any server stopped state
322
- const folderUri = client.getClientFolder();
323
- for (const worker of this.workersFailed.keys()) {
324
- const workerUri = parseExtUri(worker);
325
- if (workerUri !== undefined && client.isInFolderManagedByThisClient(workerUri)) {
326
- this.workersFailed.delete(worker);
327
- }
328
- }
329
- if (this.clientsFailed.has(folderUri.toString())) {
330
- this.clientsFailed.delete(folderUri.toString());
331
- }
332
- await this.initInfoView(window.activeTextEditor, client);
333
- }
334
- async onClientAdded(client) {
335
- logger.log(`[InfoProvider] Adding client for workspace: ${client.getClientFolder()}`);
336
- this.clientSubscriptions.push(client.restarted(async () => {
337
- logger.log('[InfoProvider] got client restarted event');
338
- // This event is triggered both the first time the server starts
339
- // as well as when the server restarts.
340
- this.clearRpcSessions(client);
341
- // Need to fully re-initialize this newly restarted client with all the
342
- // existing subscriptions and resend position info and so on so the
343
- // infoview updates properly.
344
- await this.onClientRestarted(client);
345
- }), client.restartedWorker(async (uri) => {
346
- logger.log('[InfoProvider] got worker restarted event');
347
- await this.onWorkerRestarted(uri);
348
- }), client.didSetLanguage(() => this.onLanguageChanged()));
349
- // Note that when new client is first created it still fires client.restarted
350
- // event, so all onClientRestarted can happen there so we don't do it twice.
351
- }
352
- async onWorkerRestarted(uri) {
353
- await this.webviewPanel?.api.serverStopped(undefined); // clear any server stopped state
354
- if (this.workersFailed.has(uri)) {
355
- this.workersFailed.delete(uri);
356
- logger.log('[InfoProvider] Restarting worker for file: ' + uri);
357
- }
358
- await this.sendPosition();
359
- }
360
- async onWorkerStopped(uri, client, reason) {
361
- await this.webviewPanel?.api.serverStopped(reason);
362
- const extUri = parseExtUri(uri);
363
- if (extUri === undefined) {
364
- return;
365
- }
366
- if (!this.workersFailed.has(uri)) {
367
- this.workersFailed.set(uri, reason);
368
- }
369
- logger.log(`[InfoProvider]client crashed: ${uri}`);
370
- client.showRestartMessage(true, extUri);
371
- }
372
- onClientRemoved(client) {
373
- // todo: remove subscriptions for this client...
374
- }
375
- async onActiveClientStopped(client, activeClient, reason) {
376
- // Will show a message in case the active client stops
377
- // add failed client into a list (will be removed in case the client is restarted)
378
- if (activeClient) {
379
- // means that client and active client are the same and just show the error message
380
- await this.webviewPanel?.api.serverStopped(reason);
381
- }
382
- logger.log(`[InfoProvider] client stopped: ${client.getClientFolder()}`);
383
- // remember this client is in a stopped state
384
- const key = client.getClientFolder();
385
- await this.sendPosition();
386
- if (!this.clientsFailed.has(key.toString())) {
387
- this.clientsFailed.set(key.toString(), reason);
388
- }
389
- logger.log(`[InfoProvider] client stopped: ${key}`);
390
- client.showRestartMessage();
391
- }
392
- dispose() {
393
- // active client is changing.
394
- this.clearNotificationHandlers();
395
- this.clearRpcSessions(null);
396
- for (const s of this.clientSubscriptions) {
397
- s.dispose();
398
- }
399
- for (const s of this.subscriptions) {
400
- s.dispose();
401
- }
402
- this.webviewPanel?.dispose();
403
- }
404
- isOpen() {
405
- return this.webviewPanel?.visible === true;
406
- }
407
- async runTestScript(javaScript) {
408
- if (this.webviewPanel) {
409
- return this.webviewPanel.api.runTestScript(javaScript);
410
- }
411
- else {
412
- throw new Error('Cannot run test script, infoview is closed.');
413
- }
414
- }
415
- async getHtmlContents() {
416
- if (this.webviewPanel) {
417
- return this.webviewPanel.api.getInfoviewHtml();
418
- }
419
- else {
420
- throw new Error('Cannot retrieve infoview HTML, infoview is closed.');
421
- }
422
- }
423
- sleep(ms) {
424
- return new Promise(resolve => setTimeout(resolve, ms));
425
- }
426
- async toggleAllMessages() {
427
- if (this.webviewPanel) {
428
- await this.webviewPanel.api.requestedAction({ kind: 'toggleAllMessages' });
429
- }
430
- }
431
- updateStylesheet() {
432
- // Here we add extra CSS variables which depend on the editor configuration,
433
- // but are not exposed by default.
434
- // Ref: https://code.visualstudio.com/api/extension-guides/webview#theming-webview-content
435
- const extraCSS = `
436
- html {
437
- --vscode-editor-line-height: ${getEditorLineHeight()}px;
438
- }
439
- `;
440
- const configCSS = getInfoViewStyle();
441
- this.stylesheet = extraCSS + configCSS;
442
- }
443
- async autoOpen() {
444
- if (!this.webviewPanel && !this.autoOpened && getInfoViewAutoOpen() && window.activeTextEditor) {
445
- // only auto-open for lean files, not for markdown.
446
- if (languages.match(this.leanDocs, window.activeTextEditor.document)) {
447
- // remember we've auto opened during this session so if user closes it it remains closed.
448
- this.autoOpened = true;
449
- return await this.openPreview(window.activeTextEditor);
450
- }
451
- }
452
- return false;
453
- }
454
- clearNotificationHandlers() {
455
- for (const [, [, subscriptions]] of this.clientNotifSubscriptions)
456
- for (const h of subscriptions)
457
- h.dispose();
458
- this.clientNotifSubscriptions.clear();
459
- for (const [, [, subscriptions]] of this.serverNotifSubscriptions)
460
- for (const h of subscriptions)
461
- h.dispose();
462
- this.serverNotifSubscriptions.clear();
463
- }
464
- clearRpcSessions(client) {
465
- const remaining = new Map();
466
- for (const [sessionId, sess] of this.rpcSessions) {
467
- if (client === null || sess.client === client) {
468
- sess.dispose();
469
- }
470
- else {
471
- remaining.set(sessionId, sess);
472
- }
473
- }
474
- this.rpcSessions = remaining;
475
- }
476
- async toggleInfoview() {
477
- if (this.webviewPanel) {
478
- this.webviewPanel.dispose();
479
- // the onDispose handler sets this.webviewPanel = undefined
480
- }
481
- else if (window.activeTextEditor && window.activeTextEditor.document.languageId === 'lean4') {
482
- await this.openPreview(window.activeTextEditor);
483
- }
484
- else {
485
- displayError('No active Lean editor tab. Make sure to focus the Lean editor tab for which you want to open the infoview.');
486
- }
487
- }
488
- async openPreview(editor) {
489
- const docUri = toExtUri(editor.document.uri);
490
- if (docUri === undefined) {
491
- return false;
492
- }
493
- let column = editor && editor.viewColumn ? editor.viewColumn + 1 : ViewColumn.Two;
494
- if (column === 4) {
495
- column = ViewColumn.Three;
496
- }
497
- if (this.webviewPanel) {
498
- this.webviewPanel.reveal(column, true);
499
- }
500
- else {
501
- this.webviewPanel = this.infoWebviewFactory.make(this.editorApi, this.stylesheet, column);
502
- this.webviewPanel.onDidDispose(() => {
503
- this.webviewPanel = undefined;
504
- this.clearNotificationHandlers();
505
- this.clearRpcSessions(null); // should be after `webviewPanel = undefined`
506
- });
507
- const client = this.clientProvider.findClient(docUri);
508
- await this.initInfoView(editor, client);
509
- }
510
- return true;
511
- }
512
- async initInfoView(editor, client) {
513
- if (editor) {
514
- const loc = this.getLocation(editor);
515
- if (loc) {
516
- await this.webviewPanel?.api.initialize(loc);
517
- }
518
- }
519
- // The infoview gets information about file progress, diagnostics, etc.
520
- // by listening to notifications. Send these notifications when the infoview starts
521
- // so that it has up-to-date information.
522
- if (client?.initializeResult) {
523
- logger.log('[InfoProvider] initInfoView!');
524
- await this.sendConfig();
525
- await this.webviewPanel?.api.serverStopped(undefined); // clear any server stopped state
526
- await this.webviewPanel?.api.serverRestarted(client.initializeResult);
527
- await this.sendDiagnostics(client);
528
- await this.sendProgress(client);
529
- await this.sendPosition();
530
- }
531
- else if (client === undefined) {
532
- logger.log('[InfoProvider] initInfoView got null client.');
533
- }
534
- else {
535
- logger.log('[InfoProvider] initInfoView got undefined client.initializeResult');
536
- }
537
- }
538
- async sendConfig() {
539
- await this.webviewPanel?.api.changedInfoviewConfig({
540
- allErrorsOnLine: getInfoViewAllErrorsOnLine(),
541
- autoOpenShowsGoal: getInfoViewAutoOpenShowsGoal(),
542
- debounceTime: getInfoViewDebounceTime(),
543
- showExpectedType: getInfoViewShowExpectedType(),
544
- showGoalNames: getInfoViewShowGoalNames(),
545
- emphasizeFirstGoal: getInfoViewEmphasizeFirstGoal(),
546
- reverseTacticState: getInfoViewReverseTacticState(),
547
- showTooltipOnHover: getInfoViewShowTooltipOnHover(),
548
- });
549
- }
550
- static async getDiagnosticParams(uri, diagnostics) {
551
- const params = {
552
- uri: c2pConverter.asUri(uri),
553
- diagnostics: await c2pConverter.asDiagnostics(diagnostics),
554
- };
555
- return params;
556
- }
557
- async sendDiagnostics(client) {
558
- const panel = this.webviewPanel;
559
- if (panel) {
560
- client.getDiagnostics()?.forEach(async (uri, diags) => {
561
- const params = InfoProvider.getDiagnosticParams(uri, diags);
562
- await panel.api.gotServerNotification('textDocument/publishDiagnostics', params);
563
- });
564
- }
565
- }
566
- async sendProgress(client) {
567
- if (!this.webviewPanel)
568
- return;
569
- for (const [uri, processing] of client.progress) {
570
- const params = {
571
- textDocument: {
572
- uri: c2pConverter.asUri(uri.asUri()),
573
- version: 0, // HACK: The infoview ignores this
574
- },
575
- processing,
576
- };
577
- await this.webviewPanel.api.gotServerNotification('$/lean/fileProgress', params);
578
- }
579
- }
580
- onLanguageChanged() {
581
- this.autoOpen()
582
- .then(async () => {
583
- await this.sendConfig();
584
- await this.sendPosition();
585
- })
586
- .catch(() => { });
587
- }
588
- getLocation(editor) {
589
- if (!editor)
590
- return undefined;
591
- const uri = editor.document.uri;
592
- const selection = editor.selection;
593
- return {
594
- uri: uri.toString(),
595
- range: {
596
- start: selection.start,
597
- end: selection.end,
598
- },
599
- };
600
- }
601
- async sendPosition() {
602
- const editor = window.activeTextEditor;
603
- if (!editor)
604
- return;
605
- const loc = this.getLocation(editor);
606
- if (languages.match(this.leanDocs, editor.document) === 0) {
607
- // language is not yet 'lean4', but the LeanClient will fire the didSetLanguage event
608
- // in openLean4Document and that's when we can send the position to update the
609
- // InfoView for the newly opened document.
610
- return;
611
- }
612
- const uri = toExtUri(editor.document.uri);
613
- if (uri === undefined) {
614
- return;
615
- }
616
- // actual editor
617
- if (this.clientsFailed.size > 0 || this.workersFailed.size > 0) {
618
- const client = this.clientProvider.findClient(uri);
619
- const uriKey = uri.toString();
620
- if (client) {
621
- const folder = client.getClientFolder().toString();
622
- let reason;
623
- if (this.clientsFailed.has(folder)) {
624
- reason = this.clientsFailed.get(folder);
625
- }
626
- else if (this.workersFailed.has(uriKey)) {
627
- reason = this.workersFailed.get(uriKey);
628
- }
629
- if (reason) {
630
- // send stopped event
631
- await this.webviewPanel?.api.serverStopped(reason);
632
- }
633
- else {
634
- await this.updateStatus(loc);
635
- }
636
- }
637
- else {
638
- logger.log('[InfoProvider] ### what does it mean to have sendPosition but no LeanClient for this document???');
639
- }
640
- }
641
- else {
642
- await this.updateStatus(loc);
643
- }
644
- }
645
- async updateStatus(loc) {
646
- await this.webviewPanel?.api.serverStopped(undefined); // clear any server stopped state
647
- await this.autoOpen();
648
- await this.webviewPanel?.api.changedCursorLocation(loc);
649
- }
650
- async revealEditorSelection(uri, selection) {
651
- let editor;
652
- for (const e of window.visibleTextEditors) {
653
- if (uri.equalsUri(e.document.uri)) {
654
- editor = e;
655
- break;
656
- }
657
- }
658
- if (!editor) {
659
- const c = window.activeTextEditor ? window.activeTextEditor.viewColumn : ViewColumn.One;
660
- editor = await window.showTextDocument(uri.asUri(), { viewColumn: c, preserveFocus: false });
661
- }
662
- if (selection !== undefined) {
663
- editor.revealRange(selection, TextEditorRevealType.InCenterIfOutsideViewport);
664
- editor.selection = new Selection(selection.start, selection.end);
665
- // ensure the text document has the keyboard focus.
666
- await window.showTextDocument(editor.document, { viewColumn: editor.viewColumn, preserveFocus: false });
667
- }
668
- }
669
- async handleInsertText(text, kind, uri, pos) {
670
- let editor;
671
- if (uri) {
672
- editor = window.visibleTextEditors.find(e => uri.equalsUri(e.document.uri));
673
- }
674
- else {
675
- editor = window.activeTextEditor;
676
- if (!editor) {
677
- // sometimes activeTextEditor is null.
678
- editor = window.visibleTextEditors.find(e => e.document.languageId === 'lean4');
679
- }
680
- }
681
- if (!editor) {
682
- // user must have switch away from any lean source file in which case we don't know
683
- // what to do here. TODO: show a popup error? Or should we use the last uri used in
684
- // sendPosition and automatically activate that editor?
685
- return;
686
- }
687
- pos = pos ? pos : editor.selection.active;
688
- if (kind === 'above') {
689
- // in this case, assume that we actually want to insert at the same
690
- // indentation level as the neighboring text
691
- const current_line = editor.document.lineAt(pos.line);
692
- const spaces = current_line.firstNonWhitespaceCharacterIndex;
693
- const margin_str = [...Array(spaces).keys()].map(x => ' ').join('');
694
- let new_command = text.replace(/\n/g, '\n' + margin_str);
695
- new_command = `${margin_str}${new_command}\n`;
696
- const insertPosition = current_line.range.start;
697
- await editor.edit(builder => {
698
- builder.insert(insertPosition, new_command);
699
- });
700
- }
701
- else {
702
- await editor.edit(builder => {
703
- if (pos)
704
- builder.insert(pos, text);
705
- });
706
- editor.selection = new Selection(pos, pos);
707
- }
708
- // ensure the text document has the keyboard focus.
709
- await window.showTextDocument(editor.document, { viewColumn: editor.viewColumn, preserveFocus: false });
710
- }
711
- }