@theia/plugin-ext 1.27.0-next.3 → 1.27.0-next.34

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 (133) hide show
  1. package/lib/common/connection.d.ts +3 -3
  2. package/lib/common/connection.d.ts.map +1 -1
  3. package/lib/common/connection.js +0 -1
  4. package/lib/common/connection.js.map +1 -1
  5. package/lib/common/plugin-api-rpc.d.ts +20 -11
  6. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  7. package/lib/common/plugin-api-rpc.js.map +1 -1
  8. package/lib/common/plugin-protocol.d.ts +13 -0
  9. package/lib/common/plugin-protocol.d.ts.map +1 -1
  10. package/lib/common/plugin-protocol.js.map +1 -1
  11. package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
  12. package/lib/hosted/node/plugin-host-rpc.js.map +1 -1
  13. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  14. package/lib/hosted/node/scanners/scanner-theia.js +2 -1
  15. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  16. package/lib/main/browser/custom-editors/custom-editor-opener.d.ts.map +1 -1
  17. package/lib/main/browser/custom-editors/custom-editor-opener.js +2 -2
  18. package/lib/main/browser/custom-editors/custom-editor-opener.js.map +1 -1
  19. package/lib/main/browser/debug/plugin-debug-service.d.ts +6 -0
  20. package/lib/main/browser/debug/plugin-debug-service.d.ts.map +1 -1
  21. package/lib/main/browser/debug/plugin-debug-service.js +25 -3
  22. package/lib/main/browser/debug/plugin-debug-service.js.map +1 -1
  23. package/lib/main/browser/debug/plugin-debug-session-factory.d.ts +3 -3
  24. package/lib/main/browser/debug/plugin-debug-session-factory.d.ts.map +1 -1
  25. package/lib/main/browser/debug/plugin-debug-session-factory.js.map +1 -1
  26. package/lib/main/browser/documents-main.d.ts +1 -2
  27. package/lib/main/browser/documents-main.d.ts.map +1 -1
  28. package/lib/main/browser/documents-main.js +26 -6
  29. package/lib/main/browser/documents-main.js.map +1 -1
  30. package/lib/main/browser/editors-and-documents-main.d.ts +2 -0
  31. package/lib/main/browser/editors-and-documents-main.d.ts.map +1 -1
  32. package/lib/main/browser/editors-and-documents-main.js +14 -2
  33. package/lib/main/browser/editors-and-documents-main.js.map +1 -1
  34. package/lib/main/browser/languages-main.d.ts.map +1 -1
  35. package/lib/main/browser/languages-main.js +2 -1
  36. package/lib/main/browser/languages-main.js.map +1 -1
  37. package/lib/main/browser/main-context.js +3 -3
  38. package/lib/main/browser/main-context.js.map +1 -1
  39. package/lib/main/browser/plugin-contribution-handler.d.ts +2 -0
  40. package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
  41. package/lib/main/browser/plugin-contribution-handler.js +36 -1
  42. package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
  43. package/lib/main/browser/plugin-shared-style.d.ts +1 -1
  44. package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
  45. package/lib/main/browser/plugin-shared-style.js.map +1 -1
  46. package/lib/main/browser/text-editors-main.d.ts +6 -3
  47. package/lib/main/browser/text-editors-main.d.ts.map +1 -1
  48. package/lib/main/browser/text-editors-main.js +8 -1
  49. package/lib/main/browser/text-editors-main.js.map +1 -1
  50. package/lib/main/browser/view/plugin-tree-view-node-label-provider.d.ts.map +1 -1
  51. package/lib/main/browser/view/plugin-tree-view-node-label-provider.js +7 -5
  52. package/lib/main/browser/view/plugin-tree-view-node-label-provider.js.map +1 -1
  53. package/lib/main/browser/view/plugin-view-registry.d.ts +1 -1
  54. package/lib/main/browser/view/plugin-view-registry.js +2 -2
  55. package/lib/main/browser/view/plugin-view-registry.js.map +1 -1
  56. package/lib/main/browser/view/tree-view-widget.d.ts +10 -5
  57. package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
  58. package/lib/main/browser/view/tree-view-widget.js +39 -13
  59. package/lib/main/browser/view/tree-view-widget.js.map +1 -1
  60. package/lib/main/browser/webview/webview-theme-data-provider.d.ts +1 -1
  61. package/lib/main/browser/webview/webview-theme-data-provider.d.ts.map +1 -1
  62. package/lib/main/browser/webview/webview-theme-data-provider.js.map +1 -1
  63. package/lib/plugin/custom-editors.d.ts +1 -2
  64. package/lib/plugin/custom-editors.d.ts.map +1 -1
  65. package/lib/plugin/custom-editors.js.map +1 -1
  66. package/lib/plugin/languages-utils.d.ts.map +1 -1
  67. package/lib/plugin/languages-utils.js +3 -2
  68. package/lib/plugin/languages-utils.js.map +1 -1
  69. package/lib/plugin/node/debug/plugin-debug-adapter-session.d.ts +2 -2
  70. package/lib/plugin/node/debug/plugin-debug-adapter-session.d.ts.map +1 -1
  71. package/lib/plugin/node/debug/plugin-debug-adapter-session.js.map +1 -1
  72. package/lib/plugin/plugin-context.d.ts.map +1 -1
  73. package/lib/plugin/plugin-context.js +0 -1
  74. package/lib/plugin/plugin-context.js.map +1 -1
  75. package/lib/plugin/text-editor.d.ts +2 -0
  76. package/lib/plugin/text-editor.d.ts.map +1 -1
  77. package/lib/plugin/text-editor.js +9 -0
  78. package/lib/plugin/text-editor.js.map +1 -1
  79. package/lib/plugin/theming.d.ts +1 -1
  80. package/lib/plugin/theming.d.ts.map +1 -1
  81. package/lib/plugin/tree/tree-views.d.ts +1 -0
  82. package/lib/plugin/tree/tree-views.d.ts.map +1 -1
  83. package/lib/plugin/tree/tree-views.js +10 -9
  84. package/lib/plugin/tree/tree-views.js.map +1 -1
  85. package/lib/plugin/types-impl.d.ts +1 -0
  86. package/lib/plugin/types-impl.d.ts.map +1 -1
  87. package/lib/plugin/types-impl.js +3 -2
  88. package/lib/plugin/types-impl.js.map +1 -1
  89. package/package.json +24 -24
  90. package/src/common/connection.ts +3 -4
  91. package/src/common/plugin-api-rpc.ts +23 -17
  92. package/src/common/plugin-protocol.ts +15 -0
  93. package/src/hosted/node/hosted-plugin-process.ts +2 -2
  94. package/src/hosted/node/plugin-host-rpc.ts +1 -1
  95. package/src/hosted/node/scanners/scanner-theia.ts +2 -1
  96. package/src/main/browser/custom-editors/custom-editor-opener.tsx +2 -2
  97. package/src/main/browser/debug/plugin-debug-service.ts +32 -3
  98. package/src/main/browser/debug/plugin-debug-session-factory.ts +2 -2
  99. package/src/main/browser/documents-main.ts +26 -8
  100. package/src/main/browser/editors-and-documents-main.ts +16 -2
  101. package/src/main/browser/languages-main.ts +2 -1
  102. package/src/main/browser/main-context.ts +2 -2
  103. package/src/main/browser/plugin-contribution-handler.ts +41 -3
  104. package/src/main/browser/plugin-icon-theme-service.ts +1 -1
  105. package/src/main/browser/plugin-shared-style.ts +2 -1
  106. package/src/main/browser/text-editors-main.ts +12 -2
  107. package/src/main/browser/view/plugin-tree-view-node-label-provider.ts +7 -5
  108. package/src/main/browser/view/plugin-view-registry.ts +3 -3
  109. package/src/main/browser/view/tree-view-widget.tsx +44 -16
  110. package/src/main/browser/webview/webview-theme-data-provider.ts +2 -1
  111. package/src/plugin/custom-editors.ts +2 -3
  112. package/src/plugin/languages-utils.ts +3 -2
  113. package/src/plugin/node/debug/plugin-debug-adapter-session.ts +2 -2
  114. package/src/plugin/plugin-context.ts +0 -1
  115. package/src/plugin/text-editor.ts +16 -5
  116. package/src/plugin/theming.ts +1 -1
  117. package/src/plugin/tree/tree-views.ts +15 -12
  118. package/src/plugin/types-impl.ts +1 -1
  119. package/lib/main/browser/custom-editors/glob.d.ts +0 -51
  120. package/lib/main/browser/custom-editors/glob.d.ts.map +0 -1
  121. package/lib/main/browser/custom-editors/glob.js +0 -593
  122. package/lib/main/browser/custom-editors/glob.js.map +0 -1
  123. package/lib/main/browser/custom-editors/paths.d.ts +0 -25
  124. package/lib/main/browser/custom-editors/paths.d.ts.map +0 -1
  125. package/lib/main/browser/custom-editors/paths.js +0 -227
  126. package/lib/main/browser/custom-editors/paths.js.map +0 -1
  127. package/lib/main/browser/editor/untitled-resource.d.ts +0 -3
  128. package/lib/main/browser/editor/untitled-resource.d.ts.map +0 -1
  129. package/lib/main/browser/editor/untitled-resource.js +0 -24
  130. package/lib/main/browser/editor/untitled-resource.js.map +0 -1
  131. package/src/main/browser/custom-editors/glob.ts +0 -743
  132. package/src/main/browser/custom-editors/paths.ts +0 -250
  133. package/src/main/browser/editor/untitled-resource.ts +0 -18
@@ -15,6 +15,8 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { DebuggerDescription, DebugPath, DebugService } from '@theia/debug/lib/common/debug-service';
18
+ import debounce = require('@theia/core/shared/lodash.debounce');
19
+ import { Emitter, Event } from '@theia/core';
18
20
  import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
19
21
  import { DebugConfiguration } from '@theia/debug/lib/common/debug-configuration';
20
22
  import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
@@ -40,6 +42,11 @@ export class PluginDebugService implements DebugService {
40
42
  protected readonly configurationProviders = new Map<number, PluginDebugConfigurationProvider>();
41
43
  protected readonly toDispose = new DisposableCollection();
42
44
 
45
+ protected readonly onDidChangeDebugConfigurationProvidersEmitter = new Emitter<void>();
46
+ get onDidChangeDebugConfigurationProviders(): Event<void> {
47
+ return this.onDidChangeDebugConfigurationProvidersEmitter.event;
48
+ }
49
+
43
50
  // maps session and contribution
44
51
  protected readonly sessionId2contrib = new Map<string, PluginDebugAdapterContribution>();
45
52
  protected delegated: DebugService;
@@ -79,14 +86,21 @@ export class PluginDebugService implements DebugService {
79
86
  this.contributors.delete(debugType);
80
87
  }
81
88
 
89
+ // debouncing to send a single notification for multiple registrations at initialization time
90
+ fireOnDidConfigurationProvidersChanged = debounce(() => {
91
+ this.onDidChangeDebugConfigurationProvidersEmitter.fire();
92
+ }, 100);
93
+
82
94
  registerDebugConfigurationProvider(provider: PluginDebugConfigurationProvider): Disposable {
83
95
  const handle = provider.handle;
84
96
  this.configurationProviders.set(handle, provider);
97
+ this.fireOnDidConfigurationProvidersChanged();
85
98
  return Disposable.create(() => this.unregisterDebugConfigurationProvider(handle));
86
99
  }
87
100
 
88
101
  unregisterDebugConfigurationProvider(handle: number): void {
89
102
  this.configurationProviders.delete(handle);
103
+ this.fireOnDidConfigurationProvidersChanged();
90
104
  }
91
105
 
92
106
  async debugTypes(): Promise<string[]> {
@@ -123,6 +137,24 @@ export class PluginDebugService implements DebugService {
123
137
  return results;
124
138
  }
125
139
 
140
+ async fetchDynamicDebugConfiguration(name: string, providerType: string): Promise<DebugConfiguration | undefined> {
141
+ const pluginProviders =
142
+ Array.from(this.configurationProviders.values()).filter(p => (
143
+ p.triggerKind === DebugConfigurationProviderTriggerKind.Dynamic &&
144
+ p.type === providerType &&
145
+ p.provideDebugConfigurations
146
+ ));
147
+
148
+ for (const provider of pluginProviders) {
149
+ const configurations = await provider.provideDebugConfigurations(undefined);
150
+ for (const configuration of configurations) {
151
+ if (configuration.name === name) {
152
+ return configuration;
153
+ }
154
+ }
155
+ }
156
+ }
157
+
126
158
  async provideDynamicDebugConfigurations(): Promise<Record<string, DebugConfiguration[]>> {
127
159
  const pluginProviders =
128
160
  Array.from(this.configurationProviders.values()).filter(p => (
@@ -134,9 +166,6 @@ export class PluginDebugService implements DebugService {
134
166
 
135
167
  await Promise.all(pluginProviders.map(async provider => {
136
168
  const configurations = await provider.provideDebugConfigurations(undefined);
137
- for (const configuration of configurations) {
138
- configuration.dynamic = true;
139
- }
140
169
  let configurationsPerType = configurationsRecord[provider.type];
141
170
  configurationsPerType = configurationsPerType ? configurationsPerType.concat(configurations) : configurations;
142
171
 
@@ -30,8 +30,8 @@ import { TerminalOptionsExt } from '../../../common/plugin-api-rpc';
30
30
  import { FileService } from '@theia/filesystem/lib/browser/file-service';
31
31
  import { DebugContribution } from '@theia/debug/lib/browser/debug-contribution';
32
32
  import { ContributionProvider } from '@theia/core/lib/common/contribution-provider';
33
- import { Channel } from '@theia/debug/lib/common/debug-service';
34
33
  import { WorkspaceService } from '@theia/workspace/lib/browser';
34
+ import { PluginChannel } from '../../../common/connection';
35
35
 
36
36
  export class PluginDebugSession extends DebugSession {
37
37
  constructor(
@@ -71,7 +71,7 @@ export class PluginDebugSessionFactory extends DefaultDebugSessionFactory {
71
71
  protected override readonly messages: MessageClient,
72
72
  protected override readonly outputChannelManager: OutputChannelManager,
73
73
  protected override readonly debugPreferences: DebugPreferences,
74
- protected readonly connectionFactory: (sessionId: string) => Promise<Channel>,
74
+ protected readonly connectionFactory: (sessionId: string) => Promise<PluginChannel>,
75
75
  protected override readonly fileService: FileService,
76
76
  protected readonly terminalOptionsExt: TerminalOptionsExt | undefined,
77
77
  protected override readonly debugContributionProvider: ContributionProvider<DebugContribution>,
@@ -16,11 +16,10 @@
16
16
  import { DocumentsMain, MAIN_RPC_CONTEXT, DocumentsExt } from '../../common/plugin-api-rpc';
17
17
  import { UriComponents } from '../../common/uri-components';
18
18
  import { EditorsAndDocumentsMain } from './editors-and-documents-main';
19
- import { DisposableCollection, Disposable } from '@theia/core';
19
+ import { DisposableCollection, Disposable, UntitledResourceResolver } from '@theia/core';
20
20
  import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
21
21
  import { RPCProtocol } from '../../common/rpc-protocol';
22
22
  import { EditorModelService } from './text-editor-model-service';
23
- import { UntitledResourceResolver } from './editor/untitled-resource';
24
23
  import { EditorManager, EditorOpenerOptions } from '@theia/editor/lib/browser';
25
24
  import URI from '@theia/core/lib/common/uri';
26
25
  import { URI as CodeURI } from '@theia/core/shared/vscode-uri';
@@ -248,16 +247,35 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
248
247
  }
249
248
  /* fall back to side group -> split relative to the active widget */
250
249
  let widgetOptions: ApplicationShell.WidgetOptions | undefined = { mode: 'split-right' };
251
- const viewColumn = options.viewColumn;
250
+ let viewColumn = options.viewColumn;
251
+ if (viewColumn === -2) {
252
+ /* show besides -> compute current column and adjust viewColumn accordingly */
253
+ const tabBars = shell.mainAreaTabBars;
254
+ const currentTabBar = shell.currentTabBar;
255
+ if (currentTabBar) {
256
+ const currentColumn = tabBars.indexOf(currentTabBar);
257
+ if (currentColumn > -1) {
258
+ // +2 because conversion from 0-based to 1-based index and increase of 1
259
+ viewColumn = currentColumn + 2;
260
+ }
261
+ }
262
+ }
252
263
  if (viewColumn === undefined || viewColumn === -1) {
253
264
  /* active group -> skip (default behaviour) */
254
265
  widgetOptions = undefined;
255
- } else if (viewColumn > 0) {
266
+ } else if (viewColumn > 0 && shell.mainAreaTabBars.length > 0) {
256
267
  const tabBars = shell.mainAreaTabBars;
257
- // convert to zero-based index
258
- const tabBar = tabBars[viewColumn - 1];
259
- if (tabBar && tabBar.currentTitle) {
260
- widgetOptions = { ref: tabBar.currentTitle.owner };
268
+ if (viewColumn <= tabBars.length) {
269
+ // convert to zero-based index
270
+ const tabBar = tabBars[viewColumn - 1];
271
+ if (tabBar?.currentTitle) {
272
+ widgetOptions = { ref: tabBar.currentTitle.owner };
273
+ }
274
+ } else {
275
+ const tabBar = tabBars[tabBars.length - 1];
276
+ if (tabBar?.currentTitle) {
277
+ widgetOptions!.ref = tabBar.currentTitle.owner;
278
+ }
261
279
  }
262
280
  }
263
281
  return {
@@ -41,6 +41,7 @@ export class EditorsAndDocumentsMain implements Disposable {
41
41
  private readonly textEditors = new Map<string, TextEditorMain>();
42
42
 
43
43
  private readonly modelService: EditorModelService;
44
+ private readonly editorService: EditorManager;
44
45
 
45
46
  private readonly onTextEditorAddEmitter = new Emitter<TextEditorMain[]>();
46
47
  private readonly onTextEditorRemoveEmitter = new Emitter<string[]>();
@@ -59,10 +60,10 @@ export class EditorsAndDocumentsMain implements Disposable {
59
60
  constructor(rpc: RPCProtocol, container: interfaces.Container) {
60
61
  this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.EDITORS_AND_DOCUMENTS_EXT);
61
62
 
62
- const editorService = container.get(EditorManager);
63
+ this.editorService = container.get(EditorManager);
63
64
  this.modelService = container.get(EditorModelService);
64
65
 
65
- this.stateComputer = new EditorAndDocumentStateComputer(d => this.onDelta(d), editorService, this.modelService);
66
+ this.stateComputer = new EditorAndDocumentStateComputer(d => this.onDelta(d), this.editorService, this.modelService);
66
67
  this.toDispose.push(this.stateComputer);
67
68
  this.toDispose.push(this.onTextEditorAddEmitter);
68
69
  this.toDispose.push(this.onTextEditorRemoveEmitter);
@@ -168,6 +169,19 @@ export class EditorsAndDocumentsMain implements Disposable {
168
169
  saveAll(includeUntitled?: boolean): Promise<boolean> {
169
170
  return this.modelService.saveAll(includeUntitled);
170
171
  }
172
+
173
+ hideEditor(id: string): Promise<void> {
174
+ for (const editorWidget of this.editorService.all) {
175
+ const monacoEditor = MonacoEditor.get(editorWidget);
176
+ if (monacoEditor) {
177
+ if (id === new EditorSnapshot(monacoEditor).id) {
178
+ editorWidget.close();
179
+ break;
180
+ }
181
+ }
182
+ }
183
+ return Promise.resolve();
184
+ }
171
185
  }
172
186
 
173
187
  class EditorAndDocumentStateComputer implements Disposable {
@@ -1075,7 +1075,8 @@ function reviveOnEnterRule(onEnterRule: SerializedOnEnterRule): monaco.languages
1075
1075
  return {
1076
1076
  beforeText: reviveRegExp(onEnterRule.beforeText)!,
1077
1077
  afterText: reviveRegExp(onEnterRule.afterText),
1078
- action: onEnterRule.action
1078
+ previousLineText: reviveRegExp(onEnterRule.previousLineText),
1079
+ action: onEnterRule.action,
1079
1080
  };
1080
1081
  }
1081
1082
 
@@ -46,7 +46,6 @@ import { OpenerService } from '@theia/core/lib/browser/opener-service';
46
46
  import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell';
47
47
  import { MonacoBulkEditService } from '@theia/monaco/lib/browser/monaco-bulk-edit-service';
48
48
  import { MonacoEditorService } from '@theia/monaco/lib/browser/monaco-editor-service';
49
- import { UntitledResourceResolver } from './editor/untitled-resource';
50
49
  import { MainFileSystemEventService } from './main-file-system-event-service';
51
50
  import { LabelServiceMainImpl } from './label-service-main';
52
51
  import { TimelineMainImpl } from './timeline-main';
@@ -58,6 +57,7 @@ import { SecretsMainImpl } from './secrets-main';
58
57
  import { WebviewViewsMainImpl } from './webview-views/webview-views-main';
59
58
  import { MonacoLanguages } from '@theia/monaco/lib/browser/monaco-languages';
60
59
  import { NotificationExtImpl } from '../../plugin/notification';
60
+ import { UntitledResourceResolver } from '@theia/core/lib/common/resource';
61
61
 
62
62
  export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container): void {
63
63
  const authenticationMain = new AuthenticationMainImpl(rpc, container);
@@ -94,7 +94,7 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
94
94
 
95
95
  const bulkEditService = container.get(MonacoBulkEditService);
96
96
  const monacoEditorService = container.get(MonacoEditorService);
97
- const editorsMain = new TextEditorsMainImpl(editorsAndDocuments, rpc, bulkEditService, monacoEditorService);
97
+ const editorsMain = new TextEditorsMainImpl(editorsAndDocuments, documentsMain, rpc, bulkEditService, monacoEditorService);
98
98
  rpc.set(PLUGIN_RPC_CONTEXT.TEXT_EDITORS_MAIN, editorsMain);
99
99
 
100
100
  // start listening only after all clients are subscribed to events
@@ -20,7 +20,7 @@ import { TextmateRegistry, getEncodedLanguageId, MonacoTextmateService, GrammarD
20
20
  import { MenusContributionPointHandler } from './menus/menus-contribution-handler';
21
21
  import { PluginViewRegistry } from './view/plugin-view-registry';
22
22
  import { PluginCustomEditorRegistry } from './custom-editors/plugin-custom-editor-registry';
23
- import { PluginContribution, IndentationRules, FoldingRules, ScopeMap, DeployedPlugin, GrammarsContribution } from '../../common';
23
+ import { PluginContribution, IndentationRules, FoldingRules, ScopeMap, DeployedPlugin, GrammarsContribution, EnterAction, OnEnterRule } from '../../common';
24
24
  import {
25
25
  DefaultUriLabelProviderContribution,
26
26
  LabelProviderContribution,
@@ -172,7 +172,8 @@ export class PluginContributionHandler {
172
172
  comments: langConfiguration.comments,
173
173
  folding: this.convertFolding(langConfiguration.folding),
174
174
  surroundingPairs: langConfiguration.surroundingPairs,
175
- indentationRules: this.convertIndentationRules(langConfiguration.indentationRules)
175
+ indentationRules: this.convertIndentationRules(langConfiguration.indentationRules),
176
+ onEnterRules: this.convertOnEnterRules(langConfiguration.onEnterRules),
176
177
  }));
177
178
  }
178
179
  }
@@ -484,7 +485,6 @@ export class PluginContributionHandler {
484
485
  }
485
486
 
486
487
  return result;
487
-
488
488
  }
489
489
 
490
490
  private convertTokenTypes(tokenTypes?: ScopeMap): ITokenTypeMap | undefined {
@@ -530,4 +530,42 @@ export class PluginContributionHandler {
530
530
  return result;
531
531
  }
532
532
 
533
+ private convertOnEnterRules(onEnterRules?: OnEnterRule[]): monaco.languages.OnEnterRule[] | undefined {
534
+ if (!onEnterRules) {
535
+ return undefined;
536
+ }
537
+
538
+ const result: monaco.languages.OnEnterRule[] = [];
539
+ for (const onEnterRule of onEnterRules) {
540
+ const rule: monaco.languages.OnEnterRule = {
541
+ beforeText: this.createRegex(onEnterRule.beforeText)!,
542
+ afterText: this.createRegex(onEnterRule.afterText),
543
+ previousLineText: this.createRegex(onEnterRule.previousLineText),
544
+ action: this.createEnterAction(onEnterRule.action),
545
+ };
546
+ result.push(rule);
547
+ }
548
+
549
+ return result;
550
+ }
551
+
552
+ private createEnterAction(action: EnterAction): monaco.languages.EnterAction {
553
+ let indentAction: monaco.languages.IndentAction;
554
+ switch (action.indent) {
555
+ case 'indent':
556
+ indentAction = monaco.languages.IndentAction.Indent;
557
+ break;
558
+ case 'indentOutdent':
559
+ indentAction = monaco.languages.IndentAction.IndentOutdent;
560
+ break;
561
+ case 'outdent':
562
+ indentAction = monaco.languages.IndentAction.Outdent;
563
+ break;
564
+ default:
565
+ indentAction = monaco.languages.IndentAction.None;
566
+ break;
567
+ }
568
+ return { indentAction, appendText: action.appendText, removeText: action.removeText };
569
+ }
570
+
533
571
  }
@@ -30,7 +30,7 @@ import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposa
30
30
  import { Emitter } from '@theia/core/lib/common/event';
31
31
  import { RecursivePartial } from '@theia/core/lib/common/types';
32
32
  import { LabelProviderContribution, DidChangeLabelEvent, LabelProvider, URIIconReference } from '@theia/core/lib/browser/label-provider';
33
- import { ThemeType } from '@theia/core/lib/browser/theming';
33
+ import { ThemeType } from '@theia/core/lib/common/theme';
34
34
  import { FileStatNode, DirNode } from '@theia/filesystem/lib/browser';
35
35
  import { WorkspaceRootNode } from '@theia/navigator/lib/browser/navigator-tree';
36
36
  import { Endpoint } from '@theia/core/lib/browser/endpoint';
@@ -16,7 +16,8 @@
16
16
 
17
17
  import { injectable } from '@theia/core/shared/inversify';
18
18
  import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
19
- import { ThemeService, Theme } from '@theia/core/lib/browser/theming';
19
+ import { ThemeService } from '@theia/core/lib/browser/theming';
20
+ import { Theme } from '@theia/core/lib/common/theme';
20
21
  import { IconUrl } from '../../common/plugin-protocol';
21
22
  import { Reference, SyncReferenceCollection } from '@theia/core/lib/common/reference';
22
23
  import { Endpoint } from '@theia/core/lib/browser/endpoint';
@@ -28,9 +28,10 @@ import {
28
28
  DecorationRenderOptions,
29
29
  ThemeDecorationInstanceRenderOptions,
30
30
  DecorationOptions,
31
- WorkspaceEditDto
31
+ WorkspaceEditDto,
32
+ DocumentsMain,
32
33
  } from '../../common/plugin-api-rpc';
33
- import { Range } from '../../common/plugin-api-rpc-model';
34
+ import { Range, TextDocumentShowOptions } from '../../common/plugin-api-rpc-model';
34
35
  import { EditorsAndDocumentsMain } from './editors-and-documents-main';
35
36
  import { RPCProtocol } from '../../common/rpc-protocol';
36
37
  import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
@@ -54,6 +55,7 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
54
55
 
55
56
  constructor(
56
57
  private readonly editorsAndDocuments: EditorsAndDocumentsMain,
58
+ private readonly documents: DocumentsMain,
57
59
  rpc: RPCProtocol,
58
60
  private readonly bulkEditService: MonacoBulkEditService,
59
61
  private readonly monacoEditorService: MonacoEditorService,
@@ -87,6 +89,10 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
87
89
  }
88
90
  }
89
91
 
92
+ $tryShowTextDocument(uri: UriComponents, options?: TextDocumentShowOptions): Promise<void> {
93
+ return this.documents.$tryShowDocument(uri, options);
94
+ }
95
+
90
96
  $trySetOptions(id: string, options: TextEditorConfigurationUpdate): Promise<void> {
91
97
  if (!this.editorsAndDocuments.getEditor(id)) {
92
98
  return Promise.reject(disposed(`TextEditor: ${id}`));
@@ -173,6 +179,10 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
173
179
  this.monacoEditorService.removeDecorationType(key);
174
180
  }
175
181
 
182
+ $tryHideEditor(id: string): Promise<void> {
183
+ return this.editorsAndDocuments.hideEditor(id);
184
+ }
185
+
176
186
  $trySetDecorations(id: string, key: string, ranges: DecorationOptions[]): Promise<void> {
177
187
  if (!this.editorsAndDocuments.getEditor(id)) {
178
188
  return Promise.reject(disposed(`TextEditor(${id})`));
@@ -33,7 +33,7 @@ export class PluginTreeViewNodeLabelProvider implements LabelProviderContributio
33
33
 
34
34
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
35
  canHandle(element: TreeViewNode | any): number {
36
- if (TreeNode.is(element) && ('resourceUri' in element || 'themeIconId' in element)) {
36
+ if (TreeNode.is(element) && ('resourceUri' in element || 'themeIcon' in element)) {
37
37
  return this.treeLabelProvider.canHandle(element) + 1;
38
38
  }
39
39
  return 0;
@@ -43,12 +43,14 @@ export class PluginTreeViewNodeLabelProvider implements LabelProviderContributio
43
43
  if (node.icon) {
44
44
  return node.icon;
45
45
  }
46
- if (node.themeIconId) {
47
- if (node.themeIconId === 'file' || node.themeIconId === 'folder') {
46
+ if (node.themeIcon) {
47
+ if (node.themeIcon.id === 'file' || node.themeIcon.id === 'folder') {
48
48
  const uri = node.resourceUri && new URI(node.resourceUri) || undefined;
49
- return this.labelProvider.getIcon(URIIconReference.create(node.themeIconId, uri));
49
+ if (uri) {
50
+ return this.labelProvider.getIcon(URIIconReference.create(node.themeIcon.id, uri));
51
+ }
50
52
  }
51
- return ThemeIcon.asClassName({ id: node.themeIconId });
53
+ return ThemeIcon.asClassName(node.themeIcon);
52
54
  }
53
55
  if (node.resourceUri) {
54
56
  return this.labelProvider.getIcon(new URI(node.resourceUri));
@@ -35,7 +35,7 @@ import { Emitter, Event } from '@theia/core/lib/common/event';
35
35
  import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
36
36
  import { ViewContextKeyService } from './view-context-key-service';
37
37
  import { PROBLEMS_WIDGET_ID } from '@theia/markers/lib/browser/problem/problem-widget';
38
- import { OUTPUT_WIDGET_KIND } from '@theia/output/lib/browser/output-widget';
38
+ import { OutputWidget } from '@theia/output/lib/browser/output-widget';
39
39
  import { DebugConsoleContribution } from '@theia/debug/lib/browser/console/debug-console-contribution';
40
40
  import { TERMINAL_WIDGET_FACTORY_ID } from '@theia/terminal/lib/browser/terminal-widget-impl';
41
41
  import { TreeViewWidget } from './tree-view-widget';
@@ -113,7 +113,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
113
113
 
114
114
  // VS Code Panels
115
115
  this.trackVisibleWidget(PROBLEMS_WIDGET_ID, { panelId: 'workbench.panel.markers' });
116
- this.trackVisibleWidget(OUTPUT_WIDGET_KIND, { panelId: 'workbench.panel.output' });
116
+ this.trackVisibleWidget(OutputWidget.ID, { panelId: 'workbench.panel.output' });
117
117
  this.trackVisibleWidget(DebugConsoleContribution.options.id, { panelId: 'workbench.panel.repl' });
118
118
  this.trackVisibleWidget(TERMINAL_WIDGET_FACTORY_ID, { panelId: 'workbench.panel.terminal' });
119
119
  // TODO workbench.panel.comments - Theia does not have a proper comments view yet
@@ -715,7 +715,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
715
715
  }
716
716
 
717
717
  /**
718
- * retrieve restored layout state from previous user session but close widgets
718
+ * retrieve restored layout state from previous user session but close widgets
719
719
  * widgets should be opened only when view data providers are registered
720
720
  */
721
721
  onDidInitializeLayout(): void {
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { URI } from '@theia/core/shared/vscode-uri';
18
18
  import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
19
- import { TreeViewsExt, TreeViewItemCollapsibleState, TreeViewItem, TreeViewSelection } from '../../../common/plugin-api-rpc';
19
+ import { TreeViewsExt, TreeViewItemCollapsibleState, TreeViewItem, TreeViewSelection, ThemeIcon } from '../../../common/plugin-api-rpc';
20
20
  import { Command } from '../../../common/plugin-api-rpc-model';
21
21
  import {
22
22
  TreeNode,
@@ -46,6 +46,9 @@ import * as markdownit from '@theia/core/shared/markdown-it';
46
46
  import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
47
47
  import { LabelParser } from '@theia/core/lib/browser/label-parser';
48
48
  import { AccessibilityInformation } from '@theia/plugin';
49
+ import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
50
+ import { DecoratedTreeNode } from '@theia/core/lib/browser/tree/tree-decorator';
51
+ import { WidgetDecoration } from '@theia/core/lib/browser/widget-decoration';
49
52
 
50
53
  export const TREE_NODE_HYPERLINK = 'theia-TreeNodeHyperlink';
51
54
  export const VIEW_ITEM_CONTEXT_MENU: MenuPath = ['view-item-context-menu'];
@@ -56,11 +59,11 @@ export interface SelectionEventHandler {
56
59
  readonly contextSelection: boolean;
57
60
  }
58
61
 
59
- export interface TreeViewNode extends SelectableTreeNode {
62
+ export interface TreeViewNode extends SelectableTreeNode, DecoratedTreeNode {
60
63
  contextValue?: string;
61
64
  command?: Command;
62
65
  resourceUri?: string;
63
- themeIconId?: string | 'folder' | 'file';
66
+ themeIcon?: ThemeIcon;
64
67
  tooltip?: string;
65
68
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
69
  description?: string | boolean | any;
@@ -68,7 +71,7 @@ export interface TreeViewNode extends SelectableTreeNode {
68
71
  }
69
72
  export namespace TreeViewNode {
70
73
  export function is(arg: TreeNode | undefined): arg is TreeViewNode {
71
- return !!arg && SelectableTreeNode.is(arg) && !ExpandableTreeNode.is(arg) && !CompositeTreeNode.is(arg);
74
+ return !!arg && SelectableTreeNode.is(arg) && DecoratedTreeNode.is(arg);
72
75
  }
73
76
  }
74
77
 
@@ -78,7 +81,7 @@ export interface CompositeTreeViewNode extends TreeViewNode, ExpandableTreeNode,
78
81
  }
79
82
  export namespace CompositeTreeViewNode {
80
83
  export function is(arg: TreeNode | undefined): arg is CompositeTreeViewNode {
81
- return !!arg && SelectableTreeNode.is(arg) && ExpandableTreeNode.is(arg) && CompositeTreeNode.is(arg);
84
+ return TreeViewNode.is(arg) && ExpandableTreeNode.is(arg) && CompositeTreeNode.is(arg);
82
85
  }
83
86
  }
84
87
 
@@ -149,14 +152,16 @@ export class PluginTree extends TreeImpl {
149
152
  }
150
153
 
151
154
  protected createTreeNode(item: TreeViewItem, parent: CompositeTreeNode): TreeNode {
155
+ const decorationData = this.toDecorationData(item);
152
156
  const icon = this.toIconClass(item);
153
157
  const resourceUri = item.resourceUri && URI.revive(item.resourceUri).toString();
154
- const themeIconId = item.themeIconId ? item.themeIconId : item.collapsibleState !== TreeViewItemCollapsibleState.None ? 'folder' : 'file';
158
+ const themeIcon = item.themeIcon ? item.themeIcon : item.collapsibleState !== TreeViewItemCollapsibleState.None ? { id: 'folder' } : { id: 'file' };
155
159
  const update: Partial<TreeViewNode> = {
156
160
  name: item.label,
161
+ decorationData,
157
162
  icon,
158
163
  description: item.description,
159
- themeIconId,
164
+ themeIcon,
160
165
  resourceUri,
161
166
  tooltip: item.tooltip,
162
167
  contextValue: item.contextValue,
@@ -178,7 +183,7 @@ export class PluginTree extends TreeImpl {
178
183
  command: item.command
179
184
  }, update);
180
185
  }
181
- if (TreeViewNode.is(node)) {
186
+ if (TreeViewNode.is(node) && !ExpandableTreeNode.is(node)) {
182
187
  return Object.assign(node, update, { command: item.command });
183
188
  }
184
189
  return Object.assign({
@@ -190,6 +195,17 @@ export class PluginTree extends TreeImpl {
190
195
  }, update);
191
196
  }
192
197
 
198
+ protected toDecorationData(item: TreeViewItem): WidgetDecoration.Data {
199
+ let decoration: WidgetDecoration.Data = {};
200
+ if (item.highlights) {
201
+ const highlight = {
202
+ ranges: item.highlights.map(h => ({ offset: h[0], length: h[1] - h[0] }))
203
+ };
204
+ decoration = { highlight };
205
+ }
206
+ return decoration;
207
+ }
208
+
193
209
  protected toIconClass(item: TreeViewItem): string | undefined {
194
210
  if (item.icon) {
195
211
  return 'fa ' + item.icon;
@@ -257,6 +273,9 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
257
273
  @inject(LabelParser)
258
274
  protected readonly labelParser: LabelParser;
259
275
 
276
+ @inject(ColorRegistry)
277
+ protected readonly colorRegistry: ColorRegistry;
278
+
260
279
  protected readonly markdownIt = markdownit();
261
280
 
262
281
  @postConstruct()
@@ -286,7 +305,14 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
286
305
  protected override renderIcon(node: TreeNode, props: NodeProps): React.ReactNode {
287
306
  const icon = this.toNodeIcon(node);
288
307
  if (icon) {
289
- return <div className={icon + ' theia-tree-view-icon'}></div>;
308
+ let style: React.CSSProperties | undefined;
309
+ if (TreeViewNode.is(node) && node.themeIcon?.color) {
310
+ const color = this.colorRegistry.getCurrentColor(node.themeIcon.color.id);
311
+ if (color) {
312
+ style = { color };
313
+ }
314
+ }
315
+ return <div className={icon + ' theia-tree-view-icon'} style={style}></div>;
290
316
  }
291
317
  return undefined;
292
318
  }
@@ -358,7 +384,9 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
358
384
  const inlineCommands = menu.children.filter((item): item is ActionMenuNode => item instanceof ActionMenuNode);
359
385
  const tailDecorations = super.renderTailDecorations(node, props);
360
386
  return <React.Fragment>
361
- {inlineCommands.length > 0 && <div className={TREE_NODE_SEGMENT_CLASS}>{inlineCommands.map((item, index) => this.renderInlineCommand(item, index, arg))}</div>}
387
+ {inlineCommands.length > 0 && <div className={TREE_NODE_SEGMENT_CLASS}>
388
+ {inlineCommands.map((item, index) => this.renderInlineCommand(item, index, this.focusService.hasFocus(node), arg))}
389
+ </div>}
362
390
  {tailDecorations !== undefined && <div className={TREE_NODE_SEGMENT_CLASS}>{super.renderTailDecorations(node, props)}</div>}
363
391
  </React.Fragment>;
364
392
  });
@@ -369,13 +397,14 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
369
397
  }
370
398
 
371
399
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
372
- protected renderInlineCommand(node: ActionMenuNode, index: number, arg: any): React.ReactNode {
400
+ protected renderInlineCommand(node: ActionMenuNode, index: number, tabbable: boolean, arg: any): React.ReactNode {
373
401
  const { icon } = node;
374
402
  if (!icon || !this.commands.isVisible(node.action.commandId, arg) || !node.action.when || !this.contextKeys.match(node.action.when)) {
375
403
  return false;
376
404
  }
377
405
  const className = [TREE_NODE_SEGMENT_CLASS, TREE_NODE_TAIL_CLASS, icon, ACTION_ITEM, 'theia-tree-view-inline-action'].join(' ');
378
- return <div key={index} className={className} title={node.label} onClick={e => {
406
+ const tabIndex = tabbable ? 0 : undefined;
407
+ return <div key={index} className={className} title={node.label} tabIndex={tabIndex} onClick={e => {
379
408
  e.stopPropagation();
380
409
  this.commands.executeCommand(node.action.commandId, arg);
381
410
  }} />;
@@ -404,13 +433,12 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
404
433
  this.tryExecuteCommand();
405
434
  }
406
435
 
407
- override handleClickEvent(node: TreeNode, event: React.MouseEvent<HTMLElement>): void {
408
- super.handleClickEvent(node, event);
409
- // If clicked on item (not collapsable icon) - execute command or toggle expansion if item has no command
436
+ protected override tapNode(node?: TreeNode): void {
437
+ super.tapNode(node);
410
438
  const commandMap = this.findCommands(node);
411
439
  if (commandMap.size > 0) {
412
440
  this.tryExecuteCommandMap(commandMap);
413
- } else if (this.isExpandable(node) && !this.hasShiftMask(event) && !this.hasCtrlCmdMask(event)) {
441
+ } else if (node && this.isExpandable(node)) {
414
442
  this.model.toggleNodeExpansion(node);
415
443
  }
416
444
  }
@@ -22,7 +22,8 @@
22
22
  import { inject, postConstruct, injectable } from '@theia/core/shared/inversify';
23
23
  import { Emitter } from '@theia/core/lib/common/event';
24
24
  import { EditorPreferences, EditorConfiguration } from '@theia/editor/lib/browser/editor-preferences';
25
- import { Theme, ThemeService } from '@theia/core/lib/browser/theming';
25
+ import { ThemeService } from '@theia/core/lib/browser/theming';
26
+ import { Theme } from '@theia/core/lib/common/theme';
26
27
  import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
27
28
  import { ColorApplicationContribution } from '@theia/core/lib/browser/color-application-contribution';
28
29
 
@@ -29,7 +29,6 @@ import { WebviewImpl, WebviewsExtImpl } from './webviews';
29
29
  import { CancellationToken, CancellationTokenSource } from '@theia/core/lib/common/cancellation';
30
30
  import { DisposableCollection } from '@theia/core/lib/common/disposable';
31
31
  import { WorkspaceExtImpl } from './workspace';
32
- import { WidgetOpenerOptions } from '@theia/core/lib/browser';
33
32
 
34
33
  export class CustomEditorsExtImpl implements CustomEditorsExt {
35
34
  private readonly proxy: CustomEditorsMain;
@@ -116,12 +115,12 @@ export class CustomEditorsExtImpl implements CustomEditorsExt {
116
115
  document.dispose();
117
116
  }
118
117
 
119
- async $resolveWebviewEditor(
118
+ async $resolveWebviewEditor<T>(
120
119
  resource: UriComponents,
121
120
  handler: string,
122
121
  viewType: string,
123
122
  title: string,
124
- widgetOpenerOptions: WidgetOpenerOptions | undefined,
123
+ widgetOpenerOptions: T | undefined,
125
124
  options: theia.WebviewPanelOptions & theia.WebviewOptions,
126
125
  cancellation: CancellationToken
127
126
  ): Promise<void> {
@@ -24,9 +24,10 @@ export function serializeEnterRules(rules?: theia.OnEnterRule[]): SerializedOnEn
24
24
 
25
25
  return rules.map(r =>
26
26
  ({
27
- action: r.action,
28
27
  beforeText: serializeRegExp(r.beforeText),
29
- afterText: serializeRegExp(r.afterText)
28
+ afterText: serializeRegExp(r.afterText),
29
+ previousLineText: serializeRegExp(r.previousLineText),
30
+ action: r.action,
30
31
  } as SerializedOnEnterRule));
31
32
  }
32
33