@theia/plugin-ext 1.42.0 → 1.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/lib/common/arrays.d.ts +4 -0
  2. package/lib/common/arrays.d.ts.map +1 -1
  3. package/lib/common/arrays.js +15 -1
  4. package/lib/common/arrays.js.map +1 -1
  5. package/lib/common/commands.d.ts +4 -0
  6. package/lib/common/commands.d.ts.map +1 -0
  7. package/lib/common/commands.js +17 -0
  8. package/lib/common/commands.js.map +1 -0
  9. package/lib/common/plugin-api-rpc-model.d.ts +1 -0
  10. package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
  11. package/lib/common/plugin-api-rpc-model.js.map +1 -1
  12. package/lib/common/plugin-api-rpc.d.ts +48 -6
  13. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  14. package/lib/common/plugin-api-rpc.js +3 -2
  15. package/lib/common/plugin-api-rpc.js.map +1 -1
  16. package/lib/common/plugin-protocol.d.ts +27 -3
  17. package/lib/common/plugin-protocol.d.ts.map +1 -1
  18. package/lib/common/plugin-protocol.js +8 -1
  19. package/lib/common/plugin-protocol.js.map +1 -1
  20. package/lib/common/test-types.d.ts +83 -0
  21. package/lib/common/test-types.d.ts.map +1 -0
  22. package/lib/common/test-types.js +40 -0
  23. package/lib/common/test-types.js.map +1 -0
  24. package/lib/hosted/browser/hosted-plugin.d.ts +4 -1
  25. package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
  26. package/lib/hosted/browser/hosted-plugin.js +11 -0
  27. package/lib/hosted/browser/hosted-plugin.js.map +1 -1
  28. package/lib/hosted/node/hosted-plugin-localization-service.d.ts.map +1 -1
  29. package/lib/hosted/node/hosted-plugin-localization-service.js +71 -33
  30. package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
  31. package/lib/hosted/node/plugin-reader.d.ts.map +1 -1
  32. package/lib/hosted/node/plugin-reader.js +4 -2
  33. package/lib/hosted/node/plugin-reader.js.map +1 -1
  34. package/lib/hosted/node/scanners/scanner-theia.d.ts +5 -4
  35. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  36. package/lib/hosted/node/scanners/scanner-theia.js +79 -19
  37. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  38. package/lib/main/browser/command-registry-main.d.ts +3 -0
  39. package/lib/main/browser/command-registry-main.d.ts.map +1 -1
  40. package/lib/main/browser/command-registry-main.js +11 -1
  41. package/lib/main/browser/command-registry-main.js.map +1 -1
  42. package/lib/main/browser/languages-main.d.ts.map +1 -1
  43. package/lib/main/browser/languages-main.js +7 -5
  44. package/lib/main/browser/languages-main.js.map +1 -1
  45. package/lib/main/browser/main-context.d.ts.map +1 -1
  46. package/lib/main/browser/main-context.js +3 -0
  47. package/lib/main/browser/main-context.js.map +1 -1
  48. package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts +2 -2
  49. package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts.map +1 -1
  50. package/lib/main/browser/menus/vscode-theia-menu-mappings.js +3 -0
  51. package/lib/main/browser/menus/vscode-theia-menu-mappings.js.map +1 -1
  52. package/lib/main/browser/notebooks/notebook-documents-and-editors-main.js +2 -2
  53. package/lib/main/browser/notebooks/notebook-documents-and-editors-main.js.map +1 -1
  54. package/lib/main/browser/notebooks/notebook-documents-main.js +1 -1
  55. package/lib/main/browser/notebooks/notebook-documents-main.js.map +1 -1
  56. package/lib/main/browser/notebooks/notebook-dto.js +2 -2
  57. package/lib/main/browser/notebooks/notebook-dto.js.map +1 -1
  58. package/lib/main/browser/notebooks/notebook-kernels-main.d.ts.map +1 -1
  59. package/lib/main/browser/notebooks/notebook-kernels-main.js +4 -10
  60. package/lib/main/browser/notebooks/notebook-kernels-main.js.map +1 -1
  61. package/lib/main/browser/notebooks/notebook-renderers-main.js +1 -1
  62. package/lib/main/browser/notebooks/notebook-renderers-main.js.map +1 -1
  63. package/lib/main/browser/notebooks/notebooks-main.d.ts +2 -2
  64. package/lib/main/browser/notebooks/notebooks-main.d.ts.map +1 -1
  65. package/lib/main/browser/notebooks/notebooks-main.js +5 -5
  66. package/lib/main/browser/notebooks/notebooks-main.js.map +1 -1
  67. package/lib/main/browser/notebooks/renderers/cell-output-webview.d.ts.map +1 -1
  68. package/lib/main/browser/notebooks/renderers/cell-output-webview.js +3 -0
  69. package/lib/main/browser/notebooks/renderers/cell-output-webview.js.map +1 -1
  70. package/lib/main/browser/notebooks/renderers/output-webview-internal.d.ts.map +1 -1
  71. package/lib/main/browser/notebooks/renderers/output-webview-internal.js +4 -2
  72. package/lib/main/browser/notebooks/renderers/output-webview-internal.js.map +1 -1
  73. package/lib/main/browser/plugin-contribution-handler.d.ts +2 -0
  74. package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
  75. package/lib/main/browser/plugin-contribution-handler.js +19 -1
  76. package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
  77. package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
  78. package/lib/main/browser/plugin-ext-frontend-module.js +3 -0
  79. package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
  80. package/lib/main/browser/plugin-icon-service.d.ts +20 -0
  81. package/lib/main/browser/plugin-icon-service.d.ts.map +1 -0
  82. package/lib/main/browser/plugin-icon-service.js +156 -0
  83. package/lib/main/browser/plugin-icon-service.js.map +1 -0
  84. package/lib/main/browser/terminal-main.d.ts +2 -2
  85. package/lib/main/browser/terminal-main.d.ts.map +1 -1
  86. package/lib/main/browser/terminal-main.js +5 -9
  87. package/lib/main/browser/terminal-main.js.map +1 -1
  88. package/lib/main/browser/test-main.d.ts +141 -0
  89. package/lib/main/browser/test-main.d.ts.map +1 -0
  90. package/lib/main/browser/test-main.js +560 -0
  91. package/lib/main/browser/test-main.js.map +1 -0
  92. package/lib/main/browser/view/plugin-view-registry.d.ts +14 -3
  93. package/lib/main/browser/view/plugin-view-registry.d.ts.map +1 -1
  94. package/lib/main/browser/view/plugin-view-registry.js +108 -56
  95. package/lib/main/browser/view/plugin-view-registry.js.map +1 -1
  96. package/lib/main/browser/webview-views/webview-views-main.d.ts.map +1 -1
  97. package/lib/main/browser/webview-views/webview-views-main.js +5 -2
  98. package/lib/main/browser/webview-views/webview-views-main.js.map +1 -1
  99. package/lib/main/browser/webview-views/webview-views.d.ts +1 -0
  100. package/lib/main/browser/webview-views/webview-views.d.ts.map +1 -1
  101. package/lib/main/node/plugin-service.d.ts +2 -0
  102. package/lib/main/node/plugin-service.d.ts.map +1 -1
  103. package/lib/main/node/plugin-service.js +14 -1
  104. package/lib/main/node/plugin-service.js.map +1 -1
  105. package/lib/plugin/command-registry.d.ts +1 -3
  106. package/lib/plugin/command-registry.d.ts.map +1 -1
  107. package/lib/plugin/command-registry.js.map +1 -1
  108. package/lib/plugin/notebook/notebook-kernels.d.ts.map +1 -1
  109. package/lib/plugin/notebook/notebook-kernels.js +1 -0
  110. package/lib/plugin/notebook/notebook-kernels.js.map +1 -1
  111. package/lib/plugin/notebook/notebooks.d.ts.map +1 -1
  112. package/lib/plugin/notebook/notebooks.js +2 -2
  113. package/lib/plugin/notebook/notebooks.js.map +1 -1
  114. package/lib/plugin/plugin-context.d.ts.map +1 -1
  115. package/lib/plugin/plugin-context.js +9 -18
  116. package/lib/plugin/plugin-context.js.map +1 -1
  117. package/lib/plugin/telemetry-ext.js +1 -1
  118. package/lib/plugin/telemetry-ext.js.map +1 -1
  119. package/lib/plugin/terminal-ext.d.ts +11 -9
  120. package/lib/plugin/terminal-ext.d.ts.map +1 -1
  121. package/lib/plugin/terminal-ext.js +37 -25
  122. package/lib/plugin/terminal-ext.js.map +1 -1
  123. package/lib/plugin/test-item.d.ts +47 -0
  124. package/lib/plugin/test-item.d.ts.map +1 -0
  125. package/lib/plugin/test-item.js +196 -0
  126. package/lib/plugin/test-item.js.map +1 -0
  127. package/lib/plugin/tests.d.ts +117 -0
  128. package/lib/plugin/tests.d.ts.map +1 -0
  129. package/lib/plugin/tests.js +402 -0
  130. package/lib/plugin/tests.js.map +1 -0
  131. package/lib/plugin/tree/tree-views.d.ts.map +1 -1
  132. package/lib/plugin/tree/tree-views.js +2 -1
  133. package/lib/plugin/tree/tree-views.js.map +1 -1
  134. package/lib/plugin/type-converters.d.ts +10 -1
  135. package/lib/plugin/type-converters.d.ts.map +1 -1
  136. package/lib/plugin/type-converters.js +74 -2
  137. package/lib/plugin/type-converters.js.map +1 -1
  138. package/lib/plugin/types-impl.d.ts +29 -4
  139. package/lib/plugin/types-impl.d.ts.map +1 -1
  140. package/lib/plugin/types-impl.js +30 -8
  141. package/lib/plugin/types-impl.js.map +1 -1
  142. package/package.json +30 -29
  143. package/src/common/arrays.ts +16 -0
  144. package/src/common/commands.ts +19 -0
  145. package/src/common/plugin-api-rpc-model.ts +1 -0
  146. package/src/common/plugin-api-rpc.ts +69 -7
  147. package/src/common/plugin-protocol.ts +31 -3
  148. package/src/common/test-types.ts +133 -0
  149. package/src/hosted/browser/hosted-plugin.ts +13 -1
  150. package/src/hosted/node/hosted-plugin-localization-service.ts +72 -37
  151. package/src/hosted/node/plugin-reader.ts +4 -2
  152. package/src/hosted/node/scanners/scanner-theia.ts +85 -20
  153. package/src/main/browser/command-registry-main.ts +14 -1
  154. package/src/main/browser/languages-main.ts +7 -5
  155. package/src/main/browser/main-context.ts +4 -0
  156. package/src/main/browser/menus/vscode-theia-menu-mappings.ts +3 -0
  157. package/src/main/browser/notebooks/notebook-documents-and-editors-main.ts +2 -2
  158. package/src/main/browser/notebooks/notebook-documents-main.ts +1 -1
  159. package/src/main/browser/notebooks/notebook-dto.ts +2 -2
  160. package/src/main/browser/notebooks/notebook-kernels-main.ts +6 -11
  161. package/src/main/browser/notebooks/notebook-renderers-main.ts +1 -1
  162. package/src/main/browser/notebooks/notebooks-main.ts +6 -6
  163. package/src/main/browser/notebooks/renderers/cell-output-webview.tsx +3 -0
  164. package/src/main/browser/notebooks/renderers/output-webview-internal.ts +3 -2
  165. package/src/main/browser/plugin-contribution-handler.ts +19 -2
  166. package/src/main/browser/plugin-ext-frontend-module.ts +4 -0
  167. package/src/main/browser/plugin-icon-service.ts +156 -0
  168. package/src/main/browser/terminal-main.ts +7 -11
  169. package/src/main/browser/test-main.ts +618 -0
  170. package/src/main/browser/view/plugin-view-registry.ts +114 -56
  171. package/src/main/browser/webview-views/webview-views-main.ts +5 -2
  172. package/src/main/browser/webview-views/webview-views.ts +1 -0
  173. package/src/main/node/plugin-service.ts +12 -1
  174. package/src/plugin/command-registry.ts +1 -5
  175. package/src/plugin/notebook/notebook-kernels.ts +3 -1
  176. package/src/plugin/notebook/notebooks.ts +1 -3
  177. package/src/plugin/plugin-context.ts +13 -32
  178. package/src/plugin/telemetry-ext.ts +1 -1
  179. package/src/plugin/terminal-ext.ts +40 -26
  180. package/src/plugin/test-item.ts +174 -0
  181. package/src/plugin/tests.ts +482 -0
  182. package/src/plugin/tree/tree-views.ts +2 -1
  183. package/src/plugin/type-converters.ts +87 -3
  184. package/src/plugin/types-impl.ts +36 -5
  185. package/lib/plugin/stubs/tests-api.d.ts +0 -25
  186. package/lib/plugin/stubs/tests-api.d.ts.map +0 -1
  187. package/lib/plugin/stubs/tests-api.js +0 -70
  188. package/lib/plugin/stubs/tests-api.js.map +0 -1
  189. package/src/plugin/stubs/tests-api.ts +0 -102
@@ -23,6 +23,7 @@ import {
23
23
  buildFrontendModuleName,
24
24
  DebuggerContribution,
25
25
  IconThemeContribution,
26
+ IconContribution,
26
27
  IconUrl,
27
28
  Keybinding,
28
29
  LanguageConfiguration,
@@ -60,7 +61,8 @@ import {
60
61
  PluginPackageTranslation,
61
62
  Translation,
62
63
  PluginIdentifiers,
63
- TerminalProfile
64
+ TerminalProfile,
65
+ PluginIconContribution
64
66
  } from '../../../common/plugin-protocol';
65
67
  import { promises as fs } from 'fs';
66
68
  import * as path from 'path';
@@ -74,6 +76,7 @@ import { deepClone } from '@theia/core/lib/common/objects';
74
76
  import { PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/common/preferences/preference-schema';
75
77
  import { TaskDefinition } from '@theia/task/lib/common/task-protocol';
76
78
  import { ColorDefinition } from '@theia/core/lib/common/color';
79
+ import { CSSIcon } from '@theia/core/lib/common/markdown-rendering/icon-utilities';
77
80
  import { PluginUriFactory } from './plugin-uri-factory';
78
81
 
79
82
  namespace nls {
@@ -89,6 +92,12 @@ const INTERNAL_CONSOLE_OPTIONS_SCHEMA = {
89
92
  };
90
93
 
91
94
  const colorIdPattern = '^\\w+[.\\w+]*$';
95
+ const iconIdPattern = `^${CSSIcon.iconNameSegment}(-${CSSIcon.iconNameSegment})+$`;
96
+
97
+ function getFileExtension(filePath: string): string {
98
+ const index = filePath.lastIndexOf('.');
99
+ return index === -1 ? '' : filePath.substring(index + 1);
100
+ }
92
101
 
93
102
  @injectable()
94
103
  export class TheiaPluginScanner implements PluginScanner {
@@ -331,6 +340,12 @@ export class TheiaPluginScanner implements PluginScanner {
331
340
  console.error(`Could not read '${rawPlugin.name}' contribution 'themes'.`, rawPlugin.contributes.themes, err);
332
341
  }
333
342
 
343
+ try {
344
+ contributions.icons = this.readIcons(rawPlugin);
345
+ } catch (err) {
346
+ console.error(`Could not read '${rawPlugin.name}' contribution 'icons'.`, rawPlugin.contributes.icons, err);
347
+ }
348
+
334
349
  try {
335
350
  contributions.iconThemes = this.readIconThemes(rawPlugin);
336
351
  } catch (err) {
@@ -349,18 +364,17 @@ export class TheiaPluginScanner implements PluginScanner {
349
364
  console.error(`Could not read '${rawPlugin.name}' contribution 'terminals'.`, rawPlugin.contributes.terminal, err);
350
365
  }
351
366
 
352
- const [localizationsResult, languagesResult, grammarsResult] = await Promise.allSettled([
353
- this.readLocalizations(rawPlugin),
367
+ try {
368
+ contributions.localizations = this.readLocalizations(rawPlugin);
369
+ } catch (err) {
370
+ console.error(`Could not read '${rawPlugin.name}' contribution 'localizations'.`, rawPlugin.contributes.localizations, err);
371
+ }
372
+
373
+ const [languagesResult, grammarsResult] = await Promise.allSettled([
354
374
  rawPlugin.contributes.languages ? this.readLanguages(rawPlugin.contributes.languages, rawPlugin.packagePath) : undefined,
355
375
  rawPlugin.contributes.grammars ? this.grammarsReader.readGrammars(rawPlugin.contributes.grammars, rawPlugin.packagePath) : undefined
356
376
  ]);
357
377
 
358
- if (localizationsResult.status === 'fulfilled') {
359
- contributions.localizations = localizationsResult.value;
360
- } else {
361
- console.error(`Could not read '${rawPlugin.name}' contribution 'localizations'.`, rawPlugin.contributes.localizations, localizationsResult.reason);
362
- }
363
-
364
378
  if (rawPlugin.contributes.languages) {
365
379
  if (languagesResult.status === 'fulfilled') {
366
380
  contributions.languages = languagesResult.value;
@@ -387,31 +401,29 @@ export class TheiaPluginScanner implements PluginScanner {
387
401
  return pck.contributes.terminal.profiles.filter(profile => profile.id && profile.title);
388
402
  }
389
403
 
390
- protected async readLocalizations(pck: PluginPackage): Promise<Localization[] | undefined> {
404
+ protected readLocalizations(pck: PluginPackage): Localization[] | undefined {
391
405
  if (!pck.contributes || !pck.contributes.localizations) {
392
406
  return undefined;
393
407
  }
394
- return Promise.all(pck.contributes.localizations.map(e => this.readLocalization(e, pck.packagePath)));
408
+ return pck.contributes.localizations.map(e => this.readLocalization(e, pck.packagePath));
395
409
  }
396
410
 
397
- protected async readLocalization({ languageId, languageName, localizedLanguageName, translations }: PluginPackageLocalization, pluginPath: string): Promise<Localization> {
411
+ protected readLocalization({ languageId, languageName, localizedLanguageName, translations }: PluginPackageLocalization, pluginPath: string): Localization {
398
412
  const local: Localization = {
399
413
  languageId,
400
414
  languageName,
401
415
  localizedLanguageName,
402
416
  translations: []
403
417
  };
404
- local.translations = await Promise.all(translations.map(e => this.readTranslation(e, pluginPath)));
418
+ local.translations = translations.map(e => this.readTranslation(e, pluginPath));
405
419
  return local;
406
420
  }
407
421
 
408
- protected async readTranslation(packageTranslation: PluginPackageTranslation, pluginPath: string): Promise<Translation> {
409
- const translation = await this.readJson<Translation>(path.resolve(pluginPath, packageTranslation.path));
410
- if (!translation) {
411
- throw new Error(`Could not read json file '${packageTranslation.path}'.`);
412
- }
413
- translation.id = packageTranslation.id;
414
- translation.path = packageTranslation.path;
422
+ protected readTranslation(packageTranslation: PluginPackageTranslation, pluginPath: string): Translation {
423
+ const translation: Translation = {
424
+ id: packageTranslation.id,
425
+ path: packageTranslation.path
426
+ };
415
427
  return translation;
416
428
  }
417
429
 
@@ -523,6 +535,59 @@ export class TheiaPluginScanner implements PluginScanner {
523
535
  return result;
524
536
  }
525
537
 
538
+ protected readIcons(pck: PluginPackage): IconContribution[] | undefined {
539
+ if (!pck.contributes || !pck.contributes.icons) {
540
+ return undefined;
541
+ }
542
+ const result: IconContribution[] = [];
543
+ const iconEntries = <PluginIconContribution>(<unknown>pck.contributes.icons);
544
+ for (const id in iconEntries) {
545
+ if (pck.contributes.icons.hasOwnProperty(id)) {
546
+ if (!id.match(iconIdPattern)) {
547
+ console.error("'configuration.icons' keys represent the icon id and can only contain letter, digits and minuses. " +
548
+ 'They need to consist of at least two segments in the form `component-iconname`.', 'extension: ', pck.name, 'icon id: ', id);
549
+ return;
550
+ }
551
+ const iconContribution = iconEntries[id];
552
+ if (typeof iconContribution.description !== 'string' || iconContribution.description['length'] === 0) {
553
+ console.error('configuration.icons.description must be defined and can not be empty, ', 'extension: ', pck.name, 'icon id: ', id);
554
+ return;
555
+ }
556
+
557
+ const defaultIcon = iconContribution.default;
558
+ if (typeof defaultIcon === 'string') {
559
+ result.push({
560
+ id,
561
+ extensionId: pck.publisher + '.' + pck.name,
562
+ description: iconContribution.description,
563
+ defaults: { id: defaultIcon }
564
+ });
565
+ } else if (typeof defaultIcon === 'object' && typeof defaultIcon.fontPath === 'string' && typeof defaultIcon.fontCharacter === 'string') {
566
+ const format = getFileExtension(defaultIcon.fontPath);
567
+ if (['woff', 'woff2', 'ttf'].indexOf(format) === -1) {
568
+ console.warn("Expected `contributes.icons.default.fontPath` to have file extension 'woff', woff2' or 'ttf', is '{0}'.", format);
569
+ return;
570
+ }
571
+
572
+ const iconFontLocation = this.pluginUriFactory.createUri(pck, defaultIcon.fontPath).toString();
573
+ result.push({
574
+ id,
575
+ extensionId: pck.publisher + '.' + pck.name,
576
+ description: iconContribution.description,
577
+ defaults: {
578
+ fontCharacter: defaultIcon.fontCharacter,
579
+ location: iconFontLocation
580
+ }
581
+ });
582
+ } else {
583
+ console.error("'configuration.icons.default' must be either a reference to the id of an other theme icon (string) or a icon definition (object) with ",
584
+ 'properties `fontPath` and `fontCharacter`.');
585
+ }
586
+ }
587
+ }
588
+ return result;
589
+ }
590
+
526
591
  protected readSnippets(pck: PluginPackage): SnippetContribution[] | undefined {
527
592
  if (!pck.contributes || !pck.contributes.snippets) {
528
593
  return undefined;
@@ -22,6 +22,7 @@ import { CommandRegistryMain, CommandRegistryExt, MAIN_RPC_CONTEXT } from '../..
22
22
  import { RPCProtocol } from '../../common/rpc-protocol';
23
23
  import { KeybindingRegistry } from '@theia/core/lib/browser';
24
24
  import { PluginContributionHandler } from './plugin-contribution-handler';
25
+ import { ArgumentProcessor } from '../../common/commands';
25
26
 
26
27
  export class CommandRegistryMainImpl implements CommandRegistryMain, Disposable {
27
28
  private readonly proxy: CommandRegistryExt;
@@ -31,6 +32,8 @@ export class CommandRegistryMainImpl implements CommandRegistryMain, Disposable
31
32
  private readonly keyBinding: KeybindingRegistry;
32
33
  private readonly contributions: PluginContributionHandler;
33
34
 
35
+ private readonly argumentProcessors: ArgumentProcessor[] = [];
36
+
34
37
  protected readonly toDispose = new DisposableCollection();
35
38
 
36
39
  constructor(rpc: RPCProtocol, container: interfaces.Container) {
@@ -44,6 +47,16 @@ export class CommandRegistryMainImpl implements CommandRegistryMain, Disposable
44
47
  this.toDispose.dispose();
45
48
  }
46
49
 
50
+ registerArgumentProcessor(processor: ArgumentProcessor): Disposable {
51
+ this.argumentProcessors.push(processor);
52
+ return Disposable.create(() => {
53
+ const index = this.argumentProcessors.lastIndexOf(processor);
54
+ if (index >= 0) {
55
+ this.argumentProcessors.splice(index, 1);
56
+ }
57
+ });
58
+ }
59
+
47
60
  $registerCommand(command: theia.CommandDescription): void {
48
61
  const id = command.id;
49
62
  this.commands.set(id, this.contributions.registerCommand(command));
@@ -59,7 +72,7 @@ export class CommandRegistryMainImpl implements CommandRegistryMain, Disposable
59
72
 
60
73
  $registerHandler(id: string): void {
61
74
  this.handlers.set(id, this.contributions.registerCommandHandler(id, (...args) =>
62
- this.proxy.$executeCommand(id, ...args)
75
+ this.proxy.$executeCommand(id, ...args.map(arg => this.argumentProcessors.reduce((currentValue, processor) => processor.processArgument(currentValue), arg)))
63
76
  ));
64
77
  this.toDispose.push(Disposable.create(() => this.$unregisterHandler(id)));
65
78
  }
@@ -740,7 +740,8 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
740
740
 
741
741
  createDocumentDropEditProvider(handle: number, _metadata?: DocumentDropEditProviderMetadata): DocumentOnDropEditProvider {
742
742
  return {
743
- // @monaco-uplift dropMimeTypes should be supported by the monaco drop editor provider after 1.79.0
743
+ // @monaco-uplift id and dropMimeTypes should be supported by the monaco drop editor provider after 1.82.0
744
+ // id?: string;
744
745
  // dropMimeTypes: metadata?.dropMimeTypes ?? ['*/*'],
745
746
  provideDocumentOnDropEdits: async (model, position, dataTransfer, token) => this.provideDocumentDropEdits(handle, model, position, dataTransfer, token)
746
747
  };
@@ -752,10 +753,11 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
752
753
  const edit = await this.proxy.$provideDocumentDropEdits(handle, model.uri, position, await DataTransfer.toDataTransferDTO(dataTransfer), token);
753
754
  if (edit) {
754
755
  return {
755
- // @monaco-uplift id, priority and label should be supported by monaco after 1.79.0. The implementation relies on a copy of the plugin data
756
- // id: edit.id ? plugin.identifier.value + '.' + edit.id : plugin.identifier.value,
757
- // label: edit.label ?? nls.localizeByDefault("Drop using '{0}' extension", plugin.displayName || plugin.name),
758
- // priority: edit.priority ?? 0,
756
+ // @monaco-uplift label and yieldTo should be supported by monaco after 1.82.0. The implementation relies on a copy of the plugin data
757
+ // label: label: edit.label ?? localize('defaultDropLabel', "Drop using '{0}' extension", this._extension.displayName || this._extension.name),,
758
+ // yieldTo: edit.yieldTo?.map(yTo => {
759
+ // return 'mimeType' in yTo ? yTo : { providerId: DocumentOnDropEditAdapter.toInternalProviderId(yTo.extensionId, yTo.providerId) };
760
+ // }),
759
761
  insertText: edit.insertText instanceof SnippetString ? { snippet: edit.insertText.value } : edit.insertText,
760
762
  additionalEdit: toMonacoWorkspaceEdit(edit?.additionalEdit)
761
763
  };
@@ -68,6 +68,7 @@ import { NotebookEditorsMainImpl } from './notebooks/notebook-editors-main';
68
68
  import { NotebookDocumentsMainImpl } from './notebooks/notebook-documents-main';
69
69
  import { NotebookKernelsMainImpl } from './notebooks/notebook-kernels-main';
70
70
  import { NotebooksAndEditorsMain } from './notebooks/notebook-documents-and-editors-main';
71
+ import { TestingMainImpl } from './test-main';
71
72
 
72
73
  export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container): void {
73
74
  const authenticationMain = new AuthenticationMainImpl(rpc, container);
@@ -130,6 +131,9 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
130
131
  const notificationMain = new NotificationMainImpl(rpc, container);
131
132
  rpc.set(PLUGIN_RPC_CONTEXT.NOTIFICATION_MAIN, notificationMain);
132
133
 
134
+ const testingMain = new TestingMainImpl(rpc, container, commandRegistryMain);
135
+ rpc.set(PLUGIN_RPC_CONTEXT.TESTING_MAIN, testingMain);
136
+
133
137
  const terminalMain = new TerminalServiceMainImpl(rpc, container);
134
138
  rpc.set(PLUGIN_RPC_CONTEXT.TERMINAL_MAIN, terminalMain);
135
139
 
@@ -31,6 +31,7 @@ import { COMMENT_CONTEXT, COMMENT_THREAD_CONTEXT, COMMENT_TITLE } from '../comme
31
31
  import { VIEW_ITEM_CONTEXT_MENU } from '../view/tree-view-widget';
32
32
  import { WebviewWidget } from '../webview/webview';
33
33
  import { EDITOR_LINENUMBER_CONTEXT_MENU } from '@theia/editor/lib/browser/editor-linenumber-contribution';
34
+ import { TEST_VIEW_CONTEXT_MENU } from '@theia/test/lib/browser/view/test-view-contribution';
34
35
 
35
36
  export const PLUGIN_EDITOR_TITLE_MENU = ['plugin_editor/title'];
36
37
  export const PLUGIN_EDITOR_TITLE_RUN_MENU = ['plugin_editor/title/run'];
@@ -55,6 +56,7 @@ export const implementedVSCodeContributionPoints = [
55
56
  'scm/resourceState/context',
56
57
  'scm/title',
57
58
  'timeline/item/context',
59
+ 'testing/item/context',
58
60
  'view/item/context',
59
61
  'view/title'
60
62
  ] as const;
@@ -79,6 +81,7 @@ export const codeToTheiaMappings = new Map<ContributionPoint, MenuPath[]>([
79
81
  ['scm/resourceGroup/context', [ScmTreeWidget.RESOURCE_GROUP_CONTEXT_MENU]],
80
82
  ['scm/resourceState/context', [ScmTreeWidget.RESOURCE_CONTEXT_MENU]],
81
83
  ['scm/title', [PLUGIN_SCM_TITLE_MENU]],
84
+ ['testing/item/context', [TEST_VIEW_CONTEXT_MENU]],
82
85
  ['timeline/item/context', [TIMELINE_ITEM_CONTEXT_MENU]],
83
86
  ['view/item/context', [VIEW_ITEM_CONTEXT_MENU]],
84
87
  ['view/title', [PLUGIN_VIEW_TITLE_MENU]],
@@ -111,7 +111,7 @@ export class NotebooksAndEditorsMain implements NotebookDocumentsAndEditorsMain
111
111
  // this.WidgetManager.onActiveEditorChanged(() => this.updateState(), this, this.disposables);
112
112
  this.notebookEditorService.onDidAddNotebookEditor(async editor => this.handleEditorAdd(editor), this, this.disposables);
113
113
  this.notebookEditorService.onDidRemoveNotebookEditor(async editor => this.handleEditorRemove(editor), this, this.disposables);
114
- this.notebookEditorService.onFocusedEditorChanged(async editor => this.updateState(editor), this, this.disposables);
114
+ this.notebookEditorService.onDidChangeFocusedEditor(async editor => this.updateState(editor), this, this.disposables);
115
115
  }
116
116
 
117
117
  dispose(): void {
@@ -154,7 +154,7 @@ export class NotebooksAndEditorsMain implements NotebookDocumentsAndEditorsMain
154
154
  }
155
155
  }
156
156
 
157
- const activeNotebookEditor = this.notebookEditorService.currentFocusedEditor;
157
+ const activeNotebookEditor = this.notebookEditorService.focusedEditor;
158
158
  let activeEditor: string | null = null;
159
159
  if (activeNotebookEditor) {
160
160
  activeEditor = activeNotebookEditor.id;
@@ -131,7 +131,7 @@ export class NotebookDocumentsMainImpl implements NotebookDocumentsMain {
131
131
  }
132
132
 
133
133
  async $tryCreateNotebook(options: { viewType: string; content?: NotebookDataDto }): Promise<UriComponents> {
134
- const ref = await this.notebookModelResolverService.resolve({ untitledResource: undefined }, options.viewType);
134
+ const ref = await this.notebookModelResolverService.resolveUntitledResource({ untitledResource: undefined }, options.viewType);
135
135
 
136
136
  // untitled notebooks are disposed when they get saved. we should not hold a reference
137
137
  // to such a disposed notebook and therefore dispose the reference as well
@@ -88,11 +88,11 @@ export namespace NotebookDto {
88
88
  }
89
89
 
90
90
  export function toNotebookCellDto(cell: NotebookCellModel): rpc.NotebookCellDto {
91
- const eol = OS.backend.isWindows ? '\r\n' : '\n';
91
+ const eol = OS.backend.EOL;
92
92
  return {
93
93
  handle: cell.handle,
94
94
  uri: cell.uri.toComponents(),
95
- source: cell.textBuffer.split(eol),
95
+ source: cell.text.split(eol),
96
96
  eol,
97
97
  language: cell.language,
98
98
  cellKind: cell.cellKind,
@@ -36,7 +36,7 @@ abstract class NotebookKernel {
36
36
 
37
37
  readonly id: string;
38
38
  readonly viewType: string;
39
- readonly extension: string;
39
+ readonly extensionId: string;
40
40
 
41
41
  implementsInterrupt: boolean;
42
42
  label: string;
@@ -57,7 +57,7 @@ abstract class NotebookKernel {
57
57
  constructor(data: NotebookKernelDto, private languageService: LanguageService) {
58
58
  this.id = data.id;
59
59
  this.viewType = data.notebookType;
60
- this.extension = data.extensionId;
60
+ this.extensionId = data.extensionId;
61
61
 
62
62
  this.implementsInterrupt = data.supportsInterrupt ?? false;
63
63
  this.label = data.label;
@@ -104,10 +104,6 @@ abstract class NotebookKernel {
104
104
  abstract cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise<void>;
105
105
  }
106
106
 
107
- class KernelDetectionTask {
108
- constructor(readonly notebookType: string) { }
109
- }
110
-
111
107
  export interface KernelSourceActionProvider {
112
108
  readonly viewType: string;
113
109
  onDidChangeSourceActions?: Event<void>;
@@ -120,7 +116,7 @@ export class NotebookKernelsMainImpl implements NotebookKernelsMain {
120
116
 
121
117
  private readonly kernels = new Map<number, [kernel: NotebookKernel, registration: Disposable]>();
122
118
 
123
- private readonly kernelDetectionTasks = new Map<number, [task: KernelDetectionTask, registration: Disposable]>();
119
+ private readonly kernelDetectionTasks = new Map<number, [task: string, registration: Disposable]>();
124
120
 
125
121
  private readonly kernelSourceActionProviders = new Map<number, [provider: KernelSourceActionProvider, registration: Disposable]>();
126
122
  private readonly kernelSourceActionProvidersEventRegistrations = new Map<number, Disposable>();
@@ -202,7 +198,7 @@ export class NotebookKernelsMainImpl implements NotebookKernelsMain {
202
198
  if (!kernel.selected || kernel.selected.id !== controllerId) {
203
199
  throw new Error(`Kernel is not selected: ${kernel.selected?.id} !== ${controllerId}`);
204
200
  }
205
- const execution = this.notebookExecutionStateService.createCellExecution(uri, cellHandle);
201
+ const execution = this.notebookExecutionStateService.getOrCreateCellExecution(uri, cellHandle);
206
202
  execution.confirm();
207
203
  this.executions.set(handle, execution);
208
204
  }
@@ -234,9 +230,8 @@ export class NotebookKernelsMainImpl implements NotebookKernelsMain {
234
230
  }
235
231
 
236
232
  async $addKernelDetectionTask(handle: number, notebookType: string): Promise<void> {
237
- const kernelDetectionTask = new KernelDetectionTask(notebookType);
238
- const registration = this.notebookKernelService.registerNotebookKernelDetectionTask(kernelDetectionTask);
239
- this.kernelDetectionTasks.set(handle, [kernelDetectionTask, registration]);
233
+ const registration = this.notebookKernelService.registerNotebookKernelDetectionTask(notebookType);
234
+ this.kernelDetectionTasks.set(handle, [notebookType, registration]);
240
235
  }
241
236
  $removeKernelDetectionTask(handle: number): void {
242
237
  const tuple = this.kernelDetectionTasks.get(handle);
@@ -32,7 +32,7 @@ export class NotebookRenderersMainImpl implements NotebookRenderersMain {
32
32
  ) {
33
33
  this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.NOTEBOOK_RENDERERS_EXT);
34
34
  this.rendererMessagingService = container.get(NotebookRendererMessagingService);
35
- this.rendererMessagingService.onShouldPostMessage(e => {
35
+ this.rendererMessagingService.onPostMessage(e => {
36
36
  this.proxy.$postRendererMessage(e.editorId, e.rendererId, e.message);
37
37
  });
38
38
  }
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { CancellationToken, DisposableCollection, Emitter } from '@theia/core';
18
18
  import { BinaryBuffer } from '@theia/core/lib/common/buffer';
19
- import { NotebookCellStatusBarItemList, NotebookCellStatusBarItemProvider, NotebookData, NotebookExtensionDescription, TransientOptions } from '@theia/notebook/lib/common';
19
+ import { NotebookCellStatusBarItemList, NotebookCellStatusBarItemProvider, NotebookData, TransientOptions } from '@theia/notebook/lib/common';
20
20
  import { NotebookService } from '@theia/notebook/lib/browser';
21
21
  import { Disposable } from '@theia/plugin';
22
22
  import { MAIN_RPC_CONTEXT, NotebooksExt, NotebooksMain } from '../../../common';
@@ -39,7 +39,7 @@ export class NotebooksMainImpl implements NotebooksMain {
39
39
  plugins: HostedPluginSupport
40
40
  ) {
41
41
  this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.NOTEBOOKS_EXT);
42
- notebookService.onNotebookSerializer(async event => plugins.activateByEvent(event));
42
+ notebookService.onWillUseNotebookSerializer(async event => plugins.activateByNotebookSerializer(event));
43
43
  notebookService.markReady();
44
44
  }
45
45
 
@@ -50,16 +50,16 @@ export class NotebooksMainImpl implements NotebooksMain {
50
50
  }
51
51
  }
52
52
 
53
- $registerNotebookSerializer(handle: number, extension: NotebookExtensionDescription, viewType: string, options: TransientOptions): void {
53
+ $registerNotebookSerializer(handle: number, viewType: string, options: TransientOptions): void {
54
54
  const disposables = new DisposableCollection();
55
55
 
56
- disposables.push(this.notebookService.registerNotebookSerializer(viewType, extension, {
56
+ disposables.push(this.notebookService.registerNotebookSerializer(viewType, {
57
57
  options,
58
- dataToNotebook: async (data: BinaryBuffer): Promise<NotebookData> => {
58
+ toNotebook: async (data: BinaryBuffer): Promise<NotebookData> => {
59
59
  const dto = await this.proxy.$dataToNotebook(handle, data, CancellationToken.None);
60
60
  return NotebookDto.fromNotebookDataDto(dto);
61
61
  },
62
- notebookToData: (data: NotebookData): Promise<BinaryBuffer> =>
62
+ fromNotebook: (data: NotebookData): Promise<BinaryBuffer> =>
63
63
  this.proxy.$notebookToData(handle, NotebookDto.toNotebookDataDto(data), CancellationToken.None)
64
64
 
65
65
  }));
@@ -75,6 +75,9 @@ export class CellOutputWebviewImpl implements CellOutputWebview, Disposable {
75
75
  @postConstruct()
76
76
  protected async init(): Promise<void> {
77
77
  this.cell.onDidChangeOutputs(outputChange => this.updateOutput(outputChange));
78
+ this.cell.onDidChangeOutputItems(output => {
79
+ this.updateOutput({start: this.cell.outputs.findIndex(o => o.getData().outputId === o.outputId), deleteCount: 1, newOutputs: [output]});
80
+ });
78
81
 
79
82
  this.webviewWidget = await this.widgetManager.getOrCreateWidget(WebviewWidget.FACTORY_ID, { id: this.id });
80
83
  this.webviewWidget.setContentOptions({ allowScripts: true });
@@ -160,8 +160,8 @@ export async function outputWebviewPreload(ctx: PreloadContext): Promise<void> {
160
160
  if (this.rendererApi) {
161
161
  return this.rendererApi;
162
162
  }
163
-
164
- const rendererModule = await __import(this.data.entrypoint.uri) as { activate: rendererApi.ActivationFunction };
163
+ const baseUri = window.location.href.replace(/\/webview\/index\.html.*/, '');
164
+ const rendererModule = await __import(`${baseUri}/${this.data.entrypoint.uri}`) as { activate: rendererApi.ActivationFunction };
165
165
  this.rendererApi = await rendererModule.activate(this.createRendererContext());
166
166
  return this.rendererApi;
167
167
  }
@@ -381,6 +381,7 @@ export async function outputWebviewPreload(ctx: PreloadContext): Promise<void> {
381
381
  function clearOutput(outputId: string): void {
382
382
  outputs.get(outputId)?.clear();
383
383
  outputs.delete(outputId);
384
+ document.getElementById(outputId)?.remove();
384
385
  }
385
386
 
386
387
  function outputsChanged(changedEvent: webviewCommunication.OutputChangedMessage): void {
@@ -23,7 +23,7 @@ import { PluginViewRegistry } from './view/plugin-view-registry';
23
23
  import { PluginCustomEditorRegistry } from './custom-editors/plugin-custom-editor-registry';
24
24
  import {
25
25
  PluginContribution, IndentationRules, FoldingRules, ScopeMap, DeployedPlugin,
26
- GrammarsContribution, EnterAction, OnEnterRule, RegExpOptions, getPluginId
26
+ GrammarsContribution, EnterAction, OnEnterRule, RegExpOptions, IconContribution, PluginPackage
27
27
  } from '../../common';
28
28
  import {
29
29
  DefaultUriLabelProviderContribution,
@@ -43,6 +43,7 @@ import { PluginDebugService } from './debug/plugin-debug-service';
43
43
  import { DebugSchemaUpdater } from '@theia/debug/lib/browser/debug-schema-updater';
44
44
  import { MonacoThemingService } from '@theia/monaco/lib/browser/monaco-theming-service';
45
45
  import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
46
+ import { PluginIconService } from './plugin-icon-service';
46
47
  import { PluginIconThemeService } from './plugin-icon-theme-service';
47
48
  import { ContributionProvider } from '@theia/core/lib/common';
48
49
  import * as monaco from '@theia/monaco-editor-core';
@@ -112,6 +113,9 @@ export class PluginContributionHandler {
112
113
  @inject(ColorRegistry)
113
114
  protected readonly colors: ColorRegistry;
114
115
 
116
+ @inject(PluginIconService)
117
+ protected readonly iconService: PluginIconService;
118
+
115
119
  @inject(PluginIconThemeService)
116
120
  protected readonly iconThemeService: PluginIconThemeService;
117
121
 
@@ -332,6 +336,19 @@ export class PluginContributionHandler {
332
336
  }
333
337
  }
334
338
 
339
+ if (contributions.icons && contributions.icons.length) {
340
+ for (const icon of contributions.icons) {
341
+ const defaultIcon = icon.defaults;
342
+ let key: string;
343
+ if (IconContribution.isIconDefinition(defaultIcon)) {
344
+ key = defaultIcon.location;
345
+ } else {
346
+ key = defaultIcon.id;
347
+ }
348
+ pushContribution(`icons.${key}`, () => this.iconService.register(icon, plugin));
349
+ }
350
+ }
351
+
335
352
  const colors = contributions.colors;
336
353
  if (colors) {
337
354
  pushContribution('colors', () => this.colors.register(...colors));
@@ -416,7 +433,7 @@ export class PluginContributionHandler {
416
433
  if (contributions.notebookRenderer) {
417
434
  for (const renderer of contributions.notebookRenderer) {
418
435
  pushContribution(`notebookRenderer.${renderer.id}`,
419
- () => this.notebookRendererRegistry.registerNotebookRenderer(renderer, `/hostedPlugin/${getPluginId(plugin.metadata.model)}`)
436
+ () => this.notebookRendererRegistry.registerNotebookRenderer(renderer, PluginPackage.toPluginUrl(plugin.metadata.model, ''))
420
437
  );
421
438
  }
422
439
  }
@@ -79,6 +79,7 @@ import { bindTreeViewDecoratorUtilities, TreeViewDecoratorService } from './view
79
79
  import { CodeEditorWidgetUtil } from './menus/vscode-theia-menu-mappings';
80
80
  import { PluginMenuCommandAdapter } from './menus/plugin-menu-command-adapter';
81
81
  import './theme-icon-override';
82
+ import { PluginIconService } from './plugin-icon-service';
82
83
  import { PluginTerminalRegistry } from './plugin-terminal-registry';
83
84
  import { DnDFileContentStore } from './view/dnd-file-content-store';
84
85
  import { WebviewContextKeys } from './webview/webview-context-keys';
@@ -248,6 +249,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
248
249
  bind(WebviewFrontendSecurityWarnings).toSelf().inSingletonScope();
249
250
  bind(FrontendApplicationContribution).toService(WebviewFrontendSecurityWarnings);
250
251
 
252
+ bind(PluginIconService).toSelf().inSingletonScope();
253
+ bind(FrontendApplicationContribution).toService(PluginIconService);
254
+
251
255
  bind(PluginAuthenticationServiceImpl).toSelf().inSingletonScope();
252
256
  rebind(AuthenticationService).toService(PluginAuthenticationServiceImpl);
253
257