@theia/core 1.45.0 → 1.46.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 (162) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +4 -0
  3. package/i18n/nls.de.json +4 -0
  4. package/i18n/nls.es.json +4 -0
  5. package/i18n/nls.fr.json +4 -0
  6. package/i18n/nls.hu.json +4 -0
  7. package/i18n/nls.it.json +4 -0
  8. package/i18n/nls.ja.json +4 -0
  9. package/i18n/nls.json +4 -0
  10. package/i18n/nls.pl.json +4 -0
  11. package/i18n/nls.pt-br.json +4 -0
  12. package/i18n/nls.pt-pt.json +4 -0
  13. package/i18n/nls.ru.json +4 -0
  14. package/i18n/nls.zh-cn.json +4 -0
  15. package/lib/browser/browser.d.ts +3 -0
  16. package/lib/browser/browser.d.ts.map +1 -1
  17. package/lib/browser/browser.js +5 -1
  18. package/lib/browser/browser.js.map +1 -1
  19. package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
  20. package/lib/browser/common-frontend-contribution.js +3 -3
  21. package/lib/browser/common-frontend-contribution.js.map +1 -1
  22. package/lib/browser/frontend-application-module.d.ts.map +1 -1
  23. package/lib/browser/frontend-application-module.js +2 -1
  24. package/lib/browser/frontend-application-module.js.map +1 -1
  25. package/lib/browser/messaging/ws-connection-source.d.ts +2 -0
  26. package/lib/browser/messaging/ws-connection-source.d.ts.map +1 -1
  27. package/lib/browser/messaging/ws-connection-source.js +38 -22
  28. package/lib/browser/messaging/ws-connection-source.js.map +1 -1
  29. package/lib/browser/tree/index.d.ts +1 -0
  30. package/lib/browser/tree/index.d.ts.map +1 -1
  31. package/lib/browser/tree/index.js +1 -0
  32. package/lib/browser/tree/index.js.map +1 -1
  33. package/lib/browser/tree/tree-preference.d.ts +11 -0
  34. package/lib/browser/tree/tree-preference.d.ts.map +1 -0
  35. package/lib/browser/tree/tree-preference.js +47 -0
  36. package/lib/browser/tree/tree-preference.js.map +1 -0
  37. package/lib/browser/tree/tree-widget.d.ts +6 -3
  38. package/lib/browser/tree/tree-widget.d.ts.map +1 -1
  39. package/lib/browser/tree/tree-widget.js +24 -3
  40. package/lib/browser/tree/tree-widget.js.map +1 -1
  41. package/lib/browser/tree/tree.d.ts.map +1 -1
  42. package/lib/browser/tree/tree.js +4 -1
  43. package/lib/browser/tree/tree.js.map +1 -1
  44. package/lib/browser/widget-manager.d.ts +9 -0
  45. package/lib/browser/widget-manager.d.ts.map +1 -1
  46. package/lib/browser/widget-manager.js +23 -0
  47. package/lib/browser/widget-manager.js.map +1 -1
  48. package/lib/browser/widgets/select-component.d.ts.map +1 -1
  49. package/lib/browser/widgets/select-component.js +1 -0
  50. package/lib/browser/widgets/select-component.js.map +1 -1
  51. package/lib/browser-only/frontend-only-application-module.d.ts +5 -0
  52. package/lib/browser-only/frontend-only-application-module.d.ts.map +1 -0
  53. package/lib/browser-only/frontend-only-application-module.js +115 -0
  54. package/lib/browser-only/frontend-only-application-module.js.map +1 -0
  55. package/lib/browser-only/i18n/i18n-frontend-only-module.d.ts +4 -0
  56. package/lib/browser-only/i18n/i18n-frontend-only-module.d.ts.map +1 -0
  57. package/lib/browser-only/i18n/i18n-frontend-only-module.js +35 -0
  58. package/lib/browser-only/i18n/i18n-frontend-only-module.js.map +1 -0
  59. package/lib/browser-only/logger-frontend-only-module.d.ts +3 -0
  60. package/lib/browser-only/logger-frontend-only-module.d.ts.map +1 -0
  61. package/lib/browser-only/logger-frontend-only-module.js +61 -0
  62. package/lib/browser-only/logger-frontend-only-module.js.map +1 -0
  63. package/lib/browser-only/messaging/frontend-only-service-connection-provider.d.ts +14 -0
  64. package/lib/browser-only/messaging/frontend-only-service-connection-provider.d.ts.map +1 -0
  65. package/lib/browser-only/messaging/frontend-only-service-connection-provider.js +57 -0
  66. package/lib/browser-only/messaging/frontend-only-service-connection-provider.js.map +1 -0
  67. package/lib/browser-only/messaging/messaging-frontend-only-module.d.ts +3 -0
  68. package/lib/browser-only/messaging/messaging-frontend-only-module.d.ts.map +1 -0
  69. package/lib/browser-only/messaging/messaging-frontend-only-module.js +48 -0
  70. package/lib/browser-only/messaging/messaging-frontend-only-module.js.map +1 -0
  71. package/lib/browser-only/preload/frontend-only-preload-module.d.ts +4 -0
  72. package/lib/browser-only/preload/frontend-only-preload-module.d.ts.map +1 -0
  73. package/lib/browser-only/preload/frontend-only-preload-module.js +52 -0
  74. package/lib/browser-only/preload/frontend-only-preload-module.js.map +1 -0
  75. package/lib/common/application-protocol.d.ts +1 -0
  76. package/lib/common/application-protocol.d.ts.map +1 -1
  77. package/lib/common/disposable.d.ts +9 -0
  78. package/lib/common/disposable.d.ts.map +1 -1
  79. package/lib/common/disposable.js +26 -1
  80. package/lib/common/disposable.js.map +1 -1
  81. package/lib/{node → common}/file-uri.d.ts +1 -1
  82. package/lib/common/file-uri.d.ts.map +1 -0
  83. package/lib/{node → common}/file-uri.js +2 -2
  84. package/lib/common/file-uri.js.map +1 -0
  85. package/lib/common/menu/menu-model-registry.d.ts +2 -2
  86. package/lib/common/menu/menu-model-registry.d.ts.map +1 -1
  87. package/lib/common/menu/menu-model-registry.js +16 -2
  88. package/lib/common/menu/menu-model-registry.js.map +1 -1
  89. package/lib/common/menu/menu.spec.js +28 -1
  90. package/lib/common/menu/menu.spec.js.map +1 -1
  91. package/lib/common/message-rpc/msg-pack-extension-manager.d.ts +1 -1
  92. package/lib/common/message-rpc/msg-pack-extension-manager.js +1 -1
  93. package/lib/common/message-rpc/rpc-protocol.d.ts +3 -1
  94. package/lib/common/message-rpc/rpc-protocol.d.ts.map +1 -1
  95. package/lib/common/message-rpc/rpc-protocol.js +19 -1
  96. package/lib/common/message-rpc/rpc-protocol.js.map +1 -1
  97. package/lib/common/messaging/proxy-factory.d.ts.map +1 -1
  98. package/lib/common/messaging/proxy-factory.js +1 -8
  99. package/lib/common/messaging/proxy-factory.js.map +1 -1
  100. package/lib/common/quick-pick-service.d.ts +1 -1
  101. package/lib/common/quick-pick-service.d.ts.map +1 -1
  102. package/lib/common/uuid.d.ts +6 -0
  103. package/lib/common/uuid.d.ts.map +1 -1
  104. package/lib/common/uuid.js +13 -1
  105. package/lib/common/uuid.js.map +1 -1
  106. package/lib/electron-main/electron-main-application.js +1 -1
  107. package/lib/electron-main/electron-main-application.js.map +1 -1
  108. package/lib/electron-main/theia-electron-window.js +1 -1
  109. package/lib/electron-main/theia-electron-window.js.map +1 -1
  110. package/lib/node/application-server.d.ts +1 -0
  111. package/lib/node/application-server.d.ts.map +1 -1
  112. package/lib/node/application-server.js +7 -1
  113. package/lib/node/application-server.js.map +1 -1
  114. package/lib/node/env-variables/env-variables-server.js +1 -1
  115. package/lib/node/env-variables/env-variables-server.js.map +1 -1
  116. package/lib/node/file-uri.spec.js +1 -1
  117. package/lib/node/file-uri.spec.js.map +1 -1
  118. package/lib/node/index.d.ts +1 -1
  119. package/lib/node/index.d.ts.map +1 -1
  120. package/lib/node/index.js +1 -1
  121. package/lib/node/index.js.map +1 -1
  122. package/lib/node/messaging/websocket-frontend-connection-service.d.ts +2 -1
  123. package/lib/node/messaging/websocket-frontend-connection-service.d.ts.map +1 -1
  124. package/lib/node/messaging/websocket-frontend-connection-service.js +8 -3
  125. package/lib/node/messaging/websocket-frontend-connection-service.js.map +1 -1
  126. package/package.json +10 -6
  127. package/src/browser/browser.ts +6 -1
  128. package/src/browser/common-frontend-contribution.ts +3 -3
  129. package/src/browser/frontend-application-module.ts +2 -1
  130. package/src/browser/messaging/ws-connection-source.ts +41 -21
  131. package/src/browser/style/select-component.css +12 -13
  132. package/src/browser/tree/index.ts +1 -0
  133. package/src/browser/tree/tree-preference.ts +50 -0
  134. package/src/browser/tree/tree-widget.tsx +24 -5
  135. package/src/browser/tree/tree.ts +2 -1
  136. package/src/browser/widget-manager.ts +25 -0
  137. package/src/browser/widgets/select-component.tsx +1 -0
  138. package/src/browser-only/frontend-only-application-module.ts +115 -0
  139. package/src/browser-only/i18n/i18n-frontend-only-module.ts +37 -0
  140. package/src/browser-only/logger-frontend-only-module.ts +63 -0
  141. package/src/browser-only/messaging/frontend-only-service-connection-provider.ts +39 -0
  142. package/src/browser-only/messaging/messaging-frontend-only-module.ts +42 -0
  143. package/src/browser-only/preload/frontend-only-preload-module.ts +49 -0
  144. package/src/common/application-protocol.ts +1 -0
  145. package/src/common/disposable.ts +25 -0
  146. package/src/{node → common}/file-uri.ts +2 -2
  147. package/src/common/menu/menu-model-registry.ts +22 -5
  148. package/src/common/menu/menu.spec.ts +30 -2
  149. package/src/common/message-rpc/msg-pack-extension-manager.ts +1 -1
  150. package/src/common/message-rpc/rpc-protocol.ts +22 -2
  151. package/src/common/messaging/proxy-factory.ts +1 -8
  152. package/src/common/quick-pick-service.ts +1 -1
  153. package/src/common/uuid.ts +13 -0
  154. package/src/electron-main/electron-main-application.ts +1 -1
  155. package/src/electron-main/theia-electron-window.ts +1 -1
  156. package/src/node/application-server.ts +8 -1
  157. package/src/node/env-variables/env-variables-server.ts +1 -1
  158. package/src/node/file-uri.spec.ts +1 -1
  159. package/src/node/index.ts +1 -1
  160. package/src/node/messaging/websocket-frontend-connection-service.ts +10 -5
  161. package/lib/node/file-uri.d.ts.map +0 -1
  162. package/lib/node/file-uri.js.map +0 -1
@@ -26,3 +26,4 @@ export * from './tree-container';
26
26
  export * from './tree-decorator';
27
27
  export * from './tree-search';
28
28
  export * from './tree-compression';
29
+ export * from './tree-preference';
@@ -0,0 +1,50 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 STMicroelectronics and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { interfaces } from 'inversify';
18
+ import { PreferenceProxy, PreferenceContribution, PreferenceSchema } from '../preferences';
19
+ import { PreferenceProxyFactory } from '../preferences/injectable-preference-proxy';
20
+ import { nls } from '../../common/nls';
21
+
22
+ export const PREFERENCE_NAME_TREE_INDENT = 'workbench.tree.indent';
23
+
24
+ export const treePreferencesSchema: PreferenceSchema = {
25
+ type: 'object',
26
+ properties: {
27
+ [PREFERENCE_NAME_TREE_INDENT]: {
28
+ description: nls.localizeByDefault('Controls tree indentation in pixels.'),
29
+ type: 'number',
30
+ default: 8,
31
+ minimum: 4,
32
+ maximum: 40
33
+ },
34
+ }
35
+ };
36
+
37
+ export class TreeConfiguration {
38
+ [PREFERENCE_NAME_TREE_INDENT]: number;
39
+ }
40
+
41
+ export const TreePreferences = Symbol('treePreferences');
42
+ export type TreePreferences = PreferenceProxy<TreeConfiguration>;
43
+
44
+ export function bindTreePreferences(bind: interfaces.Bind): void {
45
+ bind(TreePreferences).toDynamicValue(ctx => {
46
+ const factory = ctx.container.get<PreferenceProxyFactory>(PreferenceProxyFactory);
47
+ return factory(treePreferencesSchema);
48
+ }).inSingletonScope();
49
+ bind(PreferenceContribution).toConstantValue({ schema: treePreferencesSchema });
50
+ }
@@ -43,6 +43,8 @@ import { LabelProvider } from '../label-provider';
43
43
  import { CorePreferences } from '../core-preferences';
44
44
  import { TreeFocusService } from './tree-focus-service';
45
45
  import { useEffect } from 'react';
46
+ import { PreferenceService, PreferenceChange } from '../preferences';
47
+ import { PREFERENCE_NAME_TREE_INDENT } from './tree-preference';
46
48
 
47
49
  const debounce = require('lodash.debounce');
48
50
 
@@ -73,8 +75,7 @@ export interface TreeProps {
73
75
  readonly contextMenuPath?: MenuPath;
74
76
 
75
77
  /**
76
- * The size of the padding (in pixels) per hierarchy depth. The root element won't have left padding but
77
- * the padding for the children will be calculated as `leftPadding * hierarchyDepth` and so on.
78
+ * The size of the padding (in pixels) for the root node of the tree.
78
79
  */
79
80
  readonly leftPadding: number;
80
81
 
@@ -174,6 +175,9 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
174
175
  @inject(SelectionService)
175
176
  protected readonly selectionService: SelectionService;
176
177
 
178
+ @inject(PreferenceService)
179
+ protected readonly preferenceService: PreferenceService;
180
+
177
181
  @inject(LabelProvider)
178
182
  protected readonly labelProvider: LabelProvider;
179
183
 
@@ -182,6 +186,8 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
182
186
 
183
187
  protected shouldScrollToRow = true;
184
188
 
189
+ protected treeIndent: number = 8;
190
+
185
191
  constructor(
186
192
  @inject(TreeProps) readonly props: TreeProps,
187
193
  @inject(TreeModel) readonly model: TreeModel,
@@ -198,6 +204,7 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
198
204
 
199
205
  @postConstruct()
200
206
  protected init(): void {
207
+ this.treeIndent = this.preferenceService.get(PREFERENCE_NAME_TREE_INDENT, this.treeIndent);
201
208
  if (this.props.search) {
202
209
  this.searchBox = this.searchBoxFactory({ ...SearchBoxProps.DEFAULT, showButtons: true, showFilter: true });
203
210
  this.searchBox.node.addEventListener('focus', () => {
@@ -264,6 +271,12 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
264
271
  return;
265
272
  }
266
273
  }
274
+ }),
275
+ this.preferenceService.onPreferenceChanged((event: PreferenceChange) => {
276
+ if (event.preferenceName === PREFERENCE_NAME_TREE_INDENT) {
277
+ this.treeIndent = event.newValue;
278
+ this.update();
279
+ }
267
280
  })
268
281
  ]);
269
282
  setTimeout(() => {
@@ -1227,12 +1240,15 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
1227
1240
 
1228
1241
  /**
1229
1242
  * Handle the `space key` keyboard event.
1230
- * - By default should be similar to a single-click action.
1243
+ * - If the element has a checkbox, it will be toggled.
1244
+ * - Otherwise, it should be similar to a single-click action.
1231
1245
  * @param event the `space key` keyboard event.
1232
1246
  */
1233
1247
  protected handleSpace(event: KeyboardEvent): void {
1234
1248
  const { focusedNode } = this.focusService;
1235
- if (!this.props.multiSelect || (!event.ctrlKey && !event.metaKey && !event.shiftKey)) {
1249
+ if (focusedNode && focusedNode.checkboxInfo) {
1250
+ this.model.markAsChecked(focusedNode, !focusedNode.checkboxInfo.checked);
1251
+ } else if (!this.props.multiSelect || (!event.ctrlKey && !event.metaKey && !event.shiftKey)) {
1236
1252
  this.tapNode(focusedNode);
1237
1253
  }
1238
1254
  }
@@ -1497,7 +1513,10 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
1497
1513
  return this.labelProvider.getLongName(node);
1498
1514
  }
1499
1515
  protected getDepthPadding(depth: number): number {
1500
- return depth * this.props.leftPadding;
1516
+ if (depth === 1) {
1517
+ return this.props.leftPadding;
1518
+ }
1519
+ return depth * this.treeIndent;
1501
1520
  }
1502
1521
  }
1503
1522
  export namespace TreeWidget {
@@ -397,9 +397,10 @@ export class TreeImpl implements Tree {
397
397
 
398
398
  protected async doMarkAsBusy(node: Mutable<TreeNode>, ms: number, token: CancellationToken): Promise<void> {
399
399
  try {
400
+ token.onCancellationRequested(() => this.doResetBusy(node));
400
401
  await timeout(ms, token);
402
+ if (token.isCancellationRequested) { return; }
401
403
  this.doSetBusy(node);
402
- token.onCancellationRequested(() => this.doResetBusy(node));
403
404
  } catch {
404
405
  /* no-op */
405
406
  }
@@ -194,6 +194,31 @@ export class WidgetManager {
194
194
  return widget;
195
195
  }
196
196
 
197
+ /**
198
+ * Finds a widget that matches the given test predicate.
199
+ * @param factoryId The widget factory id.
200
+ * @param predicate The test predicate.
201
+ *
202
+ * @returns a promise resolving to the widget if available, else `undefined`.
203
+ */
204
+ async findWidget<T extends Widget>(factoryId: string, predicate: (options?: any) => boolean): Promise<T | undefined> {
205
+ for (const [key, widget] of this.widgets.entries()) {
206
+ if (this.testPredicate(key, factoryId, predicate)) {
207
+ return widget as T;
208
+ }
209
+ }
210
+ for (const [key, widget] of this.pendingWidgetPromises.entries()) {
211
+ if (this.testPredicate(key, factoryId, predicate)) {
212
+ return widget as T;
213
+ }
214
+ }
215
+ }
216
+
217
+ protected testPredicate(key: string, factoryId: string, predicate: (options?: any) => boolean): boolean {
218
+ const constructionOptions = this.fromKey(key);
219
+ return constructionOptions.factoryId === factoryId && predicate(constructionOptions.options);
220
+ }
221
+
197
222
  protected doGetWidget<T extends Widget>(key: string): MaybePromise<T> | undefined {
198
223
  const pendingWidget = this.widgets.get(key) ?? this.pendingWidgetPromises.get(key);
199
224
  if (pendingWidget) {
@@ -77,6 +77,7 @@ export class SelectComponent extends React.Component<SelectComponentProps, Selec
77
77
  if (!list) {
78
78
  list = document.createElement('div');
79
79
  list.id = SELECT_COMPONENT_CONTAINER;
80
+ list.className = 'theia-select-component-container';
80
81
  document.body.appendChild(list);
81
82
  }
82
83
  this.dropdownElement = list;
@@ -0,0 +1,115 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ContainerModule } from 'inversify';
18
+ import { BackendStopwatch, CommandRegistry, Emitter, MeasurementOptions, OS } from '../common';
19
+ import { ApplicationInfo, ApplicationServer, ExtensionInfo } from '../common/application-protocol';
20
+ import { EnvVariable, EnvVariablesServer } from './../common/env-variables';
21
+ import { bindMessageService } from '../browser/frontend-application-bindings';
22
+ import { KeyStoreService } from '../common/key-store';
23
+ import { QuickPickService } from '../common/quick-pick-service';
24
+ import { QuickPickServiceImpl } from '../browser/quick-input';
25
+ import { BackendRequestService, RequestService } from '@theia/request';
26
+ import { ConnectionStatus, ConnectionStatusService } from '../browser/connection-status-service';
27
+
28
+ export { bindMessageService };
29
+
30
+ // is loaded directly after the regular frontend module
31
+ export const frontendOnlyApplicationModule = new ContainerModule((bind, unbind, isBound, rebind) => {
32
+
33
+ if (isBound(CommandRegistry)) {
34
+ rebind(CommandRegistry).toSelf().inSingletonScope();
35
+ } else {
36
+ bind(CommandRegistry).toSelf().inSingletonScope();
37
+ }
38
+
39
+ const stopwatch: BackendStopwatch = {
40
+ start: async (_name: string, _options?: MeasurementOptions | undefined): Promise<number> => -1,
41
+ stop: async (_measurement: number, _message: string, _messageArgs: unknown[]): Promise<void> => { }
42
+ };
43
+ if (isBound(BackendStopwatch)) {
44
+ rebind(BackendStopwatch).toConstantValue(stopwatch);
45
+ } else {
46
+ bind(BackendStopwatch).toConstantValue(stopwatch);
47
+ }
48
+
49
+ if (isBound(CommandRegistry)) {
50
+ rebind(QuickPickService).to(QuickPickServiceImpl).inSingletonScope();
51
+ } else {
52
+ bind(QuickPickService).to(QuickPickServiceImpl).inSingletonScope();
53
+ }
54
+
55
+ const mockedApplicationServer: ApplicationServer = {
56
+ getExtensionsInfos: async (): Promise<ExtensionInfo[]> => [],
57
+ getApplicationInfo: async (): Promise<ApplicationInfo | undefined> => undefined,
58
+ getApplicationRoot: async (): Promise<string> => '',
59
+ getBackendOS: async (): Promise<OS.Type> => OS.Type.Linux
60
+ };
61
+ if (isBound(ApplicationServer)) {
62
+ rebind(ApplicationServer).toConstantValue(mockedApplicationServer);
63
+ } else {
64
+ bind(ApplicationServer).toConstantValue(mockedApplicationServer);
65
+ }
66
+
67
+ const varServer: EnvVariablesServer = {
68
+ getExecPath: async (): Promise<string> => '',
69
+ getVariables: async (): Promise<EnvVariable[]> => [],
70
+ getValue: async (_key: string): Promise<EnvVariable | undefined> => undefined,
71
+ getConfigDirUri: async (): Promise<string> => '',
72
+ getHomeDirUri: async (): Promise<string> => '',
73
+ getDrives: async (): Promise<string[]> => []
74
+ };
75
+ if (isBound(EnvVariablesServer)) {
76
+ rebind(EnvVariablesServer).toConstantValue(varServer);
77
+ } else {
78
+ bind(EnvVariablesServer).toConstantValue(varServer);
79
+ }
80
+
81
+ const keyStoreService: KeyStoreService = {
82
+ deletePassword: () => Promise.resolve(false),
83
+ findCredentials: () => Promise.resolve([]),
84
+ findPassword: () => Promise.resolve(undefined),
85
+ setPassword: () => Promise.resolve(),
86
+ getPassword: () => Promise.resolve(undefined)
87
+ };
88
+ if (isBound(KeyStoreService)) {
89
+ rebind<KeyStoreService>(KeyStoreService).toConstantValue(keyStoreService);
90
+ } else {
91
+ bind<KeyStoreService>(KeyStoreService).toConstantValue(keyStoreService);
92
+ }
93
+
94
+ const requestService: RequestService = {
95
+ configure: () => Promise.resolve(),
96
+ request: () => Promise.reject(),
97
+ resolveProxy: () => Promise.resolve(undefined)
98
+ };
99
+ if (isBound(BackendRequestService)) {
100
+ rebind<RequestService>(BackendRequestService).toConstantValue(requestService);
101
+ } else {
102
+ bind<RequestService>(BackendRequestService).toConstantValue(requestService);
103
+ }
104
+
105
+ const connectionStatusService: ConnectionStatusService = {
106
+ currentStatus: ConnectionStatus.ONLINE,
107
+ onStatusChange: new Emitter<ConnectionStatus>().event
108
+ };
109
+ if (isBound(ConnectionStatusService)) {
110
+ rebind<ConnectionStatusService>(ConnectionStatusService).toConstantValue(connectionStatusService);
111
+ } else {
112
+ bind<ConnectionStatusService>(ConnectionStatusService).toConstantValue(connectionStatusService);
113
+ }
114
+
115
+ });
@@ -0,0 +1,37 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ContainerModule } from 'inversify';
18
+ import { AsyncLocalizationProvider, LanguageInfo, Localization } from '../../common/i18n/localization';
19
+ import { LanguageQuickPickService } from '../../browser/i18n/language-quick-pick-service';
20
+
21
+ export default new ContainerModule(bind => {
22
+ const i18nMock: AsyncLocalizationProvider = {
23
+ getCurrentLanguage: async (): Promise<string> => 'en',
24
+ setCurrentLanguage: async (_languageId: string): Promise<void> => {
25
+
26
+ },
27
+ getAvailableLanguages: async (): Promise<LanguageInfo[]> =>
28
+ []
29
+ ,
30
+ loadLocalization: async (_languageId: string): Promise<Localization> => ({
31
+ translations: {},
32
+ languageId: 'en'
33
+ })
34
+ };
35
+ bind(AsyncLocalizationProvider).toConstantValue(i18nMock);
36
+ bind(LanguageQuickPickService).toSelf().inSingletonScope();
37
+ });
@@ -0,0 +1,63 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ContainerModule, Container } from 'inversify';
18
+ import { ILoggerServer, ILoggerClient, LogLevel, ConsoleLogger } from '../common/logger-protocol';
19
+ import { ILogger, Logger, LoggerFactory, LoggerName } from '../common/logger';
20
+
21
+ // is loaded directly after the regular logger frontend module
22
+ export const loggerFrontendOnlyModule = new ContainerModule((bind, unbind, isBound, rebind) => {
23
+ const logger: ILoggerServer = {
24
+ setLogLevel: async (_name: string, _logLevel: number): Promise<void> => { },
25
+ getLogLevel: async (_name: string): Promise<number> => LogLevel.INFO,
26
+ log: async (name: string, logLevel: number, message: string, params: unknown[]): Promise<void> => {
27
+ ConsoleLogger.log(name, logLevel, message, params);
28
+
29
+ },
30
+ child: async (_name: string): Promise<void> => { },
31
+ dispose: (): void => {
32
+ },
33
+ setClient: (_client: ILoggerClient | undefined): void => {
34
+ }
35
+ };
36
+ if (isBound(ILoggerServer)) {
37
+ rebind(ILoggerServer).toConstantValue(logger);
38
+ } else {
39
+ bind(ILoggerServer).toConstantValue(logger);
40
+ }
41
+
42
+ if (isBound(ILoggerServer)) {
43
+ rebind(LoggerFactory).toFactory(ctx =>
44
+ (name: string) => {
45
+ const child = new Container({ defaultScope: 'Singleton' });
46
+ child.parent = ctx.container;
47
+ child.bind(ILogger).to(Logger).inTransientScope();
48
+ child.bind(LoggerName).toConstantValue(name);
49
+ return child.get(ILogger);
50
+ }
51
+ );
52
+ } else {
53
+ bind(LoggerFactory).toFactory(ctx =>
54
+ (name: string) => {
55
+ const child = new Container({ defaultScope: 'Singleton' });
56
+ child.parent = ctx.container;
57
+ child.bind(ILogger).to(Logger).inTransientScope();
58
+ child.bind(LoggerName).toConstantValue(name);
59
+ return child.get(ILogger);
60
+ }
61
+ );
62
+ }
63
+ });
@@ -0,0 +1,39 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+ import { Event, RpcProxy, Channel, RpcProxyFactory, Emitter } from '../../common';
17
+ import { injectable } from 'inversify';
18
+ import { ServiceConnectionProvider } from '../../browser/messaging/service-connection-provider';
19
+ import { ConnectionSource } from '../../browser/messaging/connection-source';
20
+
21
+ @injectable()
22
+ export class FrontendOnlyConnectionSource implements ConnectionSource {
23
+ onConnectionDidOpen = new Emitter<Channel>().event;
24
+ }
25
+
26
+ @injectable()
27
+ export class FrontendOnlyServiceConnectionProvider extends ServiceConnectionProvider {
28
+ onSocketDidOpen = Event.None;
29
+ onSocketDidClose = Event.None;
30
+ onIncomingMessageActivity = Event.None;
31
+ override createProxy<T extends object>(path: unknown, target?: unknown): RpcProxy<T> {
32
+ console.debug(`[Frontend-Only Fallback] Created proxy connection for ${path}`);
33
+ const factory = target instanceof RpcProxyFactory ? target : new RpcProxyFactory<T>(target);
34
+ return factory.createProxy();
35
+ }
36
+ override listen(path: string, handler: ServiceConnectionProvider.ConnectionHandler, reconnect: boolean): void {
37
+ console.debug('[Frontend-Only Fallback] Listen to websocket connection requested');
38
+ }
39
+ }
@@ -0,0 +1,42 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+ import { ContainerModule } from 'inversify';
17
+ import { WebSocketConnectionSource } from '../../browser/messaging/ws-connection-source';
18
+ import { FrontendOnlyConnectionSource, FrontendOnlyServiceConnectionProvider } from './frontend-only-service-connection-provider';
19
+ import { ConnectionSource } from '../../browser/messaging/connection-source';
20
+ import { LocalConnectionProvider, RemoteConnectionProvider } from '../../browser/messaging/service-connection-provider';
21
+
22
+ // is loaded directly after the regular message frontend module
23
+ export const messagingFrontendOnlyModule = new ContainerModule((bind, unbind, isBound, rebind) => {
24
+ unbind(WebSocketConnectionSource);
25
+ bind(FrontendOnlyConnectionSource).toSelf().inSingletonScope();
26
+ if (isBound(ConnectionSource)) {
27
+ rebind(ConnectionSource).toService(FrontendOnlyConnectionSource);
28
+ } else {
29
+ bind(ConnectionSource).toService(FrontendOnlyConnectionSource);
30
+ }
31
+ bind(FrontendOnlyServiceConnectionProvider).toSelf().inSingletonScope();
32
+ if (isBound(LocalConnectionProvider)) {
33
+ rebind(LocalConnectionProvider).toService(FrontendOnlyServiceConnectionProvider);
34
+ } else {
35
+ bind(LocalConnectionProvider).toService(FrontendOnlyServiceConnectionProvider);
36
+ }
37
+ if (isBound(RemoteConnectionProvider)) {
38
+ rebind(RemoteConnectionProvider).toService(FrontendOnlyServiceConnectionProvider);
39
+ } else {
40
+ bind(RemoteConnectionProvider).toService(FrontendOnlyServiceConnectionProvider);
41
+ }
42
+ });
@@ -0,0 +1,49 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 TypeFox and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ContainerModule } from 'inversify';
18
+ import { LocalizationServer } from '../../common/i18n/localization-server';
19
+ import { OS, OSBackendProvider } from '../../common/os';
20
+ import { Localization } from '../../common/i18n/localization';
21
+
22
+ // loaded after regular preload module
23
+ export default new ContainerModule((bind, unbind, isBound, rebind) => {
24
+ const frontendOnlyLocalizationServer: LocalizationServer = {
25
+ loadLocalization: async (languageId: string): Promise<Localization> => ({ translations: {}, languageId })
26
+ };
27
+ if (isBound(LocalizationServer)) {
28
+ rebind(LocalizationServer).toConstantValue(frontendOnlyLocalizationServer);
29
+ } else {
30
+ bind(LocalizationServer).toConstantValue(frontendOnlyLocalizationServer);
31
+ }
32
+
33
+ const frontendOnlyOSBackendProvider: OSBackendProvider = {
34
+ getBackendOS: async (): Promise<OS.Type> => {
35
+ if (window.navigator.platform.startsWith('Win')) {
36
+ return OS.Type.Windows;
37
+ } else if (window.navigator.platform.startsWith('Mac')) {
38
+ return OS.Type.OSX;
39
+ } else {
40
+ return OS.Type.Linux;
41
+ }
42
+ }
43
+ };
44
+ if (isBound(OSBackendProvider)) {
45
+ rebind(OSBackendProvider).toConstantValue(frontendOnlyOSBackendProvider);
46
+ } else {
47
+ bind(OSBackendProvider).toConstantValue(frontendOnlyOSBackendProvider);
48
+ }
49
+ });
@@ -23,6 +23,7 @@ export const ApplicationServer = Symbol('ApplicationServer');
23
23
  export interface ApplicationServer {
24
24
  getExtensionsInfos(): Promise<ExtensionInfo[]>;
25
25
  getApplicationInfo(): Promise<ApplicationInfo | undefined>;
26
+ getApplicationRoot(): Promise<string>;
26
27
  /**
27
28
  * @deprecated since 1.25.0. Use `OS.backend.type()` instead.
28
29
  */
@@ -133,3 +133,28 @@ export function disposableTimeout(...args: Parameters<typeof setTimeout>): Dispo
133
133
  const handle = setTimeout(...args);
134
134
  return { dispose: () => clearTimeout(handle) };
135
135
  }
136
+
137
+ /**
138
+ * Wrapper for a {@link Disposable} that is not available immediately.
139
+ */
140
+ export class DisposableWrapper implements Disposable {
141
+
142
+ private disposed = false;
143
+ private disposable: Disposable | undefined = undefined;
144
+
145
+ set(disposable: Disposable): void {
146
+ if (this.disposed) {
147
+ disposable.dispose();
148
+ } else {
149
+ this.disposable = disposable;
150
+ }
151
+ }
152
+
153
+ dispose(): void {
154
+ this.disposed = true;
155
+ if (this.disposable) {
156
+ this.disposable.dispose();
157
+ this.disposable = undefined;
158
+ }
159
+ }
160
+ }
@@ -15,8 +15,8 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { URI as Uri } from 'vscode-uri';
18
- import URI from '../common/uri';
19
- import { isWindows } from '../common/os';
18
+ import URI from './uri';
19
+ import { isWindows } from './os';
20
20
 
21
21
  export namespace FileUri {
22
22
 
@@ -14,13 +14,13 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { injectable, inject, named } from 'inversify';
18
- import { Disposable } from '../disposable';
19
- import { CommandRegistry, Command } from '../command';
17
+ import { inject, injectable, named } from 'inversify';
18
+ import { Command, CommandRegistry } from '../command';
20
19
  import { ContributionProvider } from '../contribution-provider';
21
- import { CompositeMenuNode, CompositeMenuNodeWrapper } from './composite-menu-node';
22
- import { CompoundMenuNode, MenuAction, MenuNode, MenuPath, MutableCompoundMenuNode, SubMenuOptions } from './menu-types';
20
+ import { Disposable } from '../disposable';
23
21
  import { ActionMenuNode } from './action-menu-node';
22
+ import { CompositeMenuNode, CompositeMenuNodeWrapper } from './composite-menu-node';
23
+ import { CompoundMenuNode, MenuAction, MenuNode, MenuNodeMetadata, MenuPath, MutableCompoundMenuNode, SubMenuOptions } from './menu-types';
24
24
 
25
25
  export const MenuContribution = Symbol('MenuContribution');
26
26
 
@@ -157,6 +157,23 @@ export class MenuModelRegistry {
157
157
  linkSubmenu(parentPath: MenuPath | string, childId: string | MenuPath, options?: SubMenuOptions, group?: string): Disposable {
158
158
  const child = this.getMenuNode(childId);
159
159
  const parent = this.getMenuNode(parentPath, group);
160
+
161
+ const isRecursive = (node: MenuNodeMetadata, childNode: MenuNodeMetadata): boolean => {
162
+ if (node.id === childNode.id) {
163
+ return true;
164
+ }
165
+ if (node.parent) {
166
+ return isRecursive(node.parent, childNode);
167
+ }
168
+ return false;
169
+ };
170
+
171
+ // check for menu contribution recursion
172
+ if (isRecursive(parent, child)) {
173
+ console.warn(`Recursive menu contribution detected: ${child.id} is already in hierarchy of ${parent.id}.`);
174
+ return Disposable.NULL;
175
+ }
176
+
160
177
  const wrapper = new CompositeMenuNodeWrapper(child, parent, options);
161
178
  return parent.addNode(wrapper);
162
179
  }