@theia/plugin-ext 1.44.0 → 1.45.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 (115) hide show
  1. package/lib/common/plugin-api-rpc.d.ts +2 -1
  2. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  3. package/lib/common/plugin-api-rpc.js.map +1 -1
  4. package/lib/common/proxy-handler.d.ts.map +1 -1
  5. package/lib/common/proxy-handler.js +3 -1
  6. package/lib/common/proxy-handler.js.map +1 -1
  7. package/lib/common/test-types.d.ts +9 -0
  8. package/lib/common/test-types.d.ts.map +1 -1
  9. package/lib/common/test-types.js +36 -1
  10. package/lib/common/test-types.js.map +1 -1
  11. package/lib/hosted/browser/hosted-plugin.d.ts +2 -0
  12. package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
  13. package/lib/hosted/browser/hosted-plugin.js +54 -6
  14. package/lib/hosted/browser/hosted-plugin.js.map +1 -1
  15. package/lib/hosted/node/plugin-activation-events.d.ts.map +1 -1
  16. package/lib/hosted/node/plugin-activation-events.js +1 -1
  17. package/lib/hosted/node/plugin-activation-events.js.map +1 -1
  18. package/lib/main/browser/debug/plugin-debug-service.d.ts.map +1 -1
  19. package/lib/main/browser/debug/plugin-debug-service.js +7 -0
  20. package/lib/main/browser/debug/plugin-debug-service.js.map +1 -1
  21. package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts +1 -0
  22. package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts.map +1 -1
  23. package/lib/main/browser/menus/plugin-menu-command-adapter.js +30 -0
  24. package/lib/main/browser/menus/plugin-menu-command-adapter.js.map +1 -1
  25. package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts +2 -2
  26. package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts.map +1 -1
  27. package/lib/main/browser/menus/vscode-theia-menu-mappings.js +6 -1
  28. package/lib/main/browser/menus/vscode-theia-menu-mappings.js.map +1 -1
  29. package/lib/main/browser/notebooks/notebook-documents-and-editors-main.d.ts +4 -2
  30. package/lib/main/browser/notebooks/notebook-documents-and-editors-main.d.ts.map +1 -1
  31. package/lib/main/browser/notebooks/notebook-documents-and-editors-main.js +34 -21
  32. package/lib/main/browser/notebooks/notebook-documents-and-editors-main.js.map +1 -1
  33. package/lib/main/browser/notebooks/notebook-documents-main.d.ts.map +1 -1
  34. package/lib/main/browser/notebooks/notebook-documents-main.js +8 -9
  35. package/lib/main/browser/notebooks/notebook-documents-main.js.map +1 -1
  36. package/lib/main/browser/notebooks/notebook-dto.d.ts +3 -0
  37. package/lib/main/browser/notebooks/notebook-dto.d.ts.map +1 -1
  38. package/lib/main/browser/notebooks/notebook-dto.js +27 -34
  39. package/lib/main/browser/notebooks/notebook-dto.js.map +1 -1
  40. package/lib/main/browser/notebooks/notebook-kernels-main.js +3 -3
  41. package/lib/main/browser/notebooks/notebook-kernels-main.js.map +1 -1
  42. package/lib/main/browser/notebooks/notebooks-main.d.ts +12 -1
  43. package/lib/main/browser/notebooks/notebooks-main.d.ts.map +1 -1
  44. package/lib/main/browser/notebooks/notebooks-main.js.map +1 -1
  45. package/lib/main/browser/notebooks/renderers/cell-output-webview.d.ts +1 -2
  46. package/lib/main/browser/notebooks/renderers/cell-output-webview.d.ts.map +1 -1
  47. package/lib/main/browser/notebooks/renderers/cell-output-webview.js +1 -1
  48. package/lib/main/browser/notebooks/renderers/cell-output-webview.js.map +1 -1
  49. package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
  50. package/lib/main/browser/plugin-shared-style.js +3 -2
  51. package/lib/main/browser/plugin-shared-style.js.map +1 -1
  52. package/lib/main/browser/webview/webview.d.ts +13 -1
  53. package/lib/main/browser/webview/webview.d.ts.map +1 -1
  54. package/lib/main/browser/webview/webview.js +28 -1
  55. package/lib/main/browser/webview/webview.js.map +1 -1
  56. package/lib/main/node/plugin-deployer-contribution.d.ts.map +1 -1
  57. package/lib/main/node/plugin-deployer-contribution.js +2 -1
  58. package/lib/main/node/plugin-deployer-contribution.js.map +1 -1
  59. package/lib/main/node/plugin-deployer-impl.d.ts.map +1 -1
  60. package/lib/main/node/plugin-deployer-impl.js +2 -1
  61. package/lib/main/node/plugin-deployer-impl.js.map +1 -1
  62. package/lib/plugin/command-registry.d.ts.map +1 -1
  63. package/lib/plugin/command-registry.js +9 -3
  64. package/lib/plugin/command-registry.js.map +1 -1
  65. package/lib/plugin/notebook/notebook-document.js +3 -3
  66. package/lib/plugin/notebook/notebook-document.js.map +1 -1
  67. package/lib/plugin/notebook/notebooks.d.ts.map +1 -1
  68. package/lib/plugin/notebook/notebooks.js +7 -4
  69. package/lib/plugin/notebook/notebooks.js.map +1 -1
  70. package/lib/plugin/plugin-manager.d.ts +1 -1
  71. package/lib/plugin/plugin-manager.d.ts.map +1 -1
  72. package/lib/plugin/plugin-manager.js +3 -23
  73. package/lib/plugin/plugin-manager.js.map +1 -1
  74. package/lib/plugin/tests.d.ts +6 -1
  75. package/lib/plugin/tests.d.ts.map +1 -1
  76. package/lib/plugin/tests.js +22 -0
  77. package/lib/plugin/tests.js.map +1 -1
  78. package/lib/plugin/type-converters.d.ts +1 -12
  79. package/lib/plugin/type-converters.d.ts.map +1 -1
  80. package/lib/plugin/type-converters.js +3 -121
  81. package/lib/plugin/type-converters.js.map +1 -1
  82. package/lib/plugin/types-impl.d.ts +1 -0
  83. package/lib/plugin/types-impl.d.ts.map +1 -1
  84. package/lib/plugin/types-impl.js.map +1 -1
  85. package/lib/plugin/window-state.d.ts.map +1 -1
  86. package/lib/plugin/window-state.js +3 -4
  87. package/lib/plugin/window-state.js.map +1 -1
  88. package/package.json +29 -29
  89. package/src/common/plugin-api-rpc.ts +2 -1
  90. package/src/common/proxy-handler.ts +3 -1
  91. package/src/common/test-types.ts +20 -0
  92. package/src/hosted/browser/hosted-plugin.ts +51 -6
  93. package/src/hosted/node/plugin-activation-events.ts +10 -9
  94. package/src/main/browser/debug/plugin-debug-service.ts +7 -0
  95. package/src/main/browser/menus/plugin-menu-command-adapter.ts +30 -0
  96. package/src/main/browser/menus/vscode-theia-menu-mappings.ts +7 -2
  97. package/src/main/browser/notebooks/notebook-documents-and-editors-main.ts +36 -22
  98. package/src/main/browser/notebooks/notebook-documents-main.ts +11 -12
  99. package/src/main/browser/notebooks/notebook-dto.ts +24 -34
  100. package/src/main/browser/notebooks/notebook-kernels-main.ts +1 -1
  101. package/src/main/browser/notebooks/notebooks-main.ts +13 -2
  102. package/src/main/browser/notebooks/renderers/cell-output-webview.tsx +3 -3
  103. package/src/main/browser/plugin-shared-style.ts +3 -2
  104. package/src/main/browser/webview/pre/main.js +27 -2
  105. package/src/main/browser/webview/webview.ts +32 -1
  106. package/src/main/node/plugin-deployer-contribution.ts +2 -1
  107. package/src/main/node/plugin-deployer-impl.ts +2 -1
  108. package/src/plugin/command-registry.ts +8 -3
  109. package/src/plugin/notebook/notebook-document.ts +8 -8
  110. package/src/plugin/notebook/notebooks.ts +6 -4
  111. package/src/plugin/plugin-manager.ts +4 -24
  112. package/src/plugin/tests.ts +25 -1
  113. package/src/plugin/type-converters.ts +3 -123
  114. package/src/plugin/types-impl.ts +1 -0
  115. package/src/plugin/window-state.ts +4 -4
@@ -20,7 +20,7 @@ import { interfaces } from '@theia/core/shared/inversify';
20
20
  import { NotebookModelResolverService } from '@theia/notebook/lib/browser';
21
21
  import { NotebookModel } from '@theia/notebook/lib/browser/view-model/notebook-model';
22
22
  import { NotebookCellsChangeType } from '@theia/notebook/lib/common';
23
- import { MAIN_RPC_CONTEXT, NotebookCellDto, NotebookCellsChangedEventDto, NotebookDataDto, NotebookDocumentsExt, NotebookDocumentsMain } from '../../../common';
23
+ import { MAIN_RPC_CONTEXT, NotebookCellsChangedEventDto, NotebookDataDto, NotebookDocumentsExt, NotebookDocumentsMain } from '../../../common';
24
24
  import { RPCProtocol } from '../../../common/rpc-protocol';
25
25
  import { NotebookDto } from './notebook-dto';
26
26
 
@@ -54,23 +54,22 @@ export class NotebookDocumentsMainImpl implements NotebookDocumentsMain {
54
54
 
55
55
  handleNotebooksAdded(notebooks: readonly NotebookModel[]): void {
56
56
 
57
- for (const textModel of notebooks) {
58
- const disposableStore = new DisposableCollection();
59
- disposableStore.push(textModel.onDidChangeContent(event => {
57
+ for (const notebook of notebooks) {
58
+ const listener = notebook.onDidChangeContent(events => {
60
59
 
61
60
  const eventDto: NotebookCellsChangedEventDto = {
62
61
  versionId: 1, // TODO implement version ID support
63
62
  rawEvents: []
64
63
  };
65
64
 
66
- for (const e of event.rawEvents) {
65
+ for (const e of events) {
67
66
 
68
67
  switch (e.kind) {
69
68
  case NotebookCellsChangeType.ModelChange:
70
69
  eventDto.rawEvents.push({
71
70
  kind: e.kind,
72
71
  changes: e.changes.map(diff =>
73
- [diff[0], diff[1], diff[2].map(NotebookDto.toNotebookCellDto)] as [number, number, NotebookCellDto[]])
72
+ ({ ...diff, newItems: diff.newItems.map(NotebookDto.toNotebookCellDto) }))
74
73
  });
75
74
  break;
76
75
  case NotebookCellsChangeType.Move:
@@ -106,20 +105,20 @@ export class NotebookDocumentsMainImpl implements NotebookDocumentsMain {
106
105
  }
107
106
  }
108
107
 
109
- const hasDocumentMetadataChangeEvent = event.rawEvents.find(e => e.kind === NotebookCellsChangeType.ChangeDocumentMetadata);
108
+ const hasDocumentMetadataChangeEvent = events.find(e => e.kind === NotebookCellsChangeType.ChangeDocumentMetadata);
110
109
 
111
110
  // using the model resolver service to know if the model is dirty or not.
112
111
  // assuming this is the first listener it can mean that at first the model
113
112
  // is marked as dirty and that another event is fired
114
113
  this.proxy.$acceptModelChanged(
115
- textModel.uri.toComponents(),
114
+ notebook.uri.toComponents(),
116
115
  eventDto,
117
- textModel.isDirty(),
118
- hasDocumentMetadataChangeEvent ? textModel.metadata : undefined
116
+ notebook.isDirty(),
117
+ hasDocumentMetadataChangeEvent ? notebook.metadata : undefined
119
118
  );
120
- }));
119
+ });
121
120
 
122
- this.documentEventListenersMapping.set(textModel.uri.toString(), disposableStore);
121
+ this.documentEventListenersMapping.set(notebook.uri.toString(), new DisposableCollection(listener));
123
122
  }
124
123
  }
125
124
 
@@ -18,6 +18,8 @@ import { OS } from '@theia/core';
18
18
  import * as notebookCommon from '@theia/notebook/lib/common';
19
19
  import { NotebookCellModel } from '@theia/notebook/lib/browser/view-model/notebook-cell-model';
20
20
  import * as rpc from '../../../common';
21
+ import { CellExecutionUpdateType } from '@theia/notebook/lib/common';
22
+ import { CellExecuteUpdate, CellExecutionComplete } from '@theia/notebook/lib/browser';
21
23
 
22
24
  export namespace NotebookDto {
23
25
 
@@ -102,40 +104,28 @@ export namespace NotebookDto {
102
104
  };
103
105
  }
104
106
 
105
- // export function fromCellExecuteUpdateDto(data: extHostProtocol.ICellExecuteUpdateDto): ICellExecuteUpdate {
106
- // if (data.editType === CellExecutionUpdateType.Output) {
107
- // return {
108
- // editType: data.editType,
109
- // cellHandle: data.cellHandle,
110
- // append: data.append,
111
- // outputs: data.outputs.map(fromNotebookOutputDto)
112
- // };
113
- // } else if (data.editType === CellExecutionUpdateType.OutputItems) {
114
- // return {
115
- // editType: data.editType,
116
- // append: data.append,
117
- // outputId: data.outputId,
118
- // items: data.items.map(fromNotebookOutputItemDto)
119
- // };
120
- // } else {
121
- // return data;
122
- // }
123
- // }
107
+ export function fromCellExecuteUpdateDto(data: rpc.CellExecuteUpdateDto): CellExecuteUpdate {
108
+ if (data.editType === CellExecutionUpdateType.Output) {
109
+ return {
110
+ editType: data.editType,
111
+ cellHandle: data.cellHandle,
112
+ append: data.append,
113
+ outputs: data.outputs.map(fromNotebookOutputDto)
114
+ };
115
+ } else if (data.editType === CellExecutionUpdateType.OutputItems) {
116
+ return {
117
+ editType: data.editType,
118
+ outputId: data.outputId,
119
+ append: data.append,
120
+ items: data.items.map(fromNotebookOutputItemDto)
121
+ };
122
+ } else {
123
+ return data;
124
+ }
125
+ }
124
126
 
125
- // export function fromCellExecuteCompleteDto(data: extHostProtocol.ICellExecutionCompleteDto): ICellExecutionComplete {
126
- // return data;
127
- // }
127
+ export function fromCellExecuteCompleteDto(data: rpc.CellExecutionCompleteDto): CellExecutionComplete {
128
+ return data;
129
+ }
128
130
 
129
- // export function fromCellEditOperationDto(edit: extHostProtocol.ICellEditOperationDto): notebookCommon.ICellEditOperation {
130
- // if (edit.editType === notebookCommon.CellEditType.Replace) {
131
- // return {
132
- // editType: edit.editType,
133
- // index: edit.index,
134
- // count: edit.count,
135
- // cells: edit.cells.map(fromNotebookCellDataDto)
136
- // };
137
- // } else {
138
- // return edit;
139
- // }
140
- // }
141
131
  }
@@ -27,7 +27,7 @@ import { CellExecution, NotebookExecutionStateService, NotebookKernelChangeEvent
27
27
  import { combinedDisposable } from '@theia/monaco-editor-core/esm/vs/base/common/lifecycle';
28
28
  import { interfaces } from '@theia/core/shared/inversify';
29
29
  import { NotebookKernelSourceAction } from '@theia/notebook/lib/common';
30
- import { NotebookDto } from '../../../plugin/type-converters';
30
+ import { NotebookDto } from './notebook-dto';
31
31
 
32
32
  abstract class NotebookKernel {
33
33
  private readonly onDidChangeEmitter = new Emitter<NotebookKernelChangeEvent>();
@@ -14,9 +14,9 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { CancellationToken, DisposableCollection, Emitter } from '@theia/core';
17
+ import { CancellationToken, DisposableCollection, Emitter, Event } from '@theia/core';
18
18
  import { BinaryBuffer } from '@theia/core/lib/common/buffer';
19
- import { NotebookCellStatusBarItemList, NotebookCellStatusBarItemProvider, NotebookData, TransientOptions } from '@theia/notebook/lib/common';
19
+ import { NotebookCellStatusBarItem, NotebookData, TransientOptions } from '@theia/notebook/lib/common';
20
20
  import { NotebookService } from '@theia/notebook/lib/browser';
21
21
  import { Disposable } from '@theia/plugin';
22
22
  import { MAIN_RPC_CONTEXT, NotebooksExt, NotebooksMain } from '../../../common';
@@ -25,6 +25,17 @@ import { NotebookDto } from './notebook-dto';
25
25
  import { UriComponents } from '@theia/core/lib/common/uri';
26
26
  import { HostedPluginSupport } from '../../../hosted/browser/hosted-plugin';
27
27
 
28
+ export interface NotebookCellStatusBarItemList {
29
+ items: NotebookCellStatusBarItem[];
30
+ dispose?(): void;
31
+ }
32
+
33
+ export interface NotebookCellStatusBarItemProvider {
34
+ viewType: string;
35
+ onDidChangeStatusBarItems?: Event<void>;
36
+ provideCellStatusBarItems(uri: UriComponents, index: number, token: CancellationToken): Promise<NotebookCellStatusBarItemList | undefined>;
37
+ }
38
+
28
39
  export class NotebooksMainImpl implements NotebooksMain {
29
40
 
30
41
  private readonly disposables = new DisposableCollection();
@@ -20,7 +20,7 @@
20
20
 
21
21
  import * as React from '@theia/core/shared/react';
22
22
  import { inject, injectable, interfaces, postConstruct } from '@theia/core/shared/inversify';
23
- import { NotebookRendererMessagingService, CellOutputWebview, NotebookRendererRegistry, NotebookEditorWidgetService } from '@theia/notebook/lib/browser';
23
+ import { NotebookRendererMessagingService, CellOutputWebview, NotebookRendererRegistry, NotebookEditorWidgetService, NotebookCellOutputsSplice } from '@theia/notebook/lib/browser';
24
24
  import { v4 } from 'uuid';
25
25
  import { NotebookCellModel } from '@theia/notebook/lib/browser/view-model/notebook-cell-model';
26
26
  import { WebviewWidget } from '../../webview/webview';
@@ -28,7 +28,7 @@ import { Message, WidgetManager } from '@theia/core/lib/browser';
28
28
  import { outputWebviewPreload, PreloadContext } from './output-webview-internal';
29
29
  import { WorkspaceTrustService } from '@theia/workspace/lib/browser';
30
30
  import { ChangePreferredMimetypeMessage, FromWebviewMessage, OutputChangedMessage } from './webview-communication';
31
- import { CellUri, NotebookCellOutputsSplice } from '@theia/notebook/lib/common';
31
+ import { CellUri } from '@theia/notebook/lib/common';
32
32
  import { Disposable, DisposableCollection, nls, QuickPickService } from '@theia/core';
33
33
  import { NotebookCellOutputModel } from '@theia/notebook/lib/browser/view-model/notebook-cell-output-model';
34
34
 
@@ -76,7 +76,7 @@ export class CellOutputWebviewImpl implements CellOutputWebview, Disposable {
76
76
  protected async init(): Promise<void> {
77
77
  this.cell.onDidChangeOutputs(outputChange => this.updateOutput(outputChange));
78
78
  this.cell.onDidChangeOutputItems(output => {
79
- this.updateOutput({start: this.cell.outputs.findIndex(o => o.getData().outputId === o.outputId), deleteCount: 1, newOutputs: [output]});
79
+ this.updateOutput({start: this.cell.outputs.findIndex(o => o.outputId === output.outputId), deleteCount: 1, newOutputs: [output]});
80
80
  });
81
81
 
82
82
  this.webviewWidget = await this.widgetManager.getOrCreateWidget(WebviewWidget.FACTORY_ID, { id: this.id });
@@ -125,8 +125,9 @@ export class PluginSharedStyle {
125
125
  toDispose.push(this.insertRule('.' + iconClass + '::before', theme => `
126
126
  content: "";
127
127
  background-position: 2px;
128
- width: ${size}'px';
129
- height: ${size}'px';
128
+ display: block;
129
+ width: ${size}px;
130
+ height: ${size}px;
130
131
  background: center no-repeat url("${theme.type === 'light' ? lightIconUrl : darkIconUrl}");
131
132
  background-size: ${size}px;
132
133
  `));
@@ -339,10 +339,35 @@ delete window.frameElement;
339
339
  clientY: e.clientY,
340
340
  ctrlKey: e.ctrlKey,
341
341
  metaKey: e.metaKey,
342
- shiftKey: e.shiftKey
342
+ shiftKey: e.shiftKey,
343
+ // @ts-ignore the dataset should exist if the target is an element
343
344
  });
344
345
  };
345
346
 
347
+ const handleContextMenu = (e) => {
348
+ if (e.defaultPrevented) {
349
+ return;
350
+ }
351
+
352
+ e.preventDefault();
353
+
354
+ host.postMessage('did-context-menu', {
355
+ clientX: e.clientX,
356
+ clientY: e.clientY,
357
+ context: findVscodeContext(e.target)
358
+ });
359
+ };
360
+
361
+ function findVscodeContext(node) {
362
+ if (node) {
363
+ if (node.dataset?.vscodeContext) {
364
+ return JSON.parse(node.dataset.vscodeContext);
365
+ }
366
+ return findVscodeContext(node.parentElement);
367
+ }
368
+ return {};
369
+ }
370
+
346
371
  function preventDefaultBrowserHotkeys(e) {
347
372
  var isOSX = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
348
373
 
@@ -602,7 +627,7 @@ delete window.frameElement;
602
627
  newFrame.contentWindow.addEventListener('keydown', handleInnerKeydown);
603
628
  newFrame.contentWindow.addEventListener('mousedown', handleInnerMousedown);
604
629
  newFrame.contentWindow.addEventListener('mouseup', handleInnerMouseup);
605
- newFrame.contentWindow.addEventListener('contextmenu', e => e.preventDefault());
630
+ newFrame.contentWindow.addEventListener('contextmenu', handleContextMenu);
606
631
 
607
632
  if (host.onIframeLoaded) {
608
633
  host.onIframeLoaded(newFrame);
@@ -51,10 +51,16 @@ import { BinaryBufferReadableStream } from '@theia/core/lib/common/buffer';
51
51
  import { ViewColumn } from '../../../plugin/types-impl';
52
52
  import { ExtractableWidget } from '@theia/core/lib/browser/widgets/extractable-widget';
53
53
  import { BadgeWidget } from '@theia/core/lib/browser/view-container';
54
+ import { MenuPath } from '@theia/core';
55
+ import { ContextMenuRenderer } from '@theia/core/lib/browser';
56
+ import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
57
+ import { PluginViewWidget } from '../view/plugin-view-widget';
54
58
 
55
59
  // Style from core
56
60
  const TRANSPARENT_OVERLAY_STYLE = 'theia-transparent-overlay';
57
61
 
62
+ export const WEBVIEW_CONTEXT_MENU: MenuPath = ['webview-context-menu'];
63
+
58
64
  /* eslint-disable @typescript-eslint/no-explicit-any */
59
65
 
60
66
  export const enum WebviewMessageChannels {
@@ -70,7 +76,8 @@ export const enum WebviewMessageChannels {
70
76
  didKeydown = 'did-keydown',
71
77
  didMouseDown = 'did-mousedown',
72
78
  didMouseUp = 'did-mouseup',
73
- onconsole = 'onconsole'
79
+ onconsole = 'onconsole',
80
+ didcontextmenu = 'did-context-menu'
74
81
  }
75
82
 
76
83
  export interface WebviewContentOptions {
@@ -152,6 +159,12 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract
152
159
  @inject(WebviewResourceCache)
153
160
  protected readonly resourceCache: WebviewResourceCache;
154
161
 
162
+ @inject(ContextMenuRenderer)
163
+ protected readonly contextMenuRenderer: ContextMenuRenderer;
164
+
165
+ @inject(ContextKeyService)
166
+ protected readonly contextKeyService: ContextKeyService;
167
+
155
168
  viewState: WebviewPanelViewState = {
156
169
  visible: false,
157
170
  active: false,
@@ -357,6 +370,10 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract
357
370
  this.dispatchMouseEvent('mouseup', data);
358
371
  }));
359
372
 
373
+ this.toHide.push(this.on(WebviewMessageChannels.didcontextmenu, (event: { clientX: number, clientY: number, context: any }) => {
374
+ this.handleContextMenu(event);
375
+ }));
376
+
360
377
  this.style();
361
378
  this.toHide.push(this.themeDataProvider.onDidChangeThemeData(() => this.style()));
362
379
 
@@ -380,6 +397,20 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract
380
397
  }));
381
398
  }
382
399
 
400
+ handleContextMenu(event: { clientX: number, clientY: number, context: any }): void {
401
+ const domRect = this.node.getBoundingClientRect();
402
+ this.contextKeyService.with(this.parent instanceof PluginViewWidget ?
403
+ { webviewId: this.parent.options.viewId, ...event.context } : {},
404
+ () => {
405
+ this.contextMenuRenderer.render({
406
+ menuPath: WEBVIEW_CONTEXT_MENU,
407
+ anchor: {
408
+ x: domRect.x + event.clientX, y: domRect.y + event.clientY
409
+ }
410
+ });
411
+ });
412
+ }
413
+
383
414
  protected async getRedirect(url: string): Promise<string | undefined> {
384
415
  const uri = new URI(url);
385
416
  const localhost = this.externalUriService.parseLocalhost(uri);
@@ -29,6 +29,7 @@ export class PluginDeployerContribution implements BackendApplicationContributio
29
29
  protected pluginDeployer: PluginDeployer;
30
30
 
31
31
  initialize(): Promise<void> {
32
- return this.pluginDeployer.start();
32
+ this.pluginDeployer.start().catch(error => this.logger.error('Initializing plugin deployer failed.', error));
33
+ return Promise.resolve();
33
34
  }
34
35
  }
@@ -130,8 +130,9 @@ export class PluginDeployerImpl implements PluginDeployer {
130
130
  id,
131
131
  type: PluginType.System
132
132
  }));
133
+ const resolvePlugins = this.measure('resolvePlugins');
133
134
  const plugins = await this.resolvePlugins([...unresolvedUserEntries, ...unresolvedSystemEntries]);
134
- deployPlugins.log('Resolve plugins list');
135
+ resolvePlugins.log('Resolve plugins list');
135
136
  await this.deployPlugins(plugins);
136
137
  deployPlugins.log('Deploy plugins list');
137
138
  }
@@ -204,11 +204,16 @@ export class CommandsConverter {
204
204
 
205
205
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
206
  private executeSafeCommand<R>(...args: any[]): PromiseLike<R | undefined> {
207
- const command = this.commandsMap.get(args[0]);
207
+ const handle = args[0];
208
+ if (typeof handle !== 'number') {
209
+ return Promise.reject(`Invalid handle ${handle}`);
210
+ }
211
+ const command = this.commandsMap.get(handle);
208
212
  if (!command || !command.command) {
209
- return Promise.reject(`command ${args[0]} not found`);
213
+ return Promise.reject(`Safe command with handle ${handle} not found`);
210
214
  }
211
- return this.commands.executeCommand(command.command, ...(command.arguments || []));
215
+ const allArgs = (command.arguments ?? []).concat(args.slice(1));
216
+ return this.commands.executeCommand(command.command, ...allArgs);
212
217
  }
213
218
 
214
219
  }
@@ -288,17 +288,17 @@ export class NotebookDocument implements Disposable {
288
288
  this.setCellOutputs(rawEvent.index, rawEvent.outputs);
289
289
  relaxedCellChanges.push({ cell: this.cells[rawEvent.index].apiCell, outputs: this.cells[rawEvent.index].apiCell.outputs });
290
290
 
291
- // } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.OutputItem) {
292
- // this._setCellOutputItems(rawEvent.index, rawEvent.outputId, rawEvent.append, rawEvent.outputItems);
293
- // relaxedCellChanges.push({ cell: this.cells[rawEvent.index].apiCell, outputs: this.cells[rawEvent.index].apiCell.outputs });
291
+ // } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.OutputItem) {
292
+ // this._setCellOutputItems(rawEvent.index, rawEvent.outputId, rawEvent.append, rawEvent.outputItems);
293
+ // relaxedCellChanges.push({ cell: this.cells[rawEvent.index].apiCell, outputs: this.cells[rawEvent.index].apiCell.outputs });
294
294
  } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellLanguage) {
295
295
  this.changeCellLanguage(rawEvent.index, rawEvent.language);
296
296
  relaxedCellChanges.push({ cell: this.cells[rawEvent.index].apiCell, document: this.cells[rawEvent.index].apiCell.document });
297
297
  } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellContent) {
298
298
  relaxedCellChanges.push({ cell: this.cells[rawEvent.index].apiCell, document: this.cells[rawEvent.index].apiCell.document });
299
299
 
300
- // } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMime) {
301
- // this._changeCellMime(rawEvent.index, rawEvent.mime);
300
+ // } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMime) {
301
+ // this._changeCellMime(rawEvent.index, rawEvent.mime);
302
302
  } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMetadata) {
303
303
  this.changeCellMetadata(rawEvent.index, rawEvent.metadata);
304
304
  relaxedCellChanges.push({ cell: this.cells[rawEvent.index].apiCell, metadata: this.cells[rawEvent.index].apiCell.metadata });
@@ -351,7 +351,7 @@ export class NotebookDocument implements Disposable {
351
351
  const removedCellDocuments: UriComponents[] = [];
352
352
 
353
353
  splices.reverse().forEach(splice => {
354
- const cellDtos = splice[2];
354
+ const cellDtos = splice.newItems;
355
355
  const newCells = cellDtos.map((cell: NotebookCellDto) => {
356
356
 
357
357
  const extCell = new Cell(this, this.editorsAndDocuments, cell);
@@ -361,8 +361,8 @@ export class NotebookDocument implements Disposable {
361
361
  return extCell;
362
362
  });
363
363
 
364
- const changeEvent = new RawContentChangeEvent(splice[0], splice[1], [], newCells);
365
- const deletedItems = this.cells.splice(splice[0], splice[1], ...newCells);
364
+ const changeEvent = new RawContentChangeEvent(splice.start, splice.deleteCount, [], newCells);
365
+ const deletedItems = this.cells.splice(splice.start, splice.deleteCount, ...newCells);
366
366
  for (const cell of deletedItems) {
367
367
  removedCellDocuments.push(cell.uri.toComponents());
368
368
  changeEvent.deletedItems.push(cell.apiCell);
@@ -36,6 +36,7 @@ import { NotebookDocument } from './notebook-document';
36
36
  import { NotebookEditor } from './notebook-editor';
37
37
  import { EditorsAndDocumentsExtImpl } from '../editors-and-documents';
38
38
  import { DocumentsExtImpl } from '../documents';
39
+ import { NotebookModelResource } from '@theia/notebook/lib/common';
39
40
 
40
41
  export class NotebooksExtImpl implements NotebooksExt {
41
42
 
@@ -82,11 +83,12 @@ export class NotebooksExtImpl implements NotebooksExt {
82
83
  this.notebookEditors = rpc.getProxy(PLUGIN_RPC_CONTEXT.NOTEBOOK_EDITORS_MAIN);
83
84
 
84
85
  commands.registerArgumentProcessor({
85
- processArgument: (arg: { uri: URI }) => {
86
- if (arg && arg.uri && this.documents.has(arg.uri.toString())) {
87
- return this.documents.get(arg.uri.toString())?.apiNotebook;
86
+ processArgument: arg => {
87
+ if (NotebookModelResource.is(arg)) {
88
+ return this.documents.get(arg.notebookModelUri.toString())?.apiNotebook;
89
+ } else {
90
+ return arg;
88
91
  }
89
- return arg;
90
92
  }
91
93
  });
92
94
  }
@@ -79,29 +79,6 @@ class ActivatedPlugin {
79
79
 
80
80
  export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {
81
81
 
82
- static SUPPORTED_ACTIVATION_EVENTS = new Set([
83
- '*',
84
- 'onLanguage',
85
- 'onCommand',
86
- 'onDebug',
87
- 'onDebugInitialConfigurations',
88
- 'onDebugResolve',
89
- 'onDebugAdapterProtocolTracker',
90
- 'onDebugDynamicConfigurations',
91
- 'onTaskType',
92
- 'workspaceContains',
93
- 'onView',
94
- 'onUri',
95
- 'onTerminalProfile',
96
- 'onWebviewPanel',
97
- 'onFileSystem',
98
- 'onCustomEditor',
99
- 'onStartupFinished',
100
- 'onAuthenticationRequest',
101
- 'onNotebook',
102
- 'onNotebookSerializer'
103
- ]);
104
-
105
82
  private configStorage: ConfigStorage | undefined;
106
83
  private readonly registry = new Map<string, Plugin>();
107
84
  private readonly activations = new Map<string, (() => Promise<void>)[] | undefined>();
@@ -113,6 +90,7 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {
113
90
  private onDidChangeEmitter = new Emitter<void>();
114
91
  private messageRegistryProxy: MessageRegistryMain;
115
92
  private notificationMain: NotificationMain;
93
+ private supportedActivationEvents: Set<string>;
116
94
  protected fireOnDidChange(): void {
117
95
  this.onDidChangeEmitter.fire(undefined);
118
96
  }
@@ -219,6 +197,8 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {
219
197
 
220
198
  this.webview.init(params.webview);
221
199
  this.jsonValidation = params.jsonValidation;
200
+
201
+ this.supportedActivationEvents = new Set(params.supportedActivationEvents ?? []);
222
202
  }
223
203
 
224
204
  async $start(params: PluginManagerStartParams): Promise<void> {
@@ -263,7 +243,7 @@ export class PluginManagerExtImpl implements PluginManagerExt, PluginManager {
263
243
  const activation = () => this.$activatePlugin(plugin.model.id);
264
244
  // an internal activation event is a subject to change
265
245
  this.setActivation(`onPlugin:${plugin.model.id}`, activation);
266
- const unsupportedActivationEvents = plugin.rawModel.activationEvents.filter(e => !PluginManagerExtImpl.SUPPORTED_ACTIVATION_EVENTS.has(e.split(':')[0]));
246
+ const unsupportedActivationEvents = plugin.rawModel.activationEvents.filter(e => !this.supportedActivationEvents.has(e.split(':')[0]));
267
247
  if (unsupportedActivationEvents.length) {
268
248
  console.warn(`Unsupported activation events: ${unsupportedActivationEvents.join(', ')}, please open an issue: https://github.com/eclipse-theia/theia/issues/new`);
269
249
  }
@@ -40,10 +40,11 @@ import { TestItemImpl, TestItemCollection } from './test-item';
40
40
  import { AccumulatingTreeDeltaEmitter, TreeDelta } from '@theia/test/lib/common/tree-delta';
41
41
  import {
42
42
  TestItemDTO, TestOutputDTO, TestExecutionState, TestRunProfileDTO,
43
- TestRunProfileKind, TestRunRequestDTO, TestStateChangeDTO, TestItemReference
43
+ TestRunProfileKind, TestRunRequestDTO, TestStateChangeDTO, TestItemReference, TestMessageArg, TestMessageDTO
44
44
  } from '../common/test-types';
45
45
  import { ChangeBatcher, observableProperty } from '@theia/test/lib/common/collections';
46
46
  import { TestRunRequest } from './types-impl';
47
+ import { MarkdownString } from '../common/plugin-api-rpc-model';
47
48
 
48
49
  type RefreshHandler = (token: theia.CancellationToken) => void | theia.Thenable<void>;
49
50
  type ResolveHandler = (item: theia.TestItem | undefined) => theia.Thenable<void> | void;
@@ -335,6 +336,8 @@ export class TestingExtImpl implements TestingExt {
335
336
  return this.toTestItem(arg);
336
337
  } else if (Array.isArray(arg)) {
337
338
  return arg.map(param => TestItemReference.is(param) ? this.toTestItem(param) : param);
339
+ } else if (TestMessageArg.is(arg)) {
340
+ return this.fromTestMessageArg(arg);
338
341
  } else {
339
342
  return arg;
340
343
  }
@@ -343,6 +346,27 @@ export class TestingExtImpl implements TestingExt {
343
346
 
344
347
  }
345
348
 
349
+ fromTestMessageArg(arg: TestMessageArg): { test?: theia.TestItem, message: theia.TestMessage } {
350
+ const testItem = arg.testItemReference ? this.toTestItem(arg.testItemReference) : undefined;
351
+ const message = this.toTestMessage(arg.testMessage);
352
+ return {
353
+ test: testItem,
354
+ message: message
355
+ };
356
+ }
357
+
358
+ toTestMessage(testMessage: TestMessageDTO): theia.TestMessage {
359
+ const message = MarkdownString.is(testMessage.message) ? Convert.toMarkdown(testMessage.message) : testMessage.message;
360
+
361
+ return {
362
+ message: message,
363
+ actualOutput: testMessage.actual,
364
+ expectedOutput: testMessage.expected,
365
+ contextValue: testMessage.contextValue,
366
+ location: testMessage.location ? Convert.toLocation(testMessage.location) : undefined
367
+ };
368
+ }
369
+
346
370
  toTestItem(ref: TestItemReference): theia.TestItem {
347
371
  const result = this.withController(ref.controllerId).items.find(ref.testPath);
348
372
  if (!result) {