@theia/plugin-ext-vscode 1.34.3 → 1.34.4

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 (53) hide show
  1. package/LICENSE +641 -641
  2. package/README.md +32 -32
  3. package/lib/browser/plugin-vscode-commands-contribution.d.ts +79 -79
  4. package/lib/browser/plugin-vscode-commands-contribution.js +768 -768
  5. package/lib/browser/plugin-vscode-contribution.d.ts +5 -5
  6. package/lib/browser/plugin-vscode-contribution.js +53 -53
  7. package/lib/browser/plugin-vscode-frontend-module.d.ts +3 -3
  8. package/lib/browser/plugin-vscode-frontend-module.js +30 -30
  9. package/lib/common/plugin-vscode-environment.d.ts +7 -7
  10. package/lib/common/plugin-vscode-environment.js +47 -47
  11. package/lib/common/plugin-vscode-types.d.ts +2 -2
  12. package/lib/common/plugin-vscode-types.js +21 -21
  13. package/lib/common/plugin-vscode-uri.d.ts +16 -16
  14. package/lib/common/plugin-vscode-uri.js +51 -51
  15. package/lib/node/context/plugin-vscode-init-fe.d.ts +2 -2
  16. package/lib/node/context/plugin-vscode-init-fe.js +37 -37
  17. package/lib/node/local-vsix-file-plugin-deployer-resolver.d.ts +14 -14
  18. package/lib/node/local-vsix-file-plugin-deployer-resolver.js +77 -77
  19. package/lib/node/package.spec.js +25 -25
  20. package/lib/node/plugin-reader.d.ts +6 -6
  21. package/lib/node/plugin-reader.js +36 -36
  22. package/lib/node/plugin-vscode-backend-module.d.ts +3 -3
  23. package/lib/node/plugin-vscode-backend-module.js +43 -43
  24. package/lib/node/plugin-vscode-cli-contribution.d.ts +21 -21
  25. package/lib/node/plugin-vscode-cli-contribution.js +67 -67
  26. package/lib/node/plugin-vscode-deployer-participant.d.ts +6 -6
  27. package/lib/node/plugin-vscode-deployer-participant.js +43 -43
  28. package/lib/node/plugin-vscode-directory-handler.d.ts +21 -21
  29. package/lib/node/plugin-vscode-directory-handler.js +144 -144
  30. package/lib/node/plugin-vscode-file-handler.d.ts +11 -11
  31. package/lib/node/plugin-vscode-file-handler.js +82 -82
  32. package/lib/node/plugin-vscode-init.d.ts +2 -2
  33. package/lib/node/plugin-vscode-init.js +68 -68
  34. package/lib/node/scanner-vscode.d.ts +12 -12
  35. package/lib/node/scanner-vscode.js +111 -111
  36. package/package.json +15 -15
  37. package/src/browser/plugin-vscode-commands-contribution.ts +924 -924
  38. package/src/browser/plugin-vscode-contribution.ts +47 -47
  39. package/src/browser/plugin-vscode-frontend-module.ts +30 -30
  40. package/src/common/plugin-vscode-environment.ts +36 -36
  41. package/src/common/plugin-vscode-types.ts +20 -20
  42. package/src/common/plugin-vscode-uri.ts +47 -47
  43. package/src/node/context/plugin-vscode-init-fe.ts +43 -43
  44. package/src/node/local-vsix-file-plugin-deployer-resolver.ts +65 -65
  45. package/src/node/package.spec.ts +28 -28
  46. package/src/node/plugin-reader.ts +28 -28
  47. package/src/node/plugin-vscode-backend-module.ts +50 -50
  48. package/src/node/plugin-vscode-cli-contribution.ts +64 -64
  49. package/src/node/plugin-vscode-deployer-participant.ts +32 -32
  50. package/src/node/plugin-vscode-directory-handler.ts +141 -141
  51. package/src/node/plugin-vscode-file-handler.ts +72 -72
  52. package/src/node/plugin-vscode-init.ts +80 -80
  53. package/src/node/scanner-vscode.ts +108 -108
@@ -1,924 +1,924 @@
1
- // *****************************************************************************
2
- // Copyright (C) 2018 Red Hat, Inc. 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 { Command, CommandContribution, CommandRegistry, environment, isOSX, CancellationTokenSource } from '@theia/core';
18
- import {
19
- ApplicationShell,
20
- CommonCommands,
21
- NavigatableWidget,
22
- OpenerService, OpenHandler,
23
- QuickInputService,
24
- Saveable,
25
- TabBar,
26
- Title,
27
- Widget
28
- } from '@theia/core/lib/browser';
29
- import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
30
- import { ApplicationShellMouseTracker } from '@theia/core/lib/browser/shell/application-shell-mouse-tracker';
31
- import { CommandService } from '@theia/core/lib/common/command';
32
- import TheiaURI from '@theia/core/lib/common/uri';
33
- import { EditorManager, EditorCommands } from '@theia/editor/lib/browser';
34
- import {
35
- TextDocumentShowOptions,
36
- Location,
37
- CallHierarchyItem,
38
- CallHierarchyIncomingCall,
39
- CallHierarchyOutgoingCall,
40
- TypeHierarchyItem,
41
- Hover,
42
- TextEdit,
43
- FormattingOptions,
44
- DocumentHighlight
45
- } from '@theia/plugin-ext/lib/common/plugin-api-rpc-model';
46
- import { DocumentsMainImpl } from '@theia/plugin-ext/lib/main/browser/documents-main';
47
- import { isUriComponents, toDocumentSymbol, toPosition } from '@theia/plugin-ext/lib/plugin/type-converters';
48
- import { ViewColumn } from '@theia/plugin-ext/lib/plugin/types-impl';
49
- import { WorkspaceCommands } from '@theia/workspace/lib/browser';
50
- import { WorkspaceService, WorkspaceInput } from '@theia/workspace/lib/browser/workspace-service';
51
- import { DiffService } from '@theia/workspace/lib/browser/diff-service';
52
- import { inject, injectable, optional } from '@theia/core/shared/inversify';
53
- import { Position } from '@theia/plugin-ext/lib/common/plugin-api-rpc';
54
- import { URI } from '@theia/core/shared/vscode-uri';
55
- import { PluginServer } from '@theia/plugin-ext/lib/common/plugin-protocol';
56
- import { TerminalFrontendContribution } from '@theia/terminal/lib/browser/terminal-frontend-contribution';
57
- import { QuickOpenWorkspace } from '@theia/workspace/lib/browser/quick-open-workspace';
58
- import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
59
- import {
60
- FileNavigatorCommands,
61
- FILE_NAVIGATOR_TOGGLE_COMMAND_ID
62
- } from '@theia/navigator/lib/browser/navigator-contribution';
63
- import { FILE_NAVIGATOR_ID, FileNavigatorWidget } from '@theia/navigator/lib/browser';
64
- import { SelectableTreeNode } from '@theia/core/lib/browser/tree/tree-selection';
65
- import { UriComponents } from '@theia/plugin-ext/lib/common/uri-components';
66
- import { FileService } from '@theia/filesystem/lib/browser/file-service';
67
- import { CallHierarchyServiceProvider, CallHierarchyService } from '@theia/callhierarchy/lib/browser';
68
- import { TypeHierarchyServiceProvider, TypeHierarchyService } from '@theia/typehierarchy/lib/browser';
69
- import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
70
- import {
71
- fromCallHierarchyCalleeToModelCallHierarchyOutgoingCall,
72
- fromCallHierarchyCallerToModelCallHierarchyIncomingCall,
73
- fromItemHierarchyDefinition,
74
- toItemHierarchyDefinition
75
- } from '@theia/plugin-ext/lib/main/browser/hierarchy/hierarchy-types-converters';
76
- import { CustomEditorOpener } from '@theia/plugin-ext/lib/main/browser/custom-editors/custom-editor-opener';
77
- import { nls } from '@theia/core/lib/common/nls';
78
- import { WindowService } from '@theia/core/lib/browser/window/window-service';
79
- import * as monaco from '@theia/monaco-editor-core';
80
- import { VSCodeExtensionUri } from '../common/plugin-vscode-uri';
81
- import { CodeEditorWidgetUtil } from '@theia/plugin-ext/lib/main/browser/menus/vscode-theia-menu-mappings';
82
-
83
- export namespace VscodeCommands {
84
- export const OPEN: Command = {
85
- id: 'vscode.open'
86
- };
87
-
88
- export const OPEN_WITH: Command = {
89
- id: 'vscode.openWith'
90
- };
91
-
92
- export const OPEN_FOLDER: Command = {
93
- id: 'vscode.openFolder'
94
- };
95
-
96
- export const DIFF: Command = {
97
- id: 'vscode.diff'
98
- };
99
-
100
- export const INSTALL_FROM_VSIX: Command = {
101
- id: 'workbench.extensions.installExtension'
102
- };
103
- }
104
-
105
- // https://wicg.github.io/webusb/
106
-
107
- export interface UsbDeviceData {
108
- readonly deviceClass: number;
109
- readonly deviceProtocol: number;
110
- readonly deviceSubclass: number;
111
- readonly deviceVersionMajor: number;
112
- readonly deviceVersionMinor: number;
113
- readonly deviceVersionSubminor: number;
114
- readonly manufacturerName?: string;
115
- readonly productId: number;
116
- readonly productName?: string;
117
- readonly serialNumber?: string;
118
- readonly usbVersionMajor: number;
119
- readonly usbVersionMinor: number;
120
- readonly usbVersionSubminor: number;
121
- readonly vendorId: number;
122
- }
123
-
124
- // https://wicg.github.io/serial/
125
-
126
- export interface SerialPortData {
127
- readonly usbVendorId?: number | undefined;
128
- readonly usbProductId?: number | undefined;
129
- }
130
-
131
- // https://wicg.github.io/webhid/
132
-
133
- export interface HidDeviceData {
134
- readonly opened: boolean;
135
- readonly vendorId: number;
136
- readonly productId: number;
137
- readonly productName: string;
138
- readonly collections: [];
139
- }
140
-
141
- @injectable()
142
- export class PluginVscodeCommandsContribution implements CommandContribution {
143
- @inject(CommandService)
144
- protected readonly commandService: CommandService;
145
- @inject(ContextKeyService)
146
- protected readonly contextKeyService: ContextKeyService;
147
- @inject(EditorManager)
148
- protected readonly editorManager: EditorManager;
149
- @inject(ApplicationShell)
150
- protected readonly shell: ApplicationShell;
151
- @inject(DiffService)
152
- protected readonly diffService: DiffService;
153
- @inject(OpenerService)
154
- protected readonly openerService: OpenerService;
155
- @inject(ApplicationShellMouseTracker)
156
- protected readonly mouseTracker: ApplicationShellMouseTracker;
157
- @inject(QuickInputService) @optional()
158
- protected readonly quickInput: QuickInputService;
159
- @inject(WorkspaceService)
160
- protected readonly workspaceService: WorkspaceService;
161
- @inject(TerminalFrontendContribution)
162
- protected readonly terminalContribution: TerminalFrontendContribution;
163
- @inject(QuickOpenWorkspace)
164
- protected readonly quickOpenWorkspace: QuickOpenWorkspace;
165
- @inject(TerminalService)
166
- protected readonly terminalService: TerminalService;
167
- @inject(CodeEditorWidgetUtil)
168
- protected readonly codeEditorWidgetUtil: CodeEditorWidgetUtil;
169
- @inject(PluginServer)
170
- protected readonly pluginServer: PluginServer;
171
- @inject(FileService)
172
- protected readonly fileService: FileService;
173
- @inject(CallHierarchyServiceProvider)
174
- protected readonly callHierarchyProvider: CallHierarchyServiceProvider;
175
- @inject(TypeHierarchyServiceProvider)
176
- protected readonly typeHierarchyProvider: TypeHierarchyServiceProvider;
177
- @inject(MonacoTextModelService)
178
- protected readonly textModelService: MonacoTextModelService;
179
- @inject(WindowService)
180
- protected readonly windowService: WindowService;
181
-
182
- private async openWith(commandId: string, resource: URI, columnOrOptions?: ViewColumn | TextDocumentShowOptions, openerId?: string): Promise<boolean> {
183
- if (!resource) {
184
- throw new Error(`${commandId} command requires at least URI argument.`);
185
- }
186
- if (!URI.isUri(resource)) {
187
- throw new Error(`Invalid argument for ${commandId} command with URI argument. Found ${resource}`);
188
- }
189
-
190
- let options: TextDocumentShowOptions | undefined;
191
- if (typeof columnOrOptions === 'number') {
192
- options = {
193
- viewColumn: columnOrOptions
194
- };
195
- } else if (columnOrOptions) {
196
- options = {
197
- ...columnOrOptions
198
- };
199
- }
200
-
201
- const uri = new TheiaURI(resource);
202
- const editorOptions = DocumentsMainImpl.toEditorOpenerOptions(this.shell, options);
203
-
204
- let openHandler: OpenHandler | undefined;
205
- if (typeof openerId === 'string') {
206
- const lowerViewType = openerId.toLowerCase();
207
- const openers = await this.openerService.getOpeners();
208
- for (const opener of openers) {
209
- const idLowerCase = opener.id.toLowerCase();
210
- if (lowerViewType === idLowerCase) {
211
- openHandler = opener;
212
- break;
213
- }
214
- }
215
- } else {
216
- openHandler = await this.openerService.getOpener(uri, editorOptions);
217
- }
218
-
219
- if (openHandler) {
220
- await openHandler.open(uri, editorOptions);
221
- return true;
222
- }
223
-
224
- return false;
225
- }
226
-
227
- registerCommands(commands: CommandRegistry): void {
228
- commands.registerCommand(VscodeCommands.OPEN, {
229
- isVisible: () => false,
230
- execute: async (resource: URI, columnOrOptions?: ViewColumn | TextDocumentShowOptions) => {
231
- const result = await this.openWith(VscodeCommands.OPEN.id, resource, columnOrOptions);
232
- if (!result) {
233
- throw new Error(`Could not find an editor for ${resource}`);
234
- }
235
- }
236
- });
237
-
238
- commands.registerCommand(VscodeCommands.OPEN_WITH, {
239
- isVisible: () => false,
240
- execute: async (resource: URI, viewType: string, columnOrOptions?: ViewColumn | TextDocumentShowOptions) => {
241
- if (!viewType) {
242
- throw new Error(`Running the contributed command: ${VscodeCommands.OPEN_WITH} failed.`);
243
- }
244
-
245
- if (viewType.toLowerCase() === 'default') {
246
- return commands.executeCommand(VscodeCommands.OPEN.id, resource, columnOrOptions);
247
- }
248
-
249
- let result = await this.openWith(VscodeCommands.OPEN_WITH.id, resource, columnOrOptions, viewType);
250
- if (!result) {
251
- result = await this.openWith(VscodeCommands.OPEN_WITH.id, resource, columnOrOptions, CustomEditorOpener.toCustomEditorId(viewType));
252
- }
253
-
254
- if (!result) {
255
- throw new Error(`Could not find an editor for '${viewType}'`);
256
- }
257
- }
258
- });
259
-
260
- interface IOpenFolderAPICommandOptions {
261
- forceNewWindow?: boolean;
262
- forceReuseWindow?: boolean;
263
- noRecentEntry?: boolean;
264
- }
265
-
266
- commands.registerCommand(VscodeCommands.OPEN_FOLDER, {
267
- isVisible: () => false,
268
- execute: async (resource?: URI, arg: boolean | IOpenFolderAPICommandOptions = {}) => {
269
- if (!resource) {
270
- return commands.executeCommand(WorkspaceCommands.OPEN_WORKSPACE.id);
271
- }
272
- if (!URI.isUri(resource)) {
273
- throw new Error(`Invalid argument for ${VscodeCommands.OPEN_FOLDER.id} command with URI argument. Found ${resource}`);
274
- }
275
- let options: WorkspaceInput | undefined;
276
- if (typeof arg === 'boolean') {
277
- options = { preserveWindow: !arg };
278
- } else {
279
- options = { preserveWindow: !arg.forceNewWindow };
280
- }
281
- this.workspaceService.open(new TheiaURI(resource), options);
282
- }
283
- });
284
-
285
- commands.registerCommand(VscodeCommands.DIFF, {
286
- isVisible: () => false,
287
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
288
- execute: async (left: URI, right: URI, label?: string, options?: TextDocumentShowOptions) => {
289
- if (!left || !right) {
290
- throw new Error(`${VscodeCommands.DIFF} command requires at least two URI arguments. Found left=${left}, right=${right} as arguments`);
291
- }
292
- if (!URI.isUri(left)) {
293
- throw new Error(`Invalid argument for ${VscodeCommands.DIFF.id} command with left argument. Expecting URI left type but found ${left}`);
294
- }
295
- if (!URI.isUri(right)) {
296
- throw new Error(`Invalid argument for ${VscodeCommands.DIFF.id} command with right argument. Expecting URI right type but found ${right}`);
297
- }
298
-
299
- const leftURI = new TheiaURI(left);
300
- const editorOptions = DocumentsMainImpl.toEditorOpenerOptions(this.shell, options);
301
- await this.diffService.openDiffEditor(leftURI, new TheiaURI(right), label, editorOptions);
302
- }
303
- });
304
-
305
- // https://code.visualstudio.com/docs/getstarted/keybindings#_navigation
306
- /*
307
- * internally, in VS Code, any widget opened in the main area is represented as an editor
308
- * operations below apply to them, but not to side-bar widgets, like the explorer
309
- *
310
- * in Theia, there are not such difference and any widget can be put in any area
311
- * because of it we filter out editors from views based on `NavigatableWidget.is`
312
- * and apply actions only to them
313
- */
314
- if (!environment.electron.is() || isOSX) {
315
- commands.registerCommand({ id: 'workbench.action.files.openFileFolder' }, {
316
- execute: () => commands.executeCommand(WorkspaceCommands.OPEN.id)
317
- });
318
- }
319
-
320
- commands.registerCommand({ id: 'workbench.action.files.openFile' }, {
321
- execute: () => commands.executeCommand(WorkspaceCommands.OPEN_FILE.id)
322
- });
323
- commands.registerCommand({ id: 'workbench.action.files.openFolder' }, {
324
- execute: () => commands.executeCommand(WorkspaceCommands.OPEN_FOLDER.id)
325
- });
326
- commands.registerCommand({ id: 'workbench.action.addRootFolder' }, {
327
- execute: () => commands.executeCommand(WorkspaceCommands.ADD_FOLDER.id)
328
- });
329
- commands.registerCommand({ id: 'workbench.action.saveWorkspaceAs' }, {
330
- execute: () => commands.executeCommand(WorkspaceCommands.SAVE_WORKSPACE_AS.id)
331
- });
332
- commands.registerCommand({ id: 'workbench.action.gotoLine' }, {
333
- execute: () => commands.executeCommand(EditorCommands.GOTO_LINE_COLUMN.id)
334
- });
335
- commands.registerCommand({ id: 'workbench.action.quickOpen' }, {
336
- execute: (prefix?: unknown) => this.quickInput.open(typeof prefix === 'string' ? prefix : '')
337
- });
338
- commands.registerCommand({ id: 'workbench.action.openSettings' }, {
339
- execute: (query?: string) => commands.executeCommand(CommonCommands.OPEN_PREFERENCES.id, query)
340
- });
341
- commands.registerCommand({ id: 'workbench.action.openWorkspaceConfigFile' }, {
342
- execute: () => commands.executeCommand(WorkspaceCommands.OPEN_WORKSPACE_FILE.id)
343
- });
344
- commands.registerCommand({ id: 'workbench.files.action.refreshFilesExplorer' }, {
345
- execute: () => commands.executeCommand(FileNavigatorCommands.REFRESH_NAVIGATOR.id)
346
- });
347
- commands.registerCommand({ id: VscodeCommands.INSTALL_FROM_VSIX.id }, {
348
- execute: async (vsixUriOrExtensionId: TheiaURI | UriComponents | string) => {
349
- if (typeof vsixUriOrExtensionId === 'string') {
350
- await this.pluginServer.deploy(VSCodeExtensionUri.toVsxExtensionUriString(vsixUriOrExtensionId));
351
- } else {
352
- const uriPath = isUriComponents(vsixUriOrExtensionId) ? URI.revive(vsixUriOrExtensionId).fsPath : await this.fileService.fsPath(vsixUriOrExtensionId);
353
- await this.pluginServer.deploy(`local-file:${uriPath}`);
354
- }
355
- }
356
- });
357
- commands.registerCommand({ id: 'workbench.action.files.save', }, {
358
- execute: (uri?: monaco.Uri) => {
359
- if (uri) {
360
- const uriString = uri.toString();
361
- const widget = this.shell.widgets.find(w => {
362
- const resourceUri = Saveable.is(w) && NavigatableWidget.is(w) && w.getResourceUri();
363
- return (resourceUri && resourceUri.toString()) === uriString;
364
- });
365
- if (Saveable.is(widget)) {
366
- Saveable.save(widget);
367
- }
368
- } else {
369
- this.shell.save();
370
- }
371
- }
372
- });
373
- commands.registerCommand({ id: 'workbench.action.files.saveAll', }, {
374
- execute: () => this.shell.saveAll()
375
- });
376
- commands.registerCommand({ id: 'workbench.action.closeActiveEditor' }, {
377
- execute: () => commands.executeCommand(CommonCommands.CLOSE_MAIN_TAB.id)
378
- });
379
- commands.registerCommand({ id: 'workbench.action.closeOtherEditors' }, {
380
- execute: async (uri?: monaco.Uri) => {
381
- let editor = this.editorManager.currentEditor || this.shell.currentWidget;
382
- if (uri) {
383
- const uriString = uri.toString();
384
- editor = this.editorManager.all.find(e => {
385
- const resourceUri = e.getResourceUri();
386
- return (resourceUri && resourceUri.toString()) === uriString;
387
- });
388
- }
389
- const toClose = this.shell.widgets.filter(widget => widget !== editor && this.codeEditorWidgetUtil.is(widget));
390
- await this.shell.closeMany(toClose);
391
- }
392
- });
393
-
394
- const performActionOnGroup = (
395
- cb: (
396
- tabBarOrArea: TabBar<Widget> | ApplicationShell.Area,
397
- filter?: ((title: Title<Widget>, index: number) => boolean) | undefined
398
- ) => void,
399
- uri?: monaco.Uri
400
- ): void => {
401
- let editor = this.editorManager.currentEditor || this.shell.currentWidget;
402
- if (uri) {
403
- const uriString = uri.toString();
404
- editor = this.editorManager.all.find(e => {
405
- const resourceUri = e.getResourceUri();
406
- return (resourceUri && resourceUri.toString()) === uriString;
407
- });
408
- }
409
- if (editor) {
410
- const tabBar = this.shell.getTabBarFor(editor);
411
- if (tabBar) {
412
- cb(tabBar, ({ owner }) => this.codeEditorWidgetUtil.is(owner));
413
- }
414
- }
415
- };
416
-
417
- commands.registerCommand({
418
- id: 'workbench.action.closeEditorsInGroup',
419
- label: nls.localizeByDefault('Close All Editors in Group')
420
- }, {
421
- execute: (uri?: monaco.Uri) => performActionOnGroup(this.shell.closeTabs, uri)
422
- });
423
- commands.registerCommand({
424
- id: 'workbench.files.saveAllInGroup',
425
- label: nls.localizeByDefault('Save All in Group')
426
- }, {
427
- execute: (uri?: monaco.Uri) => performActionOnGroup(this.shell.saveTabs, uri)
428
- });
429
- commands.registerCommand({ id: 'workbench.action.closeEditorsInOtherGroups' }, {
430
- execute: () => {
431
- const editor = this.editorManager.currentEditor || this.shell.currentWidget;
432
- if (editor) {
433
- const editorTabBar = this.shell.getTabBarFor(editor);
434
- for (const tabBar of this.shell.allTabBars) {
435
- if (tabBar !== editorTabBar) {
436
- this.shell.closeTabs(tabBar,
437
- ({ owner }) => this.codeEditorWidgetUtil.is(owner)
438
- );
439
- }
440
- }
441
- }
442
- }
443
- });
444
- commands.registerCommand({ id: 'workbench.action.closeEditorsToTheLeft' }, {
445
- execute: () => {
446
- const editor = this.editorManager.currentEditor || this.shell.currentWidget;
447
- if (editor) {
448
- const tabBar = this.shell.getTabBarFor(editor);
449
- if (tabBar) {
450
- let left = true;
451
- this.shell.closeTabs(tabBar,
452
- ({ owner }) => {
453
- if (owner === editor) {
454
- left = false;
455
- return false;
456
- }
457
- return left && this.codeEditorWidgetUtil.is(owner);
458
- }
459
- );
460
- }
461
- }
462
- }
463
- });
464
- commands.registerCommand({ id: 'workbench.action.closeEditorsToTheRight' }, {
465
- execute: () => {
466
- const editor = this.editorManager.currentEditor || this.shell.currentWidget;
467
- if (editor) {
468
- const tabBar = this.shell.getTabBarFor(editor);
469
- if (tabBar) {
470
- let left = true;
471
- this.shell.closeTabs(tabBar,
472
- ({ owner }) => {
473
- if (owner === editor) {
474
- left = false;
475
- return false;
476
- }
477
- return !left && this.codeEditorWidgetUtil.is(owner);
478
- }
479
- );
480
- }
481
- }
482
- }
483
- });
484
- commands.registerCommand({ id: 'workbench.action.closeAllEditors' }, {
485
- execute: async () => {
486
- const toClose = this.shell.widgets.filter(widget => this.codeEditorWidgetUtil.is(widget));
487
- await this.shell.closeMany(toClose);
488
- }
489
- });
490
- commands.registerCommand({ id: 'workbench.action.nextEditor' }, {
491
- execute: () => this.shell.activateNextTab()
492
- });
493
- commands.registerCommand({ id: 'workbench.action.previousEditor' }, {
494
- execute: () => this.shell.activatePreviousTab()
495
- });
496
- commands.registerCommand({ id: 'workbench.action.navigateBack' }, {
497
- execute: () => commands.executeCommand(EditorCommands.GO_BACK.id)
498
- });
499
- commands.registerCommand({ id: 'workbench.action.navigateForward' }, {
500
- execute: () => commands.executeCommand(EditorCommands.GO_FORWARD.id)
501
- });
502
- commands.registerCommand({ id: 'workbench.action.navigateToLastEditLocation' }, {
503
- execute: () => commands.executeCommand(EditorCommands.GO_LAST_EDIT.id)
504
- });
505
-
506
- commands.registerCommand({ id: 'openInTerminal' }, {
507
- execute: (resource: URI) => this.terminalContribution.openInTerminal(new TheiaURI(resource.toString()))
508
- });
509
-
510
- commands.registerCommand({ id: 'workbench.action.reloadWindow' }, {
511
- execute: () => {
512
- this.windowService.reload();
513
- }
514
- });
515
-
516
- /**
517
- * TODO:
518
- * Open Next: workbench.action.openNextRecentlyUsedEditorInGroup
519
- * Open Previous: workbench.action.openPreviousRecentlyUsedEditorInGroup
520
- * Copy Path of Active File: workbench.action.files.copyPathOfActiveFile
521
- * Reveal Active File in Windows: workbench.action.files.revealActiveFileInWindows
522
- * Show Opened File in New Window: workbench.action.files.showOpenedFileInNewWindow
523
- * Compare Opened File With: workbench.files.action.compareFileWith
524
- */
525
-
526
- // Register built-in language service commands
527
- // see https://code.visualstudio.com/api/references/commands
528
- /* eslint-disable @typescript-eslint/no-explicit-any */
529
-
530
- // TODO register other `vscode.execute...` commands.
531
- // see https://github.com/microsoft/vscode/blob/master/src/vs/workbench/api/common/extHostApiCommands.ts
532
- commands.registerCommand(
533
- {
534
- id: 'vscode.executeDefinitionProvider'
535
- },
536
- {
537
- execute: ((resource: URI, position: Position) =>
538
- commands.executeCommand<Location[]>('_executeDefinitionProvider', monaco.Uri.from(resource), position))
539
- }
540
- );
541
- commands.registerCommand(
542
- {
543
- id: 'vscode.executeDeclarationProvider'
544
- },
545
- {
546
- execute: ((resource: URI, position: Position) =>
547
- commands.executeCommand<Location[]>('_executeDeclarationProvider', monaco.Uri.from(resource), position))
548
- }
549
- );
550
- commands.registerCommand(
551
- {
552
- id: 'vscode.executeTypeDefinitionProvider'
553
- },
554
- {
555
- execute: ((resource: URI, position: Position) =>
556
- commands.executeCommand<Location[]>('_executeTypeDefinitionProvider', monaco.Uri.from(resource), position))
557
- }
558
- );
559
- commands.registerCommand(
560
- {
561
- id: 'vscode.executeImplementationProvider'
562
- },
563
- {
564
- execute: ((resource: URI, position: Position) =>
565
- commands.executeCommand<Location[]>('_executeImplementationProvider', monaco.Uri.from(resource), position))
566
- }
567
- );
568
- commands.registerCommand(
569
- {
570
- id: 'vscode.executeHoverProvider'
571
- },
572
- {
573
- execute: ((resource: URI, position: Position) =>
574
- commands.executeCommand<Hover[]>('_executeHoverProvider', monaco.Uri.from(resource), position))
575
- }
576
- );
577
- commands.registerCommand(
578
- {
579
- id: 'vscode.executeDocumentHighlights'
580
- },
581
- {
582
- execute: ((resource: URI, position: Position) =>
583
- commands.executeCommand<DocumentHighlight[]>('_executeDocumentHighlights', monaco.Uri.from(resource), position))
584
- }
585
- );
586
- commands.registerCommand(
587
- {
588
- id: 'vscode.executeReferenceProvider'
589
- },
590
- {
591
- execute: ((resource: URI, position: Position) => commands.executeCommand<Location[]>('_executeReferenceProvider', monaco.Uri.from(resource), position))
592
- }
593
- );
594
- commands.registerCommand(
595
- {
596
- id: 'vscode.executeDocumentSymbolProvider'
597
- },
598
- {
599
- execute: (resource: URI) => commands.executeCommand('_executeDocumentSymbolProvider',
600
- monaco.Uri.parse(resource.toString())
601
- ).then((value: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
602
- if (!Array.isArray(value) || value === undefined) {
603
- return undefined;
604
- }
605
- return value.map(loc => toDocumentSymbol(loc));
606
- })
607
- }
608
- );
609
- commands.registerCommand(
610
- {
611
- id: 'vscode.executeFormatDocumentProvider'
612
- },
613
- {
614
- execute: ((resource: URI, options: FormattingOptions) =>
615
- commands.executeCommand<TextEdit[]>('_executeFormatDocumentProvider', monaco.Uri.from(resource), options))
616
- }
617
- );
618
- commands.registerCommand(
619
- {
620
- id: 'vscode.executeFormatRangeProvider'
621
- },
622
- {
623
- execute: ((resource: URI, range: Range, options: FormattingOptions) =>
624
- commands.executeCommand<TextEdit[]>('_executeFormatRangeProvider', monaco.Uri.from(resource), range, options))
625
- }
626
- );
627
- commands.registerCommand(
628
- {
629
- id: 'vscode.executeFormatOnTypeProvider'
630
- },
631
- {
632
- execute: ((resource: URI, position: Position, ch: string, options: FormattingOptions) =>
633
- commands.executeCommand<TextEdit[]>('_executeFormatOnTypeProvider', monaco.Uri.from(resource), position, ch, options))
634
- }
635
- );
636
- commands.registerCommand(
637
- {
638
- id: 'vscode.prepareCallHierarchy'
639
- },
640
- {
641
- execute: async (resource: URI, position: Position): Promise<CallHierarchyItem[]> => {
642
- const provider = await this.getCallHierarchyServiceForUri(resource);
643
- const definition = await provider?.getRootDefinition(
644
- resource.path,
645
- toPosition(position),
646
- new CancellationTokenSource().token
647
- );
648
- if (definition) {
649
- return definition.items.map(item => fromItemHierarchyDefinition(item));
650
- };
651
- return [];
652
- }
653
- }
654
- );
655
- commands.registerCommand(
656
- {
657
- id: 'vscode.provideIncomingCalls'
658
- },
659
- {
660
- execute: async (item: CallHierarchyItem): Promise<CallHierarchyIncomingCall[]> => {
661
- const resource = URI.from(item.uri);
662
- const provider = await this.getCallHierarchyServiceForUri(resource);
663
- const incomingCalls = await provider?.getCallers(
664
- toItemHierarchyDefinition(item),
665
- new CancellationTokenSource().token,
666
- );
667
- if (incomingCalls) {
668
- return incomingCalls.map(fromCallHierarchyCallerToModelCallHierarchyIncomingCall);
669
- }
670
- return [];
671
- },
672
- },
673
- );
674
- commands.registerCommand(
675
- {
676
- id: 'vscode.provideOutgoingCalls'
677
- },
678
- {
679
- execute: async (item: CallHierarchyItem): Promise<CallHierarchyOutgoingCall[]> => {
680
- const resource = URI.from(item.uri);
681
- const provider = await this.getCallHierarchyServiceForUri(resource);
682
- const outgoingCalls = await provider?.getCallees?.(
683
- toItemHierarchyDefinition(item),
684
- new CancellationTokenSource().token,
685
- );
686
- if (outgoingCalls) {
687
- return outgoingCalls.map(fromCallHierarchyCalleeToModelCallHierarchyOutgoingCall);
688
- }
689
- return [];
690
- }
691
- }
692
- );
693
- commands.registerCommand(
694
- {
695
- id: 'vscode.prepareTypeHierarchy'
696
- },
697
- {
698
- execute: async (resource: URI, position: Position): Promise<TypeHierarchyItem[]> => {
699
- const provider = await this.getTypeHierarchyServiceForUri(resource);
700
- const session = await provider?.prepareSession(
701
- resource.path,
702
- toPosition(position),
703
- new CancellationTokenSource().token
704
- );
705
- return session ? session.items.map(item => fromItemHierarchyDefinition(item)) : [];
706
- }
707
- }
708
- );
709
- commands.registerCommand(
710
- {
711
- id: 'vscode.provideSupertypes'
712
- },
713
- {
714
- execute: async (item: TypeHierarchyItem): Promise<TypeHierarchyItem[]> => {
715
- if (!item._sessionId || !item._itemId) {
716
- return [];
717
- }
718
- const resource = URI.from(item.uri);
719
- const provider = await this.getTypeHierarchyServiceForUri(resource);
720
- const items = await provider?.provideSuperTypes(
721
- item._sessionId,
722
- item._itemId,
723
- new CancellationTokenSource().token
724
- );
725
- return (items ? items : []).map(typeItem => fromItemHierarchyDefinition(typeItem));
726
- }
727
- }
728
- );
729
- commands.registerCommand(
730
- {
731
- id: 'vscode.provideSubtypes'
732
- },
733
- {
734
- execute: async (item: TypeHierarchyItem): Promise<TypeHierarchyItem[]> => {
735
- if (!item._sessionId || !item._itemId) {
736
- return [];
737
- }
738
- const resource = URI.from(item.uri);
739
- const provider = await this.getTypeHierarchyServiceForUri(resource);
740
- const items = await provider?.provideSubTypes(
741
- item._sessionId, item._itemId,
742
- new CancellationTokenSource().token
743
- );
744
- return (items ? items : []).map(typeItem => fromItemHierarchyDefinition(typeItem));
745
-
746
- }
747
- }
748
- );
749
-
750
- commands.registerCommand({
751
- id: 'workbench.action.openRecent'
752
- }, {
753
- execute: () => this.quickOpenWorkspace.select()
754
- });
755
- commands.registerCommand({
756
- id: 'explorer.newFolder'
757
- }, {
758
- execute: () => commands.executeCommand(WorkspaceCommands.NEW_FOLDER.id)
759
- });
760
- commands.registerCommand({
761
- id: 'workbench.action.terminal.sendSequence'
762
- }, {
763
- execute: (args?: { text?: string }) => {
764
- if (args === undefined || args.text === undefined) {
765
- return;
766
- }
767
-
768
- const currentTerminal = this.terminalService.currentTerminal;
769
-
770
- if (currentTerminal === undefined) {
771
- return;
772
- }
773
-
774
- currentTerminal.sendText(args.text);
775
- }
776
- });
777
- commands.registerCommand({
778
- id: 'workbench.action.terminal.kill'
779
- }, {
780
- execute: () => {
781
- const currentTerminal = this.terminalService.currentTerminal;
782
-
783
- if (currentTerminal === undefined) {
784
- return;
785
- }
786
-
787
- currentTerminal.dispose();
788
- }
789
- });
790
- commands.registerCommand({
791
- id: 'workbench.view.explorer'
792
- }, {
793
- execute: () => commands.executeCommand(FileNavigatorCommands.FOCUS.id)
794
- });
795
- commands.registerCommand({
796
- id: 'copyFilePath'
797
- }, {
798
- execute: () => commands.executeCommand(CommonCommands.COPY_PATH.id)
799
- });
800
- commands.registerCommand({
801
- id: 'copyRelativeFilePath'
802
- }, {
803
- execute: () => commands.executeCommand(WorkspaceCommands.COPY_RELATIVE_FILE_PATH.id)
804
- });
805
- commands.registerCommand({
806
- id: 'revealInExplorer'
807
- }, {
808
- execute: async (resource: URI | object) => {
809
- if (!URI.isUri(resource)) {
810
- return;
811
- }
812
- let navigator = await this.shell.revealWidget(FILE_NAVIGATOR_ID);
813
- if (!navigator) {
814
- await this.commandService.executeCommand(FILE_NAVIGATOR_TOGGLE_COMMAND_ID);
815
- navigator = await this.shell.revealWidget(FILE_NAVIGATOR_ID);
816
- }
817
- if (navigator instanceof FileNavigatorWidget) {
818
- const model = navigator.model;
819
- const node = await model.revealFile(new TheiaURI(resource));
820
- if (SelectableTreeNode.is(node)) {
821
- model.selectNode(node);
822
- }
823
- }
824
- }
825
- });
826
-
827
- commands.registerCommand({
828
- id: 'workbench.experimental.requestUsbDevice'
829
- }, {
830
- execute: async (options?: { filters?: unknown[] }): Promise<UsbDeviceData | undefined> => {
831
- const usb = (navigator as any).usb;
832
- if (!usb) {
833
- return undefined;
834
- }
835
-
836
- const device = await usb.requestDevice({ filters: options?.filters ?? [] });
837
- if (!device) {
838
- return undefined;
839
- }
840
-
841
- return {
842
- deviceClass: device.deviceClass,
843
- deviceProtocol: device.deviceProtocol,
844
- deviceSubclass: device.deviceSubclass,
845
- deviceVersionMajor: device.deviceVersionMajor,
846
- deviceVersionMinor: device.deviceVersionMinor,
847
- deviceVersionSubminor: device.deviceVersionSubminor,
848
- manufacturerName: device.manufacturerName,
849
- productId: device.productId,
850
- productName: device.productName,
851
- serialNumber: device.serialNumber,
852
- usbVersionMajor: device.usbVersionMajor,
853
- usbVersionMinor: device.usbVersionMinor,
854
- usbVersionSubminor: device.usbVersionSubminor,
855
- vendorId: device.vendorId,
856
- };
857
- }
858
- });
859
-
860
- commands.registerCommand({
861
- id: 'workbench.experimental.requestSerialPort'
862
- }, {
863
- execute: async (options?: { filters?: unknown[] }): Promise<SerialPortData | undefined> => {
864
- const serial = (navigator as any).serial;
865
- if (!serial) {
866
- return undefined;
867
- }
868
-
869
- const port = await serial.requestPort({ filters: options?.filters ?? [] });
870
- if (!port) {
871
- return undefined;
872
- }
873
-
874
- const info = port.getInfo();
875
- return {
876
- usbVendorId: info.usbVendorId,
877
- usbProductId: info.usbProductId
878
- };
879
- }
880
- });
881
-
882
- commands.registerCommand({
883
- id: 'workbench.experimental.requestHidDevice'
884
- }, {
885
- execute: async (options?: { filters?: unknown[] }): Promise<HidDeviceData | undefined> => {
886
- const hid = (navigator as any).hid;
887
- if (!hid) {
888
- return undefined;
889
- }
890
-
891
- const devices = await hid.requestDevice({ filters: options?.filters ?? [] });
892
- if (!devices.length) {
893
- return undefined;
894
- }
895
-
896
- const device = devices[0];
897
- return {
898
- opened: device.opened,
899
- vendorId: device.vendorId,
900
- productId: device.productId,
901
- productName: device.productName,
902
- collections: device.collections
903
- };
904
- }
905
- });
906
- }
907
-
908
- private async resolveLanguageId(resource: URI): Promise<string> {
909
- const reference = await this.textModelService.createModelReference(resource);
910
- const languageId = reference.object.languageId;
911
- reference.dispose();
912
- return languageId;
913
- }
914
-
915
- protected async getCallHierarchyServiceForUri(resource: URI): Promise<CallHierarchyService | undefined> {
916
- const languageId = await this.resolveLanguageId(resource);
917
- return this.callHierarchyProvider.get(languageId, new TheiaURI(resource));
918
- }
919
-
920
- protected async getTypeHierarchyServiceForUri(resource: URI): Promise<TypeHierarchyService | undefined> {
921
- const languageId = await this.resolveLanguageId(resource);
922
- return this.typeHierarchyProvider.get(languageId, new TheiaURI(resource));
923
- }
924
- }
1
+ // *****************************************************************************
2
+ // Copyright (C) 2018 Red Hat, Inc. 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 { Command, CommandContribution, CommandRegistry, environment, isOSX, CancellationTokenSource } from '@theia/core';
18
+ import {
19
+ ApplicationShell,
20
+ CommonCommands,
21
+ NavigatableWidget,
22
+ OpenerService, OpenHandler,
23
+ QuickInputService,
24
+ Saveable,
25
+ TabBar,
26
+ Title,
27
+ Widget
28
+ } from '@theia/core/lib/browser';
29
+ import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
30
+ import { ApplicationShellMouseTracker } from '@theia/core/lib/browser/shell/application-shell-mouse-tracker';
31
+ import { CommandService } from '@theia/core/lib/common/command';
32
+ import TheiaURI from '@theia/core/lib/common/uri';
33
+ import { EditorManager, EditorCommands } from '@theia/editor/lib/browser';
34
+ import {
35
+ TextDocumentShowOptions,
36
+ Location,
37
+ CallHierarchyItem,
38
+ CallHierarchyIncomingCall,
39
+ CallHierarchyOutgoingCall,
40
+ TypeHierarchyItem,
41
+ Hover,
42
+ TextEdit,
43
+ FormattingOptions,
44
+ DocumentHighlight
45
+ } from '@theia/plugin-ext/lib/common/plugin-api-rpc-model';
46
+ import { DocumentsMainImpl } from '@theia/plugin-ext/lib/main/browser/documents-main';
47
+ import { isUriComponents, toDocumentSymbol, toPosition } from '@theia/plugin-ext/lib/plugin/type-converters';
48
+ import { ViewColumn } from '@theia/plugin-ext/lib/plugin/types-impl';
49
+ import { WorkspaceCommands } from '@theia/workspace/lib/browser';
50
+ import { WorkspaceService, WorkspaceInput } from '@theia/workspace/lib/browser/workspace-service';
51
+ import { DiffService } from '@theia/workspace/lib/browser/diff-service';
52
+ import { inject, injectable, optional } from '@theia/core/shared/inversify';
53
+ import { Position } from '@theia/plugin-ext/lib/common/plugin-api-rpc';
54
+ import { URI } from '@theia/core/shared/vscode-uri';
55
+ import { PluginServer } from '@theia/plugin-ext/lib/common/plugin-protocol';
56
+ import { TerminalFrontendContribution } from '@theia/terminal/lib/browser/terminal-frontend-contribution';
57
+ import { QuickOpenWorkspace } from '@theia/workspace/lib/browser/quick-open-workspace';
58
+ import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
59
+ import {
60
+ FileNavigatorCommands,
61
+ FILE_NAVIGATOR_TOGGLE_COMMAND_ID
62
+ } from '@theia/navigator/lib/browser/navigator-contribution';
63
+ import { FILE_NAVIGATOR_ID, FileNavigatorWidget } from '@theia/navigator/lib/browser';
64
+ import { SelectableTreeNode } from '@theia/core/lib/browser/tree/tree-selection';
65
+ import { UriComponents } from '@theia/plugin-ext/lib/common/uri-components';
66
+ import { FileService } from '@theia/filesystem/lib/browser/file-service';
67
+ import { CallHierarchyServiceProvider, CallHierarchyService } from '@theia/callhierarchy/lib/browser';
68
+ import { TypeHierarchyServiceProvider, TypeHierarchyService } from '@theia/typehierarchy/lib/browser';
69
+ import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
70
+ import {
71
+ fromCallHierarchyCalleeToModelCallHierarchyOutgoingCall,
72
+ fromCallHierarchyCallerToModelCallHierarchyIncomingCall,
73
+ fromItemHierarchyDefinition,
74
+ toItemHierarchyDefinition
75
+ } from '@theia/plugin-ext/lib/main/browser/hierarchy/hierarchy-types-converters';
76
+ import { CustomEditorOpener } from '@theia/plugin-ext/lib/main/browser/custom-editors/custom-editor-opener';
77
+ import { nls } from '@theia/core/lib/common/nls';
78
+ import { WindowService } from '@theia/core/lib/browser/window/window-service';
79
+ import * as monaco from '@theia/monaco-editor-core';
80
+ import { VSCodeExtensionUri } from '../common/plugin-vscode-uri';
81
+ import { CodeEditorWidgetUtil } from '@theia/plugin-ext/lib/main/browser/menus/vscode-theia-menu-mappings';
82
+
83
+ export namespace VscodeCommands {
84
+ export const OPEN: Command = {
85
+ id: 'vscode.open'
86
+ };
87
+
88
+ export const OPEN_WITH: Command = {
89
+ id: 'vscode.openWith'
90
+ };
91
+
92
+ export const OPEN_FOLDER: Command = {
93
+ id: 'vscode.openFolder'
94
+ };
95
+
96
+ export const DIFF: Command = {
97
+ id: 'vscode.diff'
98
+ };
99
+
100
+ export const INSTALL_FROM_VSIX: Command = {
101
+ id: 'workbench.extensions.installExtension'
102
+ };
103
+ }
104
+
105
+ // https://wicg.github.io/webusb/
106
+
107
+ export interface UsbDeviceData {
108
+ readonly deviceClass: number;
109
+ readonly deviceProtocol: number;
110
+ readonly deviceSubclass: number;
111
+ readonly deviceVersionMajor: number;
112
+ readonly deviceVersionMinor: number;
113
+ readonly deviceVersionSubminor: number;
114
+ readonly manufacturerName?: string;
115
+ readonly productId: number;
116
+ readonly productName?: string;
117
+ readonly serialNumber?: string;
118
+ readonly usbVersionMajor: number;
119
+ readonly usbVersionMinor: number;
120
+ readonly usbVersionSubminor: number;
121
+ readonly vendorId: number;
122
+ }
123
+
124
+ // https://wicg.github.io/serial/
125
+
126
+ export interface SerialPortData {
127
+ readonly usbVendorId?: number | undefined;
128
+ readonly usbProductId?: number | undefined;
129
+ }
130
+
131
+ // https://wicg.github.io/webhid/
132
+
133
+ export interface HidDeviceData {
134
+ readonly opened: boolean;
135
+ readonly vendorId: number;
136
+ readonly productId: number;
137
+ readonly productName: string;
138
+ readonly collections: [];
139
+ }
140
+
141
+ @injectable()
142
+ export class PluginVscodeCommandsContribution implements CommandContribution {
143
+ @inject(CommandService)
144
+ protected readonly commandService: CommandService;
145
+ @inject(ContextKeyService)
146
+ protected readonly contextKeyService: ContextKeyService;
147
+ @inject(EditorManager)
148
+ protected readonly editorManager: EditorManager;
149
+ @inject(ApplicationShell)
150
+ protected readonly shell: ApplicationShell;
151
+ @inject(DiffService)
152
+ protected readonly diffService: DiffService;
153
+ @inject(OpenerService)
154
+ protected readonly openerService: OpenerService;
155
+ @inject(ApplicationShellMouseTracker)
156
+ protected readonly mouseTracker: ApplicationShellMouseTracker;
157
+ @inject(QuickInputService) @optional()
158
+ protected readonly quickInput: QuickInputService;
159
+ @inject(WorkspaceService)
160
+ protected readonly workspaceService: WorkspaceService;
161
+ @inject(TerminalFrontendContribution)
162
+ protected readonly terminalContribution: TerminalFrontendContribution;
163
+ @inject(QuickOpenWorkspace)
164
+ protected readonly quickOpenWorkspace: QuickOpenWorkspace;
165
+ @inject(TerminalService)
166
+ protected readonly terminalService: TerminalService;
167
+ @inject(CodeEditorWidgetUtil)
168
+ protected readonly codeEditorWidgetUtil: CodeEditorWidgetUtil;
169
+ @inject(PluginServer)
170
+ protected readonly pluginServer: PluginServer;
171
+ @inject(FileService)
172
+ protected readonly fileService: FileService;
173
+ @inject(CallHierarchyServiceProvider)
174
+ protected readonly callHierarchyProvider: CallHierarchyServiceProvider;
175
+ @inject(TypeHierarchyServiceProvider)
176
+ protected readonly typeHierarchyProvider: TypeHierarchyServiceProvider;
177
+ @inject(MonacoTextModelService)
178
+ protected readonly textModelService: MonacoTextModelService;
179
+ @inject(WindowService)
180
+ protected readonly windowService: WindowService;
181
+
182
+ private async openWith(commandId: string, resource: URI, columnOrOptions?: ViewColumn | TextDocumentShowOptions, openerId?: string): Promise<boolean> {
183
+ if (!resource) {
184
+ throw new Error(`${commandId} command requires at least URI argument.`);
185
+ }
186
+ if (!URI.isUri(resource)) {
187
+ throw new Error(`Invalid argument for ${commandId} command with URI argument. Found ${resource}`);
188
+ }
189
+
190
+ let options: TextDocumentShowOptions | undefined;
191
+ if (typeof columnOrOptions === 'number') {
192
+ options = {
193
+ viewColumn: columnOrOptions
194
+ };
195
+ } else if (columnOrOptions) {
196
+ options = {
197
+ ...columnOrOptions
198
+ };
199
+ }
200
+
201
+ const uri = new TheiaURI(resource);
202
+ const editorOptions = DocumentsMainImpl.toEditorOpenerOptions(this.shell, options);
203
+
204
+ let openHandler: OpenHandler | undefined;
205
+ if (typeof openerId === 'string') {
206
+ const lowerViewType = openerId.toLowerCase();
207
+ const openers = await this.openerService.getOpeners();
208
+ for (const opener of openers) {
209
+ const idLowerCase = opener.id.toLowerCase();
210
+ if (lowerViewType === idLowerCase) {
211
+ openHandler = opener;
212
+ break;
213
+ }
214
+ }
215
+ } else {
216
+ openHandler = await this.openerService.getOpener(uri, editorOptions);
217
+ }
218
+
219
+ if (openHandler) {
220
+ await openHandler.open(uri, editorOptions);
221
+ return true;
222
+ }
223
+
224
+ return false;
225
+ }
226
+
227
+ registerCommands(commands: CommandRegistry): void {
228
+ commands.registerCommand(VscodeCommands.OPEN, {
229
+ isVisible: () => false,
230
+ execute: async (resource: URI, columnOrOptions?: ViewColumn | TextDocumentShowOptions) => {
231
+ const result = await this.openWith(VscodeCommands.OPEN.id, resource, columnOrOptions);
232
+ if (!result) {
233
+ throw new Error(`Could not find an editor for ${resource}`);
234
+ }
235
+ }
236
+ });
237
+
238
+ commands.registerCommand(VscodeCommands.OPEN_WITH, {
239
+ isVisible: () => false,
240
+ execute: async (resource: URI, viewType: string, columnOrOptions?: ViewColumn | TextDocumentShowOptions) => {
241
+ if (!viewType) {
242
+ throw new Error(`Running the contributed command: ${VscodeCommands.OPEN_WITH} failed.`);
243
+ }
244
+
245
+ if (viewType.toLowerCase() === 'default') {
246
+ return commands.executeCommand(VscodeCommands.OPEN.id, resource, columnOrOptions);
247
+ }
248
+
249
+ let result = await this.openWith(VscodeCommands.OPEN_WITH.id, resource, columnOrOptions, viewType);
250
+ if (!result) {
251
+ result = await this.openWith(VscodeCommands.OPEN_WITH.id, resource, columnOrOptions, CustomEditorOpener.toCustomEditorId(viewType));
252
+ }
253
+
254
+ if (!result) {
255
+ throw new Error(`Could not find an editor for '${viewType}'`);
256
+ }
257
+ }
258
+ });
259
+
260
+ interface IOpenFolderAPICommandOptions {
261
+ forceNewWindow?: boolean;
262
+ forceReuseWindow?: boolean;
263
+ noRecentEntry?: boolean;
264
+ }
265
+
266
+ commands.registerCommand(VscodeCommands.OPEN_FOLDER, {
267
+ isVisible: () => false,
268
+ execute: async (resource?: URI, arg: boolean | IOpenFolderAPICommandOptions = {}) => {
269
+ if (!resource) {
270
+ return commands.executeCommand(WorkspaceCommands.OPEN_WORKSPACE.id);
271
+ }
272
+ if (!URI.isUri(resource)) {
273
+ throw new Error(`Invalid argument for ${VscodeCommands.OPEN_FOLDER.id} command with URI argument. Found ${resource}`);
274
+ }
275
+ let options: WorkspaceInput | undefined;
276
+ if (typeof arg === 'boolean') {
277
+ options = { preserveWindow: !arg };
278
+ } else {
279
+ options = { preserveWindow: !arg.forceNewWindow };
280
+ }
281
+ this.workspaceService.open(new TheiaURI(resource), options);
282
+ }
283
+ });
284
+
285
+ commands.registerCommand(VscodeCommands.DIFF, {
286
+ isVisible: () => false,
287
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
288
+ execute: async (left: URI, right: URI, label?: string, options?: TextDocumentShowOptions) => {
289
+ if (!left || !right) {
290
+ throw new Error(`${VscodeCommands.DIFF} command requires at least two URI arguments. Found left=${left}, right=${right} as arguments`);
291
+ }
292
+ if (!URI.isUri(left)) {
293
+ throw new Error(`Invalid argument for ${VscodeCommands.DIFF.id} command with left argument. Expecting URI left type but found ${left}`);
294
+ }
295
+ if (!URI.isUri(right)) {
296
+ throw new Error(`Invalid argument for ${VscodeCommands.DIFF.id} command with right argument. Expecting URI right type but found ${right}`);
297
+ }
298
+
299
+ const leftURI = new TheiaURI(left);
300
+ const editorOptions = DocumentsMainImpl.toEditorOpenerOptions(this.shell, options);
301
+ await this.diffService.openDiffEditor(leftURI, new TheiaURI(right), label, editorOptions);
302
+ }
303
+ });
304
+
305
+ // https://code.visualstudio.com/docs/getstarted/keybindings#_navigation
306
+ /*
307
+ * internally, in VS Code, any widget opened in the main area is represented as an editor
308
+ * operations below apply to them, but not to side-bar widgets, like the explorer
309
+ *
310
+ * in Theia, there are not such difference and any widget can be put in any area
311
+ * because of it we filter out editors from views based on `NavigatableWidget.is`
312
+ * and apply actions only to them
313
+ */
314
+ if (!environment.electron.is() || isOSX) {
315
+ commands.registerCommand({ id: 'workbench.action.files.openFileFolder' }, {
316
+ execute: () => commands.executeCommand(WorkspaceCommands.OPEN.id)
317
+ });
318
+ }
319
+
320
+ commands.registerCommand({ id: 'workbench.action.files.openFile' }, {
321
+ execute: () => commands.executeCommand(WorkspaceCommands.OPEN_FILE.id)
322
+ });
323
+ commands.registerCommand({ id: 'workbench.action.files.openFolder' }, {
324
+ execute: () => commands.executeCommand(WorkspaceCommands.OPEN_FOLDER.id)
325
+ });
326
+ commands.registerCommand({ id: 'workbench.action.addRootFolder' }, {
327
+ execute: () => commands.executeCommand(WorkspaceCommands.ADD_FOLDER.id)
328
+ });
329
+ commands.registerCommand({ id: 'workbench.action.saveWorkspaceAs' }, {
330
+ execute: () => commands.executeCommand(WorkspaceCommands.SAVE_WORKSPACE_AS.id)
331
+ });
332
+ commands.registerCommand({ id: 'workbench.action.gotoLine' }, {
333
+ execute: () => commands.executeCommand(EditorCommands.GOTO_LINE_COLUMN.id)
334
+ });
335
+ commands.registerCommand({ id: 'workbench.action.quickOpen' }, {
336
+ execute: (prefix?: unknown) => this.quickInput.open(typeof prefix === 'string' ? prefix : '')
337
+ });
338
+ commands.registerCommand({ id: 'workbench.action.openSettings' }, {
339
+ execute: (query?: string) => commands.executeCommand(CommonCommands.OPEN_PREFERENCES.id, query)
340
+ });
341
+ commands.registerCommand({ id: 'workbench.action.openWorkspaceConfigFile' }, {
342
+ execute: () => commands.executeCommand(WorkspaceCommands.OPEN_WORKSPACE_FILE.id)
343
+ });
344
+ commands.registerCommand({ id: 'workbench.files.action.refreshFilesExplorer' }, {
345
+ execute: () => commands.executeCommand(FileNavigatorCommands.REFRESH_NAVIGATOR.id)
346
+ });
347
+ commands.registerCommand({ id: VscodeCommands.INSTALL_FROM_VSIX.id }, {
348
+ execute: async (vsixUriOrExtensionId: TheiaURI | UriComponents | string) => {
349
+ if (typeof vsixUriOrExtensionId === 'string') {
350
+ await this.pluginServer.deploy(VSCodeExtensionUri.toVsxExtensionUriString(vsixUriOrExtensionId));
351
+ } else {
352
+ const uriPath = isUriComponents(vsixUriOrExtensionId) ? URI.revive(vsixUriOrExtensionId).fsPath : await this.fileService.fsPath(vsixUriOrExtensionId);
353
+ await this.pluginServer.deploy(`local-file:${uriPath}`);
354
+ }
355
+ }
356
+ });
357
+ commands.registerCommand({ id: 'workbench.action.files.save', }, {
358
+ execute: (uri?: monaco.Uri) => {
359
+ if (uri) {
360
+ const uriString = uri.toString();
361
+ const widget = this.shell.widgets.find(w => {
362
+ const resourceUri = Saveable.is(w) && NavigatableWidget.is(w) && w.getResourceUri();
363
+ return (resourceUri && resourceUri.toString()) === uriString;
364
+ });
365
+ if (Saveable.is(widget)) {
366
+ Saveable.save(widget);
367
+ }
368
+ } else {
369
+ this.shell.save();
370
+ }
371
+ }
372
+ });
373
+ commands.registerCommand({ id: 'workbench.action.files.saveAll', }, {
374
+ execute: () => this.shell.saveAll()
375
+ });
376
+ commands.registerCommand({ id: 'workbench.action.closeActiveEditor' }, {
377
+ execute: () => commands.executeCommand(CommonCommands.CLOSE_MAIN_TAB.id)
378
+ });
379
+ commands.registerCommand({ id: 'workbench.action.closeOtherEditors' }, {
380
+ execute: async (uri?: monaco.Uri) => {
381
+ let editor = this.editorManager.currentEditor || this.shell.currentWidget;
382
+ if (uri) {
383
+ const uriString = uri.toString();
384
+ editor = this.editorManager.all.find(e => {
385
+ const resourceUri = e.getResourceUri();
386
+ return (resourceUri && resourceUri.toString()) === uriString;
387
+ });
388
+ }
389
+ const toClose = this.shell.widgets.filter(widget => widget !== editor && this.codeEditorWidgetUtil.is(widget));
390
+ await this.shell.closeMany(toClose);
391
+ }
392
+ });
393
+
394
+ const performActionOnGroup = (
395
+ cb: (
396
+ tabBarOrArea: TabBar<Widget> | ApplicationShell.Area,
397
+ filter?: ((title: Title<Widget>, index: number) => boolean) | undefined
398
+ ) => void,
399
+ uri?: monaco.Uri
400
+ ): void => {
401
+ let editor = this.editorManager.currentEditor || this.shell.currentWidget;
402
+ if (uri) {
403
+ const uriString = uri.toString();
404
+ editor = this.editorManager.all.find(e => {
405
+ const resourceUri = e.getResourceUri();
406
+ return (resourceUri && resourceUri.toString()) === uriString;
407
+ });
408
+ }
409
+ if (editor) {
410
+ const tabBar = this.shell.getTabBarFor(editor);
411
+ if (tabBar) {
412
+ cb(tabBar, ({ owner }) => this.codeEditorWidgetUtil.is(owner));
413
+ }
414
+ }
415
+ };
416
+
417
+ commands.registerCommand({
418
+ id: 'workbench.action.closeEditorsInGroup',
419
+ label: nls.localizeByDefault('Close All Editors in Group')
420
+ }, {
421
+ execute: (uri?: monaco.Uri) => performActionOnGroup(this.shell.closeTabs, uri)
422
+ });
423
+ commands.registerCommand({
424
+ id: 'workbench.files.saveAllInGroup',
425
+ label: nls.localizeByDefault('Save All in Group')
426
+ }, {
427
+ execute: (uri?: monaco.Uri) => performActionOnGroup(this.shell.saveTabs, uri)
428
+ });
429
+ commands.registerCommand({ id: 'workbench.action.closeEditorsInOtherGroups' }, {
430
+ execute: () => {
431
+ const editor = this.editorManager.currentEditor || this.shell.currentWidget;
432
+ if (editor) {
433
+ const editorTabBar = this.shell.getTabBarFor(editor);
434
+ for (const tabBar of this.shell.allTabBars) {
435
+ if (tabBar !== editorTabBar) {
436
+ this.shell.closeTabs(tabBar,
437
+ ({ owner }) => this.codeEditorWidgetUtil.is(owner)
438
+ );
439
+ }
440
+ }
441
+ }
442
+ }
443
+ });
444
+ commands.registerCommand({ id: 'workbench.action.closeEditorsToTheLeft' }, {
445
+ execute: () => {
446
+ const editor = this.editorManager.currentEditor || this.shell.currentWidget;
447
+ if (editor) {
448
+ const tabBar = this.shell.getTabBarFor(editor);
449
+ if (tabBar) {
450
+ let left = true;
451
+ this.shell.closeTabs(tabBar,
452
+ ({ owner }) => {
453
+ if (owner === editor) {
454
+ left = false;
455
+ return false;
456
+ }
457
+ return left && this.codeEditorWidgetUtil.is(owner);
458
+ }
459
+ );
460
+ }
461
+ }
462
+ }
463
+ });
464
+ commands.registerCommand({ id: 'workbench.action.closeEditorsToTheRight' }, {
465
+ execute: () => {
466
+ const editor = this.editorManager.currentEditor || this.shell.currentWidget;
467
+ if (editor) {
468
+ const tabBar = this.shell.getTabBarFor(editor);
469
+ if (tabBar) {
470
+ let left = true;
471
+ this.shell.closeTabs(tabBar,
472
+ ({ owner }) => {
473
+ if (owner === editor) {
474
+ left = false;
475
+ return false;
476
+ }
477
+ return !left && this.codeEditorWidgetUtil.is(owner);
478
+ }
479
+ );
480
+ }
481
+ }
482
+ }
483
+ });
484
+ commands.registerCommand({ id: 'workbench.action.closeAllEditors' }, {
485
+ execute: async () => {
486
+ const toClose = this.shell.widgets.filter(widget => this.codeEditorWidgetUtil.is(widget));
487
+ await this.shell.closeMany(toClose);
488
+ }
489
+ });
490
+ commands.registerCommand({ id: 'workbench.action.nextEditor' }, {
491
+ execute: () => this.shell.activateNextTab()
492
+ });
493
+ commands.registerCommand({ id: 'workbench.action.previousEditor' }, {
494
+ execute: () => this.shell.activatePreviousTab()
495
+ });
496
+ commands.registerCommand({ id: 'workbench.action.navigateBack' }, {
497
+ execute: () => commands.executeCommand(EditorCommands.GO_BACK.id)
498
+ });
499
+ commands.registerCommand({ id: 'workbench.action.navigateForward' }, {
500
+ execute: () => commands.executeCommand(EditorCommands.GO_FORWARD.id)
501
+ });
502
+ commands.registerCommand({ id: 'workbench.action.navigateToLastEditLocation' }, {
503
+ execute: () => commands.executeCommand(EditorCommands.GO_LAST_EDIT.id)
504
+ });
505
+
506
+ commands.registerCommand({ id: 'openInTerminal' }, {
507
+ execute: (resource: URI) => this.terminalContribution.openInTerminal(new TheiaURI(resource.toString()))
508
+ });
509
+
510
+ commands.registerCommand({ id: 'workbench.action.reloadWindow' }, {
511
+ execute: () => {
512
+ this.windowService.reload();
513
+ }
514
+ });
515
+
516
+ /**
517
+ * TODO:
518
+ * Open Next: workbench.action.openNextRecentlyUsedEditorInGroup
519
+ * Open Previous: workbench.action.openPreviousRecentlyUsedEditorInGroup
520
+ * Copy Path of Active File: workbench.action.files.copyPathOfActiveFile
521
+ * Reveal Active File in Windows: workbench.action.files.revealActiveFileInWindows
522
+ * Show Opened File in New Window: workbench.action.files.showOpenedFileInNewWindow
523
+ * Compare Opened File With: workbench.files.action.compareFileWith
524
+ */
525
+
526
+ // Register built-in language service commands
527
+ // see https://code.visualstudio.com/api/references/commands
528
+ /* eslint-disable @typescript-eslint/no-explicit-any */
529
+
530
+ // TODO register other `vscode.execute...` commands.
531
+ // see https://github.com/microsoft/vscode/blob/master/src/vs/workbench/api/common/extHostApiCommands.ts
532
+ commands.registerCommand(
533
+ {
534
+ id: 'vscode.executeDefinitionProvider'
535
+ },
536
+ {
537
+ execute: ((resource: URI, position: Position) =>
538
+ commands.executeCommand<Location[]>('_executeDefinitionProvider', monaco.Uri.from(resource), position))
539
+ }
540
+ );
541
+ commands.registerCommand(
542
+ {
543
+ id: 'vscode.executeDeclarationProvider'
544
+ },
545
+ {
546
+ execute: ((resource: URI, position: Position) =>
547
+ commands.executeCommand<Location[]>('_executeDeclarationProvider', monaco.Uri.from(resource), position))
548
+ }
549
+ );
550
+ commands.registerCommand(
551
+ {
552
+ id: 'vscode.executeTypeDefinitionProvider'
553
+ },
554
+ {
555
+ execute: ((resource: URI, position: Position) =>
556
+ commands.executeCommand<Location[]>('_executeTypeDefinitionProvider', monaco.Uri.from(resource), position))
557
+ }
558
+ );
559
+ commands.registerCommand(
560
+ {
561
+ id: 'vscode.executeImplementationProvider'
562
+ },
563
+ {
564
+ execute: ((resource: URI, position: Position) =>
565
+ commands.executeCommand<Location[]>('_executeImplementationProvider', monaco.Uri.from(resource), position))
566
+ }
567
+ );
568
+ commands.registerCommand(
569
+ {
570
+ id: 'vscode.executeHoverProvider'
571
+ },
572
+ {
573
+ execute: ((resource: URI, position: Position) =>
574
+ commands.executeCommand<Hover[]>('_executeHoverProvider', monaco.Uri.from(resource), position))
575
+ }
576
+ );
577
+ commands.registerCommand(
578
+ {
579
+ id: 'vscode.executeDocumentHighlights'
580
+ },
581
+ {
582
+ execute: ((resource: URI, position: Position) =>
583
+ commands.executeCommand<DocumentHighlight[]>('_executeDocumentHighlights', monaco.Uri.from(resource), position))
584
+ }
585
+ );
586
+ commands.registerCommand(
587
+ {
588
+ id: 'vscode.executeReferenceProvider'
589
+ },
590
+ {
591
+ execute: ((resource: URI, position: Position) => commands.executeCommand<Location[]>('_executeReferenceProvider', monaco.Uri.from(resource), position))
592
+ }
593
+ );
594
+ commands.registerCommand(
595
+ {
596
+ id: 'vscode.executeDocumentSymbolProvider'
597
+ },
598
+ {
599
+ execute: (resource: URI) => commands.executeCommand('_executeDocumentSymbolProvider',
600
+ monaco.Uri.parse(resource.toString())
601
+ ).then((value: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
602
+ if (!Array.isArray(value) || value === undefined) {
603
+ return undefined;
604
+ }
605
+ return value.map(loc => toDocumentSymbol(loc));
606
+ })
607
+ }
608
+ );
609
+ commands.registerCommand(
610
+ {
611
+ id: 'vscode.executeFormatDocumentProvider'
612
+ },
613
+ {
614
+ execute: ((resource: URI, options: FormattingOptions) =>
615
+ commands.executeCommand<TextEdit[]>('_executeFormatDocumentProvider', monaco.Uri.from(resource), options))
616
+ }
617
+ );
618
+ commands.registerCommand(
619
+ {
620
+ id: 'vscode.executeFormatRangeProvider'
621
+ },
622
+ {
623
+ execute: ((resource: URI, range: Range, options: FormattingOptions) =>
624
+ commands.executeCommand<TextEdit[]>('_executeFormatRangeProvider', monaco.Uri.from(resource), range, options))
625
+ }
626
+ );
627
+ commands.registerCommand(
628
+ {
629
+ id: 'vscode.executeFormatOnTypeProvider'
630
+ },
631
+ {
632
+ execute: ((resource: URI, position: Position, ch: string, options: FormattingOptions) =>
633
+ commands.executeCommand<TextEdit[]>('_executeFormatOnTypeProvider', monaco.Uri.from(resource), position, ch, options))
634
+ }
635
+ );
636
+ commands.registerCommand(
637
+ {
638
+ id: 'vscode.prepareCallHierarchy'
639
+ },
640
+ {
641
+ execute: async (resource: URI, position: Position): Promise<CallHierarchyItem[]> => {
642
+ const provider = await this.getCallHierarchyServiceForUri(resource);
643
+ const definition = await provider?.getRootDefinition(
644
+ resource.path,
645
+ toPosition(position),
646
+ new CancellationTokenSource().token
647
+ );
648
+ if (definition) {
649
+ return definition.items.map(item => fromItemHierarchyDefinition(item));
650
+ };
651
+ return [];
652
+ }
653
+ }
654
+ );
655
+ commands.registerCommand(
656
+ {
657
+ id: 'vscode.provideIncomingCalls'
658
+ },
659
+ {
660
+ execute: async (item: CallHierarchyItem): Promise<CallHierarchyIncomingCall[]> => {
661
+ const resource = URI.from(item.uri);
662
+ const provider = await this.getCallHierarchyServiceForUri(resource);
663
+ const incomingCalls = await provider?.getCallers(
664
+ toItemHierarchyDefinition(item),
665
+ new CancellationTokenSource().token,
666
+ );
667
+ if (incomingCalls) {
668
+ return incomingCalls.map(fromCallHierarchyCallerToModelCallHierarchyIncomingCall);
669
+ }
670
+ return [];
671
+ },
672
+ },
673
+ );
674
+ commands.registerCommand(
675
+ {
676
+ id: 'vscode.provideOutgoingCalls'
677
+ },
678
+ {
679
+ execute: async (item: CallHierarchyItem): Promise<CallHierarchyOutgoingCall[]> => {
680
+ const resource = URI.from(item.uri);
681
+ const provider = await this.getCallHierarchyServiceForUri(resource);
682
+ const outgoingCalls = await provider?.getCallees?.(
683
+ toItemHierarchyDefinition(item),
684
+ new CancellationTokenSource().token,
685
+ );
686
+ if (outgoingCalls) {
687
+ return outgoingCalls.map(fromCallHierarchyCalleeToModelCallHierarchyOutgoingCall);
688
+ }
689
+ return [];
690
+ }
691
+ }
692
+ );
693
+ commands.registerCommand(
694
+ {
695
+ id: 'vscode.prepareTypeHierarchy'
696
+ },
697
+ {
698
+ execute: async (resource: URI, position: Position): Promise<TypeHierarchyItem[]> => {
699
+ const provider = await this.getTypeHierarchyServiceForUri(resource);
700
+ const session = await provider?.prepareSession(
701
+ resource.path,
702
+ toPosition(position),
703
+ new CancellationTokenSource().token
704
+ );
705
+ return session ? session.items.map(item => fromItemHierarchyDefinition(item)) : [];
706
+ }
707
+ }
708
+ );
709
+ commands.registerCommand(
710
+ {
711
+ id: 'vscode.provideSupertypes'
712
+ },
713
+ {
714
+ execute: async (item: TypeHierarchyItem): Promise<TypeHierarchyItem[]> => {
715
+ if (!item._sessionId || !item._itemId) {
716
+ return [];
717
+ }
718
+ const resource = URI.from(item.uri);
719
+ const provider = await this.getTypeHierarchyServiceForUri(resource);
720
+ const items = await provider?.provideSuperTypes(
721
+ item._sessionId,
722
+ item._itemId,
723
+ new CancellationTokenSource().token
724
+ );
725
+ return (items ? items : []).map(typeItem => fromItemHierarchyDefinition(typeItem));
726
+ }
727
+ }
728
+ );
729
+ commands.registerCommand(
730
+ {
731
+ id: 'vscode.provideSubtypes'
732
+ },
733
+ {
734
+ execute: async (item: TypeHierarchyItem): Promise<TypeHierarchyItem[]> => {
735
+ if (!item._sessionId || !item._itemId) {
736
+ return [];
737
+ }
738
+ const resource = URI.from(item.uri);
739
+ const provider = await this.getTypeHierarchyServiceForUri(resource);
740
+ const items = await provider?.provideSubTypes(
741
+ item._sessionId, item._itemId,
742
+ new CancellationTokenSource().token
743
+ );
744
+ return (items ? items : []).map(typeItem => fromItemHierarchyDefinition(typeItem));
745
+
746
+ }
747
+ }
748
+ );
749
+
750
+ commands.registerCommand({
751
+ id: 'workbench.action.openRecent'
752
+ }, {
753
+ execute: () => this.quickOpenWorkspace.select()
754
+ });
755
+ commands.registerCommand({
756
+ id: 'explorer.newFolder'
757
+ }, {
758
+ execute: () => commands.executeCommand(WorkspaceCommands.NEW_FOLDER.id)
759
+ });
760
+ commands.registerCommand({
761
+ id: 'workbench.action.terminal.sendSequence'
762
+ }, {
763
+ execute: (args?: { text?: string }) => {
764
+ if (args === undefined || args.text === undefined) {
765
+ return;
766
+ }
767
+
768
+ const currentTerminal = this.terminalService.currentTerminal;
769
+
770
+ if (currentTerminal === undefined) {
771
+ return;
772
+ }
773
+
774
+ currentTerminal.sendText(args.text);
775
+ }
776
+ });
777
+ commands.registerCommand({
778
+ id: 'workbench.action.terminal.kill'
779
+ }, {
780
+ execute: () => {
781
+ const currentTerminal = this.terminalService.currentTerminal;
782
+
783
+ if (currentTerminal === undefined) {
784
+ return;
785
+ }
786
+
787
+ currentTerminal.dispose();
788
+ }
789
+ });
790
+ commands.registerCommand({
791
+ id: 'workbench.view.explorer'
792
+ }, {
793
+ execute: () => commands.executeCommand(FileNavigatorCommands.FOCUS.id)
794
+ });
795
+ commands.registerCommand({
796
+ id: 'copyFilePath'
797
+ }, {
798
+ execute: () => commands.executeCommand(CommonCommands.COPY_PATH.id)
799
+ });
800
+ commands.registerCommand({
801
+ id: 'copyRelativeFilePath'
802
+ }, {
803
+ execute: () => commands.executeCommand(WorkspaceCommands.COPY_RELATIVE_FILE_PATH.id)
804
+ });
805
+ commands.registerCommand({
806
+ id: 'revealInExplorer'
807
+ }, {
808
+ execute: async (resource: URI | object) => {
809
+ if (!URI.isUri(resource)) {
810
+ return;
811
+ }
812
+ let navigator = await this.shell.revealWidget(FILE_NAVIGATOR_ID);
813
+ if (!navigator) {
814
+ await this.commandService.executeCommand(FILE_NAVIGATOR_TOGGLE_COMMAND_ID);
815
+ navigator = await this.shell.revealWidget(FILE_NAVIGATOR_ID);
816
+ }
817
+ if (navigator instanceof FileNavigatorWidget) {
818
+ const model = navigator.model;
819
+ const node = await model.revealFile(new TheiaURI(resource));
820
+ if (SelectableTreeNode.is(node)) {
821
+ model.selectNode(node);
822
+ }
823
+ }
824
+ }
825
+ });
826
+
827
+ commands.registerCommand({
828
+ id: 'workbench.experimental.requestUsbDevice'
829
+ }, {
830
+ execute: async (options?: { filters?: unknown[] }): Promise<UsbDeviceData | undefined> => {
831
+ const usb = (navigator as any).usb;
832
+ if (!usb) {
833
+ return undefined;
834
+ }
835
+
836
+ const device = await usb.requestDevice({ filters: options?.filters ?? [] });
837
+ if (!device) {
838
+ return undefined;
839
+ }
840
+
841
+ return {
842
+ deviceClass: device.deviceClass,
843
+ deviceProtocol: device.deviceProtocol,
844
+ deviceSubclass: device.deviceSubclass,
845
+ deviceVersionMajor: device.deviceVersionMajor,
846
+ deviceVersionMinor: device.deviceVersionMinor,
847
+ deviceVersionSubminor: device.deviceVersionSubminor,
848
+ manufacturerName: device.manufacturerName,
849
+ productId: device.productId,
850
+ productName: device.productName,
851
+ serialNumber: device.serialNumber,
852
+ usbVersionMajor: device.usbVersionMajor,
853
+ usbVersionMinor: device.usbVersionMinor,
854
+ usbVersionSubminor: device.usbVersionSubminor,
855
+ vendorId: device.vendorId,
856
+ };
857
+ }
858
+ });
859
+
860
+ commands.registerCommand({
861
+ id: 'workbench.experimental.requestSerialPort'
862
+ }, {
863
+ execute: async (options?: { filters?: unknown[] }): Promise<SerialPortData | undefined> => {
864
+ const serial = (navigator as any).serial;
865
+ if (!serial) {
866
+ return undefined;
867
+ }
868
+
869
+ const port = await serial.requestPort({ filters: options?.filters ?? [] });
870
+ if (!port) {
871
+ return undefined;
872
+ }
873
+
874
+ const info = port.getInfo();
875
+ return {
876
+ usbVendorId: info.usbVendorId,
877
+ usbProductId: info.usbProductId
878
+ };
879
+ }
880
+ });
881
+
882
+ commands.registerCommand({
883
+ id: 'workbench.experimental.requestHidDevice'
884
+ }, {
885
+ execute: async (options?: { filters?: unknown[] }): Promise<HidDeviceData | undefined> => {
886
+ const hid = (navigator as any).hid;
887
+ if (!hid) {
888
+ return undefined;
889
+ }
890
+
891
+ const devices = await hid.requestDevice({ filters: options?.filters ?? [] });
892
+ if (!devices.length) {
893
+ return undefined;
894
+ }
895
+
896
+ const device = devices[0];
897
+ return {
898
+ opened: device.opened,
899
+ vendorId: device.vendorId,
900
+ productId: device.productId,
901
+ productName: device.productName,
902
+ collections: device.collections
903
+ };
904
+ }
905
+ });
906
+ }
907
+
908
+ private async resolveLanguageId(resource: URI): Promise<string> {
909
+ const reference = await this.textModelService.createModelReference(resource);
910
+ const languageId = reference.object.languageId;
911
+ reference.dispose();
912
+ return languageId;
913
+ }
914
+
915
+ protected async getCallHierarchyServiceForUri(resource: URI): Promise<CallHierarchyService | undefined> {
916
+ const languageId = await this.resolveLanguageId(resource);
917
+ return this.callHierarchyProvider.get(languageId, new TheiaURI(resource));
918
+ }
919
+
920
+ protected async getTypeHierarchyServiceForUri(resource: URI): Promise<TypeHierarchyService | undefined> {
921
+ const languageId = await this.resolveLanguageId(resource);
922
+ return this.typeHierarchyProvider.get(languageId, new TheiaURI(resource));
923
+ }
924
+ }