@theia/plugin-ext 1.23.0-next.31 → 1.23.0-next.36

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 (74) hide show
  1. package/lib/common/plugin-api-rpc-model.d.ts +1 -0
  2. package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
  3. package/lib/common/plugin-api-rpc-model.js.map +1 -1
  4. package/lib/common/plugin-api-rpc.d.ts +2 -0
  5. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  6. package/lib/common/plugin-api-rpc.js.map +1 -1
  7. package/lib/hosted/node-electron/scanner-theia-electron.d.ts.map +1 -1
  8. package/lib/hosted/node-electron/scanner-theia-electron.js.map +1 -1
  9. package/lib/main/browser/comments/comment-thread-widget.d.ts.map +1 -1
  10. package/lib/main/browser/comments/comment-thread-widget.js.map +1 -1
  11. package/lib/main/browser/custom-editors/custom-editor-widget.d.ts.map +1 -1
  12. package/lib/main/browser/custom-editors/custom-editor-widget.js.map +1 -1
  13. package/lib/main/browser/debug/plugin-debug-session-factory.d.ts.map +1 -1
  14. package/lib/main/browser/debug/plugin-debug-session-factory.js.map +1 -1
  15. package/lib/main/browser/dialogs/modal-notification.d.ts.map +1 -1
  16. package/lib/main/browser/dialogs/modal-notification.js.map +1 -1
  17. package/lib/main/browser/languages-main.d.ts +1 -0
  18. package/lib/main/browser/languages-main.d.ts.map +1 -1
  19. package/lib/main/browser/languages-main.js +11 -3
  20. package/lib/main/browser/languages-main.js.map +1 -1
  21. package/lib/main/browser/plugin-authentication-service.d.ts.map +1 -1
  22. package/lib/main/browser/plugin-authentication-service.js.map +1 -1
  23. package/lib/main/browser/plugin-ext-widget.d.ts.map +1 -1
  24. package/lib/main/browser/plugin-ext-widget.js.map +1 -1
  25. package/lib/main/browser/view/plugin-view-widget.d.ts.map +1 -1
  26. package/lib/main/browser/view/plugin-view-widget.js.map +1 -1
  27. package/lib/main/browser/view/tree-view-widget.d.ts +0 -2
  28. package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
  29. package/lib/main/browser/view/tree-view-widget.js +0 -2
  30. package/lib/main/browser/view/tree-view-widget.js.map +1 -1
  31. package/lib/main/browser/webview/webview.d.ts.map +1 -1
  32. package/lib/main/browser/webview/webview.js.map +1 -1
  33. package/lib/main/electron-browser/webview/electron-webview-widget-factory.d.ts.map +1 -1
  34. package/lib/main/electron-browser/webview/electron-webview-widget-factory.js.map +1 -1
  35. package/lib/plugin/languages/code-action.d.ts +7 -1
  36. package/lib/plugin/languages/code-action.d.ts.map +1 -1
  37. package/lib/plugin/languages/code-action.js +36 -2
  38. package/lib/plugin/languages/code-action.js.map +1 -1
  39. package/lib/plugin/languages.d.ts +2 -0
  40. package/lib/plugin/languages.d.ts.map +1 -1
  41. package/lib/plugin/languages.js +7 -0
  42. package/lib/plugin/languages.js.map +1 -1
  43. package/lib/plugin/node/debug/plugin-debug-adapter-session.d.ts.map +1 -1
  44. package/lib/plugin/node/debug/plugin-debug-adapter-session.js.map +1 -1
  45. package/lib/plugin/node/env-node-ext.d.ts.map +1 -1
  46. package/lib/plugin/node/env-node-ext.js.map +1 -1
  47. package/lib/plugin/plugin-context.d.ts.map +1 -1
  48. package/lib/plugin/plugin-context.js.map +1 -1
  49. package/lib/plugin/quick-open.d.ts.map +1 -1
  50. package/lib/plugin/quick-open.js.map +1 -1
  51. package/lib/plugin/types-impl.d.ts.map +1 -1
  52. package/lib/plugin/types-impl.js.map +1 -1
  53. package/package.json +23 -23
  54. package/src/common/plugin-api-rpc-model.ts +1 -0
  55. package/src/common/plugin-api-rpc.ts +3 -1
  56. package/src/hosted/node-electron/scanner-theia-electron.ts +1 -1
  57. package/src/main/browser/comments/comment-thread-widget.tsx +12 -12
  58. package/src/main/browser/custom-editors/custom-editor-widget.ts +5 -5
  59. package/src/main/browser/debug/plugin-debug-session-factory.ts +22 -22
  60. package/src/main/browser/dialogs/modal-notification.ts +1 -1
  61. package/src/main/browser/languages-main.ts +13 -3
  62. package/src/main/browser/plugin-authentication-service.ts +2 -2
  63. package/src/main/browser/plugin-ext-widget.tsx +1 -1
  64. package/src/main/browser/view/plugin-view-widget.ts +4 -4
  65. package/src/main/browser/view/tree-view-widget.tsx +14 -17
  66. package/src/main/browser/webview/webview.ts +5 -5
  67. package/src/main/electron-browser/webview/electron-webview-widget-factory.ts +2 -2
  68. package/src/plugin/languages/code-action.ts +46 -3
  69. package/src/plugin/languages.ts +9 -0
  70. package/src/plugin/node/debug/plugin-debug-adapter-session.ts +7 -7
  71. package/src/plugin/node/env-node-ext.ts +1 -1
  72. package/src/plugin/plugin-context.ts +4 -4
  73. package/src/plugin/quick-open.ts +13 -11
  74. package/src/plugin/types-impl.ts +8 -8
@@ -114,7 +114,7 @@ export class CommentThreadWidget extends BaseWidget {
114
114
  this.commentService.disposeCommentThread(this.owner, this._commentThread.threadId);
115
115
  }
116
116
 
117
- dispose(): void {
117
+ override dispose(): void {
118
118
  super.dispose();
119
119
  if (this.commentGlyphWidget) {
120
120
  this.commentGlyphWidget.dispose();
@@ -134,7 +134,7 @@ export class CommentThreadWidget extends BaseWidget {
134
134
  }
135
135
  }
136
136
 
137
- hide(): void {
137
+ override hide(): void {
138
138
  this.zoneWidget.hide();
139
139
  this.isExpanded = false;
140
140
  super.hide();
@@ -231,7 +231,7 @@ export class CommentThreadWidget extends BaseWidget {
231
231
  return label;
232
232
  }
233
233
 
234
- update(): void {
234
+ override update(): void {
235
235
  if (!this.isExpanded) {
236
236
  return;
237
237
  }
@@ -342,7 +342,7 @@ export class CommentForm<P extends CommentForm.Props = CommentForm.Props> extend
342
342
  }, 100);
343
343
  };
344
344
 
345
- componentDidMount(): void {
345
+ override componentDidMount(): void {
346
346
  // Wait for the widget to be rendered.
347
347
  setTimeout(() => {
348
348
  this.inputRef.current?.focus();
@@ -377,7 +377,7 @@ export class CommentForm<P extends CommentForm.Props = CommentForm.Props> extend
377
377
  });
378
378
  }
379
379
 
380
- render(): React.ReactNode {
380
+ override render(): React.ReactNode {
381
381
  const { commands, commentThread, contextKeyService } = this.props;
382
382
  const hasExistingComments = commentThread.comments && commentThread.comments.length > 0;
383
383
  return <div className={'comment-form' + (this.state.expanded || commentThread.comments && commentThread.comments.length === 0 ? ' expand' : '')}>
@@ -453,7 +453,7 @@ export class ReviewComment<P extends ReviewComment.Props = ReviewComment.Props>
453
453
  protected showHover = () => this.setState({ hover: true });
454
454
  protected hideHover = () => this.setState({ hover: false });
455
455
 
456
- render(): React.ReactNode {
456
+ override render(): React.ReactNode {
457
457
  const { comment, commentForm, contextKeyService, menus, commands, commentThread } = this.props;
458
458
  const commentUniqueId = comment.uniqueIdInThread;
459
459
  const { hover } = this.state;
@@ -499,7 +499,7 @@ namespace CommentBody {
499
499
  }
500
500
 
501
501
  export class CommentBody extends React.Component<CommentBody.Props> {
502
- render(): React.ReactNode {
502
+ override render(): React.ReactNode {
503
503
  const { value, isVisible } = this.props;
504
504
  if (!isVisible) {
505
505
  return false;
@@ -528,7 +528,7 @@ export class CommentEditContainer extends React.Component<CommentEditContainer.P
528
528
  private dirtyCommentMode: CommentMode | undefined;
529
529
  private dirtyCommentFormState: boolean | undefined;
530
530
 
531
- componentDidUpdate(prevProps: Readonly<CommentEditContainer.Props>, prevState: Readonly<{}>): void {
531
+ override componentDidUpdate(prevProps: Readonly<CommentEditContainer.Props>, prevState: Readonly<{}>): void {
532
532
  const commentFormState = this.props.commentForm.current?.state;
533
533
  const mode = this.props.comment.mode;
534
534
  if (this.dirtyCommentMode !== mode || (this.dirtyCommentFormState !== commentFormState?.expanded && !commentFormState?.expanded)) {
@@ -545,7 +545,7 @@ export class CommentEditContainer extends React.Component<CommentEditContainer.P
545
545
  this.dirtyCommentFormState = commentFormState?.expanded;
546
546
  }
547
547
 
548
- render(): React.ReactNode {
548
+ override render(): React.ReactNode {
549
549
  const { menus, comment, commands, commentThread, contextKeyService } = this.props;
550
550
  if (!(comment.mode === CommentMode.Editing)) {
551
551
  return false;
@@ -588,7 +588,7 @@ namespace CommentsInlineAction {
588
588
  }
589
589
 
590
590
  export class CommentsInlineAction extends React.Component<CommentsInlineAction.Props> {
591
- render(): React.ReactNode {
591
+ override render(): React.ReactNode {
592
592
  const { node, commands, contextKeyService, commentThread, commentUniqueId } = this.props;
593
593
  if (node.action.when && !contextKeyService.match(node.action.when)) {
594
594
  return false;
@@ -618,7 +618,7 @@ namespace CommentActions {
618
618
  }
619
619
 
620
620
  export class CommentActions extends React.Component<CommentActions.Props> {
621
- render(): React.ReactNode {
621
+ override render(): React.ReactNode {
622
622
  const { contextKeyService, commands, menu, commentThread, getInput, clearInput } = this.props;
623
623
  return <div className={'form-actions'}>
624
624
  {menu.children.map((node, index) => node instanceof ActionMenuNode &&
@@ -647,7 +647,7 @@ namespace CommentAction {
647
647
  }
648
648
 
649
649
  export class CommentAction extends React.Component<CommentAction.Props> {
650
- render(): React.ReactNode {
650
+ override render(): React.ReactNode {
651
651
  const classNames = ['comments-button', 'comments-text-button', 'theia-button'];
652
652
  const { node, commands, contextKeyService, onClick } = this.props;
653
653
  if (node.action.when && !contextKeyService.match(node.action.when)) {
@@ -25,9 +25,9 @@ import { CustomEditorModel } from './custom-editors-main';
25
25
 
26
26
  @injectable()
27
27
  export class CustomEditorWidget extends WebviewWidget implements SaveableSource, NavigatableWidget {
28
- static FACTORY_ID = 'plugin-custom-editor';
28
+ static override FACTORY_ID = 'plugin-custom-editor';
29
29
 
30
- id: string;
30
+ override id: string;
31
31
  resource: URI;
32
32
 
33
33
  protected _modelRef: Reference<CustomEditorModel>;
@@ -47,7 +47,7 @@ export class CustomEditorWidget extends WebviewWidget implements SaveableSource,
47
47
  protected readonly undoRedoService: UndoRedoService;
48
48
 
49
49
  @postConstruct()
50
- protected init(): void {
50
+ protected override init(): void {
51
51
  super.init();
52
52
  this.id = CustomEditorWidget.FACTORY_ID + ':' + this.identifier.id;
53
53
  this.toDispose.push(this.fileService.onDidRunOperation(e => {
@@ -83,14 +83,14 @@ export class CustomEditorWidget extends WebviewWidget implements SaveableSource,
83
83
  return this.resource.withPath(resourceUri.path);
84
84
  }
85
85
 
86
- storeState(): CustomEditorWidget.State {
86
+ override storeState(): CustomEditorWidget.State {
87
87
  return {
88
88
  ...super.storeState(),
89
89
  strResource: this.resource.toString(),
90
90
  };
91
91
  }
92
92
 
93
- restoreState(oldState: CustomEditorWidget.State): void {
93
+ override restoreState(oldState: CustomEditorWidget.State): void {
94
94
  const { strResource } = oldState;
95
95
  this.resource = new URI(strResource);
96
96
  super.restoreState(oldState);
@@ -34,22 +34,22 @@ import { Channel } from '@theia/debug/lib/common/debug-service';
34
34
 
35
35
  export class PluginDebugSession extends DebugSession {
36
36
  constructor(
37
- readonly id: string,
38
- readonly options: DebugSessionOptions,
39
- readonly parentSession: DebugSession | undefined,
40
- protected readonly connection: DebugSessionConnection,
41
- protected readonly terminalServer: TerminalService,
42
- protected readonly editorManager: EditorManager,
43
- protected readonly breakpoints: BreakpointManager,
44
- protected readonly labelProvider: LabelProvider,
45
- protected readonly messages: MessageClient,
46
- protected readonly fileService: FileService,
37
+ override readonly id: string,
38
+ override readonly options: DebugSessionOptions,
39
+ override readonly parentSession: DebugSession | undefined,
40
+ protected override readonly connection: DebugSessionConnection,
41
+ protected override readonly terminalServer: TerminalService,
42
+ protected override readonly editorManager: EditorManager,
43
+ protected override readonly breakpoints: BreakpointManager,
44
+ protected override readonly labelProvider: LabelProvider,
45
+ protected override readonly messages: MessageClient,
46
+ protected override readonly fileService: FileService,
47
47
  protected readonly terminalOptionsExt: TerminalOptionsExt | undefined,
48
- protected readonly debugContributionProvider: ContributionProvider<DebugContribution>) {
48
+ protected override readonly debugContributionProvider: ContributionProvider<DebugContribution>) {
49
49
  super(id, options, parentSession, connection, terminalServer, editorManager, breakpoints, labelProvider, messages, fileService, debugContributionProvider);
50
50
  }
51
51
 
52
- protected async doCreateTerminal(terminalWidgetOptions: TerminalWidgetOptions): Promise<TerminalWidget> {
52
+ protected override async doCreateTerminal(terminalWidgetOptions: TerminalWidgetOptions): Promise<TerminalWidget> {
53
53
  terminalWidgetOptions = Object.assign({}, terminalWidgetOptions, this.terminalOptionsExt);
54
54
  return super.doCreateTerminal(terminalWidgetOptions);
55
55
  }
@@ -61,22 +61,22 @@ export class PluginDebugSession extends DebugSession {
61
61
  */
62
62
  export class PluginDebugSessionFactory extends DefaultDebugSessionFactory {
63
63
  constructor(
64
- protected readonly terminalService: TerminalService,
65
- protected readonly editorManager: EditorManager,
66
- protected readonly breakpoints: BreakpointManager,
67
- protected readonly labelProvider: LabelProvider,
68
- protected readonly messages: MessageClient,
69
- protected readonly outputChannelManager: OutputChannelManager,
70
- protected readonly debugPreferences: DebugPreferences,
64
+ protected override readonly terminalService: TerminalService,
65
+ protected override readonly editorManager: EditorManager,
66
+ protected override readonly breakpoints: BreakpointManager,
67
+ protected override readonly labelProvider: LabelProvider,
68
+ protected override readonly messages: MessageClient,
69
+ protected override readonly outputChannelManager: OutputChannelManager,
70
+ protected override readonly debugPreferences: DebugPreferences,
71
71
  protected readonly connectionFactory: (sessionId: string) => Promise<Channel>,
72
- protected readonly fileService: FileService,
72
+ protected override readonly fileService: FileService,
73
73
  protected readonly terminalOptionsExt: TerminalOptionsExt | undefined,
74
- protected readonly debugContributionProvider: ContributionProvider<DebugContribution>
74
+ protected override readonly debugContributionProvider: ContributionProvider<DebugContribution>
75
75
  ) {
76
76
  super();
77
77
  }
78
78
 
79
- get(sessionId: string, options: DebugSessionOptions, parentSession?: DebugSession): DebugSession {
79
+ override get(sessionId: string, options: DebugSessionOptions, parentSession?: DebugSession): DebugSession {
80
80
  const connection = new DebugSessionConnection(
81
81
  sessionId,
82
82
  this.connectionFactory,
@@ -42,7 +42,7 @@ export class ModalNotification extends AbstractDialog<string | undefined> {
42
42
  super({ title: FrontendApplicationConfigProvider.get().applicationName });
43
43
  }
44
44
 
45
- protected onCloseRequest(msg: Message): void {
45
+ protected override onCloseRequest(msg: Message): void {
46
46
  this.actionTitle = undefined;
47
47
  this.accept();
48
48
  }
@@ -718,6 +718,8 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
718
718
  const markers = monaco.services.StaticServices.markerService.get().read({ resource: model.uri }).filter(m => monaco.Range.areIntersectingOrTouching(m, range));
719
719
  return this.provideCodeActions(handle, model, range, { markers, only: context.only }, token);
720
720
  },
721
+ resolveCodeAction: (codeAction: monaco.languages.CodeAction, token: monaco.CancellationToken): Promise<monaco.languages.CodeAction> =>
722
+ this.resolveCodeAction(handle, codeAction, token),
721
723
  providedCodeActionKinds
722
724
  };
723
725
  this.register(handle, monaco.modes.CodeActionProviderRegistry.register(languageSelector, quickFixProvider));
@@ -734,12 +736,20 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
734
736
  }
735
737
  return {
736
738
  actions: actions.map(a => toMonacoAction(a)),
737
- dispose: () => {
738
- // TODO this.proxy.$releaseCodeActions(handle, cacheId);
739
- }
739
+ dispose: () => this.proxy.$releaseCodeActions(handle, actions.map(a => a.cacheId))
740
740
  };
741
741
  }
742
742
 
743
+ protected async resolveCodeAction(handle: number, codeAction: monaco.languages.CodeAction, token: monaco.CancellationToken): Promise<monaco.languages.CodeAction> {
744
+ // The cacheId is kept in toMonacoAction when converting a received CodeAction DTO to a monaco code action
745
+ const cacheId = (codeAction as CodeAction).cacheId;
746
+ if (cacheId !== undefined) {
747
+ const resolvedEdit = await this.proxy.$resolveCodeAction(handle, cacheId, token);
748
+ codeAction.edit = resolvedEdit && toMonacoWorkspaceEdit(resolvedEdit);
749
+ }
750
+ return codeAction;
751
+ }
752
+
743
753
  $registerRenameProvider(handle: number, pluginInfo: PluginInfo, selector: SerializedDocumentFilter[], supportsResolveLocation: boolean): void {
744
754
  const languageSelector = this.toLanguageSelector(selector);
745
755
  const renameProvider = this.createRenameProvider(handle, supportsResolveLocation);
@@ -27,12 +27,12 @@ export function getAuthenticationProviderActivationEvent(id: string): string { r
27
27
  export class PluginAuthenticationServiceImpl extends AuthenticationServiceImpl implements AuthenticationService {
28
28
  @inject(HostedPluginSupport) protected readonly pluginService: HostedPluginSupport;
29
29
 
30
- async getSessions(id: string, scopes?: string[]): Promise<ReadonlyArray<AuthenticationSession>> {
30
+ override async getSessions(id: string, scopes?: string[]): Promise<ReadonlyArray<AuthenticationSession>> {
31
31
  await this.tryActivateProvider(id);
32
32
  return super.getSessions(id, scopes);
33
33
  }
34
34
 
35
- async login(id: string, scopes: string[]): Promise<AuthenticationSession> {
35
+ override async login(id: string, scopes: string[]): Promise<AuthenticationSession> {
36
36
  await this.tryActivateProvider(id);
37
37
  return super.login(id, scopes);
38
38
  }
@@ -52,7 +52,7 @@ export class PluginWidget extends ReactWidget {
52
52
  this.toDispose.push(this.pluginService.onDidChangePlugins(() => this.update()));
53
53
  }
54
54
 
55
- protected onActivateRequest(msg: Message): void {
55
+ protected override onActivateRequest(msg: Message): void {
56
56
  super.onActivateRequest(msg);
57
57
  this.node.focus();
58
58
  }
@@ -66,7 +66,7 @@ export class PluginViewWidget extends Panel implements StatefulWidget, Descripti
66
66
  this.toDispose.push(localContext);
67
67
  }
68
68
 
69
- protected onActivateRequest(msg: Message): void {
69
+ protected override onActivateRequest(msg: Message): void {
70
70
  super.onActivateRequest(msg);
71
71
  const widget = this.widgets[0];
72
72
  if (widget) {
@@ -144,17 +144,17 @@ export class PluginViewWidget extends Panel implements StatefulWidget, Descripti
144
144
  }
145
145
  }
146
146
 
147
- addWidget(widget: Widget): void {
147
+ override addWidget(widget: Widget): void {
148
148
  super.addWidget(widget);
149
149
  this.updateWidgetMessage();
150
150
  }
151
151
 
152
- insertWidget(index: number, widget: Widget): void {
152
+ override insertWidget(index: number, widget: Widget): void {
153
153
  super.insertWidget(index, widget);
154
154
  this.updateWidgetMessage();
155
155
  }
156
156
 
157
- dispose(): void {
157
+ override dispose(): void {
158
158
  this.toDispose.dispose();
159
159
  super.dispose();
160
160
  }
@@ -118,7 +118,7 @@ export class PluginTree extends TreeImpl {
118
118
  return this._isEmpty;
119
119
  }
120
120
 
121
- protected async resolveChildren(parent: CompositeTreeNode): Promise<TreeNode[]> {
121
+ protected override async resolveChildren(parent: CompositeTreeNode): Promise<TreeNode[]> {
122
122
  if (!this._proxy) {
123
123
  return super.resolveChildren(parent);
124
124
  }
@@ -204,7 +204,7 @@ export class PluginTree extends TreeImpl {
204
204
  export class PluginTreeModel extends TreeModelImpl {
205
205
 
206
206
  @inject(PluginTree)
207
- protected readonly tree: PluginTree;
207
+ protected override readonly tree: PluginTree;
208
208
 
209
209
  set proxy(proxy: TreeViewsExt | undefined) {
210
210
  this.tree.proxy = proxy;
@@ -242,7 +242,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
242
242
  readonly identifier: TreeViewWidgetIdentifier;
243
243
 
244
244
  @inject(PluginTreeModel)
245
- readonly model: PluginTreeModel;
245
+ override readonly model: PluginTreeModel;
246
246
 
247
247
  @inject(ContextKeyService)
248
248
  protected readonly contextKeyService: ContextKeyService;
@@ -250,11 +250,8 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
250
250
  @inject(TooltipService)
251
251
  protected readonly tooltipService: TooltipService;
252
252
 
253
- protected readonly onDidChangeVisibilityEmitter = new Emitter<boolean>();
254
- readonly onDidChangeVisibility = this.onDidChangeVisibilityEmitter.event;
255
-
256
253
  @postConstruct()
257
- protected init(): void {
254
+ protected override init(): void {
258
255
  super.init();
259
256
  this.id = this.identifier.id;
260
257
  this.addClass('theia-tree-view');
@@ -265,7 +262,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
265
262
  this.toDispose.push(this.onDidChangeVisibilityEmitter);
266
263
  }
267
264
 
268
- protected renderIcon(node: TreeNode, props: NodeProps): React.ReactNode {
265
+ protected override renderIcon(node: TreeNode, props: NodeProps): React.ReactNode {
269
266
  const icon = this.toNodeIcon(node);
270
267
  if (icon) {
271
268
  return <div className={icon + ' theia-tree-view-icon'}></div>;
@@ -273,7 +270,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
273
270
  return undefined;
274
271
  }
275
272
 
276
- protected renderCaption(node: TreeViewNode, props: NodeProps): React.ReactNode {
273
+ protected override renderCaption(node: TreeViewNode, props: NodeProps): React.ReactNode {
277
274
  const classes = [TREE_NODE_SEGMENT_CLASS];
278
275
  if (!this.hasTrailingSuffixes(node)) {
279
276
  classes.push(TREE_NODE_SEGMENT_GROW_CLASS);
@@ -325,7 +322,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
325
322
  return React.createElement('div', attrs, ...children);
326
323
  }
327
324
 
328
- protected renderTailDecorations(node: TreeViewNode, props: NodeProps): React.ReactNode {
325
+ protected override renderTailDecorations(node: TreeViewNode, props: NodeProps): React.ReactNode {
329
326
  return this.contextKeys.with({ view: this.id, viewItem: node.contextValue }, () => {
330
327
  const menu = this.menus.getMenu(VIEW_ITEM_INLINE_MENU);
331
328
  const arg = this.toTreeViewSelection(node);
@@ -352,30 +349,30 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
352
349
  }} />;
353
350
  }
354
351
 
355
- protected toContextMenuArgs(node: SelectableTreeNode): [TreeViewSelection] {
352
+ protected override toContextMenuArgs(node: SelectableTreeNode): [TreeViewSelection] {
356
353
  return [this.toTreeViewSelection(node)];
357
354
  }
358
355
 
359
- setFlag(flag: Widget.Flag): void {
356
+ override setFlag(flag: Widget.Flag): void {
360
357
  super.setFlag(flag);
361
358
  if (flag === Widget.Flag.IsVisible) {
362
359
  this.onDidChangeVisibilityEmitter.fire(this.isVisible);
363
360
  }
364
361
  }
365
362
 
366
- clearFlag(flag: Widget.Flag): void {
363
+ override clearFlag(flag: Widget.Flag): void {
367
364
  super.clearFlag(flag);
368
365
  if (flag === Widget.Flag.IsVisible) {
369
366
  this.onDidChangeVisibilityEmitter.fire(this.isVisible);
370
367
  }
371
368
  }
372
369
 
373
- handleEnter(event: KeyboardEvent): void {
370
+ override handleEnter(event: KeyboardEvent): void {
374
371
  super.handleEnter(event);
375
372
  this.tryExecuteCommand();
376
373
  }
377
374
 
378
- handleClickEvent(node: TreeNode, event: React.MouseEvent<HTMLElement>): void {
375
+ override handleClickEvent(node: TreeNode, event: React.MouseEvent<HTMLElement>): void {
379
376
  super.handleClickEvent(node, event);
380
377
  // If clicked on item (not collapsable icon) - execute command or toggle expansion if item has no command
381
378
  const commandMap = this.findCommands(node);
@@ -418,7 +415,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
418
415
  this.update();
419
416
  }
420
417
 
421
- protected render(): React.ReactNode {
418
+ protected override render(): React.ReactNode {
422
419
  const node = React.createElement('div', this.createContainerAttributes(), this.renderSearchInfo(), this.renderTree(this.model));
423
420
  this.tooltipService.update();
424
421
  return node;
@@ -431,7 +428,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
431
428
  return undefined;
432
429
  }
433
430
 
434
- shouldShowWelcomeView(): boolean {
431
+ override shouldShowWelcomeView(): boolean {
435
432
  return (this.model.proxy === undefined || this.model.isTreeEmpty) && this.message === undefined;
436
433
  }
437
434
  }
@@ -198,14 +198,14 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget {
198
198
  }));
199
199
  }
200
200
 
201
- protected onBeforeAttach(msg: Message): void {
201
+ protected override onBeforeAttach(msg: Message): void {
202
202
  super.onBeforeAttach(msg);
203
203
  this.doShow();
204
204
  // iframe has to be reloaded when moved to another DOM element
205
205
  this.toDisposeOnDetach.push(Disposable.create(() => this.forceHide()));
206
206
  }
207
207
 
208
- protected onAfterAttach(msg: Message): void {
208
+ protected override onAfterAttach(msg: Message): void {
209
209
  super.onAfterAttach(msg);
210
210
  this.addEventListener(this.node, 'focus', () => {
211
211
  if (this.element) {
@@ -214,12 +214,12 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget {
214
214
  });
215
215
  }
216
216
 
217
- protected onBeforeShow(msg: Message): void {
217
+ protected override onBeforeShow(msg: Message): void {
218
218
  super.onBeforeShow(msg);
219
219
  this.doShow();
220
220
  }
221
221
 
222
- protected onAfterHide(msg: Message): void {
222
+ protected override onAfterHide(msg: Message): void {
223
223
  super.onAfterHide(msg);
224
224
  this.doHide();
225
225
  }
@@ -410,7 +410,7 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget {
410
410
  });
411
411
  }
412
412
 
413
- protected onActivateRequest(msg: Message): void {
413
+ protected override onActivateRequest(msg: Message): void {
414
414
  super.onActivateRequest(msg);
415
415
  this.node.focus();
416
416
  }
@@ -23,7 +23,7 @@ import { CustomEditorWidget } from '../../browser/custom-editors/custom-editor-w
23
23
 
24
24
  export class ElectronWebviewWidgetFactory extends WebviewWidgetFactory {
25
25
 
26
- async createWidget(identifier: WebviewWidgetIdentifier): Promise<WebviewWidget> {
26
+ override async createWidget(identifier: WebviewWidgetIdentifier): Promise<WebviewWidget> {
27
27
  const widget = await super.createWidget(identifier);
28
28
  await this.attachElectronSecurityCookie(widget.externalEndpoint);
29
29
  return widget;
@@ -47,7 +47,7 @@ export class ElectronWebviewWidgetFactory extends WebviewWidgetFactory {
47
47
 
48
48
  export class ElectronCustomEditorWidgetFactory extends CustomEditorWidgetFactory {
49
49
 
50
- async createWidget(identifier: WebviewWidgetIdentifier): Promise<CustomEditorWidget> {
50
+ override async createWidget(identifier: WebviewWidgetIdentifier): Promise<CustomEditorWidget> {
51
51
  const widget = await super.createWidget(identifier);
52
52
  await this.attachElectronSecurityCookie(widget.externalEndpoint);
53
53
  return widget;
@@ -16,7 +16,7 @@
16
16
 
17
17
  import * as theia from '@theia/plugin';
18
18
  import { URI } from '@theia/core/shared/vscode-uri';
19
- import { Selection } from '../../common/plugin-api-rpc';
19
+ import { Selection, WorkspaceEditDto } from '../../common/plugin-api-rpc';
20
20
  import { Range, CodeActionContext, CodeAction } from '../../common/plugin-api-rpc-model';
21
21
  import * as Converter from '../type-converters';
22
22
  import { DocumentsExtImpl } from '../documents';
@@ -35,6 +35,11 @@ export class CodeActionAdapter {
35
35
  private readonly commands: CommandRegistryImpl
36
36
  ) { }
37
37
 
38
+ private readonly cache = new Map<number, theia.CodeAction | theia.Command>();
39
+ private readonly disposables = new Map<number, DisposableCollection>();
40
+
41
+ private cacheId = 0;
42
+
38
43
  async provideCodeAction(resource: URI, rangeOrSelection: Range | Selection,
39
44
  context: CodeActionContext, token: theia.CancellationToken): Promise<CodeAction[] | undefined> {
40
45
  const document = this.document.getDocumentData(resource);
@@ -64,15 +69,21 @@ export class CodeActionAdapter {
64
69
  if (!Array.isArray(commandsOrActions) || commandsOrActions.length === 0) {
65
70
  return undefined;
66
71
  }
67
- // TODO cache toDispose and dispose it
68
- const toDispose = new DisposableCollection();
69
72
  const result: CodeAction[] = [];
70
73
  for (const candidate of commandsOrActions) {
71
74
  if (!candidate) {
72
75
  continue;
73
76
  }
77
+
78
+ // Cache candidates and created commands.
79
+ const nextCacheId = this.nextCacheId();
80
+ const toDispose = new DisposableCollection();
81
+ this.cache.set(nextCacheId, candidate);
82
+ this.disposables.set(nextCacheId, toDispose);
83
+
74
84
  if (CodeActionAdapter._isCommand(candidate)) {
75
85
  result.push({
86
+ cacheId: nextCacheId,
76
87
  title: candidate.title || '',
77
88
  command: this.commands.converter.toSafeCommand(candidate, toDispose)
78
89
  });
@@ -88,6 +99,7 @@ export class CodeActionAdapter {
88
99
  }
89
100
 
90
101
  result.push({
102
+ cacheId: nextCacheId,
91
103
  title: candidate.title,
92
104
  command: this.commands.converter.toSafeCommand(candidate.command, toDispose),
93
105
  diagnostics: candidate.diagnostics && candidate.diagnostics.map(Converter.convertDiagnosticToMarkerData),
@@ -100,6 +112,37 @@ export class CodeActionAdapter {
100
112
  return result;
101
113
  }
102
114
 
115
+ async releaseCodeActions(cacheIds: number[]): Promise<void> {
116
+ cacheIds.forEach(id => {
117
+ this.cache.delete(id);
118
+ const toDispose = this.disposables.get(id);
119
+ if (toDispose) {
120
+ toDispose.dispose();
121
+ this.disposables.delete(id);
122
+ }
123
+ });
124
+ }
125
+
126
+ async resolveCodeAction(cacheId: number, token: theia.CancellationToken): Promise<WorkspaceEditDto | undefined> {
127
+ if (!this.provider.resolveCodeAction) {
128
+ return undefined;
129
+ }
130
+
131
+ // Code actions are only resolved if they are not legacy commands and don't have an edit property
132
+ // https://code.visualstudio.com/api/references/vscode-api#CodeActionProvider
133
+ const candidate = this.cache.get(cacheId);
134
+ if (!candidate || CodeActionAdapter._isCommand(candidate) || candidate.edit) {
135
+ return undefined;
136
+ }
137
+
138
+ const resolved = await this.provider.resolveCodeAction(candidate, token);
139
+ return resolved?.edit && Converter.fromWorkspaceEdit(resolved.edit);
140
+ }
141
+
142
+ private nextCacheId(): number {
143
+ return this.cacheId++;
144
+ }
145
+
103
146
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
104
147
  private static _isCommand(smth: any): smth is theia.Command {
105
148
  return typeof (<theia.Command>smth).command === 'string';
@@ -463,6 +463,15 @@ export class LanguagesExtImpl implements LanguagesExt {
463
463
  ): Promise<CodeAction[] | undefined> {
464
464
  return this.withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeAction(URI.revive(resource), rangeOrSelection, context, token), undefined);
465
465
  }
466
+
467
+ $releaseCodeActions(handle: number, cacheIds: number[]): void {
468
+ this.withAdapter(handle, CodeActionAdapter, adapter => adapter.releaseCodeActions(cacheIds), undefined);
469
+ }
470
+
471
+ $resolveCodeAction(handle: number, cacheId: number, token: theia.CancellationToken): Promise<WorkspaceEditDto | undefined> {
472
+ return this.withAdapter(handle, CodeActionAdapter, adapter => adapter.resolveCodeAction(cacheId, token), undefined);
473
+ };
474
+
466
475
  // ### Code Actions Provider end
467
476
 
468
477
  // ### Code Lens Provider begin
@@ -30,7 +30,7 @@ export class PluginDebugAdapterSession extends DebugAdapterSessionImpl {
30
30
  readonly configuration: theia.DebugConfiguration;
31
31
 
32
32
  constructor(
33
- readonly debugAdapter: DebugAdapter,
33
+ override readonly debugAdapter: DebugAdapter,
34
34
  protected readonly tracker: theia.DebugAdapterTracker,
35
35
  protected readonly theiaSession: theia.DebugSession) {
36
36
 
@@ -41,14 +41,14 @@ export class PluginDebugAdapterSession extends DebugAdapterSessionImpl {
41
41
  this.configuration = theiaSession.configuration;
42
42
  }
43
43
 
44
- async start(channel: Channel): Promise<void> {
44
+ override async start(channel: Channel): Promise<void> {
45
45
  if (this.tracker.onWillStartSession) {
46
46
  this.tracker.onWillStartSession();
47
47
  }
48
48
  await super.start(channel);
49
49
  }
50
50
 
51
- async stop(): Promise<void> {
51
+ override async stop(): Promise<void> {
52
52
  if (this.tracker.onWillStopSession) {
53
53
  this.tracker.onWillStopSession();
54
54
  }
@@ -59,14 +59,14 @@ export class PluginDebugAdapterSession extends DebugAdapterSessionImpl {
59
59
  return this.theiaSession.customRequest(command, args);
60
60
  }
61
61
 
62
- protected onDebugAdapterError(error: Error): void {
62
+ protected override onDebugAdapterError(error: Error): void {
63
63
  if (this.tracker.onError) {
64
64
  this.tracker.onError(error);
65
65
  }
66
66
  super.onDebugAdapterError(error);
67
67
  }
68
68
 
69
- protected send(message: string): void {
69
+ protected override send(message: string): void {
70
70
  try {
71
71
  super.send(message);
72
72
  } finally {
@@ -76,14 +76,14 @@ export class PluginDebugAdapterSession extends DebugAdapterSessionImpl {
76
76
  }
77
77
  }
78
78
 
79
- protected write(message: string): void {
79
+ protected override write(message: string): void {
80
80
  if (this.tracker.onWillReceiveMessage) {
81
81
  this.tracker.onWillReceiveMessage(JSON.parse(message));
82
82
  }
83
83
  super.write(message);
84
84
  }
85
85
 
86
- protected onDebugAdapterExit(): void {
86
+ protected override onDebugAdapterExit(): void {
87
87
  if (this.tracker.onExit) {
88
88
  this.tracker.onExit(undefined, undefined);
89
89
  }