@codingame/monaco-vscode-testing-service-override 2.0.3 → 2.1.0

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.
@@ -1,36 +1,48 @@
1
1
  import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
2
+ import { append, $ } from 'vscode/vscode/vs/base/browser/dom';
3
+ import { assertNever } from 'vscode/vscode/vs/base/common/assert';
4
+ import { Codicon } from 'vscode/vscode/vs/base/common/codicons';
5
+ import { memoize } from 'vscode/vscode/vs/base/common/decorators';
2
6
  import { createMatches } from 'vscode/vscode/vs/base/common/filters';
3
7
  import { Iterable } from 'vscode/vscode/vs/base/common/iterator';
4
8
  import { DisposableStore, MutableDisposable, Disposable } from 'vscode/vscode/vs/base/common/lifecycle';
5
9
  import { basenameOrAuthority } from 'vscode/vscode/vs/base/common/resources';
6
- import { localizeWithPath } from 'vscode/vscode/vs/nls';
10
+ import { ThemeIcon } from 'vscode/vscode/vs/base/common/themables';
11
+ import { Position } from 'vscode/vscode/vs/editor/common/core/position';
12
+ import { Range } from 'vscode/vscode/vs/editor/common/core/range';
13
+ import { localize2WithPath, localizeWithPath } from 'vscode/vscode/vs/nls';
14
+ import { registerAction2, MenuId } from 'vscode/vscode/vs/platform/actions/common/actions';
7
15
  import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration';
8
- import { IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
16
+ import { ContextKeyExpr, IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
9
17
  import { IContextMenuService } from 'vscode/vscode/vs/platform/contextview/browser/contextView';
10
18
  import { EditorOpenSource } from 'vscode/vscode/vs/platform/editor/common/editor';
11
19
  import { FileKind } from 'vscode/vscode/vs/platform/files/common/files';
12
20
  import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
13
21
  import { IKeybindingService } from 'vscode/vscode/vs/platform/keybinding/common/keybinding';
14
22
  import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label';
15
- import { WorkbenchCompressibleAsyncDataTree } from 'vscode/vscode/vs/platform/list/browser/listService';
23
+ import { WorkbenchCompressibleObjectTree } from 'vscode/vscode/vs/platform/list/browser/listService';
16
24
  import { IOpenerService } from 'vscode/vscode/vs/platform/opener/common/opener';
25
+ import { IQuickInputService } from 'vscode/vscode/vs/platform/quickinput/common/quickInput';
17
26
  import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
18
27
  import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService';
19
28
  import { ResourceLabels } from 'vscode/vscode/vs/workbench/browser/labels';
20
- import { ViewPane } from 'vscode/vscode/vs/workbench/browser/parts/views/viewPane';
29
+ import { ViewAction, ViewPane } from 'vscode/vscode/vs/workbench/browser/parts/views/viewPane';
21
30
  import { IViewDescriptorService } from 'vscode/vscode/vs/workbench/common/views';
31
+ import { testingWasCovered, testingStatesToIcons } from './icons.js';
22
32
  import { ManagedTestCoverageBars } from './testCoverageBars.js';
23
- import { FileCoverage } from 'vscode/vscode/vs/workbench/contrib/testing/common/testCoverage';
33
+ import { FileCoverage, getTotalCoveragePercent } from 'vscode/vscode/vs/workbench/contrib/testing/common/testCoverage';
24
34
  import { ITestCoverageService } from 'vscode/vscode/vs/workbench/contrib/testing/common/testCoverageService';
25
35
  import { SIDE_GROUP, ACTIVE_GROUP, IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
36
+ import { observableValue } from 'vscode/vscode/vs/base/common/observableInternal/base';
26
37
  import { autorun } from 'vscode/vscode/vs/base/common/observableInternal/autorun';
27
38
 
28
- var FileCoverageRenderer_1;
39
+ var FileCoverageRenderer_1, FunctionCoverageRenderer_1;
29
40
  let TestCoverageView = class TestCoverageView extends ViewPane {
30
41
  constructor(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService, coverageService) {
31
42
  super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
32
43
  this.coverageService = coverageService;
33
44
  this.tree = ( new MutableDisposable());
45
+ this.sortOrder = observableValue('sortOrder', 1 );
34
46
  }
35
47
  renderBody(container) {
36
48
  super.renderBody(container);
@@ -38,7 +50,7 @@ let TestCoverageView = class TestCoverageView extends ViewPane {
38
50
  this._register(autorun(reader => {
39
51
  const coverage = this.coverageService.selected.read(reader);
40
52
  if (coverage) {
41
- const t = (this.tree.value ??= this.instantiationService.createInstance(TestCoverageTree, container, labels));
53
+ const t = (this.tree.value ??= this.instantiationService.createInstance(TestCoverageTree, container, labels, this.sortOrder));
42
54
  t.setInput(coverage);
43
55
  }
44
56
  else {
@@ -63,17 +75,112 @@ TestCoverageView = ( __decorate([
63
75
  ( __param(9, ITelemetryService)),
64
76
  ( __param(10, ITestCoverageService))
65
77
  ], TestCoverageView));
66
- class TestCoverageInput {
67
- constructor(coverage) {
68
- this.tree = coverage.tree;
78
+ let fnNodeId = 0;
79
+ class FunctionCoverageNode {
80
+ get hits() {
81
+ return this.data.count;
82
+ }
83
+ get label() {
84
+ return this.data.name;
85
+ }
86
+ get location() {
87
+ return this.data.location;
88
+ }
89
+ get tpc() {
90
+ const attr = this.attributableCoverage();
91
+ return attr && getTotalCoveragePercent(attr.statement, attr.branch, undefined);
92
+ }
93
+ constructor(uri, data, details) {
94
+ this.uri = uri;
95
+ this.data = data;
96
+ this.id = String(fnNodeId++);
97
+ this.containedDetails = ( new Set());
98
+ this.children = [];
99
+ if (data.location instanceof Range) {
100
+ for (const detail of details) {
101
+ if (this.contains(detail.location)) {
102
+ this.containedDetails.add(detail);
103
+ }
104
+ }
105
+ }
106
+ }
107
+ contains(location) {
108
+ const own = this.data.location;
109
+ return own instanceof Range && (location instanceof Range ? own.containsRange(location) : own.containsPosition(location));
110
+ }
111
+ attributableCoverage() {
112
+ const { location, count } = this.data;
113
+ if (!(location instanceof Range) || !count) {
114
+ return;
115
+ }
116
+ const statement = { covered: 0, total: 0 };
117
+ const branch = { covered: 0, total: 0 };
118
+ for (const detail of this.containedDetails) {
119
+ if (detail.type !== 1 ) {
120
+ continue;
121
+ }
122
+ statement.covered += detail.count > 0 ? 1 : 0;
123
+ statement.total++;
124
+ if (detail.branches) {
125
+ for (const { count } of detail.branches) {
126
+ branch.covered += count > 0 ? 1 : 0;
127
+ branch.total++;
128
+ }
129
+ }
130
+ }
131
+ return { statement, branch };
132
+ }
133
+ }
134
+ FunctionCoverageNode.__decorator = ( __decorate([
135
+ memoize
136
+ ], FunctionCoverageNode.prototype, "attributableCoverage", null));
137
+ class RevealUncoveredFunctions {
138
+ get label() {
139
+ return ( localizeWithPath(
140
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
141
+ 'functionsWithoutCoverage',
142
+ "{0} functions without coverage...",
143
+ this.n
144
+ ));
145
+ }
146
+ constructor(n) {
147
+ this.n = n;
148
+ this.id = String(fnNodeId++);
149
+ }
150
+ }
151
+ class LoadingDetails {
152
+ constructor() {
153
+ this.id = String(fnNodeId++);
154
+ this.label = ( localizeWithPath(
155
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
156
+ 'loadingCoverageDetails',
157
+ "Loading Coverage Details..."
158
+ ));
69
159
  }
70
160
  }
71
- const isFileCoverage = (c) => 'value' in c;
72
- const isFunctionCoverage = (c) => 'type' in c && c.type === 0 ;
161
+ const isFileCoverage = (c) => typeof c === 'object' && 'value' in c;
162
+ const isFunctionCoverage = (c) => c instanceof FunctionCoverageNode;
163
+ const shouldShowFunctionDetailsOnExpand = (c) => isFileCoverage(c) && c.value instanceof FileCoverage && !!c.value.function?.total;
73
164
  let TestCoverageTree = class TestCoverageTree extends Disposable {
74
- constructor(container, labels, instantiationService, editorService) {
165
+ constructor(container, labels, sortOrder, instantiationService, editorService) {
75
166
  super();
76
- this.tree = instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'TestCoverageView', container, ( new TestCoverageTreeListDelegate()), ( new TestCoverageCompressionDelegate()), [instantiationService.createInstance(FileCoverageRenderer, labels)], instantiationService.createInstance(TestCoverageDataSource), {
167
+ this.tree = instantiationService.createInstance(WorkbenchCompressibleObjectTree, 'TestCoverageView', container, ( new TestCoverageTreeListDelegate()), [
168
+ instantiationService.createInstance(FileCoverageRenderer, labels),
169
+ instantiationService.createInstance(FunctionCoverageRenderer),
170
+ instantiationService.createInstance(BasicRenderer),
171
+ ], {
172
+ expandOnlyOnTwistieClick: true,
173
+ sorter: ( new Sorter(sortOrder)),
174
+ keyboardNavigationLabelProvider: {
175
+ getCompressedNodeKeyboardNavigationLabel(elements) {
176
+ return ( elements.map(e => this.getKeyboardNavigationLabel(e))).join('/');
177
+ },
178
+ getKeyboardNavigationLabel(e) {
179
+ return isFileCoverage(e)
180
+ ? basenameOrAuthority(e.value.uri)
181
+ : e.label;
182
+ },
183
+ },
77
184
  accessibilityProvider: {
78
185
  getAriaLabel(element) {
79
186
  if (isFileCoverage(element)) {
@@ -86,7 +193,9 @@ let TestCoverageTree = class TestCoverageTree extends Disposable {
86
193
  (element.value.tpc * 100).toFixed(2)
87
194
  ));
88
195
  }
89
- return element.name;
196
+ else {
197
+ return element.label;
198
+ }
90
199
  },
91
200
  getWidgetAriaLabel() {
92
201
  return ( localizeWithPath(
@@ -96,67 +205,158 @@ let TestCoverageTree = class TestCoverageTree extends Disposable {
96
205
  ));
97
206
  }
98
207
  },
99
- autoExpandSingleChildren: true,
100
208
  identityProvider: ( new TestCoverageIdentityProvider()),
101
209
  });
210
+ this._register(autorun(reader => {
211
+ sortOrder.read(reader);
212
+ this.tree.resort(null, true);
213
+ }));
102
214
  this._register(this.tree);
215
+ this._register(this.tree.onDidChangeCollapseState(e => {
216
+ const el = e.node.element;
217
+ if (!e.node.collapsed && !e.node.children.length && el && shouldShowFunctionDetailsOnExpand(el)) {
218
+ if (el.value.hasSynchronousDetails) {
219
+ this.tree.setChildren(el, [{ element: ( new LoadingDetails()), incompressible: true }]);
220
+ }
221
+ el.value.details().then(details => this.updateWithDetails(el, details));
222
+ }
223
+ }));
103
224
  this._register(this.tree.onDidOpen(e => {
104
225
  let resource;
105
- if (e.element && isFileCoverage(e.element) && !e.element.children?.size) {
106
- resource = e.element.value.uri;
226
+ let selection;
227
+ if (e.element) {
228
+ if (isFileCoverage(e.element) && !e.element.children?.size) {
229
+ resource = e.element.value.uri;
230
+ }
231
+ else if (isFunctionCoverage(e.element)) {
232
+ resource = e.element.uri;
233
+ selection = e.element.location;
234
+ }
107
235
  }
108
236
  if (!resource) {
109
237
  return;
110
238
  }
111
239
  editorService.openEditor({
112
240
  resource,
113
- options: { preserveFocus: e.editorOptions.preserveFocus, pinned: e.editorOptions.pinned, source: EditorOpenSource.USER }
241
+ options: {
242
+ selection: selection instanceof Position ? Range.fromPositions(selection, selection) : selection,
243
+ revealIfOpened: true,
244
+ selectionRevealType: 3 ,
245
+ preserveFocus: e.editorOptions.preserveFocus,
246
+ pinned: e.editorOptions.pinned,
247
+ source: EditorOpenSource.USER,
248
+ },
114
249
  }, e.sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
115
250
  }));
116
251
  }
117
252
  setInput(coverage) {
118
- this.tree.setInput(( new TestCoverageInput(coverage)));
253
+ const files = [];
254
+ for (let node of coverage.tree.nodes) {
255
+ while (!(node.value instanceof FileCoverage) && node.children?.size === 1) {
256
+ node = Iterable.first(( node.children.values()));
257
+ }
258
+ files.push(node);
259
+ }
260
+ const toChild = (file) => {
261
+ const isFile = !file.children?.size;
262
+ return {
263
+ element: file,
264
+ incompressible: isFile,
265
+ collapsed: isFile,
266
+ collapsible: !isFile || !!file.value?.function?.total,
267
+ children: file.children && ( Iterable.map(file.children?.values(), toChild))
268
+ };
269
+ };
270
+ this.tree.setChildren(null, ( Iterable.map(files, toChild)));
119
271
  }
120
272
  layout(height, width) {
121
273
  this.tree.layout(height, width);
122
274
  }
123
- };
124
- TestCoverageTree = ( __decorate([
125
- ( __param(2, IInstantiationService)),
126
- ( __param(3, IEditorService))
127
- ], TestCoverageTree));
128
- class TestCoverageDataSource {
129
- hasChildren(element) {
130
- return element instanceof TestCoverageInput || (isFileCoverage(element) && !!element.children?.size);
131
- }
132
- async getChildren(element) {
133
- if (element instanceof TestCoverageInput) {
134
- const files = [];
135
- for (let node of element.tree.nodes) {
136
- while (!(node.value instanceof FileCoverage) && node.children?.size === 1) {
137
- node = Iterable.first(( node.children.values()));
275
+ updateWithDetails(el, details) {
276
+ if (!this.tree.hasElement(el)) {
277
+ return;
278
+ }
279
+ const functions = [];
280
+ for (const fn of details) {
281
+ if (fn.type !== 0 ) {
282
+ continue;
283
+ }
284
+ let arr = functions;
285
+ while (true) {
286
+ const parent = arr.find(p => ( p.containedDetails.has(fn)));
287
+ if (parent) {
288
+ arr = parent.children;
289
+ }
290
+ else {
291
+ break;
138
292
  }
139
- files.push(node);
140
293
  }
141
- return files;
142
- }
143
- if (isFileCoverage(element) && element.children) {
144
- return ( element.children.values());
294
+ arr.push(( new FunctionCoverageNode(el.value.uri, fn, details)));
145
295
  }
146
- return Iterable.empty();
147
- }
148
- }
149
- class TestCoverageCompressionDelegate {
150
- isIncompressible(element) {
151
- return isFunctionCoverage(element) || !element.children?.size;
296
+ const makeChild = (fn) => ({
297
+ element: fn,
298
+ incompressible: true,
299
+ collapsed: true,
300
+ collapsible: fn.children.length > 0,
301
+ children: ( fn.children.map(makeChild))
302
+ });
303
+ this.tree.setChildren(el, ( functions.map(makeChild)));
152
304
  }
153
- }
305
+ };
306
+ TestCoverageTree = ( __decorate([
307
+ ( __param(3, IInstantiationService)),
308
+ ( __param(4, IEditorService))
309
+ ], TestCoverageTree));
154
310
  class TestCoverageTreeListDelegate {
155
311
  getHeight(element) {
156
312
  return 22;
157
313
  }
158
- getTemplateId(_element) {
159
- return FileCoverageRenderer.ID;
314
+ getTemplateId(element) {
315
+ if (isFileCoverage(element)) {
316
+ return FileCoverageRenderer.ID;
317
+ }
318
+ if (isFunctionCoverage(element)) {
319
+ return FunctionCoverageRenderer.ID;
320
+ }
321
+ if (element instanceof LoadingDetails || element instanceof RevealUncoveredFunctions) {
322
+ return BasicRenderer.ID;
323
+ }
324
+ assertNever();
325
+ }
326
+ }
327
+ class Sorter {
328
+ constructor(order) {
329
+ this.order = order;
330
+ }
331
+ compare(a, b) {
332
+ const order = this.order.get();
333
+ if (isFileCoverage(a) && isFileCoverage(b)) {
334
+ switch (order) {
335
+ case 1 :
336
+ case 2 :
337
+ return ( a.value.uri.toString()).localeCompare(( b.value.uri.toString()));
338
+ case 0 :
339
+ return b.value.tpc - a.value.tpc;
340
+ }
341
+ }
342
+ else if (isFunctionCoverage(a) && isFunctionCoverage(b)) {
343
+ switch (order) {
344
+ case 1 :
345
+ return Position.compare(a.location instanceof Range ? a.location.getStartPosition() : a.location, b.location instanceof Range ? b.location.getStartPosition() : b.location);
346
+ case 2 :
347
+ return a.label.localeCompare(b.label);
348
+ case 0 : {
349
+ const attrA = a.tpc;
350
+ const attrB = b.tpc;
351
+ return (attrA !== undefined && attrB !== undefined && attrB - attrA)
352
+ || (b.hits - a.hits)
353
+ || a.label.localeCompare(b.label);
354
+ }
355
+ }
356
+ }
357
+ else {
358
+ return 0;
359
+ }
160
360
  }
161
361
  }
162
362
  let FileCoverageRenderer = class FileCoverageRenderer {
@@ -206,10 +406,140 @@ FileCoverageRenderer = FileCoverageRenderer_1 = ( __decorate([
206
406
  ( __param(1, ILabelService)),
207
407
  ( __param(2, IInstantiationService))
208
408
  ], FileCoverageRenderer));
409
+ let FunctionCoverageRenderer = class FunctionCoverageRenderer {
410
+ static { FunctionCoverageRenderer_1 = this; }
411
+ static { this.ID = 'N'; }
412
+ constructor(instantiationService) {
413
+ this.instantiationService = instantiationService;
414
+ this.templateId = FunctionCoverageRenderer_1.ID;
415
+ }
416
+ renderTemplate(container) {
417
+ const templateDisposables = ( new DisposableStore());
418
+ container.classList.add('test-coverage-list-item');
419
+ const icon = append(container, $('.state'));
420
+ const label = append(container, $('.name'));
421
+ return {
422
+ container,
423
+ bars: templateDisposables.add(this.instantiationService.createInstance(ManagedTestCoverageBars, { compact: false, container })),
424
+ templateDisposables,
425
+ icon,
426
+ label,
427
+ };
428
+ }
429
+ renderElement(node, _index, templateData) {
430
+ this.doRender(node.element, templateData, node.filterData);
431
+ }
432
+ renderCompressedElements(node, _index, templateData) {
433
+ this.doRender(node.element.elements[node.element.elements.length - 1], templateData, node.filterData);
434
+ }
435
+ disposeTemplate(templateData) {
436
+ templateData.templateDisposables.dispose();
437
+ }
438
+ doRender(element, templateData, _filterData) {
439
+ const covered = element.hits > 0;
440
+ const icon = covered ? testingWasCovered : testingStatesToIcons.get(0 );
441
+ templateData.container.classList.toggle('not-covered', !covered);
442
+ templateData.icon.className = `computed-state ${ThemeIcon.asClassName(icon)}`;
443
+ templateData.label.innerText = element.label;
444
+ templateData.bars.setCoverageInfo(element.attributableCoverage());
445
+ }
446
+ };
447
+ FunctionCoverageRenderer = FunctionCoverageRenderer_1 = ( __decorate([
448
+ ( __param(0, IInstantiationService))
449
+ ], FunctionCoverageRenderer));
450
+ class BasicRenderer {
451
+ constructor() {
452
+ this.templateId = BasicRenderer.ID;
453
+ }
454
+ static { this.ID = 'B'; }
455
+ renderCompressedElements(node, _index, container) {
456
+ this.renderInner(node.element.elements[node.element.elements.length - 1], container);
457
+ }
458
+ renderTemplate(container) {
459
+ return container;
460
+ }
461
+ renderElement(node, index, container) {
462
+ this.renderInner(node.element, container);
463
+ }
464
+ disposeTemplate() {
465
+ }
466
+ renderInner(element, container) {
467
+ container.innerText = element.label;
468
+ }
469
+ }
209
470
  class TestCoverageIdentityProvider {
210
471
  getId(element) {
211
- return isFileCoverage(element) ? ( element.value.uri.toString()) : element.name;
472
+ return isFileCoverage(element)
473
+ ? ( element.value.uri.toString())
474
+ : element.id;
212
475
  }
213
476
  }
477
+ registerAction2(class TestCoverageChangeSortingAction extends ViewAction {
478
+ constructor() {
479
+ super({
480
+ id: "testing.coverageViewChangeSorting" ,
481
+ viewId: "workbench.view.testCoverage" ,
482
+ title: ( localize2WithPath(
483
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
484
+ 'testing.changeCoverageSort',
485
+ 'Change Sort Order'
486
+ )),
487
+ icon: Codicon.sortPrecedence,
488
+ menu: {
489
+ id: MenuId.ViewTitle,
490
+ when: ( ContextKeyExpr.equals('view', "workbench.view.testCoverage" )),
491
+ group: 'navigation',
492
+ }
493
+ });
494
+ }
495
+ runInView(accessor, view) {
496
+ const disposables = ( new DisposableStore());
497
+ const quickInput = disposables.add(accessor.get(IQuickInputService).createQuickPick());
498
+ const items = [
499
+ { label: ( localizeWithPath(
500
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
501
+ 'testing.coverageSortByLocation',
502
+ 'Sort by Location'
503
+ )), value: 1 , description: ( localizeWithPath(
504
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
505
+ 'testing.coverageSortByLocationDescription',
506
+ 'Files are sorted alphabetically, functions are sorted by position'
507
+ )) },
508
+ { label: ( localizeWithPath(
509
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
510
+ 'testing.coverageSortByCoverage',
511
+ 'Sort by Coverage'
512
+ )), value: 0 , description: ( localizeWithPath(
513
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
514
+ 'testing.coverageSortByCoverageDescription',
515
+ 'Files and functions are sorted by total coverage'
516
+ )) },
517
+ { label: ( localizeWithPath(
518
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
519
+ 'testing.coverageSortByName',
520
+ 'Sort by Name'
521
+ )), value: 2 , description: ( localizeWithPath(
522
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
523
+ 'testing.coverageSortByNameDescription',
524
+ 'Files and functions are sorted alphabetically'
525
+ )) },
526
+ ];
527
+ quickInput.placeholder = ( localizeWithPath(
528
+ 'vs/workbench/contrib/testing/browser/testCoverageView',
529
+ 'testing.coverageSortPlaceholder',
530
+ 'Sort the Test Coverage view...'
531
+ ));
532
+ quickInput.items = items;
533
+ quickInput.show();
534
+ quickInput.onDidHide(() => quickInput.dispose());
535
+ quickInput.onDidAccept(() => {
536
+ const picked = quickInput.selectedItems[0]?.value;
537
+ if (picked !== undefined) {
538
+ view.sortOrder.set(picked, undefined);
539
+ quickInput.dispose();
540
+ }
541
+ });
542
+ }
543
+ });
214
544
 
215
545
  export { TestCoverageView };