@theia/plugin-ext 1.28.0-next.3 → 1.28.0-next.30

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 (122) 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/common/plugin-protocol.d.ts +4 -0
  8. package/lib/common/plugin-protocol.d.ts.map +1 -1
  9. package/lib/common/plugin-protocol.js.map +1 -1
  10. package/lib/hosted/node/hosted-plugin-deployer-handler.d.ts.map +1 -1
  11. package/lib/hosted/node/hosted-plugin-deployer-handler.js +1 -0
  12. package/lib/hosted/node/hosted-plugin-deployer-handler.js.map +1 -1
  13. package/lib/hosted/node/hosted-plugin-localization-service.d.ts +15 -2
  14. package/lib/hosted/node/hosted-plugin-localization-service.d.ts.map +1 -1
  15. package/lib/hosted/node/hosted-plugin-localization-service.js +33 -3
  16. package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
  17. package/lib/hosted/node/plugin-ext-hosted-backend-module.d.ts.map +1 -1
  18. package/lib/hosted/node/plugin-ext-hosted-backend-module.js +1 -0
  19. package/lib/hosted/node/plugin-ext-hosted-backend-module.js.map +1 -1
  20. package/lib/hosted/node/scanners/scanner-theia.d.ts +5 -1
  21. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  22. package/lib/hosted/node/scanners/scanner-theia.js +22 -15
  23. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  24. package/lib/main/browser/comments/comment-thread-widget.js +5 -5
  25. package/lib/main/browser/comments/comment-thread-widget.js.map +1 -1
  26. package/lib/main/browser/debug/debug-main.d.ts +1 -0
  27. package/lib/main/browser/debug/debug-main.d.ts.map +1 -1
  28. package/lib/main/browser/debug/debug-main.js +10 -0
  29. package/lib/main/browser/debug/debug-main.js.map +1 -1
  30. package/lib/main/browser/languages-main.d.ts.map +1 -1
  31. package/lib/main/browser/languages-main.js.map +1 -1
  32. package/lib/main/browser/menus/menus-contribution-handler.d.ts +24 -88
  33. package/lib/main/browser/menus/menus-contribution-handler.d.ts.map +1 -1
  34. package/lib/main/browser/menus/menus-contribution-handler.js +108 -518
  35. package/lib/main/browser/menus/menus-contribution-handler.js.map +1 -1
  36. package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts +44 -0
  37. package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts.map +1 -0
  38. package/lib/main/browser/menus/plugin-menu-command-adapter.js +274 -0
  39. package/lib/main/browser/menus/plugin-menu-command-adapter.js.map +1 -0
  40. package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts +18 -0
  41. package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts.map +1 -0
  42. package/lib/main/browser/menus/vscode-theia-menu-mappings.js +88 -0
  43. package/lib/main/browser/menus/vscode-theia-menu-mappings.js.map +1 -0
  44. package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
  45. package/lib/main/browser/plugin-contribution-handler.js +9 -4
  46. package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
  47. package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
  48. package/lib/main/browser/plugin-ext-frontend-module.js +4 -1
  49. package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
  50. package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
  51. package/lib/main/browser/plugin-shared-style.js +0 -1
  52. package/lib/main/browser/plugin-shared-style.js.map +1 -1
  53. package/lib/main/browser/scm-main.d.ts +1 -0
  54. package/lib/main/browser/scm-main.d.ts.map +1 -1
  55. package/lib/main/browser/scm-main.js +7 -0
  56. package/lib/main/browser/scm-main.js.map +1 -1
  57. package/lib/main/browser/terminal-main.d.ts.map +1 -1
  58. package/lib/main/browser/terminal-main.js +4 -1
  59. package/lib/main/browser/terminal-main.js.map +1 -1
  60. package/lib/main/browser/view/tree-view-widget.js +2 -2
  61. package/lib/main/browser/view/tree-view-widget.js.map +1 -1
  62. package/lib/plugin/debug/debug-ext.d.ts +3 -1
  63. package/lib/plugin/debug/debug-ext.d.ts.map +1 -1
  64. package/lib/plugin/debug/debug-ext.js +26 -4
  65. package/lib/plugin/debug/debug-ext.js.map +1 -1
  66. package/lib/plugin/debug/plugin-debug-adapter-session.d.ts +1 -0
  67. package/lib/plugin/debug/plugin-debug-adapter-session.d.ts.map +1 -1
  68. package/lib/plugin/debug/plugin-debug-adapter-session.js +3 -0
  69. package/lib/plugin/debug/plugin-debug-adapter-session.js.map +1 -1
  70. package/lib/plugin/languages/signature.d.ts.map +1 -1
  71. package/lib/plugin/languages/signature.js +5 -1
  72. package/lib/plugin/languages/signature.js.map +1 -1
  73. package/lib/plugin/node/debug/debug.spec.d.ts +2 -0
  74. package/lib/plugin/node/debug/debug.spec.d.ts.map +1 -0
  75. package/lib/plugin/node/debug/debug.spec.js +68 -0
  76. package/lib/plugin/node/debug/debug.spec.js.map +1 -0
  77. package/lib/plugin/plugin-context.d.ts.map +1 -1
  78. package/lib/plugin/plugin-context.js +3 -0
  79. package/lib/plugin/plugin-context.js.map +1 -1
  80. package/lib/plugin/quick-open.d.ts.map +1 -1
  81. package/lib/plugin/quick-open.js +1 -0
  82. package/lib/plugin/quick-open.js.map +1 -1
  83. package/lib/plugin/scm.d.ts +3 -0
  84. package/lib/plugin/scm.d.ts.map +1 -1
  85. package/lib/plugin/scm.js +8 -0
  86. package/lib/plugin/scm.js.map +1 -1
  87. package/lib/plugin/type-converters.d.ts.map +1 -1
  88. package/lib/plugin/type-converters.js +4 -2
  89. package/lib/plugin/type-converters.js.map +1 -1
  90. package/lib/plugin/types-impl.d.ts +4 -3
  91. package/lib/plugin/types-impl.d.ts.map +1 -1
  92. package/lib/plugin/types-impl.js +9 -8
  93. package/lib/plugin/types-impl.js.map +1 -1
  94. package/package.json +26 -26
  95. package/src/common/plugin-api-rpc-model.ts +1 -0
  96. package/src/common/plugin-api-rpc.ts +2 -0
  97. package/src/common/plugin-protocol.ts +4 -0
  98. package/src/hosted/node/hosted-plugin-deployer-handler.ts +1 -0
  99. package/src/hosted/node/hosted-plugin-localization-service.ts +39 -5
  100. package/src/hosted/node/plugin-ext-hosted-backend-module.ts +1 -0
  101. package/src/hosted/node/scanners/scanner-theia.ts +21 -15
  102. package/src/main/browser/comments/comment-thread-widget.tsx +5 -5
  103. package/src/main/browser/debug/debug-main.ts +9 -0
  104. package/src/main/browser/languages-main.ts +5 -0
  105. package/src/main/browser/menus/menus-contribution-handler.ts +104 -578
  106. package/src/main/browser/menus/plugin-menu-command-adapter.ts +259 -0
  107. package/src/main/browser/menus/vscode-theia-menu-mappings.ts +85 -0
  108. package/src/main/browser/plugin-contribution-handler.ts +3 -1
  109. package/src/main/browser/plugin-ext-frontend-module.ts +4 -1
  110. package/src/main/browser/plugin-shared-style.ts +0 -1
  111. package/src/main/browser/scm-main.ts +10 -0
  112. package/src/main/browser/terminal-main.ts +4 -1
  113. package/src/main/browser/view/tree-view-widget.tsx +2 -2
  114. package/src/plugin/debug/debug-ext.ts +30 -5
  115. package/src/plugin/debug/plugin-debug-adapter-session.ts +4 -0
  116. package/src/plugin/languages/signature.ts +3 -1
  117. package/src/plugin/node/debug/debug.spec.ts +94 -0
  118. package/src/plugin/plugin-context.ts +3 -0
  119. package/src/plugin/quick-open.ts +1 -0
  120. package/src/plugin/scm.ts +11 -0
  121. package/src/plugin/type-converters.ts +4 -2
  122. package/src/plugin/types-impl.ts +7 -5
@@ -0,0 +1,259 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2022 Ericsson and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { CommandRegistry, Disposable, MenuCommandAdapter, MenuPath, SelectionService, UriSelection } from '@theia/core';
18
+ import { ResourceContextKey } from '@theia/core/lib/browser/resource-context-key';
19
+ import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
20
+ import { URI as CodeUri } from '@theia/core/shared/vscode-uri';
21
+ import { TreeWidgetSelection } from '@theia/core/lib/browser/tree/tree-widget-selection';
22
+ import { ScmRepository } from '@theia/scm/lib/browser/scm-repository';
23
+ import { ScmService } from '@theia/scm/lib/browser/scm-service';
24
+ import { TimelineItem } from '@theia/timeline/lib/common/timeline-model';
25
+ import { ScmCommandArg, TimelineCommandArg, TreeViewSelection } from '../../../common';
26
+ import { PluginScmProvider, PluginScmResource, PluginScmResourceGroup } from '../scm-main';
27
+ import { TreeViewWidget } from '../view/tree-view-widget';
28
+ import { CodeEditorWidgetUtil, codeToTheiaMappings, ContributionPoint } from './vscode-theia-menu-mappings';
29
+ import { TAB_BAR_TOOLBAR_CONTEXT_MENU } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
30
+
31
+ export type ArgumentAdapter = (...args: unknown[]) => unknown[];
32
+
33
+ export class ReferenceCountingSet<T> {
34
+ protected readonly references: Map<T, number>;
35
+ constructor(initialMembers?: Iterable<T>) {
36
+ this.references = new Map();
37
+ if (initialMembers) {
38
+ for (const member of initialMembers) {
39
+ this.add(member);
40
+ }
41
+ }
42
+ }
43
+
44
+ add(newMember: T): ReferenceCountingSet<T> {
45
+ const value = this.references.get(newMember) ?? 0;
46
+ this.references.set(newMember, value + 1);
47
+ return this;
48
+ }
49
+
50
+ /** @returns true if the deletion results in the removal of the element from the set */
51
+ delete(member: T): boolean {
52
+ const value = this.references.get(member);
53
+ if (value === undefined) { } else if (value <= 1) {
54
+ this.references.delete(member);
55
+ return true;
56
+ } else {
57
+ this.references.set(member, value - 1);
58
+ }
59
+ return false;
60
+ }
61
+
62
+ has(maybeMember: T): boolean {
63
+ return this.references.has(maybeMember);
64
+ }
65
+ }
66
+
67
+ @injectable()
68
+ export class PluginMenuCommandAdapter implements MenuCommandAdapter {
69
+ @inject(CommandRegistry) protected readonly commandRegistry: CommandRegistry;
70
+ @inject(CodeEditorWidgetUtil) protected readonly codeEditorUtil: CodeEditorWidgetUtil;
71
+ @inject(ScmService) protected readonly scmService: ScmService;
72
+ @inject(SelectionService) protected readonly selectionService: SelectionService;
73
+ @inject(ResourceContextKey) protected readonly resourceContextKey: ResourceContextKey;
74
+
75
+ protected readonly commands = new ReferenceCountingSet<string>();
76
+ protected readonly argumentAdapters = new Map<string, ArgumentAdapter>();
77
+ protected readonly separator = ':)(:';
78
+
79
+ @postConstruct()
80
+ protected init(): void {
81
+ const toCommentArgs: ArgumentAdapter = (...args) => this.toCommentArgs(...args);
82
+ const firstArgOnly: ArgumentAdapter = (...args) => [args[0]];
83
+ const noArgs: ArgumentAdapter = () => [];
84
+ const toScmArgs: ArgumentAdapter = (...args) => this.toScmArgs(...args);
85
+ const selectedResource = () => this.getSelectedResources();
86
+ const widgetURI: ArgumentAdapter = widget => this.codeEditorUtil.is(widget) ? [this.codeEditorUtil.getResourceUri(widget)] : [];
87
+ (<Array<[ContributionPoint, ArgumentAdapter | undefined]>>[
88
+ ['comments/comment/context', toCommentArgs],
89
+ ['comments/comment/title', toCommentArgs],
90
+ ['comments/commentThread/context', toCommentArgs],
91
+ ['debug/callstack/context', firstArgOnly],
92
+ ['debug/toolBar', noArgs],
93
+ ['editor/context', selectedResource],
94
+ ['editor/title', widgetURI],
95
+ ['editor/title/context', selectedResource],
96
+ ['explorer/context', selectedResource],
97
+ ['scm/resourceFolder/context', toScmArgs],
98
+ ['scm/resourceGroup/context', toScmArgs],
99
+ ['scm/resourceState/context', toScmArgs],
100
+ ['scm/title', () => this.toScmArg(this.scmService.selectedRepository)],
101
+ ['timeline/item/context', (...args) => this.toTimelineArgs(...args)],
102
+ ['view/item/context', (...args) => this.toTreeArgs(...args)],
103
+ ['view/title', noArgs],
104
+ ]).forEach(([contributionPoint, adapter]) => {
105
+ if (adapter) {
106
+ const paths = codeToTheiaMappings.get(contributionPoint);
107
+ if (paths) {
108
+ paths.forEach(([path]) => this.addArgumentAdapter(path, adapter));
109
+ }
110
+ }
111
+ });
112
+ this.addArgumentAdapter(TAB_BAR_TOOLBAR_CONTEXT_MENU, widgetURI);
113
+ }
114
+
115
+ canHandle(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): number {
116
+ if (this.commands.has(command) && this.getArgumentAdapterForMenu(menuPath)) {
117
+ return 500;
118
+ }
119
+ return -1;
120
+ }
121
+
122
+ executeCommand(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): Promise<unknown> {
123
+ const argumentAdapter = this.getAdapterOrThrow(menuPath);
124
+ return this.commandRegistry.executeCommand(command, ...argumentAdapter(...commandArgs));
125
+ }
126
+
127
+ isVisible(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): boolean {
128
+ const argumentAdapter = this.getAdapterOrThrow(menuPath);
129
+ return this.commandRegistry.isVisible(command, ...argumentAdapter(...commandArgs));
130
+ }
131
+
132
+ isEnabled(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): boolean {
133
+ const argumentAdapter = this.getAdapterOrThrow(menuPath);
134
+ return this.commandRegistry.isEnabled(command, ...argumentAdapter(...commandArgs));
135
+ }
136
+
137
+ isToggled(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): boolean {
138
+ const argumentAdapter = this.getAdapterOrThrow(menuPath);
139
+ return this.commandRegistry.isToggled(command, ...argumentAdapter(...commandArgs));
140
+ }
141
+
142
+ protected getAdapterOrThrow(menuPath: MenuPath): ArgumentAdapter {
143
+ const argumentAdapter = this.getArgumentAdapterForMenu(menuPath);
144
+ if (!argumentAdapter) {
145
+ throw new Error('PluginMenuCommandAdapter attempted to execute command for unregistered menu: ' + JSON.stringify(menuPath));
146
+ }
147
+ return argumentAdapter;
148
+ }
149
+
150
+ addCommand(commandId: string): Disposable {
151
+ this.commands.add(commandId);
152
+ return Disposable.create(() => this.commands.delete(commandId));
153
+ }
154
+
155
+ protected getArgumentAdapterForMenu(menuPath: MenuPath): ArgumentAdapter | undefined {
156
+ return this.argumentAdapters.get(menuPath.join(this.separator));
157
+ }
158
+
159
+ protected addArgumentAdapter(menuPath: MenuPath, adapter: ArgumentAdapter): void {
160
+ this.argumentAdapters.set(menuPath.join(this.separator), adapter);
161
+ }
162
+
163
+ /* eslint-disable @typescript-eslint/no-explicit-any */
164
+
165
+ protected toCommentArgs(...args: any[]): any[] {
166
+ const arg = args[0];
167
+ if ('text' in arg) {
168
+ if ('commentUniqueId' in arg) {
169
+ return [{
170
+ commentControlHandle: arg.thread.controllerHandle,
171
+ commentThreadHandle: arg.thread.commentThreadHandle,
172
+ text: arg.text,
173
+ commentUniqueId: arg.commentUniqueId
174
+ }];
175
+ }
176
+ return [{
177
+ commentControlHandle: arg.thread.controllerHandle,
178
+ commentThreadHandle: arg.thread.commentThreadHandle,
179
+ text: arg.text
180
+ }];
181
+ }
182
+ return [{
183
+ commentControlHandle: arg.thread.controllerHandle,
184
+ commentThreadHandle: arg.thread.commentThreadHandle,
185
+ commentUniqueId: arg.commentUniqueId
186
+ }];
187
+ }
188
+
189
+ protected toScmArgs(...args: any[]): any[] {
190
+ const scmArgs: any[] = [];
191
+ for (const arg of args) {
192
+ const scmArg = this.toScmArg(arg);
193
+ if (scmArg) {
194
+ scmArgs.push(scmArg);
195
+ }
196
+ }
197
+ return scmArgs;
198
+ }
199
+
200
+ protected toScmArg(arg: any): ScmCommandArg | undefined {
201
+ if (arg instanceof ScmRepository && arg.provider instanceof PluginScmProvider) {
202
+ return {
203
+ sourceControlHandle: arg.provider.handle
204
+ };
205
+ }
206
+ if (arg instanceof PluginScmResourceGroup) {
207
+ return {
208
+ sourceControlHandle: arg.provider.handle,
209
+ resourceGroupHandle: arg.handle
210
+ };
211
+ }
212
+ if (arg instanceof PluginScmResource) {
213
+ return {
214
+ sourceControlHandle: arg.group.provider.handle,
215
+ resourceGroupHandle: arg.group.handle,
216
+ resourceStateHandle: arg.handle
217
+ };
218
+ }
219
+ }
220
+
221
+ protected toTimelineArgs(...args: any[]): any[] {
222
+ const timelineArgs: any[] = [];
223
+ const arg = args[0];
224
+ timelineArgs.push(this.toTimelineArg(arg));
225
+ timelineArgs.push(CodeUri.parse(arg.uri));
226
+ timelineArgs.push(arg.source ?? '');
227
+ return timelineArgs;
228
+ }
229
+
230
+ protected toTimelineArg(arg: TimelineItem): TimelineCommandArg {
231
+ return {
232
+ timelineHandle: arg.handle,
233
+ source: arg.source,
234
+ uri: arg.uri
235
+ };
236
+ }
237
+
238
+ protected toTreeArgs(...args: any[]): any[] {
239
+ const treeArgs: any[] = [];
240
+ for (const arg of args) {
241
+ if (TreeViewSelection.is(arg)) {
242
+ treeArgs.push(arg);
243
+ }
244
+ }
245
+ return treeArgs;
246
+ }
247
+
248
+ protected getSelectedResources(): [CodeUri | TreeViewSelection | undefined, CodeUri[] | undefined] {
249
+ const selection = this.selectionService.selection;
250
+ const firstMember = TreeWidgetSelection.is(selection) && selection.source instanceof TreeViewWidget && selection[0]
251
+ ? selection.source.toTreeViewSelection(selection[0])
252
+ : (UriSelection.getUri(selection) ?? this.resourceContextKey.get())?.['codeUri'];
253
+ const secondMember = TreeWidgetSelection.is(selection)
254
+ ? UriSelection.getUris(selection).map(uri => uri['codeUri'])
255
+ : undefined;
256
+ return [firstMember, secondMember];
257
+ }
258
+ /* eslint-enable @typescript-eslint/no-explicit-any */
259
+ }
@@ -0,0 +1,85 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2022 Ericsson and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { MenuPath } from '@theia/core';
18
+ import { SHELL_TABBAR_CONTEXT_MENU } from '@theia/core/lib/browser';
19
+ import { Navigatable } from '@theia/core/lib/browser/navigatable';
20
+ import { injectable } from '@theia/core/shared/inversify';
21
+ import { URI as CodeUri } from '@theia/core/shared/vscode-uri';
22
+ import { DebugStackFramesWidget } from '@theia/debug/lib/browser/view/debug-stack-frames-widget';
23
+ import { DebugThreadsWidget } from '@theia/debug/lib/browser/view/debug-threads-widget';
24
+ import { EditorWidget, EDITOR_CONTEXT_MENU } from '@theia/editor/lib/browser';
25
+ import { NAVIGATOR_CONTEXT_MENU } from '@theia/navigator/lib/browser/navigator-contribution';
26
+ import { ScmTreeWidget } from '@theia/scm/lib/browser/scm-tree-widget';
27
+ import { TIMELINE_ITEM_CONTEXT_MENU } from '@theia/timeline/lib/browser/timeline-tree-widget';
28
+ import { COMMENT_CONTEXT, COMMENT_THREAD_CONTEXT, COMMENT_TITLE } from '../comments/comment-thread-widget';
29
+ import { VIEW_ITEM_CONTEXT_MENU } from '../view/tree-view-widget';
30
+ import { WebviewWidget } from '../webview/webview';
31
+
32
+ export const PLUGIN_EDITOR_TITLE_MENU = ['plugin_editor/title'];
33
+ export const PLUGIN_SCM_TITLE_MENU = ['plugin_scm/title'];
34
+ export const PLUGIN_VIEW_TITLE_MENU = ['plugin_view/title'];
35
+
36
+ export const implementedVSCodeContributionPoints = [
37
+ 'comments/comment/context',
38
+ 'comments/comment/title',
39
+ 'comments/commentThread/context',
40
+ 'debug/callstack/context',
41
+ 'editor/context',
42
+ 'editor/title',
43
+ 'editor/title/context',
44
+ 'explorer/context',
45
+ 'scm/resourceFolder/context',
46
+ 'scm/resourceGroup/context',
47
+ 'scm/resourceState/context',
48
+ 'scm/title',
49
+ 'timeline/item/context',
50
+ 'view/item/context',
51
+ 'view/title'
52
+ ] as const;
53
+
54
+ export type ContributionPoint = (typeof implementedVSCodeContributionPoints)[number];
55
+
56
+ /** The values are combinations of MenuPath and `when` clause, if any */
57
+ export const codeToTheiaMappings = new Map<ContributionPoint, Array<[MenuPath] | [MenuPath, string]>>([
58
+ ['comments/comment/context', [[COMMENT_CONTEXT]]],
59
+ ['comments/comment/title', [[COMMENT_TITLE]]],
60
+ ['comments/commentThread/context', [[COMMENT_THREAD_CONTEXT]]],
61
+ ['debug/callstack/context', [[DebugStackFramesWidget.CONTEXT_MENU], [DebugThreadsWidget.CONTEXT_MENU]]],
62
+ ['editor/context', [[EDITOR_CONTEXT_MENU]]],
63
+ ['editor/title', [[PLUGIN_EDITOR_TITLE_MENU]]],
64
+ ['editor/title/context', [[SHELL_TABBAR_CONTEXT_MENU, 'resourceSet']]],
65
+ ['explorer/context', [[NAVIGATOR_CONTEXT_MENU]]],
66
+ ['scm/resourceFolder/context', [[ScmTreeWidget.RESOURCE_FOLDER_CONTEXT_MENU]]],
67
+ ['scm/resourceGroup/context', [[ScmTreeWidget.RESOURCE_GROUP_CONTEXT_MENU]]],
68
+ ['scm/resourceState/context', [[ScmTreeWidget.RESOURCE_CONTEXT_MENU]]],
69
+ ['scm/title', [[PLUGIN_SCM_TITLE_MENU]]],
70
+ ['timeline/item/context', [[TIMELINE_ITEM_CONTEXT_MENU]]],
71
+ ['view/item/context', [[VIEW_ITEM_CONTEXT_MENU]]],
72
+ ['view/title', [[PLUGIN_VIEW_TITLE_MENU]]],
73
+ ]);
74
+
75
+ type CodeEditorWidget = EditorWidget | WebviewWidget;
76
+ @injectable()
77
+ export class CodeEditorWidgetUtil {
78
+ is(arg: unknown): arg is CodeEditorWidget {
79
+ return arg instanceof EditorWidget || arg instanceof WebviewWidget;
80
+ }
81
+ getResourceUri(editor: CodeEditorWidget): CodeUri | undefined {
82
+ const resourceUri = Navigatable.is(editor) && editor.getResourceUri();
83
+ return resourceUri ? resourceUri['codeUri'] : undefined;
84
+ }
85
+ }
@@ -222,7 +222,9 @@ export class PluginContributionHandler {
222
222
  pushContribution(`grammar.language.${language}.scope`, () => this.grammarsRegistry.mapLanguageIdToTextmateGrammar(language, grammar.scope));
223
223
  pushContribution(`grammar.language.${language}.configuration`, () => this.grammarsRegistry.registerGrammarConfiguration(language, {
224
224
  embeddedLanguages: this.convertEmbeddedLanguages(grammar.embeddedLanguages, logWarning),
225
- tokenTypes: this.convertTokenTypes(grammar.tokenTypes)
225
+ tokenTypes: this.convertTokenTypes(grammar.tokenTypes),
226
+ balancedBracketSelectors: grammar.balancedBracketScopes ?? ['*'],
227
+ unbalancedBracketSelectors: grammar.balancedBracketScopes,
226
228
  }));
227
229
  }
228
230
  // activate grammars only once everything else is loaded.
@@ -35,7 +35,7 @@ import { PluginWidget } from './plugin-ext-widget';
35
35
  import { PluginFrontendViewContribution } from './plugin-frontend-view-contribution';
36
36
  import { PluginExtDeployCommandService } from './plugin-ext-deploy-command';
37
37
  import { EditorModelService } from './text-editor-model-service';
38
- import { CodeEditorWidgetUtil, MenusContributionPointHandler } from './menus/menus-contribution-handler';
38
+ import { MenusContributionPointHandler } from './menus/menus-contribution-handler';
39
39
  import { PluginContributionHandler } from './plugin-contribution-handler';
40
40
  import { PluginViewRegistry, PLUGIN_VIEW_CONTAINER_FACTORY_ID, PLUGIN_VIEW_FACTORY_ID, PLUGIN_VIEW_DATA_FACTORY_ID } from './view/plugin-view-registry';
41
41
  import { TextContentResourceResolver } from './workspace-main';
@@ -78,6 +78,8 @@ import { WebviewFrontendSecurityWarnings } from './webview/webview-frontend-secu
78
78
  import { PluginAuthenticationServiceImpl } from './plugin-authentication-service';
79
79
  import { AuthenticationService } from '@theia/core/lib/browser/authentication-service';
80
80
  import { bindTreeViewDecoratorUtilities, TreeViewDecoratorService } from './view/tree-view-decorator-service';
81
+ import { CodeEditorWidgetUtil } from './menus/vscode-theia-menu-mappings';
82
+ import { PluginMenuCommandAdapter } from './menus/plugin-menu-command-adapter';
81
83
 
82
84
  export default new ContainerModule((bind, unbind, isBound, rebind) => {
83
85
 
@@ -213,6 +215,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
213
215
  bind(LabelProviderContribution).toService(PluginIconThemeService);
214
216
 
215
217
  bind(MenusContributionPointHandler).toSelf().inSingletonScope();
218
+ bind(PluginMenuCommandAdapter).toSelf().inSingletonScope();
216
219
  bind(CodeEditorWidgetUtil).toSelf().inSingletonScope();
217
220
  bind(KeybindingsContributionPointHandler).toSelf().inSingletonScope();
218
221
  bind(PluginContributionHandler).toSelf().inSingletonScope();
@@ -111,7 +111,6 @@ export class PluginSharedStyle {
111
111
  const iconClass = 'plugin-icon-' + this.iconSequence++;
112
112
  const toDispose = new DisposableCollection();
113
113
  toDispose.push(this.insertRule('.' + iconClass, theme => `
114
- display: inline-block;
115
114
  background-position: 2px;
116
115
  width: ${size}px;
117
116
  height: ${size}px;
@@ -430,4 +430,14 @@ export class ScmMainImpl implements ScmMain {
430
430
 
431
431
  repository.input.placeholder = placeholder;
432
432
  }
433
+
434
+ $setInputBoxVisible(sourceControlHandle: number, visible: boolean): void {
435
+ const repository = this.repositories.get(sourceControlHandle);
436
+
437
+ if (!repository) {
438
+ return;
439
+ }
440
+
441
+ repository.input.visible = visible;
442
+ }
433
443
  }
@@ -127,8 +127,11 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, Disposable
127
127
  destroyTermOnClose: true,
128
128
  useServerTitle: false,
129
129
  attributes: options.attributes,
130
- isPseudoTerminal,
130
+ isPseudoTerminal
131
131
  });
132
+ if (options.message) {
133
+ terminal.writeLine(options.message);
134
+ }
132
135
  terminal.start();
133
136
  return terminal.id;
134
137
  } catch (error) {
@@ -399,14 +399,14 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
399
399
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
400
400
  protected renderInlineCommand(node: ActionMenuNode, index: number, tabbable: boolean, arg: any): React.ReactNode {
401
401
  const { icon } = node;
402
- if (!icon || !this.commands.isVisible(node.action.commandId, arg) || !node.action.when || !this.contextKeys.match(node.action.when)) {
402
+ if (!icon || !this.commands.isVisible(node.command, arg) || !node.when || !this.contextKeys.match(node.when)) {
403
403
  return false;
404
404
  }
405
405
  const className = [TREE_NODE_SEGMENT_CLASS, TREE_NODE_TAIL_CLASS, icon, ACTION_ITEM, 'theia-tree-view-inline-action'].join(' ');
406
406
  const tabIndex = tabbable ? 0 : undefined;
407
407
  return <div key={index} className={className} title={node.label} tabIndex={tabIndex} onClick={e => {
408
408
  e.stopPropagation();
409
- this.commands.executeCommand(node.action.commandId, arg);
409
+ this.commands.executeCommand(node.command, arg);
410
410
  }} />;
411
411
  }
412
412
 
@@ -23,13 +23,15 @@ import { PluginPackageDebuggersContribution } from '../../common/plugin-protocol
23
23
  import { RPCProtocol } from '../../common/rpc-protocol';
24
24
  import { CommandRegistryImpl } from '../command-registry';
25
25
  import { ConnectionImpl } from '../../common/connection';
26
- import { Disposable, Breakpoint as BreakpointExt, SourceBreakpoint, FunctionBreakpoint, Location, Range } from '../types-impl';
26
+ import { DEBUG_SCHEME, SCHEME_PATTERN } from '@theia/debug/lib/common/debug-uri-utils';
27
+ import { Disposable, Breakpoint as BreakpointExt, SourceBreakpoint, FunctionBreakpoint, Location, Range, URI as URIImpl } from '../types-impl';
27
28
  import { PluginDebugAdapterSession } from './plugin-debug-adapter-session';
28
29
  import { PluginDebugAdapterTracker } from './plugin-debug-adapter-tracker';
29
30
  import uuid = require('uuid');
30
31
  import { DebugAdapter } from '@theia/debug/lib/common/debug-model';
31
32
  import { PluginDebugAdapterCreator } from './plugin-debug-adapter-creator';
32
33
  import { NodeDebugAdapterCreator } from '../node/debug/plugin-node-debug-adapter-creator';
34
+ import { DebugProtocol } from 'vscode-debugprotocol';
33
35
 
34
36
  interface ConfigurationProviderRecord {
35
37
  handle: number;
@@ -176,6 +178,27 @@ export class DebugExtImpl implements DebugExt {
176
178
  return this.proxy.$stopDebugging(session?.id);
177
179
  }
178
180
 
181
+ asDebugSourceUri(source: theia.DebugProtocolSource, session?: theia.DebugSession): theia.Uri {
182
+ return this.getDebugSourceUri(source, session?.id);
183
+ }
184
+
185
+ private getDebugSourceUri(raw: DebugProtocol.Source, sessionId?: string): theia.Uri {
186
+ if (raw.sourceReference && raw.sourceReference > 0) {
187
+ let query = 'ref=' + String(raw.sourceReference);
188
+ if (sessionId) {
189
+ query += `&session=${sessionId}`;
190
+ }
191
+ return URIImpl.from({ scheme: DEBUG_SCHEME, path: raw.path ?? '', query });
192
+ }
193
+ if (!raw.path) {
194
+ throw new Error('Unrecognized source type: ' + JSON.stringify(raw));
195
+ }
196
+ if (raw.path.match(SCHEME_PATTERN)) {
197
+ return URIImpl.parse(raw.path);
198
+ }
199
+ return URIImpl.file(raw.path);
200
+ }
201
+
179
202
  registerDebugAdapterDescriptorFactory(debugType: string, factory: theia.DebugAdapterDescriptorFactory): Disposable {
180
203
  if (this.descriptorFactories.has(debugType)) {
181
204
  throw new Error(`Descriptor factory for ${debugType} has been already registered`);
@@ -279,13 +302,13 @@ export class DebugExtImpl implements DebugExt {
279
302
  this.onDidChangeBreakpointsEmitter.fire({ added: a, removed: r, changed: c });
280
303
  }
281
304
 
282
- protected toBreakpointExt({ functionName, location, enabled, condition, hitCondition, logMessage }: Breakpoint): BreakpointExt | undefined {
305
+ protected toBreakpointExt({ functionName, location, enabled, condition, hitCondition, logMessage, id }: Breakpoint): BreakpointExt | undefined {
283
306
  if (location) {
284
307
  const range = new Range(location.range.startLineNumber, location.range.startColumn, location.range.endLineNumber, location.range.endColumn);
285
- return new SourceBreakpoint(new Location(URI.revive(location.uri), range), enabled, condition, hitCondition, logMessage);
308
+ return new SourceBreakpoint(new Location(URI.revive(location.uri), range), enabled, condition, hitCondition, logMessage, id);
286
309
  }
287
310
  if (functionName) {
288
- return new FunctionBreakpoint(functionName!, enabled, condition, hitCondition, logMessage);
311
+ return new FunctionBreakpoint(functionName!, enabled, condition, hitCondition, logMessage, id);
289
312
  }
290
313
  return undefined;
291
314
  }
@@ -305,7 +328,9 @@ export class DebugExtImpl implements DebugExt {
305
328
  return response.body;
306
329
  }
307
330
  return Promise.reject(new Error(response.message ?? 'custom request failed'));
308
- }
331
+ },
332
+ getDebugProtocolBreakpoint: async (breakpoint: Breakpoint) =>
333
+ this.proxy.$getDebugProtocolBreakpoint(sessionId, breakpoint.id)
309
334
  };
310
335
 
311
336
  const tracker = await this.createDebugAdapterTracker(theiaSession);
@@ -61,6 +61,10 @@ export class PluginDebugAdapterSession extends DebugAdapterSessionImpl {
61
61
  return this.theiaSession.customRequest(command, args);
62
62
  }
63
63
 
64
+ async getDebugProtocolBreakpoint(breakpoint: theia.Breakpoint): Promise<theia.DebugProtocolBreakpoint | undefined> {
65
+ return this.theiaSession.getDebugProtocolBreakpoint(breakpoint);
66
+ }
67
+
64
68
  protected override onDebugAdapterError(error: Error): void {
65
69
  if (this.tracker.onError) {
66
70
  this.tracker.onError(error);
@@ -52,6 +52,7 @@ export class SignatureHelpAdapter {
52
52
  if (!value) {
53
53
  return undefined;
54
54
  }
55
+ value.activeParameter = value.signatures[value.activeSignature].activeParameter ?? value.activeParameter;
55
56
  const id = this.idSequence++;
56
57
  this.cache.set(id, value);
57
58
  return Converter.SignatureHelp.from(id, value);
@@ -65,7 +66,8 @@ export class SignatureHelpAdapter {
65
66
  if (saved) {
66
67
  activeSignatureHelp = saved;
67
68
  activeSignatureHelp.activeSignature = revivedSignatureHelp.activeSignature;
68
- activeSignatureHelp.activeParameter = revivedSignatureHelp.activeParameter;
69
+ const { activeSignature } = revivedSignatureHelp;
70
+ activeSignatureHelp.activeParameter = revivedSignatureHelp.signatures[activeSignature].activeParameter ?? revivedSignatureHelp.activeParameter;
69
71
  } else {
70
72
  activeSignatureHelp = revivedSignatureHelp;
71
73
  }
@@ -0,0 +1,94 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2022 STMicroelectronics and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+ import { DebugSession } from '@theia/plugin';
17
+ import * as chai from 'chai';
18
+ import { ProxyIdentifier, RPCProtocol } from '../../../common/rpc-protocol';
19
+
20
+ import { DebugExtImpl } from '../../debug/debug-ext';
21
+
22
+ const expect = chai.expect;
23
+
24
+ describe('Debug API', () => {
25
+
26
+ describe('#asDebugSourceURI', () => {
27
+
28
+ const mockRPCProtocol: RPCProtocol = {
29
+ getProxy<T>(_proxyId: ProxyIdentifier<T>): T {
30
+ return {} as T;
31
+ },
32
+ set<T, R extends T>(_id: ProxyIdentifier<T>, instance: R): R {
33
+ return instance;
34
+ },
35
+ dispose(): void {
36
+ // Nothing
37
+ }
38
+ };
39
+
40
+ const debug = new DebugExtImpl(mockRPCProtocol);
41
+
42
+ it('should use sourceReference, path and sessionId', () => {
43
+ const source = {
44
+ sourceReference: 3,
45
+ path: 'test/path'
46
+ };
47
+ const session = { id: 'test-session' } as DebugSession;
48
+ const uri = debug.asDebugSourceUri(source, session);
49
+ expect(uri.toString(true)).to.be.equal('debug:test/path?ref=3&session=test-session');
50
+ });
51
+
52
+ it('should use sourceReference', () => {
53
+ const source = {
54
+ sourceReference: 5
55
+ };
56
+ const uri = debug.asDebugSourceUri(source);
57
+ expect(uri.toString(true)).to.be.equal('debug:?ref=5');
58
+ });
59
+
60
+ it('should use sourceReference and session', () => {
61
+ const source = {
62
+ sourceReference: 5
63
+ };
64
+ const session = { id: 'test-session' } as DebugSession;
65
+ const uri = debug.asDebugSourceUri(source, session);
66
+ expect(uri.toString(true)).to.be.equal('debug:?ref=5&session=test-session');
67
+ });
68
+
69
+ it('should use sourceReference and path', () => {
70
+ const source = {
71
+ sourceReference: 4,
72
+ path: 'test/path'
73
+ };
74
+ const uri = debug.asDebugSourceUri(source);
75
+ expect(uri.toString(true)).to.be.equal('debug:test/path?ref=4');
76
+ });
77
+
78
+ it('should use path', () => {
79
+ const source = {
80
+ path: 'scheme:/full/path'
81
+ };
82
+ const uri = debug.asDebugSourceUri(source);
83
+ expect(uri.toString(true)).to.be.equal('scheme:/full/path');
84
+ });
85
+
86
+ it('should use file path', () => {
87
+ const source = {
88
+ path: '/full/path'
89
+ };
90
+ const uri = debug.asDebugSourceUri(source);
91
+ expect(uri.toString(true)).to.be.equal('file:///full/path');
92
+ });
93
+ });
94
+ });
@@ -868,6 +868,9 @@ export function createAPIFactory(
868
868
  },
869
869
  removeBreakpoints(breakpoints: readonly theia.Breakpoint[]): void {
870
870
  debugExt.removeBreakpoints(breakpoints);
871
+ },
872
+ asDebugSourceUri(source: theia.DebugProtocolSource, session?: theia.DebugSession): theia.Uri {
873
+ return debugExt.asDebugSourceUri(source, session);
871
874
  }
872
875
  };
873
876
 
@@ -85,6 +85,7 @@ export class QuickOpenExtImpl implements QuickOpenExt {
85
85
  const instance = ++this._instances;
86
86
 
87
87
  const widgetPromise = this.proxy.$show(instance, {
88
+ title: options && options.title,
88
89
  canPickMany: options && options.canPickMany,
89
90
  placeHolder: options && options.placeHolder,
90
91
  matchOnDescription: options && options.matchOnDescription,