@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.
- package/package.json +8 -8
- package/vscode/src/vs/workbench/contrib/testing/browser/codeCoverageDecorations.js +567 -0
- package/vscode/src/vs/workbench/contrib/testing/browser/icons.js +22 -2
- package/vscode/src/vs/workbench/contrib/testing/browser/media/testing.css.js +1 -1
- package/vscode/src/vs/workbench/contrib/testing/browser/testCoverageBars.js +43 -22
- package/vscode/src/vs/workbench/contrib/testing/browser/testCoverageView.js +380 -50
- package/vscode/src/vs/workbench/contrib/testing/browser/testExplorerActions.js +333 -117
- package/vscode/src/vs/workbench/contrib/testing/browser/testing.contribution.js +10 -7
- package/vscode/src/vs/workbench/contrib/testing/browser/testingDecorations.js +148 -57
- package/vscode/src/vs/workbench/contrib/testing/browser/testingExplorerView.js +4 -4
- package/vscode/src/vs/workbench/contrib/testing/browser/testingOutputPeek.js +82 -48
- package/vscode/src/vs/workbench/contrib/testing/browser/testingProgressUiService.js +1 -1
- package/vscode/src/vs/workbench/contrib/testing/browser/theme.js +131 -2
- package/vscode/src/vs/workbench/contrib/testing/common/configuration.js +22 -1
- package/vscode/src/vs/workbench/contrib/testing/common/mainThreadTestCollection.js +3 -3
- package/vscode/src/vs/workbench/contrib/testing/common/testServiceImpl.js +12 -9
|
@@ -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 {
|
|
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 {
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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) =>
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
106
|
-
|
|
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: {
|
|
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
|
-
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
]
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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(
|
|
159
|
-
|
|
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)
|
|
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 };
|