@theia/plugin-ext 1.43.0 → 1.44.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 (116) hide show
  1. package/lib/common/plugin-api-rpc.d.ts +9 -0
  2. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  3. package/lib/common/plugin-api-rpc.js.map +1 -1
  4. package/lib/common/plugin-protocol.d.ts +9 -2
  5. package/lib/common/plugin-protocol.d.ts.map +1 -1
  6. package/lib/common/plugin-protocol.js.map +1 -1
  7. package/lib/hosted/node/hosted-plugin-deployer-handler.d.ts +1 -0
  8. package/lib/hosted/node/hosted-plugin-deployer-handler.d.ts.map +1 -1
  9. package/lib/hosted/node/hosted-plugin-deployer-handler.js +6 -0
  10. package/lib/hosted/node/hosted-plugin-deployer-handler.js.map +1 -1
  11. package/lib/hosted/node/scanners/scanner-theia.d.ts +0 -3
  12. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  13. package/lib/hosted/node/scanners/scanner-theia.js +11 -94
  14. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  15. package/lib/main/browser/debug/plugin-debug-service.d.ts +3 -0
  16. package/lib/main/browser/debug/plugin-debug-service.d.ts.map +1 -1
  17. package/lib/main/browser/debug/plugin-debug-service.js +78 -1
  18. package/lib/main/browser/debug/plugin-debug-service.js.map +1 -1
  19. package/lib/main/browser/languages-main.d.ts.map +1 -1
  20. package/lib/main/browser/languages-main.js +1 -0
  21. package/lib/main/browser/languages-main.js.map +1 -1
  22. package/lib/main/browser/plugin-contribution-handler.d.ts +2 -0
  23. package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
  24. package/lib/main/browser/plugin-contribution-handler.js +10 -0
  25. package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
  26. package/lib/main/browser/plugin-icon-theme-service.d.ts +12 -1
  27. package/lib/main/browser/plugin-icon-theme-service.d.ts.map +1 -1
  28. package/lib/main/browser/plugin-icon-theme-service.js +44 -8
  29. package/lib/main/browser/plugin-icon-theme-service.js.map +1 -1
  30. package/lib/main/browser/plugin-shared-style.d.ts +5 -1
  31. package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
  32. package/lib/main/browser/plugin-shared-style.js +32 -16
  33. package/lib/main/browser/plugin-shared-style.js.map +1 -1
  34. package/lib/main/browser/terminal-main.d.ts +1 -0
  35. package/lib/main/browser/terminal-main.d.ts.map +1 -1
  36. package/lib/main/browser/terminal-main.js +5 -0
  37. package/lib/main/browser/terminal-main.js.map +1 -1
  38. package/lib/main/browser/text-editor-main.d.ts.map +1 -1
  39. package/lib/main/browser/text-editor-main.js +10 -0
  40. package/lib/main/browser/text-editor-main.js.map +1 -1
  41. package/lib/main/browser/webview/webview.d.ts +8 -1
  42. package/lib/main/browser/webview/webview.d.ts.map +1 -1
  43. package/lib/main/browser/webview/webview.js +10 -0
  44. package/lib/main/browser/webview/webview.js.map +1 -1
  45. package/lib/main/node/plugin-deployer-contribution.d.ts +1 -1
  46. package/lib/main/node/plugin-deployer-contribution.d.ts.map +1 -1
  47. package/lib/main/node/plugin-deployer-contribution.js +1 -1
  48. package/lib/main/node/plugin-deployer-contribution.js.map +1 -1
  49. package/lib/main/node/plugin-deployer-impl.d.ts +1 -1
  50. package/lib/main/node/plugin-deployer-impl.d.ts.map +1 -1
  51. package/lib/main/node/plugin-deployer-impl.js +1 -1
  52. package/lib/main/node/plugin-deployer-impl.js.map +1 -1
  53. package/lib/main/node/plugin-ext-backend-module.d.ts.map +1 -1
  54. package/lib/main/node/plugin-ext-backend-module.js +3 -0
  55. package/lib/main/node/plugin-ext-backend-module.js.map +1 -1
  56. package/lib/main/node/plugin-mgmt-cli-contribution.d.ts +13 -0
  57. package/lib/main/node/plugin-mgmt-cli-contribution.d.ts.map +1 -0
  58. package/lib/main/node/plugin-mgmt-cli-contribution.js +71 -0
  59. package/lib/main/node/plugin-mgmt-cli-contribution.js.map +1 -0
  60. package/lib/plugin/env.d.ts +0 -3
  61. package/lib/plugin/env.d.ts.map +1 -1
  62. package/lib/plugin/env.js +0 -6
  63. package/lib/plugin/env.js.map +1 -1
  64. package/lib/plugin/languages-utils.d.ts +2 -1
  65. package/lib/plugin/languages-utils.d.ts.map +1 -1
  66. package/lib/plugin/languages-utils.js +14 -1
  67. package/lib/plugin/languages-utils.js.map +1 -1
  68. package/lib/plugin/languages.d.ts.map +1 -1
  69. package/lib/plugin/languages.js +2 -1
  70. package/lib/plugin/languages.js.map +1 -1
  71. package/lib/plugin/plugin-context.d.ts.map +1 -1
  72. package/lib/plugin/plugin-context.js +5 -1
  73. package/lib/plugin/plugin-context.js.map +1 -1
  74. package/lib/plugin/plugin-manager.js +1 -1
  75. package/lib/plugin/plugin-manager.js.map +1 -1
  76. package/lib/plugin/status-bar/status-bar-item.d.ts.map +1 -1
  77. package/lib/plugin/terminal-ext.d.ts +5 -0
  78. package/lib/plugin/terminal-ext.d.ts.map +1 -1
  79. package/lib/plugin/terminal-ext.js +11 -0
  80. package/lib/plugin/terminal-ext.js.map +1 -1
  81. package/lib/plugin/text-editor.d.ts +6 -2
  82. package/lib/plugin/text-editor.d.ts.map +1 -1
  83. package/lib/plugin/text-editor.js +57 -2
  84. package/lib/plugin/text-editor.js.map +1 -1
  85. package/lib/plugin/types-impl.d.ts +22 -0
  86. package/lib/plugin/types-impl.d.ts.map +1 -1
  87. package/lib/plugin/types-impl.js +36 -4
  88. package/lib/plugin/types-impl.js.map +1 -1
  89. package/package.json +29 -29
  90. package/src/common/plugin-api-rpc.ts +10 -0
  91. package/src/common/plugin-protocol.ts +9 -2
  92. package/src/hosted/node/hosted-plugin-deployer-handler.ts +7 -0
  93. package/src/hosted/node/scanners/scanner-theia.ts +10 -101
  94. package/src/main/browser/debug/plugin-debug-service.ts +84 -2
  95. package/src/main/browser/languages-main.ts +1 -0
  96. package/src/main/browser/plugin-contribution-handler.ts +9 -0
  97. package/src/main/browser/plugin-icon-theme-service.ts +46 -12
  98. package/src/main/browser/plugin-shared-style.ts +36 -17
  99. package/src/main/browser/terminal-main.ts +7 -0
  100. package/src/main/browser/text-editor-main.ts +9 -0
  101. package/src/main/browser/webview/pre/host.js +1 -1
  102. package/src/main/browser/webview/pre/main.js +57 -32
  103. package/src/main/browser/webview/webview.ts +18 -1
  104. package/src/main/node/plugin-deployer-contribution.ts +2 -2
  105. package/src/main/node/plugin-deployer-impl.ts +2 -2
  106. package/src/main/node/plugin-ext-backend-module.ts +4 -0
  107. package/src/main/node/plugin-mgmt-cli-contribution.ts +64 -0
  108. package/src/plugin/env.ts +0 -8
  109. package/src/plugin/languages-utils.ts +13 -1
  110. package/src/plugin/languages.ts +3 -2
  111. package/src/plugin/plugin-context.ts +6 -1
  112. package/src/plugin/plugin-manager.ts +1 -1
  113. package/src/plugin/status-bar/status-bar-item.ts +1 -1
  114. package/src/plugin/terminal-ext.ts +15 -0
  115. package/src/plugin/text-editor.ts +64 -4
  116. package/src/plugin/types-impl.ts +32 -0
@@ -79,18 +79,6 @@ import { ColorDefinition } from '@theia/core/lib/common/color';
79
79
  import { CSSIcon } from '@theia/core/lib/common/markdown-rendering/icon-utilities';
80
80
  import { PluginUriFactory } from './plugin-uri-factory';
81
81
 
82
- namespace nls {
83
- export function localize(key: string, _default: string): string {
84
- return _default;
85
- }
86
- }
87
-
88
- const INTERNAL_CONSOLE_OPTIONS_SCHEMA = {
89
- enum: ['neverOpen', 'openOnSessionStart', 'openOnFirstSessionStart'],
90
- default: 'openOnFirstSessionStart',
91
- description: nls.localize('internalConsoleOptions', 'Controls when the internal debug console should open.')
92
- };
93
-
94
82
  const colorIdPattern = '^\\w+[.\\w+]*$';
95
83
  const iconIdPattern = `^${CSSIcon.iconNameSegment}(-${CSSIcon.iconNameSegment})+$`;
96
84
 
@@ -371,7 +359,7 @@ export class TheiaPluginScanner implements PluginScanner {
371
359
  }
372
360
 
373
361
  const [languagesResult, grammarsResult] = await Promise.allSettled([
374
- rawPlugin.contributes.languages ? this.readLanguages(rawPlugin.contributes.languages, rawPlugin.packagePath) : undefined,
362
+ rawPlugin.contributes.languages ? this.readLanguages(rawPlugin.contributes.languages, rawPlugin) : undefined,
375
363
  rawPlugin.contributes.grammars ? this.grammarsReader.readGrammars(rawPlugin.contributes.grammars, rawPlugin.packagePath) : undefined
376
364
  ]);
377
365
 
@@ -723,8 +711,8 @@ export class TheiaPluginScanner implements PluginScanner {
723
711
  return result;
724
712
  }
725
713
 
726
- private async readLanguages(rawLanguages: PluginPackageLanguageContribution[], pluginPath: string): Promise<LanguageContribution[]> {
727
- return Promise.all(rawLanguages.map(language => this.readLanguage(language, pluginPath)));
714
+ private async readLanguages(rawLanguages: PluginPackageLanguageContribution[], plugin: PluginPackage): Promise<LanguageContribution[]> {
715
+ return Promise.all(rawLanguages.map(language => this.readLanguage(language, plugin)));
728
716
  }
729
717
 
730
718
  private readSubmenus(rawSubmenus: PluginPackageSubmenu[], plugin: PluginPackage): Submenu[] {
@@ -741,8 +729,9 @@ export class TheiaPluginScanner implements PluginScanner {
741
729
 
742
730
  }
743
731
 
744
- private async readLanguage(rawLang: PluginPackageLanguageContribution, pluginPath: string): Promise<LanguageContribution> {
732
+ private async readLanguage(rawLang: PluginPackageLanguageContribution, plugin: PluginPackage): Promise<LanguageContribution> {
745
733
  // TODO: add validation to all parameters
734
+ const icon = this.transformIconUrl(plugin, rawLang.icon);
746
735
  const result: LanguageContribution = {
747
736
  id: rawLang.id,
748
737
  aliases: rawLang.aliases,
@@ -750,10 +739,11 @@ export class TheiaPluginScanner implements PluginScanner {
750
739
  filenamePatterns: rawLang.filenamePatterns,
751
740
  filenames: rawLang.filenames,
752
741
  firstLine: rawLang.firstLine,
753
- mimetypes: rawLang.mimetypes
742
+ mimetypes: rawLang.mimetypes,
743
+ icon: icon?.iconUrl ?? icon?.themeIcon
754
744
  };
755
745
  if (rawLang.configuration) {
756
- const rawConfiguration = await this.readJson<PluginPackageLanguageContributionConfiguration>(path.resolve(pluginPath, rawLang.configuration));
746
+ const rawConfiguration = await this.readJson<PluginPackageLanguageContributionConfiguration>(path.resolve(plugin.packagePath, rawLang.configuration));
757
747
  if (rawConfiguration) {
758
748
  const configuration: LanguageConfiguration = {
759
749
  brackets: rawConfiguration.brackets,
@@ -793,12 +783,10 @@ export class TheiaPluginScanner implements PluginScanner {
793
783
  program: rawDebugger.program,
794
784
  args: rawDebugger.args,
795
785
  runtime: rawDebugger.runtime,
796
- runtimeArgs: rawDebugger.runtimeArgs
786
+ runtimeArgs: rawDebugger.runtimeArgs,
787
+ configurationAttributes: rawDebugger.configurationAttributes
797
788
  };
798
789
 
799
- result.configurationAttributes = rawDebugger.configurationAttributes
800
- && this.resolveSchemaAttributes(rawDebugger.type, rawDebugger.configurationAttributes);
801
-
802
790
  return result;
803
791
  }
804
792
 
@@ -827,85 +815,6 @@ export class TheiaPluginScanner implements PluginScanner {
827
815
  return schema;
828
816
  }
829
817
 
830
- protected resolveSchemaAttributes(type: string, configurationAttributes: { [request: string]: IJSONSchema }): IJSONSchema[] {
831
- const taskSchema = {};
832
- return Object.keys(configurationAttributes).map(request => {
833
- const attributes: IJSONSchema = deepClone(configurationAttributes[request]);
834
- const defaultRequired = ['name', 'type', 'request'];
835
- attributes.required = attributes.required && attributes.required.length ? defaultRequired.concat(attributes.required) : defaultRequired;
836
- attributes.additionalProperties = false;
837
- attributes.type = 'object';
838
- if (!attributes.properties) {
839
- attributes.properties = {};
840
- }
841
- const properties = attributes.properties;
842
- properties['type'] = {
843
- enum: [type],
844
- description: nls.localize('debugType', 'Type of configuration.'),
845
- pattern: '^(?!node2)',
846
- errorMessage: nls.localize('debugTypeNotRecognised',
847
- 'The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled.'),
848
- patternErrorMessage: nls.localize('node2NotSupported',
849
- '"node2" is no longer supported, use "node" instead and set the "protocol" attribute to "inspector".')
850
- };
851
- properties['name'] = {
852
- type: 'string',
853
- description: nls.localize('debugName', 'Name of configuration; appears in the launch configuration drop down menu.'),
854
- default: 'Launch'
855
- };
856
- properties['request'] = {
857
- enum: [request],
858
- description: nls.localize('debugRequest', 'Request type of configuration. Can be "launch" or "attach".'),
859
- };
860
- properties['debugServer'] = {
861
- type: 'number',
862
- description: nls.localize('debugServer',
863
- 'For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode'),
864
- default: 4711
865
- };
866
- properties['preLaunchTask'] = {
867
- anyOf: [taskSchema, {
868
- type: ['string'],
869
- }],
870
- default: '',
871
- description: nls.localize('debugPrelaunchTask', 'Task to run before debug session starts.')
872
- };
873
- properties['postDebugTask'] = {
874
- anyOf: [taskSchema, {
875
- type: ['string'],
876
- }],
877
- default: '',
878
- description: nls.localize('debugPostDebugTask', 'Task to run after debug session ends.')
879
- };
880
- properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA;
881
-
882
- const osProperties = Object.assign({}, properties);
883
- properties['windows'] = {
884
- type: 'object',
885
- description: nls.localize('debugWindowsConfiguration', 'Windows specific launch configuration attributes.'),
886
- properties: osProperties
887
- };
888
- properties['osx'] = {
889
- type: 'object',
890
- description: nls.localize('debugOSXConfiguration', 'OS X specific launch configuration attributes.'),
891
- properties: osProperties
892
- };
893
- properties['linux'] = {
894
- type: 'object',
895
- description: nls.localize('debugLinuxConfiguration', 'Linux specific launch configuration attributes.'),
896
- properties: osProperties
897
- };
898
- Object.keys(attributes.properties).forEach(name => {
899
- // Use schema allOf property to get independent error reporting #21113
900
- attributes!.properties![name].pattern = attributes!.properties![name].pattern || '^(?!.*\\$\\{(env|config|command)\\.)';
901
- attributes!.properties![name].patternErrorMessage = attributes!.properties![name].patternErrorMessage ||
902
- nls.localize('deprecatedVariables', "'env.', 'config.' and 'command.' are deprecated, use 'env:', 'config:' and 'command:' instead.");
903
- });
904
-
905
- return attributes;
906
- });
907
- }
908
-
909
818
  private extractValidAutoClosingPairs(langId: string, configuration: PluginPackageLanguageContributionConfiguration): AutoClosingPairConditional[] | undefined {
910
819
  const source = configuration.autoClosingPairs;
911
820
  if (typeof source === 'undefined') {
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { DebuggerDescription, DebugPath, DebugService } from '@theia/debug/lib/common/debug-service';
18
18
  import debounce = require('@theia/core/shared/lodash.debounce');
19
- import { Emitter, Event } from '@theia/core';
19
+ import { deepClone, Emitter, Event, nls } from '@theia/core';
20
20
  import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
21
21
  import { DebugConfiguration } from '@theia/debug/lib/common/debug-configuration';
22
22
  import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
@@ -293,12 +293,94 @@ export class PluginDebugService implements DebugService {
293
293
  for (const contribution of this.debuggers) {
294
294
  if (contribution.configurationAttributes &&
295
295
  (contribution.type === debugType || contribution.type === '*' || debugType === '*')) {
296
- schemas = schemas.concat(contribution.configurationAttributes);
296
+ schemas = schemas.concat(this.resolveSchemaAttributes(contribution.type, contribution.configurationAttributes));
297
297
  }
298
298
  }
299
299
  return schemas;
300
300
  }
301
301
 
302
+ protected resolveSchemaAttributes(type: string, configurationAttributes: { [request: string]: IJSONSchema }): IJSONSchema[] {
303
+ const taskSchema = {};
304
+ return Object.keys(configurationAttributes).map(request => {
305
+ const attributes: IJSONSchema = deepClone(configurationAttributes[request]);
306
+ const defaultRequired = ['name', 'type', 'request'];
307
+ attributes.required = attributes.required && attributes.required.length ? defaultRequired.concat(attributes.required) : defaultRequired;
308
+ attributes.additionalProperties = false;
309
+ attributes.type = 'object';
310
+ if (!attributes.properties) {
311
+ attributes.properties = {};
312
+ }
313
+ const properties = attributes.properties;
314
+ properties['type'] = {
315
+ enum: [type],
316
+ description: nls.localizeByDefault('Type of configuration.'),
317
+ pattern: '^(?!node2)',
318
+ errorMessage: nls.localizeByDefault('The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled.'),
319
+ patternErrorMessage: nls.localizeByDefault('"node2" is no longer supported, use "node" instead and set the "protocol" attribute to "inspector".')
320
+ };
321
+ properties['name'] = {
322
+ type: 'string',
323
+ description: nls.localizeByDefault('Name of configuration; appears in the launch configuration dropdown menu.'),
324
+ default: 'Launch'
325
+ };
326
+ properties['request'] = {
327
+ enum: [request],
328
+ description: nls.localizeByDefault('Request type of configuration. Can be "launch" or "attach".'),
329
+ };
330
+ properties['debugServer'] = {
331
+ type: 'number',
332
+ description: nls.localizeByDefault(
333
+ 'For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode'
334
+ ),
335
+ default: 4711
336
+ };
337
+ properties['preLaunchTask'] = {
338
+ anyOf: [taskSchema, {
339
+ type: ['string'],
340
+ }],
341
+ default: '',
342
+ description: nls.localizeByDefault('Task to run before debug session starts.')
343
+ };
344
+ properties['postDebugTask'] = {
345
+ anyOf: [taskSchema, {
346
+ type: ['string'],
347
+ }],
348
+ default: '',
349
+ description: nls.localizeByDefault('Task to run after debug session ends.')
350
+ };
351
+ properties['internalConsoleOptions'] = {
352
+ enum: ['neverOpen', 'openOnSessionStart', 'openOnFirstSessionStart'],
353
+ default: 'openOnFirstSessionStart',
354
+ description: nls.localizeByDefault('Controls when the internal Debug Console should open.')
355
+ };
356
+
357
+ const osProperties = Object.assign({}, properties);
358
+ properties['windows'] = {
359
+ type: 'object',
360
+ description: nls.localizeByDefault('Windows specific launch configuration attributes.'),
361
+ properties: osProperties
362
+ };
363
+ properties['osx'] = {
364
+ type: 'object',
365
+ description: nls.localizeByDefault('OS X specific launch configuration attributes.'),
366
+ properties: osProperties
367
+ };
368
+ properties['linux'] = {
369
+ type: 'object',
370
+ description: nls.localizeByDefault('Linux specific launch configuration attributes.'),
371
+ properties: osProperties
372
+ };
373
+ Object.keys(attributes.properties).forEach(name => {
374
+ // Use schema allOf property to get independent error reporting #21113
375
+ attributes!.properties![name].pattern = attributes!.properties![name].pattern || '^(?!.*\\$\\{(env|config|command)\\.)';
376
+ attributes!.properties![name].patternErrorMessage = attributes!.properties![name].patternErrorMessage ||
377
+ nls.localizeByDefault("'env.', 'config.' and 'command.' are deprecated, use 'env:', 'config:' and 'command:' instead.");
378
+ });
379
+
380
+ return attributes;
381
+ });
382
+ }
383
+
302
384
  async getConfigurationSnippets(): Promise<IJSONSchemaSnippet[]> {
303
385
  let snippets = await this.delegated.getConfigurationSnippets();
304
386
 
@@ -167,6 +167,7 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
167
167
  wordPattern: reviveRegExp(configuration.wordPattern),
168
168
  indentationRules: reviveIndentationRule(configuration.indentationRules),
169
169
  onEnterRules: reviveOnEnterRules(configuration.onEnterRules),
170
+ autoClosingPairs: configuration.autoClosingPairs
170
171
  };
171
172
 
172
173
  this.register(handle, monaco.languages.setLanguageConfiguration(languageId, config));
@@ -53,6 +53,7 @@ import { TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget
53
53
  import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
54
54
  import { PluginTerminalRegistry } from './plugin-terminal-registry';
55
55
  import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
56
+ import { LanguageService } from '@theia/core/lib/browser/language-service';
56
57
 
57
58
  @injectable()
58
59
  export class PluginContributionHandler {
@@ -89,6 +90,9 @@ export class PluginContributionHandler {
89
90
  @inject(CommandRegistry)
90
91
  protected readonly commands: CommandRegistry;
91
92
 
93
+ @inject(LanguageService)
94
+ protected readonly languageService: LanguageService;
95
+
92
96
  @inject(PluginSharedStyle)
93
97
  protected readonly style: PluginSharedStyle;
94
98
 
@@ -195,6 +199,11 @@ export class PluginContributionHandler {
195
199
  firstLine: lang.firstLine,
196
200
  mimetypes: lang.mimetypes
197
201
  });
202
+ if (lang.icon) {
203
+ const languageIcon = this.style.toFileIconClass(lang.icon);
204
+ pushContribution(`language.${lang.id}.icon`, () => languageIcon);
205
+ pushContribution(`language.${lang.id}.iconRegistration`, () => this.languageService.registerIcon(lang.id, languageIcon.object.iconClass));
206
+ }
198
207
  const langConfiguration = lang.configuration;
199
208
  if (langConfiguration) {
200
209
  pushContribution(`language.${lang.id}.configuration`, () => monaco.languages.setLanguageConfiguration(lang.id, {
@@ -39,6 +39,8 @@ import { FileStat, FileChangeType } from '@theia/filesystem/lib/common/files';
39
39
  import { WorkspaceService } from '@theia/workspace/lib/browser';
40
40
  import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
41
41
  import { ILanguageService } from '@theia/monaco-editor-core/esm/vs/editor/common/languages/language';
42
+ import { LanguageService } from '@theia/core/lib/browser/language-service';
43
+ import { DEFAULT_ICON_SIZE, PLUGIN_FILE_ICON_CLASS } from './plugin-shared-style';
42
44
 
43
45
  export interface PluginIconDefinition {
44
46
  iconPath: string;
@@ -79,6 +81,7 @@ export interface PluginIconThemeDocument extends PluginIconsAssociation {
79
81
  light?: PluginIconsAssociation;
80
82
  highContrast?: PluginIconsAssociation;
81
83
  hidesExplorerArrows?: boolean;
84
+ showLanguageModeIcons?: boolean;
82
85
  }
83
86
 
84
87
  export const PluginIconThemeFactory = Symbol('PluginIconThemeFactory');
@@ -96,8 +99,14 @@ export class PluginIconThemeDefinition implements IconThemeDefinition, IconTheme
96
99
  hasFileIcons?: boolean;
97
100
  hasFolderIcons?: boolean;
98
101
  hidesExplorerArrows?: boolean;
102
+ showLanguageModeIcons?: boolean;
99
103
  }
100
104
 
105
+ class PluginLanguageIconInfo {
106
+ hasSpecificFileIcons: boolean = false;
107
+ coveredLanguages: { [languageId: string]: boolean } = {};
108
+ };
109
+
101
110
  @injectable()
102
111
  export class PluginIconTheme extends PluginIconThemeDefinition implements IconTheme, Disposable {
103
112
 
@@ -113,6 +122,9 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
113
122
  @inject(WorkspaceService)
114
123
  protected readonly workspaceService: WorkspaceService;
115
124
 
125
+ @inject(LanguageService)
126
+ protected readonly languageService: LanguageService;
127
+
116
128
  protected readonly onDidChangeEmitter = new Emitter<DidChangeLabelEvent>();
117
129
  readonly onDidChange = this.onDidChangeEmitter.event;
118
130
 
@@ -240,17 +252,18 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
240
252
  selectors.push(selector + '::before');
241
253
  definitionSelectors.set(definitionId, selectors);
242
254
  };
243
- this.collectSelectors(json, acceptSelector.bind(undefined, 'dark'));
255
+
256
+ let iconInfo = this.collectSelectors(json, acceptSelector.bind(undefined, 'dark'));
244
257
  if (json.light) {
245
- this.collectSelectors(json.light, acceptSelector.bind(undefined, 'light'));
258
+ iconInfo = this.collectSelectors(json.light, acceptSelector.bind(undefined, 'light'));
246
259
  }
247
260
  if (json.highContrast) {
248
- this.collectSelectors(json.highContrast, acceptSelector.bind(undefined, 'hc'));
261
+ iconInfo = this.collectSelectors(json.highContrast, acceptSelector.bind(undefined, 'hc'));
249
262
  }
250
263
 
251
- if (!this.icons.size) {
252
- return;
253
- }
264
+ const showLanguageModeIcons = this.showLanguageModeIcons === true
265
+ || json.showLanguageModeIcons === true
266
+ || (iconInfo.hasSpecificFileIcons && json.showLanguageModeIcons !== false);
254
267
 
255
268
  const fonts = json.fonts;
256
269
  if (Array.isArray(fonts)) {
@@ -303,7 +316,7 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
303
316
  this.styleSheetContent += `${selectors.join(', ')} {
304
317
  content: ' ';
305
318
  background-image: ${cssUrl};
306
- background-size: 16px;
319
+ background-size: ${DEFAULT_ICON_SIZE}px;
307
320
  background-position: left center;
308
321
  background-repeat: no-repeat;
309
322
  }
@@ -327,6 +340,20 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
327
340
  }
328
341
  }
329
342
  }
343
+
344
+ if (showLanguageModeIcons) {
345
+ for (const language of this.languageService.languages) {
346
+ // only show language icons if there are no more specific icons in the style document
347
+ if (!iconInfo.coveredLanguages[language.id]) {
348
+ const icon = this.languageService.getIcon(language.id);
349
+ if (icon) {
350
+ this.icons.add(this.fileIcon);
351
+ this.icons.add(this.languageIcon(language.id));
352
+ this.icons.add(icon);
353
+ }
354
+ }
355
+ }
356
+ }
330
357
  }
331
358
 
332
359
  protected toCSSUrl(iconPath: string | undefined): string | undefined {
@@ -348,7 +375,7 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
348
375
  return value;
349
376
  }
350
377
 
351
- protected readonly fileIcon = 'theia-plugin-file-icon';
378
+ protected readonly fileIcon = PLUGIN_FILE_ICON_CLASS;
352
379
  protected readonly folderIcon = 'theia-plugin-folder-icon';
353
380
  protected readonly folderExpandedIcon = 'theia-plugin-folder-expanded-icon';
354
381
  protected readonly rootFolderIcon = 'theia-plugin-root-folder-icon';
@@ -384,10 +411,8 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
384
411
  return 'theia-plugin-' + this.escapeCSS(languageId) + '-lang-file-icon';
385
412
  }
386
413
 
387
- protected collectSelectors(
388
- associations: RecursivePartial<PluginIconsAssociation>,
389
- accept: (definitionId: string, ...icons: string[]) => void
390
- ): void {
414
+ protected collectSelectors(associations: RecursivePartial<PluginIconsAssociation>, accept: (definitionId: string, ...icons: string[]) => void): PluginLanguageIconInfo {
415
+ const iconInfo = new PluginLanguageIconInfo();
391
416
  if (associations.folder) {
392
417
  accept(associations.folder, this.folderIcon);
393
418
  if (associations.folderExpanded === undefined) {
@@ -441,6 +466,8 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
441
466
  for (const languageId in languageIds) {
442
467
  accept(languageIds[languageId]!, this.languageIcon(languageId), this.fileIcon);
443
468
  this.hasFileIcons = true;
469
+ iconInfo.hasSpecificFileIcons = true;
470
+ iconInfo.coveredLanguages[languageId] = true;
444
471
  }
445
472
  }
446
473
  const fileExtensions = associations.fileExtensions;
@@ -449,6 +476,7 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
449
476
  for (const fileExtension in fileExtensions) {
450
477
  accept(fileExtensions[fileExtension]!, ...this.fileExtensionIcon(fileExtension), this.fileIcon);
451
478
  this.hasFileIcons = true;
479
+ iconInfo.hasSpecificFileIcons = true;
452
480
  }
453
481
  }
454
482
  const fileNames = associations.fileNames;
@@ -457,8 +485,10 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
457
485
  for (const fileName in fileNames) {
458
486
  accept(fileNames[fileName]!, ...this.fileNameIcon(fileName), this.fileIcon);
459
487
  this.hasFileIcons = true;
488
+ iconInfo.hasSpecificFileIcons = true;
460
489
  }
461
490
  }
491
+ return iconInfo;
462
492
  }
463
493
 
464
494
  /**
@@ -529,6 +559,10 @@ export class PluginIconTheme extends PluginIconThemeDefinition implements IconTh
529
559
  }
530
560
  const language = StandaloneServices.get(ILanguageService).createByFilepathOrFirstLine(parsedURI['codeUri']);
531
561
  classNames.push(this.languageIcon(language.languageId));
562
+ const defaultLanguageIcon = this.languageService.getIcon(language.languageId);
563
+ if (defaultLanguageIcon) {
564
+ classNames.push(defaultLanguageIcon);
565
+ }
532
566
  }
533
567
  return classNames;
534
568
  }
@@ -23,14 +23,19 @@ import { Reference, SyncReferenceCollection } from '@theia/core/lib/common/refer
23
23
  import { Endpoint } from '@theia/core/lib/browser/endpoint';
24
24
 
25
25
  export interface PluginIconKey {
26
- url: IconUrl
27
- size: number
26
+ url: IconUrl;
27
+ size?: number;
28
+ type?: 'icon' | 'file';
28
29
  }
29
30
 
30
31
  export interface PluginIcon extends Disposable {
31
32
  readonly iconClass: string
32
33
  }
33
34
 
35
+ export const PLUGIN_FILE_ICON_CLASS = 'theia-plugin-file-icon';
36
+
37
+ export const DEFAULT_ICON_SIZE = 16;
38
+
34
39
  @injectable()
35
40
  export class PluginSharedStyle {
36
41
 
@@ -98,30 +103,44 @@ export class PluginSharedStyle {
98
103
  }
99
104
 
100
105
  private readonly icons = new SyncReferenceCollection<PluginIconKey, PluginIcon>(key => this.createPluginIcon(key));
101
- toIconClass(url: IconUrl, { size }: { size: number } = { size: 16 }): Reference<PluginIcon> {
106
+ toIconClass(url: IconUrl, { size }: { size: number } = { size: DEFAULT_ICON_SIZE }): Reference<PluginIcon> {
102
107
  return this.icons.acquire({ url, size });
103
108
  }
104
109
 
110
+ toFileIconClass(url: IconUrl): Reference<PluginIcon> {
111
+ return this.icons.acquire({ url, type: 'file' });
112
+ }
113
+
105
114
  private iconSequence = 0;
106
115
  protected createPluginIcon(key: PluginIconKey): PluginIcon {
107
116
  const iconUrl = key.url;
108
- const size = key.size;
117
+ const size = key.size ?? DEFAULT_ICON_SIZE;
118
+ const type = key.type ?? 'icon';
109
119
  const darkIconUrl = PluginSharedStyle.toExternalIconUrl(`${typeof iconUrl === 'object' ? iconUrl.dark : iconUrl}`);
110
120
  const lightIconUrl = PluginSharedStyle.toExternalIconUrl(`${typeof iconUrl === 'object' ? iconUrl.light : iconUrl}`);
111
- const iconClass = 'plugin-icon-' + this.iconSequence++;
121
+
112
122
  const toDispose = new DisposableCollection();
113
- toDispose.push(this.insertRule('.' + iconClass + '::before', theme => `
114
- content: "";
115
- background-position: 2px;
116
- width: ${size}px;
117
- height: ${size}px;
118
- background: center no-repeat url("${theme.type === 'light' ? lightIconUrl : darkIconUrl}");
119
- background-size: ${size}px;
120
- `));
121
- return {
122
- iconClass,
123
- dispose: () => toDispose.dispose()
124
- };
123
+ let iconClass = 'plugin-icon-' + this.iconSequence++;
124
+ if (type === 'icon') {
125
+ toDispose.push(this.insertRule('.' + iconClass + '::before', theme => `
126
+ content: "";
127
+ background-position: 2px;
128
+ width: ${size}'px';
129
+ height: ${size}'px';
130
+ background: center no-repeat url("${theme.type === 'light' ? lightIconUrl : darkIconUrl}");
131
+ background-size: ${size}px;
132
+ `));
133
+ } else {
134
+ toDispose.push(this.insertRule('.' + iconClass + '::before', theme => `
135
+ content: "";
136
+ background-image: url("${theme.type === 'light' ? lightIconUrl : darkIconUrl}");
137
+ background-size: ${DEFAULT_ICON_SIZE}px;
138
+ background-position: left center;
139
+ background-repeat: no-repeat;
140
+ `));
141
+ iconClass += ' ' + PLUGIN_FILE_ICON_CLASS;
142
+ }
143
+ return { iconClass, dispose: () => toDispose.dispose() };
125
144
  }
126
145
 
127
146
  static toExternalIconUrl(iconUrl: string): string {
@@ -18,6 +18,7 @@ import { interfaces } from '@theia/core/shared/inversify';
18
18
  import { ApplicationShell, WidgetOpenerOptions } from '@theia/core/lib/browser';
19
19
  import { TerminalEditorLocationOptions, TerminalOptions } from '@theia/plugin';
20
20
  import { TerminalLocation, TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget';
21
+ import { TerminalProfileService } from '@theia/terminal/lib/browser/terminal-profile-service';
21
22
  import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
22
23
  import { TerminalServiceMain, TerminalServiceExt, MAIN_RPC_CONTEXT } from '../../common/plugin-api-rpc';
23
24
  import { RPCProtocol } from '../../common/rpc-protocol';
@@ -36,6 +37,7 @@ import { HostedPluginSupport } from '../../hosted/browser/hosted-plugin';
36
37
  export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLinkProvider, Disposable {
37
38
 
38
39
  private readonly terminals: TerminalService;
40
+ private readonly terminalProfileService: TerminalProfileService;
39
41
  private readonly pluginTerminalRegistry: PluginTerminalRegistry;
40
42
  private readonly hostedPluginSupport: HostedPluginSupport;
41
43
  private readonly shell: ApplicationShell;
@@ -47,6 +49,7 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
47
49
 
48
50
  constructor(rpc: RPCProtocol, container: interfaces.Container) {
49
51
  this.terminals = container.get(TerminalService);
52
+ this.terminalProfileService = container.get(TerminalProfileService);
50
53
  this.pluginTerminalRegistry = container.get(PluginTerminalRegistry);
51
54
  this.hostedPluginSupport = container.get(HostedPluginSupport);
52
55
  this.shell = container.get(ApplicationShell);
@@ -64,6 +67,10 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
64
67
  this.pluginTerminalRegistry.startCallback = id => this.startProfile(id);
65
68
 
66
69
  container.bind(TerminalLinkProvider).toDynamicValue(() => this);
70
+
71
+ this.toDispose.push(this.terminalProfileService.onDidChangeDefaultShell(shell => {
72
+ this.extProxy.$setShell(shell);
73
+ }));
67
74
  }
68
75
 
69
76
  async startProfile(id: string): Promise<string> {
@@ -194,6 +194,13 @@ export class TextEditorMain implements Disposable {
194
194
  if (typeof newConfiguration.tabSize !== 'undefined') {
195
195
  newOpts.tabSize = newConfiguration.tabSize;
196
196
  }
197
+ if (typeof newConfiguration.indentSize !== 'undefined') {
198
+ if (newConfiguration.indentSize === 'tabSize') {
199
+ newOpts.indentSize = newConfiguration.tabSize;
200
+ } else if (typeof newConfiguration.indentSize == 'number') {
201
+ newOpts.indentSize = newConfiguration.indentSize;
202
+ }
203
+ }
197
204
  this.model.updateOptions(newOpts);
198
205
  }
199
206
 
@@ -408,6 +415,7 @@ export class TextEditorPropertiesMain {
408
415
  const modelOptions = model.getOptions();
409
416
  return {
410
417
  insertSpaces: modelOptions.insertSpaces,
418
+ indentSize: modelOptions.indentSize,
411
419
  tabSize: modelOptions.tabSize,
412
420
  cursorStyle,
413
421
  lineNumbers,
@@ -443,6 +451,7 @@ export class TextEditorPropertiesMain {
443
451
  return (
444
452
  a.tabSize === b.tabSize
445
453
  && a.insertSpaces === b.insertSpaces
454
+ && a.indentSize === b.indentSize
446
455
  && a.cursorStyle === b.cursorStyle
447
456
  && a.lineNumbers === b.lineNumbers
448
457
  );
@@ -36,7 +36,7 @@
36
36
  break;
37
37
  }
38
38
  }
39
- if (sourceIsChildFrame && e.data && (e.data.command === 'onmessage' || e.data.command === 'do-update-state')) {
39
+ if (sourceIsChildFrame && e.data && (e.data.command === 'onmessage' || e.data.command === 'do-update-state' || e.data.command === 'onconsole')) {
40
40
  this.postMessage(e.data.command, e.data.data);
41
41
  } else if (sourceIsChildFrame || sourceIsSelfOrParentFrame) {
42
42
  const channel = e.data.channel;