@codingame/monaco-vscode-api 1.83.15 → 1.83.16

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 (48) hide show
  1. package/README.md +430 -0
  2. package/contributions.js +3 -0
  3. package/localExtensionHost.js +3 -2
  4. package/missing-services.js +57 -1
  5. package/monaco-editor-treemending.patch +957 -957
  6. package/package.json +6 -6
  7. package/vscode/src/vs/base/common/prefixTree.js +130 -0
  8. package/vscode/src/vs/platform/actions/browser/floatingMenu.js +26 -2
  9. package/vscode/src/vs/platform/terminal/common/capabilities/bufferMarkCapability.js +41 -0
  10. package/vscode/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.js +566 -0
  11. package/vscode/src/vs/platform/terminal/common/capabilities/cwdDetectionCapability.js +29 -0
  12. package/vscode/src/vs/platform/terminal/common/capabilities/partialCommandDetectionCapability.js +48 -0
  13. package/vscode/src/vs/platform/terminal/common/capabilities/terminalCapabilityStore.js +94 -0
  14. package/vscode/src/vs/platform/terminal/common/terminalEnvironment.js +37 -0
  15. package/vscode/src/vs/platform/terminal/common/terminalStrings.js +16 -0
  16. package/vscode/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.js +319 -0
  17. package/vscode/src/vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput.js +91 -1
  18. package/vscode/src/vs/workbench/contrib/format/browser/formatActionsMultiple.js +423 -0
  19. package/vscode/src/vs/workbench/contrib/format/browser/formatActionsNone.js +82 -0
  20. package/vscode/src/vs/workbench/contrib/terminal/browser/detachedTerminal.js +67 -0
  21. package/vscode/src/vs/workbench/contrib/terminal/browser/terminalExtensions.js +25 -0
  22. package/vscode/src/vs/workbench/contrib/terminal/browser/terminalIcons.js +64 -0
  23. package/vscode/src/vs/workbench/contrib/terminal/browser/widgets/widgetManager.js +36 -0
  24. package/vscode/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.js +538 -0
  25. package/vscode/src/vs/workbench/contrib/terminal/browser/xterm/decorationStyles.js +104 -0
  26. package/vscode/src/vs/workbench/contrib/terminal/browser/xterm/markNavigationAddon.js +416 -0
  27. package/vscode/src/vs/workbench/contrib/terminal/browser/xterm/suggestAddon.js +390 -0
  28. package/vscode/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.js +799 -0
  29. package/vscode/src/vs/workbench/contrib/testing/common/getComputedState.js +101 -0
  30. package/vscode/src/vs/workbench/contrib/testing/common/observableValue.js +30 -0
  31. package/vscode/src/vs/workbench/contrib/testing/common/storedValue.js +36 -0
  32. package/vscode/src/vs/workbench/contrib/testing/common/testExplorerFilterState.js +116 -0
  33. package/vscode/src/vs/workbench/contrib/testing/common/testProfileService.js +172 -1
  34. package/vscode/src/vs/workbench/contrib/testing/common/testResult.js +384 -0
  35. package/vscode/src/vs/workbench/contrib/testing/common/testResultService.js +156 -1
  36. package/vscode/src/vs/workbench/contrib/testing/common/testResultStorage.js +156 -0
  37. package/vscode/src/vs/workbench/contrib/testing/common/testService.js +75 -1
  38. package/vscode/src/vs/workbench/contrib/testing/common/testTypes.js +9 -1
  39. package/vscode/src/vs/workbench/contrib/testing/common/testingContextKeys.js +179 -0
  40. package/vscode/src/vs/workbench/contrib/testing/common/testingContinuousRunService.js +102 -0
  41. package/vscode/src/vs/workbench/contrib/testing/common/testingDecorations.js +29 -0
  42. package/vscode/src/vs/workbench/contrib/testing/common/testingPeekOpener.js +3 -0
  43. package/vscode/src/vs/workbench/contrib/testing/common/testingStates.js +47 -0
  44. package/vscode/src/vs/workbench/services/suggest/browser/media/suggest.css.js +4 -0
  45. package/vscode/src/vs/workbench/services/suggest/browser/simpleCompletionItem.js +10 -0
  46. package/vscode/src/vs/workbench/services/suggest/browser/simpleCompletionModel.js +98 -0
  47. package/vscode/src/vs/workbench/services/suggest/browser/simpleSuggestWidget.js +428 -0
  48. package/vscode/src/vs/workbench/services/suggest/browser/simpleSuggestWidgetRenderer.js +83 -0
@@ -0,0 +1,384 @@
1
+ import { DeferredPromise } from 'monaco-editor/esm/vs/base/common/async.js';
2
+ import { VSBuffer } from 'monaco-editor/esm/vs/base/common/buffer.js';
3
+ import { Event, Emitter } from 'monaco-editor/esm/vs/base/common/event.js';
4
+ import { Lazy } from 'monaco-editor/esm/vs/base/common/lazy.js';
5
+ import { Disposable } from 'monaco-editor/esm/vs/base/common/lifecycle.js';
6
+ import { language } from 'monaco-editor/esm/vs/base/common/platform.js';
7
+ import { removeAnsiEscapeCodes } from 'monaco-editor/esm/vs/base/common/strings.js';
8
+ import { localizeWithPath } from 'monaco-editor/esm/vs/nls.js';
9
+ import { refreshComputedState } from './getComputedState.js';
10
+ import { MutableObservableValue, staticObservableValue } from './observableValue.js';
11
+ import { TestId } from './testId.js';
12
+ import { makeEmptyCounts, terminalStatePriorities, maxPriority, statesInOrder } from './testingStates.js';
13
+ import { TestResultItem, getMarkId } from './testTypes.js';
14
+ const emptyRawOutput = {
15
+ buffers: [],
16
+ length: 0,
17
+ onDidWriteData: Event.None,
18
+ endPromise: Promise.resolve(),
19
+ getRange: () => VSBuffer.alloc(0),
20
+ getRangeIter: () => [],
21
+ };
22
+ class TaskRawOutput {
23
+ constructor() {
24
+ this.writeDataEmitter = ( new Emitter());
25
+ this.endDeferred = ( new DeferredPromise());
26
+ this.offset = 0;
27
+ this.onDidWriteData = this.writeDataEmitter.event;
28
+ this.endPromise = this.endDeferred.p;
29
+ this.buffers = [];
30
+ }
31
+ get length() {
32
+ return this.offset;
33
+ }
34
+ getRange(start, length) {
35
+ const buf = VSBuffer.alloc(length);
36
+ let bufLastWrite = 0;
37
+ for (const chunk of this.getRangeIter(start, length)) {
38
+ buf.buffer.set(chunk.buffer, bufLastWrite);
39
+ bufLastWrite += chunk.byteLength;
40
+ }
41
+ return bufLastWrite < length ? buf.slice(0, bufLastWrite) : buf;
42
+ }
43
+ *getRangeIter(start, length) {
44
+ let soFar = 0;
45
+ let internalLastRead = 0;
46
+ for (const b of this.buffers) {
47
+ if (internalLastRead + b.byteLength <= start) {
48
+ internalLastRead += b.byteLength;
49
+ continue;
50
+ }
51
+ const bstart = Math.max(0, start - internalLastRead);
52
+ const bend = Math.min(b.byteLength, bstart + length - soFar);
53
+ yield b.slice(bstart, bend);
54
+ soFar += bend - bstart;
55
+ internalLastRead += b.byteLength;
56
+ if (soFar === length) {
57
+ break;
58
+ }
59
+ }
60
+ }
61
+ append(data, marker) {
62
+ const offset = this.offset;
63
+ let length = data.byteLength;
64
+ if (marker === undefined) {
65
+ this.push(data);
66
+ return { offset, length };
67
+ }
68
+ const start = VSBuffer.fromString(getMarkCode(marker, true));
69
+ const end = VSBuffer.fromString(getMarkCode(marker, false));
70
+ length += start.byteLength + end.byteLength;
71
+ this.push(start);
72
+ let trimLen = data.byteLength;
73
+ for (; trimLen > 0; trimLen--) {
74
+ const last = data.buffer[trimLen - 1];
75
+ if (last !== 13 && last !== 10 ) {
76
+ break;
77
+ }
78
+ }
79
+ this.push(data.slice(0, trimLen));
80
+ this.push(end);
81
+ this.push(data.slice(trimLen));
82
+ return { offset, length };
83
+ }
84
+ push(data) {
85
+ if (data.byteLength === 0) {
86
+ return;
87
+ }
88
+ this.buffers.push(data);
89
+ this.writeDataEmitter.fire(data);
90
+ this.offset += data.byteLength;
91
+ }
92
+ end() {
93
+ this.endDeferred.complete();
94
+ }
95
+ }
96
+ const resultItemParents = function* (results, item) {
97
+ for (const id of TestId.fromString(item.item.extId).idsToRoot()) {
98
+ yield results.getStateById(( id.toString()));
99
+ }
100
+ };
101
+ const maxCountPriority = (counts) => {
102
+ for (const state of statesInOrder) {
103
+ if (counts[state] > 0) {
104
+ return state;
105
+ }
106
+ }
107
+ return 0 ;
108
+ };
109
+ const getMarkCode = (marker, start) => `\x1b]633;SetMark;Id=${getMarkId(marker, start)};Hidden\x07`;
110
+ const itemToNode = (controllerId, item, parent) => ({
111
+ controllerId,
112
+ expand: 0 ,
113
+ item: { ...item },
114
+ children: [],
115
+ tasks: [],
116
+ ownComputedState: 0 ,
117
+ computedState: 0 ,
118
+ });
119
+ class LiveTestResult extends Disposable {
120
+ get completedAt() {
121
+ return this._completedAt;
122
+ }
123
+ get tests() {
124
+ return ( this.testById.values());
125
+ }
126
+ constructor(id, persist, request) {
127
+ super();
128
+ this.id = id;
129
+ this.persist = persist;
130
+ this.request = request;
131
+ this.completeEmitter = this._register(( new Emitter()));
132
+ this.newTaskEmitter = this._register(( new Emitter()));
133
+ this.endTaskEmitter = this._register(( new Emitter()));
134
+ this.changeEmitter = this._register(( new Emitter()));
135
+ this.testById = ( new Map());
136
+ this.testMarkerCounter = 0;
137
+ this.startedAt = Date.now();
138
+ this.onChange = this.changeEmitter.event;
139
+ this.onComplete = this.completeEmitter.event;
140
+ this.onNewTask = this.newTaskEmitter.event;
141
+ this.onEndTask = this.endTaskEmitter.event;
142
+ this.tasks = [];
143
+ this.name = ( localizeWithPath(
144
+ 'vs/workbench/contrib/testing/common/testResult',
145
+ 'runFinished',
146
+ 'Test run at {0}',
147
+ ( new Date()).toLocaleString(language)
148
+ ));
149
+ this.counts = makeEmptyCounts();
150
+ this.computedStateAccessor = {
151
+ getOwnState: i => i.ownComputedState,
152
+ getCurrentComputedState: i => i.computedState,
153
+ setComputedState: (i, s) => i.computedState = s,
154
+ getChildren: i => i.children,
155
+ getParents: i => {
156
+ const { testById: testByExtId } = this;
157
+ return (function* () {
158
+ const parentId = TestId.fromString(i.item.extId).parentId;
159
+ if (parentId) {
160
+ for (const id of parentId.idsToRoot()) {
161
+ yield testByExtId.get(( id.toString()));
162
+ }
163
+ }
164
+ })();
165
+ },
166
+ };
167
+ this.doSerialize = ( new Lazy(() => ({
168
+ id: this.id,
169
+ completedAt: this.completedAt,
170
+ tasks: ( this.tasks.map(t => ({ id: t.id, name: t.name }))),
171
+ name: this.name,
172
+ request: this.request,
173
+ items: ( [...( this.testById.values())].map(TestResultItem.serializeWithoutMessages)),
174
+ })));
175
+ this.doSerializeWithMessages = ( new Lazy(() => ({
176
+ id: this.id,
177
+ completedAt: this.completedAt,
178
+ tasks: ( this.tasks.map(t => ({ id: t.id, name: t.name }))),
179
+ name: this.name,
180
+ request: this.request,
181
+ items: ( [...( this.testById.values())].map(TestResultItem.serialize)),
182
+ })));
183
+ }
184
+ getStateById(extTestId) {
185
+ return this.testById.get(extTestId);
186
+ }
187
+ appendOutput(output, taskId, location, testId) {
188
+ const preview = output.byteLength > 100 ? ( output.slice(0, 100).toString()) + '…' : ( output.toString());
189
+ let marker;
190
+ if (testId || location) {
191
+ marker = this.testMarkerCounter++;
192
+ }
193
+ const index = this.mustGetTaskIndex(taskId);
194
+ const task = this.tasks[index];
195
+ const { offset, length } = task.output.append(output, marker);
196
+ const message = {
197
+ location,
198
+ message: removeAnsiEscapeCodes(preview),
199
+ offset,
200
+ length,
201
+ marker,
202
+ type: 1 ,
203
+ };
204
+ const test = testId && this.testById.get(testId);
205
+ if (test) {
206
+ test.tasks[index].messages.push(message);
207
+ this.changeEmitter.fire({ item: test, result: this, reason: 2 , message });
208
+ }
209
+ else {
210
+ task.otherMessages.push(message);
211
+ }
212
+ }
213
+ addTask(task) {
214
+ this.tasks.push({ ...task, coverage: this._register(( new MutableObservableValue(undefined))), otherMessages: [], output: ( new TaskRawOutput()) });
215
+ for (const test of this.tests) {
216
+ test.tasks.push({ duration: undefined, messages: [], state: 0 });
217
+ }
218
+ this.newTaskEmitter.fire(this.tasks.length - 1);
219
+ }
220
+ addTestChainToRun(controllerId, chain) {
221
+ let parent = this.testById.get(chain[0].extId);
222
+ if (!parent) {
223
+ parent = this.addTestToRun(controllerId, chain[0], null);
224
+ }
225
+ for (let i = 1; i < chain.length; i++) {
226
+ parent = this.addTestToRun(controllerId, chain[i], parent.item.extId);
227
+ }
228
+ return undefined;
229
+ }
230
+ updateState(testId, taskId, state, duration) {
231
+ const entry = this.testById.get(testId);
232
+ if (!entry) {
233
+ return;
234
+ }
235
+ const index = this.mustGetTaskIndex(taskId);
236
+ const oldTerminalStatePrio = terminalStatePriorities[entry.tasks[index].state];
237
+ const newTerminalStatePrio = terminalStatePriorities[state];
238
+ if (oldTerminalStatePrio !== undefined &&
239
+ (newTerminalStatePrio === undefined || newTerminalStatePrio < oldTerminalStatePrio)) {
240
+ return;
241
+ }
242
+ this.fireUpdateAndRefresh(entry, index, state, duration);
243
+ }
244
+ appendMessage(testId, taskId, message) {
245
+ const entry = this.testById.get(testId);
246
+ if (!entry) {
247
+ return;
248
+ }
249
+ entry.tasks[this.mustGetTaskIndex(taskId)].messages.push(message);
250
+ this.changeEmitter.fire({ item: entry, result: this, reason: 2 , message });
251
+ }
252
+ markTaskComplete(taskId) {
253
+ const index = this.mustGetTaskIndex(taskId);
254
+ const task = this.tasks[index];
255
+ task.running = false;
256
+ task.output.end();
257
+ this.setAllToState(0 , taskId, t => t.state === 1 || t.state === 2 );
258
+ this.endTaskEmitter.fire(index);
259
+ }
260
+ markComplete() {
261
+ if (this._completedAt !== undefined) {
262
+ throw new Error('cannot complete a test result multiple times');
263
+ }
264
+ for (const task of this.tasks) {
265
+ if (task.running) {
266
+ this.markTaskComplete(task.id);
267
+ }
268
+ }
269
+ this._completedAt = Date.now();
270
+ this.completeEmitter.fire();
271
+ }
272
+ markRetired(testIds) {
273
+ for (const [id, test] of this.testById) {
274
+ if (!test.retired && (!testIds || testIds.hasKeyOrParent(TestId.fromString(id).path))) {
275
+ test.retired = true;
276
+ this.changeEmitter.fire({ reason: 0 , item: test, result: this });
277
+ }
278
+ }
279
+ }
280
+ toJSON() {
281
+ return this.completedAt && this.persist ? this.doSerialize.value : undefined;
282
+ }
283
+ toJSONWithMessages() {
284
+ return this.completedAt && this.persist ? this.doSerializeWithMessages.value : undefined;
285
+ }
286
+ setAllToState(state, taskId, when) {
287
+ const index = this.mustGetTaskIndex(taskId);
288
+ for (const test of ( this.testById.values())) {
289
+ if (when(test.tasks[index], test)) {
290
+ this.fireUpdateAndRefresh(test, index, state);
291
+ }
292
+ }
293
+ }
294
+ fireUpdateAndRefresh(entry, taskIndex, newState, newOwnDuration) {
295
+ const previousOwnComputed = entry.ownComputedState;
296
+ const previousOwnDuration = entry.ownDuration;
297
+ const changeEvent = {
298
+ item: entry,
299
+ result: this,
300
+ reason: 1 ,
301
+ previousState: previousOwnComputed,
302
+ previousOwnDuration: previousOwnDuration,
303
+ };
304
+ entry.tasks[taskIndex].state = newState;
305
+ if (newOwnDuration !== undefined) {
306
+ entry.tasks[taskIndex].duration = newOwnDuration;
307
+ entry.ownDuration = Math.max(entry.ownDuration || 0, newOwnDuration);
308
+ }
309
+ const newOwnComputed = maxPriority(...( entry.tasks.map(t => t.state)));
310
+ if (newOwnComputed === previousOwnComputed) {
311
+ if (newOwnDuration !== previousOwnDuration) {
312
+ this.changeEmitter.fire(changeEvent);
313
+ }
314
+ return;
315
+ }
316
+ entry.ownComputedState = newOwnComputed;
317
+ this.counts[previousOwnComputed]--;
318
+ this.counts[newOwnComputed]++;
319
+ refreshComputedState(this.computedStateAccessor, entry).forEach(t => this.changeEmitter.fire(t === entry ? changeEvent : {
320
+ item: t,
321
+ result: this,
322
+ reason: 0 ,
323
+ }));
324
+ }
325
+ addTestToRun(controllerId, item, parent) {
326
+ const node = itemToNode(controllerId, item);
327
+ this.testById.set(item.extId, node);
328
+ this.counts[0 ]++;
329
+ if (parent) {
330
+ this.testById.get(parent)?.children.push(node);
331
+ }
332
+ if (this.tasks.length) {
333
+ for (let i = 0; i < this.tasks.length; i++) {
334
+ node.tasks.push({ duration: undefined, messages: [], state: 0 });
335
+ }
336
+ }
337
+ return node;
338
+ }
339
+ mustGetTaskIndex(taskId) {
340
+ const index = this.tasks.findIndex(t => t.id === taskId);
341
+ if (index === -1) {
342
+ throw new Error(`Unknown task ${taskId} in updateState`);
343
+ }
344
+ return index;
345
+ }
346
+ }
347
+ class HydratedTestResult {
348
+ get tests() {
349
+ return ( this.testById.values());
350
+ }
351
+ constructor(serialized, persist = true) {
352
+ this.serialized = serialized;
353
+ this.persist = persist;
354
+ this.counts = makeEmptyCounts();
355
+ this.testById = ( new Map());
356
+ this.id = serialized.id;
357
+ this.completedAt = serialized.completedAt;
358
+ this.tasks = ( serialized.tasks.map((task, i) => ({
359
+ id: task.id,
360
+ name: task.name,
361
+ running: false,
362
+ coverage: staticObservableValue(undefined),
363
+ output: emptyRawOutput,
364
+ otherMessages: []
365
+ })));
366
+ this.name = serialized.name;
367
+ this.request = serialized.request;
368
+ for (const item of serialized.items) {
369
+ const de = TestResultItem.deserialize(item);
370
+ this.counts[de.ownComputedState]++;
371
+ this.testById.set(item.item.extId, de);
372
+ }
373
+ }
374
+ getStateById(extTestId) {
375
+ return this.testById.get(extTestId);
376
+ }
377
+ toJSON() {
378
+ return this.persist ? this.serialized : undefined;
379
+ }
380
+ toJSONWithMessages() {
381
+ return this.toJSON();
382
+ }
383
+ }
384
+ export { HydratedTestResult, LiveTestResult, TaskRawOutput, maxCountPriority, resultItemParents };
@@ -1,3 +1,158 @@
1
+ import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
2
+ import { findFirstIdxMonotonousOrArrLen } from 'monaco-editor/esm/vs/base/common/arraysFind.js';
3
+ import { RunOnceScheduler } from 'monaco-editor/esm/vs/base/common/async.js';
4
+ import { Emitter } from 'monaco-editor/esm/vs/base/common/event.js';
5
+ import { createSingleCallFunction } from 'monaco-editor/esm/vs/base/common/functional.js';
6
+ import { Disposable, toDisposable, dispose, DisposableStore } from 'monaco-editor/esm/vs/base/common/lifecycle.js';
7
+ import { generateUuid } from 'monaco-editor/esm/vs/base/common/uuid.js';
8
+ import { IContextKeyService } from 'monaco-editor/esm/vs/platform/contextkey/common/contextkey.js';
1
9
  import { createDecorator } from 'monaco-editor/esm/vs/platform/instantiation/common/instantiation.js';
10
+ import { TestingContextKeys } from './testingContextKeys.js';
11
+ import { ITestProfileService } from './testProfileService.js';
12
+ import { LiveTestResult } from './testResult.js';
13
+ import { RETAIN_MAX_RESULTS, ITestResultStorage } from './testResultStorage.js';
14
+ const isRunningTests = (service) => service.results.length > 0 && service.results[0].completedAt === undefined;
2
15
  const ITestResultService = ( createDecorator('testResultService'));
3
- export { ITestResultService };
16
+ let TestResultService = class TestResultService extends Disposable {
17
+ get results() {
18
+ this.loadResults();
19
+ return this._results;
20
+ }
21
+ constructor(contextKeyService, storage, testProfiles) {
22
+ super();
23
+ this.storage = storage;
24
+ this.testProfiles = testProfiles;
25
+ this.changeResultEmitter = this._register(( new Emitter()));
26
+ this._results = [];
27
+ this._resultsDisposables = [];
28
+ this.testChangeEmitter = this._register(( new Emitter()));
29
+ this.onResultsChanged = this.changeResultEmitter.event;
30
+ this.onTestChanged = this.testChangeEmitter.event;
31
+ this.loadResults = createSingleCallFunction(() => this.storage.read().then(loaded => {
32
+ for (let i = loaded.length - 1; i >= 0; i--) {
33
+ this.push(loaded[i]);
34
+ }
35
+ }));
36
+ this.persistScheduler = ( new RunOnceScheduler(() => this.persistImmediately(), 500));
37
+ this._register(toDisposable(() => dispose(this._resultsDisposables)));
38
+ this.isRunning = TestingContextKeys.isRunning.bindTo(contextKeyService);
39
+ this.hasAnyResults = TestingContextKeys.hasAnyResults.bindTo(contextKeyService);
40
+ }
41
+ getStateById(extId) {
42
+ for (const result of this.results) {
43
+ const lookup = result.getStateById(extId);
44
+ if (lookup && lookup.computedState !== 0 ) {
45
+ return [result, lookup];
46
+ }
47
+ }
48
+ return undefined;
49
+ }
50
+ createLiveResult(req) {
51
+ if ('targets' in req) {
52
+ const id = generateUuid();
53
+ return this.push(( new LiveTestResult(id, true, req)));
54
+ }
55
+ let profile;
56
+ if (req.profile) {
57
+ const profiles = this.testProfiles.getControllerProfiles(req.controllerId);
58
+ profile = profiles.find(c => c.profileId === req.profile.id);
59
+ }
60
+ const resolved = {
61
+ isUiTriggered: false,
62
+ targets: [],
63
+ exclude: req.exclude,
64
+ continuous: req.continuous,
65
+ };
66
+ if (profile) {
67
+ resolved.targets.push({
68
+ profileGroup: profile.group,
69
+ profileId: profile.profileId,
70
+ controllerId: req.controllerId,
71
+ testIds: req.include,
72
+ });
73
+ }
74
+ return this.push(( new LiveTestResult(req.id, req.persist, resolved)));
75
+ }
76
+ push(result) {
77
+ if (result.completedAt === undefined) {
78
+ this.results.unshift(result);
79
+ }
80
+ else {
81
+ const index = findFirstIdxMonotonousOrArrLen(this.results, r => r.completedAt !== undefined && r.completedAt <= result.completedAt);
82
+ this.results.splice(index, 0, result);
83
+ this.persistScheduler.schedule();
84
+ }
85
+ this.hasAnyResults.set(true);
86
+ if (this.results.length > RETAIN_MAX_RESULTS) {
87
+ this.results.pop();
88
+ this._resultsDisposables.pop()?.dispose();
89
+ }
90
+ const ds = ( new DisposableStore());
91
+ this._resultsDisposables.push(ds);
92
+ if (result instanceof LiveTestResult) {
93
+ ds.add(result);
94
+ ds.add(result.onComplete(() => this.onComplete(result)));
95
+ ds.add(result.onChange(this.testChangeEmitter.fire, this.testChangeEmitter));
96
+ this.isRunning.set(true);
97
+ this.changeResultEmitter.fire({ started: result });
98
+ }
99
+ else {
100
+ this.changeResultEmitter.fire({ inserted: result });
101
+ for (const item of result.tests) {
102
+ for (const otherResult of this.results) {
103
+ if (otherResult === result) {
104
+ this.testChangeEmitter.fire({ item, result, reason: 0 });
105
+ break;
106
+ }
107
+ else if (otherResult.getStateById(item.item.extId) !== undefined) {
108
+ break;
109
+ }
110
+ }
111
+ }
112
+ }
113
+ return result;
114
+ }
115
+ getResult(id) {
116
+ return this.results.find(r => r.id === id);
117
+ }
118
+ clear() {
119
+ const keep = [];
120
+ const removed = [];
121
+ for (const result of this.results) {
122
+ if (result.completedAt !== undefined) {
123
+ removed.push(result);
124
+ }
125
+ else {
126
+ keep.push(result);
127
+ }
128
+ }
129
+ this._results = keep;
130
+ this.persistScheduler.schedule();
131
+ if (keep.length === 0) {
132
+ this.hasAnyResults.set(false);
133
+ }
134
+ this.changeResultEmitter.fire({ removed });
135
+ }
136
+ onComplete(result) {
137
+ this.resort();
138
+ this.updateIsRunning();
139
+ this.persistScheduler.schedule();
140
+ this.changeResultEmitter.fire({ completed: result });
141
+ }
142
+ resort() {
143
+ this.results.sort((a, b) => (b.completedAt ?? Number.MAX_SAFE_INTEGER) - (a.completedAt ?? Number.MAX_SAFE_INTEGER));
144
+ }
145
+ updateIsRunning() {
146
+ this.isRunning.set(isRunningTests(this));
147
+ }
148
+ async persistImmediately() {
149
+ await this.loadResults();
150
+ this.storage.persist(this.results);
151
+ }
152
+ };
153
+ TestResultService = ( __decorate([
154
+ ( __param(0, IContextKeyService)),
155
+ ( __param(1, ITestResultStorage)),
156
+ ( __param(2, ITestProfileService))
157
+ ], TestResultService));
158
+ export { ITestResultService, TestResultService };
@@ -0,0 +1,156 @@
1
+ import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
2
+ import { VSBuffer, bufferToStream, newWriteableBufferStream } from 'monaco-editor/esm/vs/base/common/buffer.js';
3
+ import { Disposable } from 'monaco-editor/esm/vs/base/common/lifecycle.js';
4
+ import { isDefined } from 'monaco-editor/esm/vs/base/common/types.js';
5
+ import { URI } from 'monaco-editor/esm/vs/base/common/uri.js';
6
+ import { IEnvironmentService } from 'monaco-editor/esm/vs/platform/environment/common/environment.js';
7
+ import { IFileService } from 'monaco-editor/esm/vs/platform/files/common/files.js';
8
+ import { createDecorator } from 'monaco-editor/esm/vs/platform/instantiation/common/instantiation.js';
9
+ import { ILogService } from 'monaco-editor/esm/vs/platform/log/common/log.js';
10
+ import { IStorageService } from 'monaco-editor/esm/vs/platform/storage/common/storage.js';
11
+ import { IWorkspaceContextService } from 'monaco-editor/esm/vs/platform/workspace/common/workspace.js';
12
+ import { StoredValue } from './storedValue.js';
13
+ import { HydratedTestResult } from './testResult.js';
14
+ const RETAIN_MAX_RESULTS = 128;
15
+ const RETAIN_MIN_RESULTS = 16;
16
+ const RETAIN_MAX_BYTES = 1024 * 128;
17
+ const CLEANUP_PROBABILITY = 0.2;
18
+ const ITestResultStorage = ( createDecorator('ITestResultStorage'));
19
+ const currentRevision = 1;
20
+ let BaseTestResultStorage = class BaseTestResultStorage extends Disposable {
21
+ constructor(storageService, logService) {
22
+ super();
23
+ this.storageService = storageService;
24
+ this.logService = logService;
25
+ this.stored = this._register(( new StoredValue({
26
+ key: 'storedTestResults',
27
+ scope: 1 ,
28
+ target: 1
29
+ }, this.storageService)));
30
+ }
31
+ async read() {
32
+ const results = await Promise.all(( this.stored.get([]).map(async ({ id, rev }) => {
33
+ if (rev !== currentRevision) {
34
+ return undefined;
35
+ }
36
+ try {
37
+ const contents = await this.readForResultId(id);
38
+ if (!contents) {
39
+ return undefined;
40
+ }
41
+ return ( new HydratedTestResult(contents));
42
+ }
43
+ catch (e) {
44
+ this.logService.warn(`Error deserializing stored test result ${id}`, e);
45
+ return undefined;
46
+ }
47
+ })));
48
+ return results.filter(isDefined);
49
+ }
50
+ getResultOutputWriter(resultId) {
51
+ const stream = newWriteableBufferStream();
52
+ this.storeOutputForResultId(resultId, stream);
53
+ return stream;
54
+ }
55
+ async persist(results) {
56
+ const toDelete = ( new Map(( this.stored.get([]).map(({ id, bytes }) => [id, bytes]))));
57
+ const toStore = [];
58
+ const todo = [];
59
+ let budget = RETAIN_MAX_BYTES;
60
+ for (let i = 0; i < results.length && i < RETAIN_MAX_RESULTS && (budget > 0 || toStore.length < RETAIN_MIN_RESULTS); i++) {
61
+ const result = results[i];
62
+ const existingBytes = toDelete.get(result.id);
63
+ if (existingBytes !== undefined) {
64
+ toDelete.delete(result.id);
65
+ toStore.push({ id: result.id, rev: currentRevision, bytes: existingBytes });
66
+ budget -= existingBytes;
67
+ continue;
68
+ }
69
+ const obj = result.toJSON();
70
+ if (!obj) {
71
+ continue;
72
+ }
73
+ const contents = VSBuffer.fromString(JSON.stringify(obj));
74
+ todo.push(this.storeForResultId(result.id, obj));
75
+ toStore.push({ id: result.id, rev: currentRevision, bytes: contents.byteLength });
76
+ budget -= contents.byteLength;
77
+ }
78
+ for (const id of ( toDelete.keys())) {
79
+ todo.push(this.deleteForResultId(id).catch(() => undefined));
80
+ }
81
+ this.stored.store(toStore);
82
+ await Promise.all(todo);
83
+ }
84
+ };
85
+ BaseTestResultStorage = ( __decorate([
86
+ ( __param(0, IStorageService)),
87
+ ( __param(1, ILogService))
88
+ ], BaseTestResultStorage));
89
+ let TestResultStorage = class TestResultStorage extends BaseTestResultStorage {
90
+ constructor(storageService, logService, workspaceContext, fileService, environmentService) {
91
+ super(storageService, logService);
92
+ this.fileService = fileService;
93
+ this.directory = URI.joinPath(environmentService.workspaceStorageHome, workspaceContext.getWorkspace().id, 'testResults');
94
+ }
95
+ async readForResultId(id) {
96
+ const contents = await this.fileService.readFile(this.getResultJsonPath(id));
97
+ return JSON.parse(( contents.value.toString()));
98
+ }
99
+ storeForResultId(id, contents) {
100
+ return this.fileService.writeFile(this.getResultJsonPath(id), VSBuffer.fromString(JSON.stringify(contents)));
101
+ }
102
+ deleteForResultId(id) {
103
+ return this.fileService.del(this.getResultJsonPath(id)).catch(() => undefined);
104
+ }
105
+ async readOutputRangeForResultId(id, offset, length) {
106
+ try {
107
+ const { value } = await this.fileService.readFile(this.getResultOutputPath(id), { position: offset, length });
108
+ return value;
109
+ }
110
+ catch {
111
+ return VSBuffer.alloc(0);
112
+ }
113
+ }
114
+ async readOutputForResultId(id) {
115
+ try {
116
+ const { value } = await this.fileService.readFileStream(this.getResultOutputPath(id));
117
+ return value;
118
+ }
119
+ catch {
120
+ return bufferToStream(VSBuffer.alloc(0));
121
+ }
122
+ }
123
+ async storeOutputForResultId(id, input) {
124
+ await this.fileService.createFile(this.getResultOutputPath(id), input);
125
+ }
126
+ async persist(results) {
127
+ await super.persist(results);
128
+ if (Math.random() < CLEANUP_PROBABILITY) {
129
+ await this.cleanupDereferenced();
130
+ }
131
+ }
132
+ async cleanupDereferenced() {
133
+ const { children } = await this.fileService.resolve(this.directory);
134
+ if (!children) {
135
+ return;
136
+ }
137
+ const stored = ( new Set(( this.stored.get([]).filter(s => s.rev === currentRevision).map(s => s.id))));
138
+ await Promise.all(( children
139
+ .filter(child => !( stored.has(child.name.replace(/\.[a-z]+$/, ''))))
140
+ .map(child => this.fileService.del(child.resource).catch(() => undefined))));
141
+ }
142
+ getResultJsonPath(id) {
143
+ return URI.joinPath(this.directory, `${id}.json`);
144
+ }
145
+ getResultOutputPath(id) {
146
+ return URI.joinPath(this.directory, `${id}.output`);
147
+ }
148
+ };
149
+ TestResultStorage = ( __decorate([
150
+ ( __param(0, IStorageService)),
151
+ ( __param(1, ILogService)),
152
+ ( __param(2, IWorkspaceContextService)),
153
+ ( __param(3, IFileService)),
154
+ ( __param(4, IEnvironmentService))
155
+ ], TestResultStorage));
156
+ export { BaseTestResultStorage, ITestResultStorage, RETAIN_MAX_RESULTS, TestResultStorage };