@codingame/monaco-vscode-testing-service-override 5.2.0 → 6.0.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 +3 -3
- package/vscode/src/vs/workbench/contrib/testing/browser/codeCoverageDecorations.js +332 -114
- package/vscode/src/vs/workbench/contrib/testing/browser/codeCoverageDisplayUtils.js +85 -0
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/index.js +6 -5
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/listProjection.js +9 -8
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/treeProjection.js +13 -12
- package/vscode/src/vs/workbench/contrib/testing/browser/icons.js +8 -7
- package/vscode/src/vs/workbench/contrib/testing/browser/media/testing.css.js +1 -1
- package/vscode/src/vs/workbench/contrib/testing/browser/testCoverageBars.js +30 -65
- package/vscode/src/vs/workbench/contrib/testing/browser/testCoverageView.js +113 -35
- package/vscode/src/vs/workbench/contrib/testing/browser/testExplorerActions.js +216 -196
- package/vscode/src/vs/workbench/contrib/testing/browser/testMessageColorizer.js +18 -8
- package/vscode/src/vs/workbench/contrib/testing/browser/testing.contribution.js +26 -31
- package/vscode/src/vs/workbench/contrib/testing/browser/testingConfigurationUi.js +1 -1
- package/vscode/src/vs/workbench/contrib/testing/browser/testingDecorations.js +63 -54
- package/vscode/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.js +13 -10
- package/vscode/src/vs/workbench/contrib/testing/browser/testingExplorerView.js +106 -87
- package/vscode/src/vs/workbench/contrib/testing/browser/testingOutputPeek.js +200 -102
- package/vscode/src/vs/workbench/contrib/testing/browser/testingProgressUiService.js +37 -17
- package/vscode/src/vs/workbench/contrib/testing/browser/testingViewPaneContainer.js +2 -1
- package/vscode/src/vs/workbench/contrib/testing/browser/theme.js +15 -14
- package/vscode/src/vs/workbench/contrib/testing/common/configuration.js +97 -37
- package/vscode/src/vs/workbench/contrib/testing/common/mainThreadTestCollection.js +4 -4
- package/vscode/src/vs/workbench/contrib/testing/common/testCoverageService.js +19 -8
- package/vscode/src/vs/workbench/contrib/testing/common/testExclusions.js +3 -2
- package/vscode/src/vs/workbench/contrib/testing/common/testExplorerFilterState.js +15 -7
- package/vscode/src/vs/workbench/contrib/testing/common/testProfileService.js +17 -16
- package/vscode/src/vs/workbench/contrib/testing/common/testResultService.js +4 -3
- package/vscode/src/vs/workbench/contrib/testing/common/testResultStorage.js +3 -2
- package/vscode/src/vs/workbench/contrib/testing/common/testService.js +8 -6
- package/vscode/src/vs/workbench/contrib/testing/common/testServiceImpl.js +33 -6
- package/vscode/src/vs/workbench/contrib/testing/common/testingContentProvider.js +11 -10
- package/vscode/src/vs/workbench/contrib/testing/common/testingContextKeys.js +37 -19
- package/vscode/src/vs/workbench/contrib/testing/common/testingContinuousRunService.js +3 -2
- package/vscode/src/vs/workbench/contrib/testing/common/testingUri.js +41 -24
- package/vscode/src/vs/workbench/contrib/testing/common/constants.js +0 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codingame/monaco-vscode-testing-service-override",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"keywords": [],
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "CodinGame",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"vscode": "npm:@codingame/monaco-vscode-api@
|
|
30
|
-
"@codingame/monaco-vscode-terminal-service-override": "
|
|
29
|
+
"vscode": "npm:@codingame/monaco-vscode-api@6.0.0",
|
|
30
|
+
"@codingame/monaco-vscode-terminal-service-override": "6.0.0"
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -1,55 +1,76 @@
|
|
|
1
1
|
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { h, addStandardDisposableListener, EventType, reset } from 'vscode/vscode/vs/base/browser/dom';
|
|
3
|
+
import { ActionViewItem } from 'vscode/vscode/vs/base/browser/ui/actionbar/actionViewItems';
|
|
4
|
+
import { ActionBar, ActionsOrientation } from 'vscode/vscode/vs/base/browser/ui/actionbar/actionbar';
|
|
5
|
+
import { renderIcon } from 'vscode/vscode/vs/base/browser/ui/iconLabel/iconLabels';
|
|
6
|
+
import { Action } from 'vscode/vscode/vs/base/common/actions';
|
|
4
7
|
import { mapFindFirst } from 'vscode/vscode/vs/base/common/arraysFind';
|
|
5
|
-
import { assertNever } from 'vscode/vscode/vs/base/common/assert';
|
|
8
|
+
import { assertNever, assert } from 'vscode/vscode/vs/base/common/assert';
|
|
6
9
|
import { CancellationTokenSource } from 'vscode/vscode/vs/base/common/cancellation';
|
|
10
|
+
import { Codicon } from 'vscode/vscode/vs/base/common/codicons';
|
|
7
11
|
import { MarkdownString } from 'vscode/vscode/vs/base/common/htmlContent';
|
|
8
|
-
import { KeyChord } from 'vscode/vscode/vs/base/common/keyCodes';
|
|
12
|
+
import { KeyChord, KeyMod, KeyCode } from 'vscode/vscode/vs/base/common/keyCodes';
|
|
9
13
|
import { Lazy } from 'vscode/vscode/vs/base/common/lazy';
|
|
10
|
-
import { Disposable, DisposableStore, toDisposable } from 'vscode/vscode/vs/base/common/lifecycle';
|
|
14
|
+
import { Disposable, DisposableStore, toDisposable, MutableDisposable } from 'vscode/vscode/vs/base/common/lifecycle';
|
|
11
15
|
import { observableValue } from 'vscode/vscode/vs/base/common/observableInternal/base';
|
|
12
16
|
import { derived } from 'vscode/vscode/vs/base/common/observableInternal/derived';
|
|
13
17
|
import { autorun } from 'vscode/vscode/vs/base/common/observableInternal/autorun';
|
|
14
18
|
import { observableFromEvent } from 'vscode/vscode/vs/base/common/observableInternal/utils';
|
|
15
19
|
import 'vscode/vscode/vs/base/common/arrays';
|
|
16
20
|
import { ThemeIcon } from 'vscode/vscode/vs/base/common/themables';
|
|
17
|
-
import {
|
|
21
|
+
import { isUriComponents, URI } from 'vscode/vscode/vs/base/common/uri';
|
|
22
|
+
import { MouseTargetType, OverlayWidgetPositionPreference } from 'vscode/vscode/vs/editor/browser/editorBrowser';
|
|
23
|
+
import { ICodeEditorService } from 'vscode/vscode/vs/editor/browser/services/codeEditorService';
|
|
24
|
+
import { EditorOption } from 'vscode/vscode/vs/editor/common/config/editorOptions';
|
|
18
25
|
import { Position } from 'vscode/vscode/vs/editor/common/core/position';
|
|
19
26
|
import { Range } from 'vscode/vscode/vs/editor/common/core/range';
|
|
20
27
|
import { InjectedTextCursorStops } from 'vscode/vscode/vs/editor/common/model';
|
|
21
|
-
import { HoverOperation } from 'vscode/vscode/vs/editor/contrib/hover/browser/hoverOperation';
|
|
22
28
|
import { localizeWithPath, localize2WithPath } from 'vscode/vscode/vs/nls';
|
|
23
29
|
import { Categories } from 'vscode/vscode/vs/platform/action/common/actionCommonCategories';
|
|
24
|
-
import { registerAction2, Action2 } from 'vscode/vscode/vs/platform/actions/common/actions';
|
|
30
|
+
import { MenuId, registerAction2, Action2 } from 'vscode/vscode/vs/platform/actions/common/actions';
|
|
31
|
+
import { ICommandService } from 'vscode/vscode/vs/platform/commands/common/commands.service';
|
|
32
|
+
import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service';
|
|
33
|
+
import { ContextKeyExpr } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
|
|
34
|
+
import { IContextMenuService } from 'vscode/vscode/vs/platform/contextview/browser/contextView.service';
|
|
25
35
|
import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
|
|
26
36
|
import { IKeybindingService } from 'vscode/vscode/vs/platform/keybinding/common/keybinding.service';
|
|
37
|
+
import { KeybindingWeight } from 'vscode/vscode/vs/platform/keybinding/common/keybindingsRegistry';
|
|
27
38
|
import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service';
|
|
28
|
-
import {
|
|
39
|
+
import { observableConfigValue } from 'vscode/vscode/vs/platform/observable/common/platformObservableUtils';
|
|
40
|
+
import { IQuickInputService } from 'vscode/vscode/vs/platform/quickinput/common/quickInput.service';
|
|
41
|
+
import { labels, getLabelForItem } from './codeCoverageDisplayUtils.js';
|
|
42
|
+
import { testingCoverageMissingBranch, testingCoverageReport, testingFilterIcon, testingRerunIcon } from './icons.js';
|
|
43
|
+
import { ManagedTestCoverageBars } from './testCoverageBars.js';
|
|
44
|
+
import { TestingConfigKeys, getTestingConfiguration } from '../common/configuration.js';
|
|
45
|
+
import { TestCommandId } from 'vscode/vscode/vs/workbench/contrib/testing/common/constants';
|
|
46
|
+
import { FileCoverage } from 'vscode/vscode/vs/workbench/contrib/testing/common/testCoverage';
|
|
29
47
|
import { ITestCoverageService } from 'vscode/vscode/vs/workbench/contrib/testing/common/testCoverageService.service';
|
|
48
|
+
import { TestId } from 'vscode/vscode/vs/workbench/contrib/testing/common/testId';
|
|
49
|
+
import { ITestService } from 'vscode/vscode/vs/workbench/contrib/testing/common/testService.service';
|
|
50
|
+
import { DetailType } from 'vscode/vscode/vs/workbench/contrib/testing/common/testTypes';
|
|
30
51
|
import { TestingContextKeys } from '../common/testingContextKeys.js';
|
|
31
52
|
|
|
32
|
-
var CodeCoverageDecorations_1
|
|
53
|
+
var CodeCoverageDecorations_1;
|
|
33
54
|
const _moduleId = "vs/workbench/contrib/testing/browser/codeCoverageDecorations";
|
|
34
55
|
const MAX_HOVERED_LINES = 30;
|
|
35
56
|
const CLASS_HIT = 'coverage-deco-hit';
|
|
36
57
|
const CLASS_MISS = 'coverage-deco-miss';
|
|
37
|
-
const TOGGLE_INLINE_COMMAND_TEXT = ( localizeWithPath(_moduleId, 0, 'Toggle Inline
|
|
58
|
+
const TOGGLE_INLINE_COMMAND_TEXT = ( localizeWithPath(_moduleId, 0, 'Toggle Inline'));
|
|
38
59
|
const TOGGLE_INLINE_COMMAND_ID = 'testing.toggleInlineCoverage';
|
|
39
60
|
const BRANCH_MISS_INDICATOR_CHARS = 4;
|
|
40
61
|
let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
41
62
|
static { CodeCoverageDecorations_1 = this; }
|
|
42
63
|
static { this.showInline = observableValue('inlineCoverage', false); }
|
|
43
64
|
static { this.fileCoverageDecorations = ( (new WeakMap())); }
|
|
44
|
-
constructor(editor, instantiationService, coverage, log) {
|
|
65
|
+
constructor(editor, instantiationService, coverage, configurationService, log) {
|
|
45
66
|
super();
|
|
46
67
|
this.editor = editor;
|
|
47
68
|
this.log = log;
|
|
48
69
|
this.displayedStore = this._register(( (new DisposableStore())));
|
|
49
70
|
this.hoveredStore = this._register(( (new DisposableStore())));
|
|
50
71
|
this.decorationIds = ( (new Map()));
|
|
51
|
-
this.
|
|
52
|
-
() => this._register(instantiationService.createInstance(
|
|
72
|
+
this.summaryWidget = ( (new Lazy(
|
|
73
|
+
() => this._register(instantiationService.createInstance(CoverageToolbarWidget, this.editor))
|
|
53
74
|
)));
|
|
54
75
|
const modelObs = observableFromEvent(editor.onDidChangeModel, () => editor.getModel());
|
|
55
76
|
const configObs = observableFromEvent(editor.onDidChangeConfiguration, i => i);
|
|
@@ -62,8 +83,12 @@ let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
|
62
83
|
if (!model) {
|
|
63
84
|
return;
|
|
64
85
|
}
|
|
65
|
-
|
|
86
|
+
let file = report.getUri(model.uri);
|
|
66
87
|
if (file) {
|
|
88
|
+
const testFilter = coverage.filterToTest.read(reader);
|
|
89
|
+
if (testFilter) {
|
|
90
|
+
file = file.perTestData?.get(( (testFilter.toString()))) || file;
|
|
91
|
+
}
|
|
67
92
|
return file;
|
|
68
93
|
}
|
|
69
94
|
report.didAddCoverage.read(reader);
|
|
@@ -78,22 +103,31 @@ let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
|
78
103
|
this.clear();
|
|
79
104
|
}
|
|
80
105
|
}));
|
|
106
|
+
const toolbarEnabled = observableConfigValue(TestingConfigKeys.CoverageToolbarEnabled, true, configurationService);
|
|
107
|
+
this._register(autorun(reader => {
|
|
108
|
+
const c = fileCoverage.read(reader);
|
|
109
|
+
if (c && toolbarEnabled.read(reader)) {
|
|
110
|
+
this.summaryWidget.value.setCoverage(c);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
this.summaryWidget.rawValue?.setCoverage(undefined);
|
|
114
|
+
}
|
|
115
|
+
}));
|
|
81
116
|
this._register(autorun(reader => {
|
|
82
117
|
const c = fileCoverage.read(reader);
|
|
83
118
|
if (c) {
|
|
84
119
|
const evt = configObs.read(reader);
|
|
85
|
-
if (evt?.hasChanged(
|
|
120
|
+
if (evt?.hasChanged(EditorOption.lineHeight) !== false) {
|
|
86
121
|
this.updateEditorStyles();
|
|
87
122
|
}
|
|
88
123
|
}
|
|
89
124
|
}));
|
|
90
125
|
this._register(editor.onMouseMove(e => {
|
|
91
126
|
const model = editor.getModel();
|
|
92
|
-
if (e.target.type ===
|
|
127
|
+
if (e.target.type === MouseTargetType.GUTTER_LINE_NUMBERS && model) {
|
|
93
128
|
this.hoverLineNumber(editor.getModel(), e.target.position.lineNumber);
|
|
94
129
|
}
|
|
95
|
-
else if (
|
|
96
|
-
else if (CodeCoverageDecorations_1.showInline.get() && e.target.type === 6 && model) {
|
|
130
|
+
else if (CodeCoverageDecorations_1.showInline.get() && e.target.type === MouseTargetType.CONTENT_TEXT && model) {
|
|
97
131
|
this.hoverInlineDecoration(model, e.target.position);
|
|
98
132
|
}
|
|
99
133
|
else {
|
|
@@ -114,7 +148,7 @@ let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
|
114
148
|
}));
|
|
115
149
|
}
|
|
116
150
|
updateEditorStyles() {
|
|
117
|
-
const lineHeight = this.editor.getOption(
|
|
151
|
+
const lineHeight = this.editor.getOption(EditorOption.lineHeight);
|
|
118
152
|
const { style } = this.editor.getContainerDomNode();
|
|
119
153
|
style.setProperty('--vscode-testing-coverage-lineHeight', `${lineHeight}px`);
|
|
120
154
|
}
|
|
@@ -150,7 +184,6 @@ let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
|
150
184
|
this.hoveredSubject = lineNumber;
|
|
151
185
|
const todo = [{ line: lineNumber, dir: 0 }];
|
|
152
186
|
const toEnable = ( (new Set()));
|
|
153
|
-
const inlineEnabled = CodeCoverageDecorations_1.showInline.get();
|
|
154
187
|
if (!CodeCoverageDecorations_1.showInline.get()) {
|
|
155
188
|
for (let i = 0; i < todo.length && i < MAX_HOVERED_LINES; i++) {
|
|
156
189
|
const { line, dir } = todo[i];
|
|
@@ -179,14 +212,10 @@ let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
|
179
212
|
}
|
|
180
213
|
});
|
|
181
214
|
}
|
|
182
|
-
if (toEnable.size || inlineEnabled) {
|
|
183
|
-
this.lineHoverWidget.value.startShowingAt(lineNumber);
|
|
184
|
-
}
|
|
185
215
|
this.hoveredStore.add(this.editor.onMouseLeave(() => {
|
|
186
216
|
this.hoveredStore.clear();
|
|
187
217
|
}));
|
|
188
218
|
this.hoveredStore.add(toDisposable(() => {
|
|
189
|
-
this.lineHoverWidget.value.hide();
|
|
190
219
|
this.hoveredSubject = undefined;
|
|
191
220
|
model.changeDecorations(e => {
|
|
192
221
|
for (const id of toEnable) {
|
|
@@ -207,7 +236,7 @@ let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
|
207
236
|
model.changeDecorations(e => {
|
|
208
237
|
for (const detailRange of details.ranges) {
|
|
209
238
|
const { metadata: { detail, description }, range, primary } = detailRange;
|
|
210
|
-
if (detail.type ===
|
|
239
|
+
if (detail.type === DetailType.Branch) {
|
|
211
240
|
const hits = detail.detail.branches[detail.branch].count;
|
|
212
241
|
const cls = hits ? CLASS_HIT : CLASS_MISS;
|
|
213
242
|
const showMissIndicator = !hits && range.isEmpty() && ( (detail.detail.branches.some(b => b.count)));
|
|
@@ -238,7 +267,7 @@ let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
|
238
267
|
}
|
|
239
268
|
this.decorationIds.set(e.addDecoration(range, options), { options, applyHoverOptions, detail: detailRange });
|
|
240
269
|
}
|
|
241
|
-
else if (detail.type ===
|
|
270
|
+
else if (detail.type === DetailType.Statement) {
|
|
242
271
|
const cls = detail.count ? CLASS_HIT : CLASS_MISS;
|
|
243
272
|
const options = {
|
|
244
273
|
showIfCollapsed: false,
|
|
@@ -300,7 +329,8 @@ let CodeCoverageDecorations = class CodeCoverageDecorations extends Disposable {
|
|
|
300
329
|
CodeCoverageDecorations = CodeCoverageDecorations_1 = ( (__decorate([
|
|
301
330
|
( (__param(1, IInstantiationService))),
|
|
302
331
|
( (__param(2, ITestCoverageService))),
|
|
303
|
-
( (__param(3,
|
|
332
|
+
( (__param(3, IConfigurationService))),
|
|
333
|
+
( (__param(4, ILogService)))
|
|
304
334
|
], CodeCoverageDecorations)));
|
|
305
335
|
const countBadge = (count) => {
|
|
306
336
|
if (count === 0) {
|
|
@@ -323,9 +353,9 @@ class CoverageDetailsModel {
|
|
|
323
353
|
metadata: { detail, description: this.describe(detail, textModel) }
|
|
324
354
|
}))));
|
|
325
355
|
for (const { range, metadata: { detail } } of detailRanges) {
|
|
326
|
-
if (detail.type ===
|
|
356
|
+
if (detail.type === DetailType.Statement && detail.branches) {
|
|
327
357
|
for (let i = 0; i < detail.branches.length; i++) {
|
|
328
|
-
const branch = { type:
|
|
358
|
+
const branch = { type: DetailType.Branch, branch: i, detail };
|
|
329
359
|
detailRanges.push({
|
|
330
360
|
range: tidyLocation(detail.branches[i].location || Range.fromPositions(range.getEndPosition())),
|
|
331
361
|
primary: true,
|
|
@@ -375,10 +405,10 @@ class CoverageDetailsModel {
|
|
|
375
405
|
}
|
|
376
406
|
}
|
|
377
407
|
describe(detail, model) {
|
|
378
|
-
if (detail.type ===
|
|
408
|
+
if (detail.type === DetailType.Declaration) {
|
|
379
409
|
return namedDetailLabel(detail.name, detail);
|
|
380
410
|
}
|
|
381
|
-
else if (detail.type ===
|
|
411
|
+
else if (detail.type === DetailType.Statement) {
|
|
382
412
|
const text = wrapName(model.getValueInRange(tidyLocation(detail.location)).trim() || `<empty statement>`);
|
|
383
413
|
if (detail.branches?.length) {
|
|
384
414
|
const covered = detail.branches.filter(b => !!b.count).length;
|
|
@@ -395,7 +425,7 @@ class CoverageDetailsModel {
|
|
|
395
425
|
return namedDetailLabel(text, detail);
|
|
396
426
|
}
|
|
397
427
|
}
|
|
398
|
-
else if (detail.type ===
|
|
428
|
+
else if (detail.type === DetailType.Branch) {
|
|
399
429
|
const text = wrapName(model.getValueInRange(tidyLocation(detail.detail.location)).trim() || `<empty statement>`);
|
|
400
430
|
const { count, label } = detail.detail.branches[detail.branch];
|
|
401
431
|
const label2 = label ? wrapInBackticks(label) : `#${detail.branch + 1}`;
|
|
@@ -432,26 +462,6 @@ function tidyLocation(location) {
|
|
|
432
462
|
}
|
|
433
463
|
return location;
|
|
434
464
|
}
|
|
435
|
-
let LineHoverComputer = class LineHoverComputer {
|
|
436
|
-
constructor(keybindingService) {
|
|
437
|
-
this.keybindingService = keybindingService;
|
|
438
|
-
this.line = -1;
|
|
439
|
-
}
|
|
440
|
-
computeSync() {
|
|
441
|
-
const strs = [];
|
|
442
|
-
const s = ( (new MarkdownString())).appendMarkdown(`[${TOGGLE_INLINE_COMMAND_TEXT}](command:${TOGGLE_INLINE_COMMAND_ID})`);
|
|
443
|
-
s.isTrusted = true;
|
|
444
|
-
const binding = this.keybindingService.lookupKeybinding(TOGGLE_INLINE_COMMAND_ID);
|
|
445
|
-
if (binding) {
|
|
446
|
-
s.appendText(` (${binding.getLabel()})`);
|
|
447
|
-
}
|
|
448
|
-
strs.push(s);
|
|
449
|
-
return strs;
|
|
450
|
-
}
|
|
451
|
-
};
|
|
452
|
-
LineHoverComputer = ( (__decorate([
|
|
453
|
-
( (__param(0, IKeybindingService)))
|
|
454
|
-
], LineHoverComputer)));
|
|
455
465
|
function wrapInBackticks(str) {
|
|
456
466
|
return '`' + str.replace(/[\n\r`]/g, '') + '`';
|
|
457
467
|
}
|
|
@@ -461,97 +471,305 @@ function wrapName(functionNameOrCode) {
|
|
|
461
471
|
}
|
|
462
472
|
return wrapInBackticks(functionNameOrCode);
|
|
463
473
|
}
|
|
464
|
-
let
|
|
465
|
-
|
|
466
|
-
static { this.ID = 'editor.contrib.testingCoverageLineHoverWidget'; }
|
|
467
|
-
constructor(editor, instantiationService) {
|
|
474
|
+
let CoverageToolbarWidget = class CoverageToolbarWidget extends Disposable {
|
|
475
|
+
constructor(editor, configurationService, contextMenuService, testService, keybindingService, commandService, instaService) {
|
|
468
476
|
super();
|
|
469
477
|
this.editor = editor;
|
|
470
|
-
this.
|
|
471
|
-
this.
|
|
472
|
-
this.
|
|
473
|
-
this.
|
|
474
|
-
this.
|
|
475
|
-
this.
|
|
476
|
-
this.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
478
|
+
this.configurationService = configurationService;
|
|
479
|
+
this.contextMenuService = contextMenuService;
|
|
480
|
+
this.testService = testService;
|
|
481
|
+
this.keybindingService = keybindingService;
|
|
482
|
+
this.commandService = commandService;
|
|
483
|
+
this.registered = false;
|
|
484
|
+
this.isRunning = false;
|
|
485
|
+
this.showStore = this._register(( (new DisposableStore())));
|
|
486
|
+
this._domNode = h('div.coverage-summary-widget', [
|
|
487
|
+
h('div', [
|
|
488
|
+
h('span.bars@bars'),
|
|
489
|
+
h('span.toolbar@toolbar'),
|
|
490
|
+
]),
|
|
491
|
+
]);
|
|
492
|
+
this.bars = this._register(instaService.createInstance(ManagedTestCoverageBars, {
|
|
493
|
+
compact: false,
|
|
494
|
+
overall: false,
|
|
495
|
+
container: this._domNode.bars,
|
|
496
|
+
}));
|
|
497
|
+
this.actionBar = this._register(instaService.createInstance(ActionBar, this._domNode.toolbar, {
|
|
498
|
+
orientation: ActionsOrientation.HORIZONTAL,
|
|
499
|
+
actionViewItemProvider: (action, options) => {
|
|
500
|
+
const vm = ( (new CodiconActionViewItem(undefined, action, options)));
|
|
501
|
+
if (action instanceof ActionWithIcon) {
|
|
502
|
+
vm.themeIcon = action.icon;
|
|
503
|
+
}
|
|
504
|
+
return vm;
|
|
482
505
|
}
|
|
483
|
-
});
|
|
484
|
-
this.
|
|
506
|
+
}));
|
|
507
|
+
this._register(autorun(reader => {
|
|
508
|
+
CodeCoverageDecorations.showInline.read(reader);
|
|
509
|
+
this.setActions();
|
|
510
|
+
}));
|
|
511
|
+
this._register(addStandardDisposableListener(this._domNode.root, EventType.CONTEXT_MENU, e => {
|
|
512
|
+
this.contextMenuService.showContextMenu({
|
|
513
|
+
menuId: MenuId.StickyScrollContext,
|
|
514
|
+
getAnchor: () => e,
|
|
515
|
+
});
|
|
516
|
+
}));
|
|
485
517
|
}
|
|
486
518
|
getId() {
|
|
487
|
-
return
|
|
519
|
+
return 'coverage-summary-widget';
|
|
488
520
|
}
|
|
489
521
|
getDomNode() {
|
|
490
|
-
return this.
|
|
522
|
+
return this._domNode.root;
|
|
491
523
|
}
|
|
492
524
|
getPosition() {
|
|
493
|
-
return
|
|
525
|
+
return {
|
|
526
|
+
preference: OverlayWidgetPositionPreference.TOP_CENTER,
|
|
527
|
+
stackOridinal: 9,
|
|
528
|
+
};
|
|
494
529
|
}
|
|
495
|
-
|
|
496
|
-
this.
|
|
497
|
-
|
|
530
|
+
setCoverage(coverage) {
|
|
531
|
+
this.current = coverage;
|
|
532
|
+
this.bars.setCoverageInfo(coverage);
|
|
533
|
+
if (!coverage) {
|
|
534
|
+
this.hide();
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
this.setActions();
|
|
538
|
+
this.show();
|
|
539
|
+
}
|
|
498
540
|
}
|
|
499
|
-
|
|
500
|
-
this.
|
|
501
|
-
const
|
|
502
|
-
if (!
|
|
541
|
+
setActions() {
|
|
542
|
+
this.actionBar.clear();
|
|
543
|
+
const coverage = this.current;
|
|
544
|
+
if (!coverage) {
|
|
503
545
|
return;
|
|
504
546
|
}
|
|
505
|
-
|
|
506
|
-
|
|
547
|
+
const toggleAction = ( (new ActionWithIcon('toggleInline', CodeCoverageDecorations.showInline.get()
|
|
548
|
+
? ( localizeWithPath(_moduleId, 8, 'Hide Inline Coverage'))
|
|
549
|
+
: ( localizeWithPath(_moduleId, 9, 'Show Inline Coverage')), testingCoverageReport, undefined, () => CodeCoverageDecorations.showInline.set(!CodeCoverageDecorations.showInline.get(), undefined))));
|
|
550
|
+
const kb = this.keybindingService.lookupKeybinding(TOGGLE_INLINE_COMMAND_ID);
|
|
551
|
+
if (kb) {
|
|
552
|
+
toggleAction.tooltip = `${TOGGLE_INLINE_COMMAND_TEXT} (${kb.getLabel()})`;
|
|
553
|
+
}
|
|
554
|
+
this.actionBar.push(toggleAction);
|
|
555
|
+
if (coverage.isForTest) {
|
|
556
|
+
const testItem = coverage.fromResult.getTestById(( (coverage.isForTest.id.toString())));
|
|
557
|
+
assert(!!testItem, 'got coverage for an unreported test');
|
|
558
|
+
this.actionBar.push(( (new ActionWithIcon(
|
|
559
|
+
'perTestFilter',
|
|
560
|
+
labels.showingFilterFor(testItem.label),
|
|
561
|
+
testingFilterIcon,
|
|
562
|
+
undefined,
|
|
563
|
+
() => this.commandService.executeCommand(TestCommandId.CoverageFilterToTestInEditor, this.current)
|
|
564
|
+
))));
|
|
565
|
+
}
|
|
566
|
+
else if (coverage.perTestData?.size) {
|
|
567
|
+
this.actionBar.push(( (new ActionWithIcon('perTestFilter', ( localizeWithPath(
|
|
568
|
+
_moduleId,
|
|
569
|
+
10,
|
|
570
|
+
"{0} test(s) ran code in this file",
|
|
571
|
+
coverage.perTestData.size
|
|
572
|
+
)), testingFilterIcon, undefined, () => this.commandService.executeCommand(TestCommandId.CoverageFilterToTestInEditor, this.current)))));
|
|
573
|
+
}
|
|
574
|
+
this.actionBar.push(( (new ActionWithIcon('rerun', ( localizeWithPath(_moduleId, 11, 'Rerun')), testingRerunIcon, !this.isRunning, () => this.rerunTest()))));
|
|
507
575
|
}
|
|
508
|
-
|
|
509
|
-
this.
|
|
510
|
-
|
|
576
|
+
show() {
|
|
577
|
+
if (this.registered) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
this.registered = true;
|
|
581
|
+
let viewZoneId;
|
|
582
|
+
const ds = this.showStore;
|
|
583
|
+
this.editor.addOverlayWidget(this);
|
|
584
|
+
this.editor.changeViewZones(accessor => {
|
|
585
|
+
viewZoneId = accessor.addZone({
|
|
586
|
+
afterLineNumber: 0,
|
|
587
|
+
afterColumn: 0,
|
|
588
|
+
domNode: document.createElement('div'),
|
|
589
|
+
heightInPx: 30,
|
|
590
|
+
ordinal: -1,
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
ds.add(toDisposable(() => {
|
|
594
|
+
this.registered = false;
|
|
595
|
+
this.editor.removeOverlayWidget(this);
|
|
596
|
+
this.editor.changeViewZones(accessor => {
|
|
597
|
+
accessor.removeZone(viewZoneId);
|
|
598
|
+
});
|
|
599
|
+
}));
|
|
600
|
+
ds.add(this.configurationService.onDidChangeConfiguration(e => {
|
|
601
|
+
if (e.affectsConfiguration(TestingConfigKeys.CoverageBarThresholds) || e.affectsConfiguration(TestingConfigKeys.CoveragePercent)) {
|
|
602
|
+
this.setCoverage(this.current);
|
|
603
|
+
}
|
|
604
|
+
}));
|
|
511
605
|
}
|
|
512
|
-
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
606
|
+
rerunTest() {
|
|
607
|
+
const current = this.current;
|
|
608
|
+
if (current) {
|
|
609
|
+
this.isRunning = true;
|
|
610
|
+
this.setActions();
|
|
611
|
+
this.testService.runResolvedTests(current.fromResult.request).finally(() => {
|
|
612
|
+
this.isRunning = false;
|
|
613
|
+
this.setActions();
|
|
614
|
+
});
|
|
521
615
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
const editorLayout = editor.getLayoutInfo();
|
|
526
|
-
const topForLineNumber = editor.getTopForLineNumber(this.computer.line);
|
|
527
|
-
const editorScrollTop = editor.getScrollTop();
|
|
528
|
-
const lineHeight = editor.getOption(67 );
|
|
529
|
-
const nodeHeight = h.containerDomNode.clientHeight;
|
|
530
|
-
const top = topForLineNumber - editorScrollTop - ((nodeHeight - lineHeight) / 2);
|
|
531
|
-
const left = editorLayout.lineNumbersLeft + editorLayout.lineNumbersWidth;
|
|
532
|
-
h.containerDomNode.style.left = `${left}px`;
|
|
533
|
-
h.containerDomNode.style.top = `${Math.max(Math.round(top), 0)}px`;
|
|
616
|
+
}
|
|
617
|
+
hide() {
|
|
618
|
+
this.showStore.clear();
|
|
534
619
|
}
|
|
535
620
|
};
|
|
536
|
-
|
|
537
|
-
( (__param(1,
|
|
538
|
-
|
|
621
|
+
CoverageToolbarWidget = ( (__decorate([
|
|
622
|
+
( (__param(1, IConfigurationService))),
|
|
623
|
+
( (__param(2, IContextMenuService))),
|
|
624
|
+
( (__param(3, ITestService))),
|
|
625
|
+
( (__param(4, IKeybindingService))),
|
|
626
|
+
( (__param(5, ICommandService))),
|
|
627
|
+
( (__param(6, IInstantiationService)))
|
|
628
|
+
], CoverageToolbarWidget)));
|
|
539
629
|
registerAction2(class ToggleInlineCoverage extends Action2 {
|
|
540
630
|
constructor() {
|
|
541
631
|
super({
|
|
542
632
|
id: TOGGLE_INLINE_COMMAND_ID,
|
|
543
|
-
title: ( localize2WithPath(_moduleId,
|
|
633
|
+
title: ( localize2WithPath(_moduleId, 12, "Show Inline Coverage")),
|
|
544
634
|
category: Categories.Test,
|
|
545
635
|
keybinding: {
|
|
546
|
-
weight:
|
|
547
|
-
primary: KeyChord(
|
|
636
|
+
weight: KeybindingWeight.WorkbenchContrib,
|
|
637
|
+
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.Semicolon, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyI),
|
|
548
638
|
},
|
|
549
|
-
|
|
639
|
+
icon: testingCoverageReport,
|
|
640
|
+
menu: [
|
|
641
|
+
{ id: MenuId.CommandPalette, when: TestingContextKeys.isTestCoverageOpen },
|
|
642
|
+
{ id: MenuId.EditorTitle, when: ( (ContextKeyExpr.and(
|
|
643
|
+
TestingContextKeys.isTestCoverageOpen,
|
|
644
|
+
(TestingContextKeys.coverageToolbarEnabled.notEqualsTo(true))
|
|
645
|
+
))), group: 'navigation' },
|
|
646
|
+
]
|
|
550
647
|
});
|
|
551
648
|
}
|
|
552
649
|
run() {
|
|
553
650
|
CodeCoverageDecorations.showInline.set(!CodeCoverageDecorations.showInline.get(), undefined);
|
|
554
651
|
}
|
|
555
652
|
});
|
|
653
|
+
registerAction2(class ToggleCoverageToolbar extends Action2 {
|
|
654
|
+
constructor() {
|
|
655
|
+
super({
|
|
656
|
+
id: TestCommandId.CoverageToggleToolbar,
|
|
657
|
+
title: ( localize2WithPath(_moduleId, 13, "Test Coverage Toolbar")),
|
|
658
|
+
metadata: {
|
|
659
|
+
description: ( localize2WithPath(_moduleId, 14, 'Toggle the sticky coverage bar in the editor.'))
|
|
660
|
+
},
|
|
661
|
+
category: Categories.Test,
|
|
662
|
+
toggled: {
|
|
663
|
+
condition: TestingContextKeys.coverageToolbarEnabled,
|
|
664
|
+
},
|
|
665
|
+
menu: [
|
|
666
|
+
{ id: MenuId.CommandPalette, when: TestingContextKeys.isTestCoverageOpen },
|
|
667
|
+
{ id: MenuId.StickyScrollContext, when: TestingContextKeys.isTestCoverageOpen },
|
|
668
|
+
{ id: MenuId.EditorTitle, when: TestingContextKeys.isTestCoverageOpen, group: 'coverage@1' },
|
|
669
|
+
]
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
run(accessor) {
|
|
673
|
+
const config = accessor.get(IConfigurationService);
|
|
674
|
+
const value = getTestingConfiguration(config, TestingConfigKeys.CoverageToolbarEnabled);
|
|
675
|
+
config.updateValue(TestingConfigKeys.CoverageToolbarEnabled, !value);
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
registerAction2(class FilterCoverageToTestInEditor extends Action2 {
|
|
679
|
+
constructor() {
|
|
680
|
+
super({
|
|
681
|
+
id: TestCommandId.CoverageFilterToTestInEditor,
|
|
682
|
+
title: ( localize2WithPath(_moduleId, 15, "Filter Coverage to Test")),
|
|
683
|
+
category: Categories.Test,
|
|
684
|
+
icon: Codicon.filter,
|
|
685
|
+
toggled: {
|
|
686
|
+
icon: Codicon.filterFilled,
|
|
687
|
+
condition: TestingContextKeys.isCoverageFilteredToTest,
|
|
688
|
+
},
|
|
689
|
+
menu: [
|
|
690
|
+
{ id: MenuId.EditorTitle, when: ( (ContextKeyExpr.and(
|
|
691
|
+
TestingContextKeys.isTestCoverageOpen,
|
|
692
|
+
(TestingContextKeys.coverageToolbarEnabled.notEqualsTo(true))
|
|
693
|
+
))), group: 'navigation' },
|
|
694
|
+
]
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
run(accessor, coverageOrUri) {
|
|
698
|
+
const testCoverageService = accessor.get(ITestCoverageService);
|
|
699
|
+
const quickInputService = accessor.get(IQuickInputService);
|
|
700
|
+
const activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor();
|
|
701
|
+
let coverage;
|
|
702
|
+
if (coverageOrUri instanceof FileCoverage) {
|
|
703
|
+
coverage = coverageOrUri;
|
|
704
|
+
}
|
|
705
|
+
else if (isUriComponents(coverageOrUri)) {
|
|
706
|
+
coverage = testCoverageService.selected.get()?.getUri(( (URI.from(coverageOrUri))));
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
const uri = activeEditor?.getModel()?.uri;
|
|
710
|
+
coverage = uri && testCoverageService.selected.get()?.getUri(uri);
|
|
711
|
+
}
|
|
712
|
+
if (!coverage || !(coverage.isForTest || coverage.perTestData?.size)) {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
const options = coverage?.perTestData ?? coverage?.isForTest?.parent.perTestData;
|
|
716
|
+
if (!options) {
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
const tests = [...( (options.values()))];
|
|
720
|
+
const commonPrefix = TestId.getLengthOfCommonPrefix(tests.length, i => tests[i].isForTest.id);
|
|
721
|
+
const result = coverage.fromResult;
|
|
722
|
+
const previousSelection = testCoverageService.filterToTest.get();
|
|
723
|
+
const items = [
|
|
724
|
+
{ label: labels.allTests, item: undefined },
|
|
725
|
+
{ type: 'separator' },
|
|
726
|
+
...( (tests.map(
|
|
727
|
+
item => ({ label: getLabelForItem(result, item.isForTest.id, commonPrefix), description: labels.percentCoverage(item.tpc), item })
|
|
728
|
+
))),
|
|
729
|
+
];
|
|
730
|
+
const scrollTop = activeEditor?.getScrollTop() || 0;
|
|
731
|
+
const revealScrollCts = ( (new MutableDisposable()));
|
|
732
|
+
quickInputService.pick(items, {
|
|
733
|
+
activeItem: items.find((item) => 'item' in item && item.item === coverage),
|
|
734
|
+
placeHolder: labels.pickShowCoverage,
|
|
735
|
+
onDidFocus: (entry) => {
|
|
736
|
+
if (!entry.item) {
|
|
737
|
+
revealScrollCts.clear();
|
|
738
|
+
activeEditor?.setScrollTop(scrollTop);
|
|
739
|
+
testCoverageService.filterToTest.set(undefined, undefined);
|
|
740
|
+
}
|
|
741
|
+
else {
|
|
742
|
+
const cts = revealScrollCts.value = ( (new CancellationTokenSource()));
|
|
743
|
+
entry.item.details(cts.token).then(details => {
|
|
744
|
+
const first = details.find(d => d.type === DetailType.Statement);
|
|
745
|
+
if (!cts.token.isCancellationRequested && first) {
|
|
746
|
+
activeEditor?.revealLineNearTop(first.location instanceof Position ? first.location.lineNumber : first.location.startLineNumber);
|
|
747
|
+
}
|
|
748
|
+
}, () => { });
|
|
749
|
+
testCoverageService.filterToTest.set(entry.item.isForTest.id, undefined);
|
|
750
|
+
}
|
|
751
|
+
},
|
|
752
|
+
}).then(selected => {
|
|
753
|
+
if (!selected) {
|
|
754
|
+
activeEditor?.setScrollTop(scrollTop);
|
|
755
|
+
}
|
|
756
|
+
revealScrollCts.dispose();
|
|
757
|
+
testCoverageService.filterToTest.set(selected ? selected.item?.isForTest.id : previousSelection, undefined);
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
class ActionWithIcon extends Action {
|
|
762
|
+
constructor(id, title, icon, enabled, run) {
|
|
763
|
+
super(id, title, undefined, enabled, run);
|
|
764
|
+
this.icon = icon;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
class CodiconActionViewItem extends ActionViewItem {
|
|
768
|
+
updateLabel() {
|
|
769
|
+
if (this.options.label && this.label && this.themeIcon) {
|
|
770
|
+
reset(this.label, renderIcon(this.themeIcon), this.action.label);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
556
774
|
|
|
557
775
|
export { CodeCoverageDecorations, CoverageDetailsModel };
|