@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.
Files changed (36) hide show
  1. package/package.json +3 -3
  2. package/vscode/src/vs/workbench/contrib/testing/browser/codeCoverageDecorations.js +332 -114
  3. package/vscode/src/vs/workbench/contrib/testing/browser/codeCoverageDisplayUtils.js +85 -0
  4. package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/index.js +6 -5
  5. package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/listProjection.js +9 -8
  6. package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/treeProjection.js +13 -12
  7. package/vscode/src/vs/workbench/contrib/testing/browser/icons.js +8 -7
  8. package/vscode/src/vs/workbench/contrib/testing/browser/media/testing.css.js +1 -1
  9. package/vscode/src/vs/workbench/contrib/testing/browser/testCoverageBars.js +30 -65
  10. package/vscode/src/vs/workbench/contrib/testing/browser/testCoverageView.js +113 -35
  11. package/vscode/src/vs/workbench/contrib/testing/browser/testExplorerActions.js +216 -196
  12. package/vscode/src/vs/workbench/contrib/testing/browser/testMessageColorizer.js +18 -8
  13. package/vscode/src/vs/workbench/contrib/testing/browser/testing.contribution.js +26 -31
  14. package/vscode/src/vs/workbench/contrib/testing/browser/testingConfigurationUi.js +1 -1
  15. package/vscode/src/vs/workbench/contrib/testing/browser/testingDecorations.js +63 -54
  16. package/vscode/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.js +13 -10
  17. package/vscode/src/vs/workbench/contrib/testing/browser/testingExplorerView.js +106 -87
  18. package/vscode/src/vs/workbench/contrib/testing/browser/testingOutputPeek.js +200 -102
  19. package/vscode/src/vs/workbench/contrib/testing/browser/testingProgressUiService.js +37 -17
  20. package/vscode/src/vs/workbench/contrib/testing/browser/testingViewPaneContainer.js +2 -1
  21. package/vscode/src/vs/workbench/contrib/testing/browser/theme.js +15 -14
  22. package/vscode/src/vs/workbench/contrib/testing/common/configuration.js +97 -37
  23. package/vscode/src/vs/workbench/contrib/testing/common/mainThreadTestCollection.js +4 -4
  24. package/vscode/src/vs/workbench/contrib/testing/common/testCoverageService.js +19 -8
  25. package/vscode/src/vs/workbench/contrib/testing/common/testExclusions.js +3 -2
  26. package/vscode/src/vs/workbench/contrib/testing/common/testExplorerFilterState.js +15 -7
  27. package/vscode/src/vs/workbench/contrib/testing/common/testProfileService.js +17 -16
  28. package/vscode/src/vs/workbench/contrib/testing/common/testResultService.js +4 -3
  29. package/vscode/src/vs/workbench/contrib/testing/common/testResultStorage.js +3 -2
  30. package/vscode/src/vs/workbench/contrib/testing/common/testService.js +8 -6
  31. package/vscode/src/vs/workbench/contrib/testing/common/testServiceImpl.js +33 -6
  32. package/vscode/src/vs/workbench/contrib/testing/common/testingContentProvider.js +11 -10
  33. package/vscode/src/vs/workbench/contrib/testing/common/testingContextKeys.js +37 -19
  34. package/vscode/src/vs/workbench/contrib/testing/common/testingContinuousRunService.js +3 -2
  35. package/vscode/src/vs/workbench/contrib/testing/common/testingUri.js +41 -24
  36. 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": "5.2.0",
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@5.2.0",
30
- "@codingame/monaco-vscode-terminal-service-override": "5.2.0"
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 { $, append, clearNode } from 'vscode/vscode/vs/base/browser/dom';
3
- import { HoverWidget } from 'vscode/vscode/vs/base/browser/ui/hover/hoverWidget';
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 { MarkdownRenderer } from 'vscode/vscode/vs/editor/browser/widget/markdownRenderer/browser/markdownRenderer';
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 { testingCoverageMissingBranch } from './icons.js';
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, LineHoverWidget_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 Coverage'));
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.lineHoverWidget = ( (new Lazy(
52
- () => this._register(instantiationService.createInstance(LineHoverWidget, this.editor))
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
- const file = report.getUri(model.uri);
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(67 ) !== false) {
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 === 3 && model) {
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 (this.lineHoverWidget.hasValue && this.lineHoverWidget.value.getDomNode().contains(e.target.element)) ;
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(67 );
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 === 2 ) {
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 === 1 ) {
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, ILogService)))
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 === 1 && detail.branches) {
356
+ if (detail.type === DetailType.Statement && detail.branches) {
327
357
  for (let i = 0; i < detail.branches.length; i++) {
328
- const branch = { type: 2 , branch: i, detail };
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 === 0 ) {
408
+ if (detail.type === DetailType.Declaration) {
379
409
  return namedDetailLabel(detail.name, detail);
380
410
  }
381
- else if (detail.type === 1 ) {
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 === 2 ) {
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 LineHoverWidget = class LineHoverWidget extends Disposable {
465
- static { LineHoverWidget_1 = this; }
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.hover = this._register(( (new HoverWidget())));
471
- this.renderDisposables = this._register(( (new DisposableStore())));
472
- this.computer = instantiationService.createInstance(LineHoverComputer);
473
- this.markdownRenderer = this._register(instantiationService.createInstance(MarkdownRenderer, { editor: this.editor }));
474
- this.hoverOperation = this._register(( (new HoverOperation(this.editor, this.computer))));
475
- this.hover.containerDomNode.classList.add('hidden');
476
- this.hoverOperation.onResult(result => {
477
- if (result.value.length) {
478
- this.render(result.value);
479
- }
480
- else {
481
- this.hide();
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.editor.addOverlayWidget(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 LineHoverWidget_1.ID;
519
+ return 'coverage-summary-widget';
488
520
  }
489
521
  getDomNode() {
490
- return this.hover.containerDomNode;
522
+ return this._domNode.root;
491
523
  }
492
524
  getPosition() {
493
- return null;
525
+ return {
526
+ preference: OverlayWidgetPositionPreference.TOP_CENTER,
527
+ stackOridinal: 9,
528
+ };
494
529
  }
495
- dispose() {
496
- this.editor.removeOverlayWidget(this);
497
- super.dispose();
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
- startShowingAt(lineNumber) {
500
- this.hide();
501
- const textModel = this.editor.getModel();
502
- if (!textModel) {
541
+ setActions() {
542
+ this.actionBar.clear();
543
+ const coverage = this.current;
544
+ if (!coverage) {
503
545
  return;
504
546
  }
505
- this.computer.line = lineNumber;
506
- this.hoverOperation.start(0 );
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
- hide() {
509
- this.hoverOperation.cancel();
510
- this.hover.containerDomNode.classList.add('hidden');
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
- render(elements) {
513
- const { hover: h, editor: editor } = this;
514
- const fragment = document.createDocumentFragment();
515
- for (const msg of elements) {
516
- const markdownHoverElement = $('div.hover-row.markdown-hover');
517
- const hoverContentsElement = append(markdownHoverElement, $('div.hover-contents'));
518
- const renderedContents = this.renderDisposables.add(this.markdownRenderer.render(msg));
519
- hoverContentsElement.appendChild(renderedContents.element);
520
- fragment.appendChild(markdownHoverElement);
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
- clearNode(h.contentsDomNode);
523
- h.contentsDomNode.appendChild(fragment);
524
- h.containerDomNode.classList.remove('hidden');
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
- LineHoverWidget = LineHoverWidget_1 = ( (__decorate([
537
- ( (__param(1, IInstantiationService)))
538
- ], LineHoverWidget)));
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, 8, "Toggle Inline Coverage")),
633
+ title: ( localize2WithPath(_moduleId, 12, "Show Inline Coverage")),
544
634
  category: Categories.Test,
545
635
  keybinding: {
546
- weight: 200 ,
547
- primary: KeyChord(2048 | 85 , 2048 | 1024 | 39 ),
636
+ weight: KeybindingWeight.WorkbenchContrib,
637
+ primary: KeyChord(KeyMod.CtrlCmd | KeyCode.Semicolon, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyI),
548
638
  },
549
- precondition: TestingContextKeys.isTestCoverageOpen,
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 };