@theia/plugin-ext-vscode 1.77.0-next.7 → 1.77.0-next.71

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 (37) hide show
  1. package/lib/browser/plugin-vscode-commands-contribution.d.ts +6 -0
  2. package/lib/browser/plugin-vscode-commands-contribution.d.ts.map +1 -1
  3. package/lib/browser/plugin-vscode-commands-contribution.js +76 -34
  4. package/lib/browser/plugin-vscode-commands-contribution.js.map +1 -1
  5. package/lib/browser/plugin-vscode-commands-contribution.spec.js +132 -0
  6. package/lib/browser/plugin-vscode-commands-contribution.spec.js.map +1 -1
  7. package/lib/common/plugin-vscode-environment.js +1 -1
  8. package/lib/common/plugin-vscode-environment.js.map +1 -1
  9. package/lib/common/plugin-vscode-uri.js +2 -1
  10. package/lib/common/plugin-vscode-uri.js.map +1 -1
  11. package/lib/node/context/plugin-vscode-init-fe.js +1 -0
  12. package/lib/node/context/plugin-vscode-init-fe.js.map +1 -1
  13. package/lib/node/local-vsix-file-plugin-deployer-resolver.d.ts.map +1 -1
  14. package/lib/node/local-vsix-file-plugin-deployer-resolver.js +2 -4
  15. package/lib/node/local-vsix-file-plugin-deployer-resolver.js.map +1 -1
  16. package/lib/node/package.spec.js +1 -0
  17. package/lib/node/package.spec.js.map +1 -1
  18. package/lib/node/plugin-vscode-deployer-participant.js +1 -1
  19. package/lib/node/plugin-vscode-deployer-participant.js.map +1 -1
  20. package/lib/node/plugin-vscode-directory-handler.js +2 -2
  21. package/lib/node/plugin-vscode-directory-handler.js.map +1 -1
  22. package/lib/node/plugin-vscode-file-handler.js +3 -3
  23. package/lib/node/plugin-vscode-file-handler.js.map +1 -1
  24. package/lib/node/plugin-vscode-init.spec.js +2 -1
  25. package/lib/node/plugin-vscode-init.spec.js.map +1 -1
  26. package/lib/node/plugin-vscode-utils.js +9 -8
  27. package/lib/node/plugin-vscode-utils.js.map +1 -1
  28. package/lib/node/scanner-vscode.js +1 -1
  29. package/lib/node/scanner-vscode.js.map +1 -1
  30. package/lib/node/scanner-vscode.spec.js +5 -4
  31. package/lib/node/scanner-vscode.spec.js.map +1 -1
  32. package/package.json +17 -17
  33. package/src/browser/plugin-vscode-commands-contribution.spec.ts +141 -0
  34. package/src/browser/plugin-vscode-commands-contribution.ts +83 -34
  35. package/src/node/local-vsix-file-plugin-deployer-resolver.ts +2 -6
  36. package/src/node/plugin-vscode-file-handler.ts +1 -1
  37. package/src/node/plugin-vscode-utils.ts +2 -2
@@ -14,7 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { Command, CommandContribution, CommandRegistry, environment, isOSX, CancellationTokenSource, MessageService, isArray, ILogger } from '@theia/core';
17
+ import { Command, CommandContribution, CommandRegistry, environment, isOSX, CancellationTokenSource, MessageService, isArray, ILogger, MEMORY_TEXT_READONLY } from '@theia/core';
18
18
  import {
19
19
  ApplicationShell,
20
20
  CommonCommands,
@@ -53,7 +53,7 @@ import { DiffService } from '@theia/workspace/lib/browser/diff-service';
53
53
  import { inject, injectable, optional, named } from '@theia/core/shared/inversify';
54
54
  import { Position } from '@theia/plugin-ext/lib/common/plugin-api-rpc';
55
55
  import { URI } from '@theia/core/shared/vscode-uri';
56
- import { PluginDeployOptions, PluginIdentifiers, PluginServer } from '@theia/plugin-ext/lib/common/plugin-protocol';
56
+ import { DuplicateExtensionError, PluginDeployOptions, PluginIdentifiers, PluginServer } from '@theia/plugin-ext/lib/common/plugin-protocol';
57
57
  import { TerminalFrontendContribution } from '@theia/terminal/lib/browser/terminal-frontend-contribution';
58
58
  import { QuickOpenWorkspace } from '@theia/workspace/lib/browser/quick-open-workspace';
59
59
  import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
@@ -84,7 +84,25 @@ import { OutlineViewContribution } from '@theia/outline-view/lib/browser/outline
84
84
  import { CompletionList, Range, Position as PluginPosition } from '@theia/plugin';
85
85
  import { MonacoLanguages } from '@theia/monaco/lib/browser/monaco-languages';
86
86
  import { ScmContribution } from '@theia/scm/lib/browser/scm-contribution';
87
+ import { ScmService } from '@theia/scm/lib/browser/scm-service';
87
88
  import { MergeEditorOpenerOptions, MergeEditorUri } from '@theia/scm/lib/browser/merge-editor/merge-editor';
89
+ import { MultiDiffEditorOpenerOptions, MultiDiffEditorUri } from '@theia/scm/lib/browser/multi-diff-editor/multi-diff-editor';
90
+
91
+ /**
92
+ * Convert a VS Code {@link UriComponents} or a string URI into a Theia {@link TheiaURI}.
93
+ * Returns `undefined` when given `undefined`.
94
+ */
95
+ function toTheiaUri(value: UriComponents | string): TheiaURI;
96
+ function toTheiaUri(value: UriComponents | string | undefined): TheiaURI | undefined;
97
+ function toTheiaUri(value: UriComponents | string | undefined): TheiaURI | undefined {
98
+ if (value === undefined) {
99
+ return undefined;
100
+ }
101
+ if (typeof value === 'string') {
102
+ return new TheiaURI(value);
103
+ }
104
+ return TheiaURI.fromComponents(value);
105
+ }
88
106
 
89
107
  export namespace VscodeCommands {
90
108
 
@@ -287,6 +305,8 @@ export class PluginVscodeCommandsContribution implements CommandContribution {
287
305
  protected monacoLanguages: MonacoLanguages;
288
306
  @inject(ScmContribution)
289
307
  protected scmContribution: ScmContribution;
308
+ @inject(ScmService)
309
+ protected readonly scmService: ScmService;
290
310
 
291
311
  @inject(ILogger) @named('plugin-ext-vscode:PluginVscodeCommandsContribution')
292
312
  protected readonly logger: ILogger;
@@ -578,14 +598,7 @@ export class PluginVscodeCommandsContribution implements CommandContribution {
578
598
  commands.registerCommand(VscodeCommands.INSTALL_EXTENSION_FROM_ID_OR_URI, {
579
599
  execute: async (vsixUriOrExtensionId: TheiaURI | UriComponents | string) => {
580
600
  if (typeof vsixUriOrExtensionId === 'string') {
581
- let extensionId = vsixUriOrExtensionId;
582
- let opts: PluginDeployOptions | undefined;
583
- const versionedId = PluginIdentifiers.idAndVersionFromVersionedId(vsixUriOrExtensionId);
584
- if (versionedId) {
585
- extensionId = versionedId.id;
586
- opts = { version: versionedId.version, ignoreOtherVersions: true };
587
- }
588
- await this.pluginServer.install(VSCodeExtensionUri.fromId(extensionId).toString(), undefined, opts);
601
+ await this.installExtensionFromId(vsixUriOrExtensionId);
589
602
  } else {
590
603
  await this.deployPlugin(vsixUriOrExtensionId);
591
604
  }
@@ -1283,13 +1296,6 @@ export class PluginVscodeCommandsContribution implements CommandContribution {
1283
1296
 
1284
1297
  commands.registerCommand({ id: '_open.mergeEditor' }, {
1285
1298
  execute: async (arg: OpenMergeEditorCommandArg): Promise<void> => {
1286
- const toTheiaUri = (o: UriComponents | string): TheiaURI => {
1287
- if (typeof o === 'string') {
1288
- return new TheiaURI(o);
1289
- }
1290
- return TheiaURI.fromComponents(o);
1291
- };
1292
-
1293
1299
  const baseUri = toTheiaUri(arg.base);
1294
1300
  const resultUri = toTheiaUri(arg.output);
1295
1301
  const side1Uri = typeof arg.input1 === 'string' ? toTheiaUri(arg.input1) : toTheiaUri(arg.input1.uri);
@@ -1312,36 +1318,79 @@ export class PluginVscodeCommandsContribution implements CommandContribution {
1312
1318
  }
1313
1319
  });
1314
1320
 
1315
- // Temporary workaround: opens a single diff editor for the revealed resource.
1316
- // TODO: GH-16280 implement a proper MultiDiffEditor widget.
1321
+ commands.registerCommand({ id: '_workbench.openScmMultiDiffEditor' }, {
1322
+ execute: async (options: { title: string; repositoryUri: UriComponents; resourceGroupId: string }): Promise<void> => {
1323
+ const repositoryUri = toTheiaUri(options.repositoryUri);
1324
+ if (!repositoryUri) {
1325
+ return;
1326
+ }
1327
+ const repository = this.scmService.repositories.find(repo => new TheiaURI(repo.provider.rootUri).isEqual(repositoryUri));
1328
+ const group = repository?.provider.groups.find(candidate => candidate.id === options.resourceGroupId);
1329
+ if (!group) {
1330
+ return;
1331
+ }
1332
+ await commands.executeCommand('_workbench.openMultiDiffEditor', {
1333
+ title: options.title,
1334
+ resources: group.resources.map(resource => ({
1335
+ originalUri: resource.multiDiffEditorOriginalUri?.toComponents(),
1336
+ modifiedUri: resource.multiDiffEditorModifiedUri?.toComponents()
1337
+ }))
1338
+ });
1339
+ }
1340
+ });
1341
+
1317
1342
  commands.registerCommand({ id: '_workbench.openMultiDiffEditor' }, {
1318
1343
  execute: async (options: {
1319
1344
  title: string;
1320
- resources?: { originalUri: UriComponents; modifiedUri: UriComponents }[];
1345
+ resources?: { originalUri?: UriComponents; modifiedUri?: UriComponents }[];
1321
1346
  reveal?: { modifiedUri: UriComponents };
1322
1347
  }): Promise<void> => {
1323
1348
  if (!options.resources?.length) {
1324
1349
  return;
1325
1350
  }
1326
- const revealModified = options.reveal?.modifiedUri;
1327
- const revealStr = revealModified ? URI.revive(revealModified)?.toString() : undefined;
1328
- const target = revealStr
1329
- ? options.resources.find(r => URI.revive(r.modifiedUri)?.toString() === revealStr)
1330
- : undefined;
1331
- const resource = target ?? options.resources[0];
1332
- const left = URI.revive(resource.originalUri);
1333
- const right = URI.revive(resource.modifiedUri);
1334
- if (left && right) {
1335
- await commands.executeCommand(VscodeCommands.DIFF.id, left, right, options.title);
1336
- } else if (right) {
1337
- await commands.executeCommand(VscodeCommands.OPEN.id, right);
1338
- } else if (left) {
1339
- await commands.executeCommand(VscodeCommands.OPEN.id, left);
1351
+ const resources = options.resources
1352
+ .map(r => {
1353
+ const originalUri = toTheiaUri(r.originalUri);
1354
+ const modifiedUri = toTheiaUri(r.modifiedUri);
1355
+ const resourceUri = modifiedUri ?? originalUri;
1356
+ if (!resourceUri) {
1357
+ return undefined;
1358
+ }
1359
+ const emptyUri = new TheiaURI().withScheme(MEMORY_TEXT_READONLY).withPath(resourceUri.path);
1360
+ return { originalUri: originalUri ?? emptyUri, modifiedUri: modifiedUri ?? emptyUri };
1361
+ })
1362
+ .filter((r): r is { originalUri: TheiaURI; modifiedUri: TheiaURI } => r !== undefined);
1363
+ if (!resources.length) {
1364
+ return;
1340
1365
  }
1366
+ const uri = MultiDiffEditorUri.encode({ title: options.title, resources });
1367
+ const reveal = toTheiaUri(options.reveal?.modifiedUri);
1368
+ const openerOptions: MultiDiffEditorOpenerOptions = { reveal };
1369
+ await open(this.openerService, uri, openerOptions);
1341
1370
  },
1342
1371
  });
1343
1372
  }
1344
1373
 
1374
+ /**
1375
+ * Installs an extension by its (optionally versioned) ID. Installing an extension that is already installed is a noop.
1376
+ */
1377
+ protected async installExtensionFromId(extensionIdOrVersionedId: string): Promise<void> {
1378
+ let extensionId = extensionIdOrVersionedId;
1379
+ let opts: PluginDeployOptions | undefined;
1380
+ const versionedId = PluginIdentifiers.idAndVersionFromVersionedId(extensionIdOrVersionedId);
1381
+ if (versionedId) {
1382
+ extensionId = versionedId.id;
1383
+ opts = { version: versionedId.version, ignoreOtherVersions: true };
1384
+ }
1385
+ try {
1386
+ await this.pluginServer.install(VSCodeExtensionUri.fromId(extensionId).toString(), undefined, opts);
1387
+ } catch (e) {
1388
+ if (!DuplicateExtensionError.is(e)) {
1389
+ throw e;
1390
+ }
1391
+ }
1392
+ }
1393
+
1345
1394
  private async deployPlugin(uri: TheiaURI | UriComponents): Promise<void> {
1346
1395
  const uriPath = isUriComponents(uri) ? URI.revive(uri).fsPath : await this.fileService.fsPath(uri);
1347
1396
  return this.pluginServer.install(`local-file:${uriPath}`);
@@ -16,7 +16,7 @@
16
16
 
17
17
  import * as path from 'path';
18
18
  import { inject, injectable, named } from '@theia/core/shared/inversify';
19
- import { PluginDeployerResolverContext, PluginIdentifiers } from '@theia/plugin-ext';
19
+ import { DuplicateExtensionError, PluginDeployerResolverContext, PluginIdentifiers } from '@theia/plugin-ext';
20
20
  import { LocalPluginDeployerResolver } from '@theia/plugin-ext/lib/main/node/resolvers/local-plugin-deployer-resolver';
21
21
  import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';
22
22
  import { isVSCodePluginFile } from './plugin-vscode-file-handler';
@@ -68,11 +68,7 @@ export class LocalVSIXFilePluginDeployerResolver extends LocalPluginDeployerReso
68
68
  // Check if the deployment directory already exists on disk
69
69
  if (await existsInDeploymentDir(this.environment, versionedId)) {
70
70
  const unversionedId = PluginIdentifiers.componentsToUnversionedId(components);
71
- const error = new Error(
72
- `Extension ${unversionedId} is already installed (version: ${components.version}).`
73
- );
74
- error.name = 'DuplicateExtensionError';
75
- throw error;
71
+ throw DuplicateExtensionError.create(`Extension ${unversionedId} is already installed (version: ${components.version}).`);
76
72
  }
77
73
 
78
74
  const extensionDeploymentDir = await unpackToDeploymentDir(this.environment, localPath, versionedId);
@@ -15,7 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { PluginDeployerFileHandler, PluginDeployerEntry, PluginDeployerFileHandlerContext } from '@theia/plugin-ext';
18
- import * as filenamify from 'filenamify';
18
+ import filenamify from 'filenamify';
19
19
  import { inject, injectable, named } from '@theia/core/shared/inversify';
20
20
  import * as fs from '@theia/core/shared/fs-extra';
21
21
  import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';
@@ -14,9 +14,9 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import * as decompress from 'decompress';
17
+ import decompress from 'decompress';
18
18
  import * as path from 'path';
19
- import * as filenamify from 'filenamify';
19
+ import filenamify from 'filenamify';
20
20
  import { FileUri } from '@theia/core/lib/node';
21
21
  import * as fs from '@theia/core/shared/fs-extra';
22
22
  import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';