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,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
|
-
}
|