@theia/core 1.73.0-next.9 → 1.73.1
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.
- package/README.md +26 -16
- package/i18n/nls.cs.json +273 -36
- package/i18n/nls.de.json +273 -36
- package/i18n/nls.es.json +273 -36
- package/i18n/nls.fr.json +273 -36
- package/i18n/nls.hu.json +273 -36
- package/i18n/nls.it.json +273 -36
- package/i18n/nls.ja.json +273 -36
- package/i18n/nls.json +273 -36
- package/i18n/nls.ko.json +273 -36
- package/i18n/nls.pl.json +273 -36
- package/i18n/nls.pt-br.json +273 -36
- package/i18n/nls.ru.json +273 -36
- package/i18n/nls.tr.json +273 -36
- package/i18n/nls.zh-cn.json +273 -36
- package/i18n/nls.zh-tw.json +273 -36
- package/lib/browser/authentication-service.d.ts +2 -0
- package/lib/browser/authentication-service.d.ts.map +1 -1
- package/lib/browser/authentication-service.js +8 -2
- package/lib/browser/authentication-service.js.map +1 -1
- package/lib/browser/catalog.json +314 -77
- package/lib/browser/frontend-application.d.ts +2 -0
- package/lib/browser/frontend-application.d.ts.map +1 -1
- package/lib/browser/frontend-application.js +15 -9
- package/lib/browser/frontend-application.js.map +1 -1
- package/lib/browser/json-schema-store.d.ts +2 -0
- package/lib/browser/json-schema-store.d.ts.map +1 -1
- package/lib/browser/json-schema-store.js +8 -2
- package/lib/browser/json-schema-store.js.map +1 -1
- package/lib/browser/keybinding.js +2 -1
- package/lib/browser/keybinding.js.map +1 -1
- package/lib/browser/keyboard/keyboard-layout-service.d.ts +2 -0
- package/lib/browser/keyboard/keyboard-layout-service.d.ts.map +1 -1
- package/lib/browser/keyboard/keyboard-layout-service.js +35 -12
- package/lib/browser/keyboard/keyboard-layout-service.js.map +1 -1
- package/lib/browser/keyboard/keyboard-layout-service.spec.js +26 -0
- package/lib/browser/keyboard/keyboard-layout-service.spec.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown.d.ts +1 -1
- package/lib/browser/markdown-rendering/markdown.d.ts.map +1 -1
- package/lib/browser/markdown-rendering/markdown.js +1 -1
- package/lib/browser/markdown-rendering/markdown.js.map +1 -1
- package/lib/browser/menu/composite-menu-node.js +4 -4
- package/lib/browser/menu/composite-menu-node.js.map +1 -1
- package/lib/browser/messaging/ws-connection-source.d.ts.map +1 -1
- package/lib/browser/messaging/ws-connection-source.js +1 -6
- package/lib/browser/messaging/ws-connection-source.js.map +1 -1
- package/lib/browser/preferences/frontend-config-preference-contributions.d.ts +2 -0
- package/lib/browser/preferences/frontend-config-preference-contributions.d.ts.map +1 -1
- package/lib/browser/preferences/frontend-config-preference-contributions.js +7 -1
- package/lib/browser/preferences/frontend-config-preference-contributions.js.map +1 -1
- package/lib/browser/preferences/preference-proxy.spec.js +7 -0
- package/lib/browser/preferences/preference-proxy.spec.js.map +1 -1
- package/lib/browser/preferences/preference-schema-provider.spec.js +3 -0
- package/lib/browser/preferences/preference-schema-provider.spec.js.map +1 -1
- package/lib/browser/preferences/preference-validation-service.d.ts +2 -0
- package/lib/browser/preferences/preference-validation-service.d.ts.map +1 -1
- package/lib/browser/preferences/preference-validation-service.js +11 -5
- package/lib/browser/preferences/preference-validation-service.js.map +1 -1
- package/lib/browser/preferences/preference-validation-service.spec.js +2 -0
- package/lib/browser/preferences/preference-validation-service.spec.js.map +1 -1
- package/lib/browser/secondary-window-handler.d.ts +2 -0
- package/lib/browser/secondary-window-handler.d.ts.map +1 -1
- package/lib/browser/secondary-window-handler.js +12 -6
- package/lib/browser/secondary-window-handler.js.map +1 -1
- package/lib/browser/shell/application-shell.d.ts +2 -0
- package/lib/browser/shell/application-shell.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +9 -3
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +6 -6
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js +2 -2
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js +131 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -1
- package/lib/browser/status-bar/status-bar.d.ts +2 -2
- package/lib/browser/status-bar/status-bar.d.ts.map +1 -1
- package/lib/browser/status-bar/status-bar.js.map +1 -1
- package/lib/browser/test/jsdom.d.ts +4 -0
- package/lib/browser/test/jsdom.d.ts.map +1 -1
- package/lib/browser/test/jsdom.js +18 -0
- package/lib/browser/test/jsdom.js.map +1 -1
- package/lib/browser/tree/tree-container.spec.js +4 -0
- package/lib/browser/tree/tree-container.spec.js.map +1 -1
- package/lib/browser/tree/tree-model.d.ts +1 -0
- package/lib/browser/tree/tree-model.d.ts.map +1 -1
- package/lib/browser/tree/tree-model.js +3 -0
- package/lib/browser/tree/tree-model.js.map +1 -1
- package/lib/browser/tree/tree-view-welcome-widget.d.ts +1 -0
- package/lib/browser/tree/tree-view-welcome-widget.d.ts.map +1 -1
- package/lib/browser/tree/tree-view-welcome-widget.js +8 -6
- package/lib/browser/tree/tree-view-welcome-widget.js.map +1 -1
- package/lib/browser/tree/tree-view-welcome-widget.spec.d.ts +2 -0
- package/lib/browser/tree/tree-view-welcome-widget.spec.d.ts.map +1 -0
- package/lib/browser/tree/tree-view-welcome-widget.spec.js +68 -0
- package/lib/browser/tree/tree-view-welcome-widget.spec.js.map +1 -0
- package/lib/browser/tree/tree-widget.js +2 -2
- package/lib/browser/tree/tree-widget.js.map +1 -1
- package/lib/browser/tree/tree.d.ts +24 -2
- package/lib/browser/tree/tree.d.ts.map +1 -1
- package/lib/browser/tree/tree.js +20 -2
- package/lib/browser/tree/tree.js.map +1 -1
- package/lib/browser/tree/tree.spec.js +27 -0
- package/lib/browser/tree/tree.spec.js.map +1 -1
- package/lib/browser/window/default-window-service.d.ts +2 -1
- package/lib/browser/window/default-window-service.d.ts.map +1 -1
- package/lib/browser/window/default-window-service.js +10 -5
- package/lib/browser/window/default-window-service.js.map +1 -1
- package/lib/browser/window/default-window-service.spec.js +2 -0
- package/lib/browser/window/default-window-service.spec.js.map +1 -1
- package/lib/browser-only/messaging/frontend-only-service-connection-provider.d.ts +2 -0
- package/lib/browser-only/messaging/frontend-only-service-connection-provider.d.ts.map +1 -1
- package/lib/browser-only/messaging/frontend-only-service-connection-provider.js +8 -2
- package/lib/browser-only/messaging/frontend-only-service-connection-provider.js.map +1 -1
- package/lib/common/command.d.ts +2 -0
- package/lib/common/command.d.ts.map +1 -1
- package/lib/common/command.js +10 -4
- package/lib/common/command.js.map +1 -1
- package/lib/common/logger.d.ts.map +1 -1
- package/lib/common/logger.js +11 -1
- package/lib/common/logger.js.map +1 -1
- package/lib/common/logger.spec.js +46 -0
- package/lib/common/logger.spec.js.map +1 -1
- package/lib/common/preferences/injectable-preference-proxy.d.ts +3 -3
- package/lib/common/preferences/injectable-preference-proxy.d.ts.map +1 -1
- package/lib/common/preferences/injectable-preference-proxy.js +6 -1
- package/lib/common/preferences/injectable-preference-proxy.js.map +1 -1
- package/lib/common/preferences/preference-proxy.d.ts.map +1 -1
- package/lib/common/preferences/preference-proxy.js +6 -1
- package/lib/common/preferences/preference-proxy.js.map +1 -1
- package/lib/electron-main/electron-main-application.d.ts.map +1 -1
- package/lib/electron-main/electron-main-application.js +4 -2
- package/lib/electron-main/electron-main-application.js.map +1 -1
- package/lib/electron-node/hosting/electron-ws-origin-validator.d.ts.map +1 -1
- package/lib/electron-node/hosting/electron-ws-origin-validator.js +5 -2
- package/lib/electron-node/hosting/electron-ws-origin-validator.js.map +1 -1
- package/lib/electron-node/hosting/electron-ws-origin-validator.spec.d.ts +2 -0
- package/lib/electron-node/hosting/electron-ws-origin-validator.spec.d.ts.map +1 -0
- package/lib/electron-node/hosting/electron-ws-origin-validator.spec.js +59 -0
- package/lib/electron-node/hosting/electron-ws-origin-validator.spec.js.map +1 -0
- package/lib/electron-node/request/electron-backend-request-service.d.ts +2 -0
- package/lib/electron-node/request/electron-backend-request-service.d.ts.map +1 -1
- package/lib/electron-node/request/electron-backend-request-service.js +7 -1
- package/lib/electron-node/request/electron-backend-request-service.js.map +1 -1
- package/lib/electron-node/token/electron-token-backend-contribution.d.ts +2 -0
- package/lib/electron-node/token/electron-token-backend-contribution.d.ts.map +1 -1
- package/lib/electron-node/token/electron-token-backend-contribution.js +7 -1
- package/lib/electron-node/token/electron-token-backend-contribution.js.map +1 -1
- package/lib/electron-node/token/electron-token-validator.d.ts +2 -0
- package/lib/electron-node/token/electron-token-validator.d.ts.map +1 -1
- package/lib/electron-node/token/electron-token-validator.js +7 -1
- package/lib/electron-node/token/electron-token-validator.js.map +1 -1
- package/lib/node/backend-application-module.d.ts.map +1 -1
- package/lib/node/backend-application-module.js +2 -0
- package/lib/node/backend-application-module.js.map +1 -1
- package/lib/node/backend-application.d.ts +11 -0
- package/lib/node/backend-application.d.ts.map +1 -1
- package/lib/node/backend-application.js +40 -12
- package/lib/node/backend-application.js.map +1 -1
- package/lib/node/backend-application.spec.js +4 -2
- package/lib/node/backend-application.spec.js.map +1 -1
- package/lib/node/hosting/backend-hosting-module.d.ts.map +1 -1
- package/lib/node/hosting/backend-hosting-module.js +7 -0
- package/lib/node/hosting/backend-hosting-module.js.map +1 -1
- package/lib/node/hosting/browser-connection-token.d.ts +46 -0
- package/lib/node/hosting/browser-connection-token.d.ts.map +1 -0
- package/lib/node/hosting/browser-connection-token.js +120 -0
- package/lib/node/hosting/browser-connection-token.js.map +1 -0
- package/lib/node/hosting/browser-connection-token.spec.d.ts +2 -0
- package/lib/node/hosting/browser-connection-token.spec.d.ts.map +1 -0
- package/lib/node/hosting/browser-connection-token.spec.js +128 -0
- package/lib/node/hosting/browser-connection-token.spec.js.map +1 -0
- package/lib/node/hosting/ws-origin-validator.d.ts.map +1 -1
- package/lib/node/hosting/ws-origin-validator.js +21 -4
- package/lib/node/hosting/ws-origin-validator.js.map +1 -1
- package/lib/node/hosting/ws-origin-validator.spec.d.ts +2 -0
- package/lib/node/hosting/ws-origin-validator.spec.d.ts.map +1 -0
- package/lib/node/hosting/ws-origin-validator.spec.js +131 -0
- package/lib/node/hosting/ws-origin-validator.spec.js.map +1 -0
- package/lib/node/index.d.ts +1 -0
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +3 -1
- package/lib/node/index.js.map +1 -1
- package/lib/node/logger-cli-contribution.d.ts +6 -0
- package/lib/node/logger-cli-contribution.d.ts.map +1 -1
- package/lib/node/logger-cli-contribution.js +28 -5
- package/lib/node/logger-cli-contribution.js.map +1 -1
- package/lib/node/logger-cli-contribution.spec.js +54 -0
- package/lib/node/logger-cli-contribution.spec.js.map +1 -1
- package/lib/node/messaging/default-messaging-service.d.ts +2 -0
- package/lib/node/messaging/default-messaging-service.d.ts.map +1 -1
- package/lib/node/messaging/default-messaging-service.js +8 -2
- package/lib/node/messaging/default-messaging-service.js.map +1 -1
- package/lib/node/messaging/test/default-messaging-service.spec.js +2 -0
- package/lib/node/messaging/test/default-messaging-service.spec.js.map +1 -1
- package/lib/node/messaging/websocket-endpoint.d.ts +7 -0
- package/lib/node/messaging/websocket-endpoint.d.ts.map +1 -1
- package/lib/node/messaging/websocket-endpoint.js +21 -6
- package/lib/node/messaging/websocket-endpoint.js.map +1 -1
- package/lib/node/process-utils.d.ts +2 -0
- package/lib/node/process-utils.d.ts.map +1 -1
- package/lib/node/process-utils.js +8 -2
- package/lib/node/process-utils.js.map +1 -1
- package/lib/node/process-utils.spec.js +11 -9
- package/lib/node/process-utils.spec.js.map +1 -1
- package/lib/node/request/backend-request-facade.d.ts +19 -0
- package/lib/node/request/backend-request-facade.d.ts.map +1 -1
- package/lib/node/request/backend-request-facade.js +93 -3
- package/lib/node/request/backend-request-facade.js.map +1 -1
- package/lib/node/request/backend-request-facade.spec.d.ts +2 -0
- package/lib/node/request/backend-request-facade.spec.d.ts.map +1 -0
- package/lib/node/request/backend-request-facade.spec.js +171 -0
- package/lib/node/request/backend-request-facade.spec.js.map +1 -0
- package/package.json +29 -20
- package/src/browser/authentication-service.ts +6 -3
- package/src/browser/frontend-application.ts +13 -9
- package/src/browser/json-schema-store.ts +6 -2
- package/src/browser/keybinding.ts +2 -2
- package/src/browser/keyboard/keyboard-layout-service.spec.ts +28 -0
- package/src/browser/keyboard/keyboard-layout-service.ts +38 -14
- package/src/browser/markdown-rendering/markdown.tsx +2 -2
- package/src/browser/menu/composite-menu-node.ts +4 -4
- package/src/browser/messaging/ws-connection-source.ts +1 -6
- package/src/browser/preferences/frontend-config-preference-contributions.ts +7 -2
- package/src/browser/preferences/preference-proxy.spec.ts +8 -0
- package/src/browser/preferences/preference-schema-provider.spec.ts +5 -0
- package/src/browser/preferences/preference-validation-service.spec.ts +3 -1
- package/src/browser/preferences/preference-validation-service.ts +9 -6
- package/src/browser/secondary-window-handler.ts +11 -7
- package/src/browser/shell/application-shell.ts +8 -4
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.tsx +6 -6
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +2 -2
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.ts +159 -1
- package/src/browser/status-bar/status-bar.tsx +3 -3
- package/src/browser/test/jsdom.ts +18 -0
- package/src/browser/tree/tree-container.spec.ts +6 -0
- package/src/browser/tree/tree-model.ts +4 -0
- package/src/browser/tree/tree-view-welcome-widget.spec.ts +82 -0
- package/src/browser/tree/tree-view-welcome-widget.tsx +10 -11
- package/src/browser/tree/tree-widget.tsx +2 -2
- package/src/browser/tree/tree.spec.ts +30 -0
- package/src/browser/tree/tree.ts +31 -4
- package/src/browser/window/default-window-service.spec.ts +3 -1
- package/src/browser/window/default-window-service.ts +9 -6
- package/src/browser-only/messaging/frontend-only-service-connection-provider.ts +8 -3
- package/src/common/command.ts +8 -4
- package/src/common/i18n/nls.metadata.json +2659 -374
- package/src/common/logger.spec.ts +62 -1
- package/src/common/logger.ts +13 -4
- package/src/common/preferences/injectable-preference-proxy.ts +10 -4
- package/src/common/preferences/preference-proxy.ts +10 -4
- package/src/electron-main/electron-main-application.ts +4 -2
- package/src/electron-node/hosting/electron-ws-origin-validator.spec.ts +69 -0
- package/src/electron-node/hosting/electron-ws-origin-validator.ts +5 -2
- package/src/electron-node/request/electron-backend-request-service.ts +6 -2
- package/src/electron-node/token/electron-token-backend-contribution.ts +6 -2
- package/src/electron-node/token/electron-token-validator.ts +6 -2
- package/src/node/backend-application-module.ts +4 -2
- package/src/node/backend-application.spec.ts +5 -3
- package/src/node/backend-application.ts +33 -11
- package/src/node/hosting/backend-hosting-module.ts +10 -0
- package/src/node/hosting/browser-connection-token.spec.ts +167 -0
- package/src/node/hosting/browser-connection-token.ts +126 -0
- package/src/node/hosting/ws-origin-validator.spec.ts +193 -0
- package/src/node/hosting/ws-origin-validator.ts +23 -4
- package/src/node/index.ts +1 -0
- package/src/node/logger-cli-contribution.spec.ts +65 -0
- package/src/node/logger-cli-contribution.ts +32 -5
- package/src/node/messaging/default-messaging-service.ts +6 -2
- package/src/node/messaging/test/default-messaging-service.spec.ts +3 -1
- package/src/node/messaging/websocket-endpoint.ts +23 -7
- package/src/node/process-utils.spec.ts +12 -9
- package/src/node/process-utils.ts +7 -3
- package/src/node/request/backend-request-facade.spec.ts +203 -0
- package/src/node/request/backend-request-facade.ts +108 -3
|
@@ -14,16 +14,21 @@
|
|
|
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 } from 'inversify';
|
|
17
|
+
import { injectable, named, inject } from 'inversify';
|
|
18
18
|
import { PreferenceContribution, PreferenceSchema, PreferenceSchemaService } from '../../common/preferences/preference-schema';
|
|
19
19
|
import { FrontendApplicationConfigProvider } from '../frontend-application-config-provider';
|
|
20
20
|
import { FrontendApplicationPreferenceConfig } from './preference-contribution';
|
|
21
21
|
import { PreferenceLanguageOverrideService } from '../../common/preferences/preference-language-override-service';
|
|
22
22
|
import { PreferenceScope } from '../../common/preferences';
|
|
23
23
|
import { DefaultTheme } from '@theia/application-package/lib/application-props';
|
|
24
|
+
import { ILogger } from '../../common/logger';
|
|
24
25
|
|
|
25
26
|
@injectable()
|
|
26
27
|
export class FrontendConfigPreferenceContribution implements PreferenceContribution {
|
|
28
|
+
|
|
29
|
+
@inject(ILogger) @named('core:FrontendConfigPreferenceContribution')
|
|
30
|
+
protected readonly logger: ILogger;
|
|
31
|
+
|
|
27
32
|
schema: PreferenceSchema = { scope: PreferenceScope.Folder, properties: {} };
|
|
28
33
|
async initSchema(service: PreferenceSchemaService): Promise<void> {
|
|
29
34
|
const config = FrontendApplicationConfigProvider.get();
|
|
@@ -44,7 +49,7 @@ export class FrontendConfigPreferenceContribution implements PreferenceContribut
|
|
|
44
49
|
}
|
|
45
50
|
}
|
|
46
51
|
} catch (e) {
|
|
47
|
-
|
|
52
|
+
this.logger.error('Failed to load preferences from frontend configuration.', e);
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
}
|
|
@@ -162,6 +162,14 @@ describe('Preference Proxy', () => {
|
|
|
162
162
|
expect(Object.keys(proxy).join()).to.equal(['my.pref'].join());
|
|
163
163
|
});
|
|
164
164
|
|
|
165
|
+
it('supports object introspection through Symbol.toStringTag', async () => {
|
|
166
|
+
const { proxy, promisedSchema } = getProxy();
|
|
167
|
+
if (promisedSchema) {
|
|
168
|
+
await promisedSchema;
|
|
169
|
+
}
|
|
170
|
+
expect(Object.prototype.toString.call(proxy)).to.equal('[object Object]');
|
|
171
|
+
});
|
|
172
|
+
|
|
165
173
|
it('it should provide access in deep style but not flat', async () => {
|
|
166
174
|
const { proxy, promisedSchema } = getProxy(undefined, { style: 'deep' });
|
|
167
175
|
if (promisedSchema) {
|
|
@@ -24,6 +24,8 @@ import { bindPreferenceService } from '../frontend-application-bindings';
|
|
|
24
24
|
import { FrontendApplicationConfigProvider } from '../frontend-application-config-provider';
|
|
25
25
|
import { IndexedAccess, PreferenceDataProperty, PreferenceSchemaService } from '../../common/preferences/preference-schema';
|
|
26
26
|
import { PreferenceProvider, PreferenceProviderProvider, PreferenceScope } from '../../common/preferences';
|
|
27
|
+
import { ILogger } from '../../common';
|
|
28
|
+
import { MockLogger } from '../../common/test/mock-logger';
|
|
27
29
|
|
|
28
30
|
disableJSDOM();
|
|
29
31
|
|
|
@@ -38,6 +40,9 @@ let testContainer: Container;
|
|
|
38
40
|
function createTestContainer(): Container {
|
|
39
41
|
const result = new Container();
|
|
40
42
|
bindPreferenceService(result.bind.bind(result));
|
|
43
|
+
|
|
44
|
+
result.bind(ILogger).to(MockLogger).inSingletonScope();
|
|
45
|
+
|
|
41
46
|
return result;
|
|
42
47
|
}
|
|
43
48
|
|
|
@@ -21,9 +21,10 @@ import { JSONValue } from '@lumino/coreutils';
|
|
|
21
21
|
import { IJSONSchema, JsonType } from '../../common/json-schema';
|
|
22
22
|
import {
|
|
23
23
|
DefaultsPreferenceProvider, Disposable, PreferenceDataProperty, PreferenceProvider,
|
|
24
|
-
PreferenceSchemaService, PreferenceSchemaServiceImpl, PreferenceScope
|
|
24
|
+
PreferenceSchemaService, PreferenceSchemaServiceImpl, PreferenceScope, ILogger
|
|
25
25
|
} from '../../common';
|
|
26
26
|
import { PreferenceLanguageOverrideService } from '../../common/preferences/preference-language-override-service';
|
|
27
|
+
import { MockLogger } from '../../common/test/mock-logger';
|
|
27
28
|
|
|
28
29
|
/* eslint-disable no-null/no-null */
|
|
29
30
|
|
|
@@ -35,6 +36,7 @@ describe('Preference Validation Service', () => {
|
|
|
35
36
|
} as unknown as PreferenceSchemaService);
|
|
36
37
|
container.bind(PreferenceLanguageOverrideService).to(PreferenceLanguageOverrideService).inSingletonScope();
|
|
37
38
|
container.bind(PreferenceProvider).to(DefaultsPreferenceProvider).inSingletonScope().whenTargetNamed(PreferenceScope.Default);
|
|
39
|
+
container.bind(ILogger).to(MockLogger).inSingletonScope();
|
|
38
40
|
|
|
39
41
|
const validator = container.resolve(PreferenceValidationService);
|
|
40
42
|
const validateBySchema: (value: JSONValue, schema: PreferenceDataProperty) => JSONValue = validator.validateBySchema.bind(validator, 'dummy');
|
|
@@ -15,11 +15,12 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { JSONObject, JSONValue } from '../../../shared/@lumino/coreutils';
|
|
18
|
-
import { inject, injectable } from '../../../shared/inversify';
|
|
18
|
+
import { inject, injectable, named } from '../../../shared/inversify';
|
|
19
19
|
import { IJSONSchema, JsonType } from '../../common/json-schema';
|
|
20
20
|
import { deepClone, unreachable } from '../../common';
|
|
21
21
|
import { PreferenceLanguageOverrideService } from '../../common/preferences/preference-language-override-service';
|
|
22
22
|
import { PreferenceSchemaService, PreferenceScope, PreferenceUtils, PreferenceDataProperty } from '../../common/preferences';
|
|
23
|
+
import { ILogger } from '../../common/logger';
|
|
23
24
|
|
|
24
25
|
export interface PreferenceValidator<T> {
|
|
25
26
|
name: string;
|
|
@@ -40,6 +41,8 @@ type ValidatablePreferenceTuple = IJSONSchema & ({ items: IJSONSchema[] } | { pr
|
|
|
40
41
|
export class PreferenceValidationService {
|
|
41
42
|
@inject(PreferenceSchemaService) protected readonly schemaService: PreferenceSchemaService;
|
|
42
43
|
@inject(PreferenceLanguageOverrideService) protected readonly languageOverrideService: PreferenceLanguageOverrideService;
|
|
44
|
+
@inject(ILogger) @named('core:PreferenceValidationService')
|
|
45
|
+
protected readonly logger: ILogger;
|
|
43
46
|
|
|
44
47
|
validateOptions(options: Record<string, JSONValue>): Record<string, JSONValue> {
|
|
45
48
|
const valid: Record<string, JSONValue> = {};
|
|
@@ -58,7 +61,7 @@ export class PreferenceValidationService {
|
|
|
58
61
|
const validValue = this.doValidateByName(preferenceName, value);
|
|
59
62
|
// If value is undefined, it means the preference wasn't set, not that a bad value was set.
|
|
60
63
|
if (validValue !== value && value !== undefined) {
|
|
61
|
-
|
|
64
|
+
this.logger.warn(`While validating options, found impermissible value for ${preferenceName}. Using valid value`, validValue, 'instead of configured value', value);
|
|
62
65
|
}
|
|
63
66
|
return validValue;
|
|
64
67
|
}
|
|
@@ -71,7 +74,7 @@ export class PreferenceValidationService {
|
|
|
71
74
|
validateBySchema(key: string, value: JSONValue, schema: IJSONSchema | undefined): JSONValue {
|
|
72
75
|
try {
|
|
73
76
|
if (!schema) {
|
|
74
|
-
|
|
77
|
+
this.logger.warn('Request to validate preference with no schema registered:', key);
|
|
75
78
|
return value;
|
|
76
79
|
}
|
|
77
80
|
if (schema.const !== undefined) {
|
|
@@ -87,7 +90,7 @@ export class PreferenceValidationService {
|
|
|
87
90
|
return this.validateOneOf(key, value, schema as IJSONSchema & { oneOf: IJSONSchema[] });
|
|
88
91
|
}
|
|
89
92
|
if (schema.type === undefined) {
|
|
90
|
-
|
|
93
|
+
this.logger.warn('Request to validate preference with no type information:', key);
|
|
91
94
|
return value;
|
|
92
95
|
}
|
|
93
96
|
if (Array.isArray(schema.type)) {
|
|
@@ -112,7 +115,7 @@ export class PreferenceValidationService {
|
|
|
112
115
|
unreachable(schema.type, `Request to validate preference with unknown type in schema: ${key}`);
|
|
113
116
|
}
|
|
114
117
|
} catch (e) {
|
|
115
|
-
|
|
118
|
+
this.logger.error('Encountered an error while validating', key, 'with value', value, 'against schema', schema, e);
|
|
116
119
|
return value;
|
|
117
120
|
}
|
|
118
121
|
}
|
|
@@ -193,7 +196,7 @@ export class PreferenceValidationService {
|
|
|
193
196
|
return [];
|
|
194
197
|
}
|
|
195
198
|
if (!schema.items && !schema.prefixItems) {
|
|
196
|
-
|
|
199
|
+
this.logger.warn('Requested validation of array without item specification:', key);
|
|
197
200
|
return candidate;
|
|
198
201
|
}
|
|
199
202
|
if (Array.isArray(schema.items) || Array.isArray(schema.prefixItems)) {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import debounce = require('lodash.debounce');
|
|
18
|
-
import { inject, injectable } from 'inversify';
|
|
18
|
+
import { inject, injectable, named } from 'inversify';
|
|
19
19
|
import { BoxLayout, ExtractableWidget, TabBar, Widget } from './widgets';
|
|
20
20
|
import { MessageService } from '../common/message-service';
|
|
21
21
|
import { ApplicationShell, DockPanelRenderer, MAIN_AREA_CLASS, MAIN_BOTTOM_AREA_CLASS } from './shell/application-shell';
|
|
@@ -23,6 +23,7 @@ import { Emitter } from '../common/event';
|
|
|
23
23
|
import { isSecondaryWindow, SecondaryWindowRootWidget, SecondaryWindowService } from './window/secondary-window-service';
|
|
24
24
|
import { KeybindingRegistry } from './keybinding';
|
|
25
25
|
import { MAIN_AREA_ID, TheiaDockPanel } from './shell/theia-dock-panel';
|
|
26
|
+
import { ILogger } from '../common/logger';
|
|
26
27
|
import { nls } from '../common/nls';
|
|
27
28
|
|
|
28
29
|
/** Widgets to be contained inside a DockPanel in the secondary window. */
|
|
@@ -104,6 +105,9 @@ export class SecondaryWindowHandler {
|
|
|
104
105
|
@inject(TheiaDockPanel.Factory)
|
|
105
106
|
protected dockPanelFactory: TheiaDockPanel.Factory;
|
|
106
107
|
|
|
108
|
+
@inject(ILogger) @named('core:SecondaryWindowHandler')
|
|
109
|
+
protected readonly logger: ILogger;
|
|
110
|
+
|
|
107
111
|
protected readonly onWillAddWidgetEmitter = new Emitter<[Widget, Window]>();
|
|
108
112
|
/** Subscribe to get notified when a widget is added to this handler, i.e. the widget was moved to an secondary window . */
|
|
109
113
|
readonly onWillAddWidget = this.onWillAddWidgetEmitter.event;
|
|
@@ -157,11 +161,11 @@ export class SecondaryWindowHandler {
|
|
|
157
161
|
*/
|
|
158
162
|
moveWidgetToSecondaryWindow(widget: ExtractableWidget): void {
|
|
159
163
|
if (!this.applicationShell) {
|
|
160
|
-
|
|
164
|
+
this.logger.error('Widget cannot be extracted because the WidgetExtractionHandler has not been initialized.');
|
|
161
165
|
return;
|
|
162
166
|
}
|
|
163
167
|
if (!widget.isExtractable) {
|
|
164
|
-
|
|
168
|
+
this.logger.error('Widget is not extractable.', widget.id);
|
|
165
169
|
return;
|
|
166
170
|
}
|
|
167
171
|
|
|
@@ -185,7 +189,7 @@ export class SecondaryWindowHandler {
|
|
|
185
189
|
|
|
186
190
|
const element = newWindow.document.getElementById('widget-host');
|
|
187
191
|
if (!element) {
|
|
188
|
-
|
|
192
|
+
this.logger.error('Could not find dom element to attach to in secondary window');
|
|
189
193
|
return;
|
|
190
194
|
}
|
|
191
195
|
|
|
@@ -240,18 +244,18 @@ export class SecondaryWindowHandler {
|
|
|
240
244
|
addWidgetToSecondaryWindow(widget: Widget, secondaryWindow: Window, options?: TheiaDockPanel.AddOptions): void {
|
|
241
245
|
const rootWidget = isSecondaryWindow(secondaryWindow) ? secondaryWindow.rootWidget : undefined;
|
|
242
246
|
if (!rootWidget) {
|
|
243
|
-
|
|
247
|
+
this.logger.error('Given secondary window no known root.');
|
|
244
248
|
return;
|
|
245
249
|
}
|
|
246
250
|
|
|
247
251
|
// we allow to add any widget to an existing secondary window unless it is marked as not extractable or is already extracted
|
|
248
252
|
if (ExtractableWidget.is(widget)) {
|
|
249
253
|
if (!widget.isExtractable) {
|
|
250
|
-
|
|
254
|
+
this.logger.error('Widget is not extractable.', widget.id);
|
|
251
255
|
return;
|
|
252
256
|
}
|
|
253
257
|
if (widget.secondaryWindow !== undefined) {
|
|
254
|
-
|
|
258
|
+
this.logger.error('Widget is extracted already.', widget.id);
|
|
255
259
|
return;
|
|
256
260
|
}
|
|
257
261
|
widget.secondaryWindow = secondaryWindow;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { injectable, inject, optional, postConstruct } from 'inversify';
|
|
17
|
+
import { injectable, inject, optional, postConstruct, named } from 'inversify';
|
|
18
18
|
import { ArrayExt, find, toArray, each } from '@lumino/algorithm';
|
|
19
19
|
import {
|
|
20
20
|
BoxLayout, BoxPanel, DockLayout, DockPanel, FocusTracker, Layout, Panel, SplitLayout,
|
|
@@ -46,6 +46,7 @@ import { OpenerService } from '../opener-service';
|
|
|
46
46
|
import { PreviewableWidget } from '../widgets/previewable-widget';
|
|
47
47
|
import { WindowService } from '../window/window-service';
|
|
48
48
|
import { TheiaSplitPanel } from './theia-split-panel';
|
|
49
|
+
import { ILogger } from '../../common/logger';
|
|
49
50
|
|
|
50
51
|
/** The class name added to ApplicationShell instances. */
|
|
51
52
|
export const APPLICATION_SHELL_CLASS = 'theia-ApplicationShell';
|
|
@@ -242,6 +243,9 @@ export class ApplicationShell extends Widget {
|
|
|
242
243
|
@inject(UntitledResourceResolver)
|
|
243
244
|
protected readonly untitledResourceResolver: UntitledResourceResolver;
|
|
244
245
|
|
|
246
|
+
@inject(ILogger) @named('core:ApplicationShell')
|
|
247
|
+
protected readonly logger: ILogger;
|
|
248
|
+
|
|
245
249
|
protected readonly onDidAddWidgetEmitter = new Emitter<Widget>();
|
|
246
250
|
readonly onDidAddWidget = this.onDidAddWidgetEmitter.event;
|
|
247
251
|
protected fireDidAddWidget(widget: Widget): void {
|
|
@@ -595,7 +599,7 @@ export class ApplicationShell extends Widget {
|
|
|
595
599
|
const opener = await this.openerService.getOpener(fileUri);
|
|
596
600
|
opener.open(fileUri);
|
|
597
601
|
} catch (e) {
|
|
598
|
-
|
|
602
|
+
this.logger.info(`no opener found for '${fileUri}'`);
|
|
599
603
|
}
|
|
600
604
|
};
|
|
601
605
|
|
|
@@ -975,7 +979,7 @@ export class ApplicationShell extends Widget {
|
|
|
975
979
|
*/
|
|
976
980
|
async addWidget(widget: Widget, options?: Readonly<ApplicationShell.WidgetOptions>): Promise<void> {
|
|
977
981
|
if (!widget.id) {
|
|
978
|
-
|
|
982
|
+
this.logger.error('Widgets added to the application shell must have a unique id property.');
|
|
979
983
|
return;
|
|
980
984
|
}
|
|
981
985
|
const { area, addOptions } = this.getInsertionOptions(options);
|
|
@@ -1430,7 +1434,7 @@ export class ApplicationShell extends Widget {
|
|
|
1430
1434
|
if (delta < this.activationTimeout) {
|
|
1431
1435
|
request = setTimeout(step, 0);
|
|
1432
1436
|
} else {
|
|
1433
|
-
|
|
1437
|
+
this.logger.warn(`Widget was activated, but did not accept focus after ${this.activationTimeout}ms: ${widget.id}`);
|
|
1434
1438
|
}
|
|
1435
1439
|
};
|
|
1436
1440
|
let request = setTimeout(step, 0);
|
|
@@ -96,9 +96,9 @@ abstract class AbstractToolbarMenuWrapper {
|
|
|
96
96
|
const icon = this.icon || 'ellipsis';
|
|
97
97
|
const contextMatcher: ContextMatcher = this.contextKeyService;
|
|
98
98
|
const className = `${icon} ${ACTION_ITEM}`;
|
|
99
|
-
if (CompoundMenuNode.is(this.menuNode) && !this.menuNode.isEmpty(this.effectiveMenuPath, this.contextKeyService, widget.node)) {
|
|
99
|
+
if (CompoundMenuNode.is(this.menuNode) && !this.menuNode.isEmpty(this.effectiveMenuPath, this.contextKeyService, widget.node, widget)) {
|
|
100
100
|
return <div key={this.id} className={TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM + ' enabled menu'}>
|
|
101
|
-
<div className={className}
|
|
101
|
+
<div id={this.id} className={className}
|
|
102
102
|
title={this.tooltip || this.text}
|
|
103
103
|
onClick={e => this.executeCommand(widget, e)}
|
|
104
104
|
/>
|
|
@@ -108,7 +108,7 @@ abstract class AbstractToolbarMenuWrapper {
|
|
|
108
108
|
</div>;
|
|
109
109
|
} else {
|
|
110
110
|
return <div key={this.id} className={TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM + ' enabled menu'}>
|
|
111
|
-
<div className={className}
|
|
111
|
+
<div id={this.id} className={className}
|
|
112
112
|
title={this.tooltip || this.text}
|
|
113
113
|
onClick={e => this.executeCommand(widget, e)}
|
|
114
114
|
/>
|
|
@@ -308,7 +308,7 @@ abstract class AbstractMenuNodeAsToolbarItemWrapper<T extends MenuNode> {
|
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
isVisible<K>(effectiveMenuPath: MenuPath, contextMatcher: ContextExpressionMatcher<K>, context: K | undefined, ...args: unknown[]): boolean {
|
|
311
|
-
return this.menuNode!.isVisible(this.effectiveMenuPath, contextMatcher, context, args);
|
|
311
|
+
return this.menuNode!.isVisible(this.effectiveMenuPath, contextMatcher, context, ...args);
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
314
|
|
|
@@ -321,7 +321,7 @@ class ToolbarItemAsSubmenuWrapper extends AbstractMenuNodeAsToolbarItemWrapper<C
|
|
|
321
321
|
return this.menuNode.contextKeyOverlays;
|
|
322
322
|
}
|
|
323
323
|
isEmpty<T>(effectiveMenuPath: MenuPath, contextMatcher: ContextExpressionMatcher<T>, context: T | undefined, ...args: unknown[]): boolean {
|
|
324
|
-
return this.menuNode.isEmpty(this.effectiveMenuPath, contextMatcher, context, args);
|
|
324
|
+
return this.menuNode.isEmpty(this.effectiveMenuPath, contextMatcher, context, ...args);
|
|
325
325
|
}
|
|
326
326
|
get children(): MenuNode[] {
|
|
327
327
|
return this.menuNode.children;
|
|
@@ -340,7 +340,7 @@ class ToolbarItemAsCommandMenuWrapper extends AbstractMenuNodeAsToolbarItemWrapp
|
|
|
340
340
|
return this.menuNode.isToggled(this.effectiveMenuPath, ...args);
|
|
341
341
|
}
|
|
342
342
|
run(effectiveMenuPath: MenuPath, ...args: unknown[]): Promise<void> {
|
|
343
|
-
return this.menuNode.run(this.effectiveMenuPath, args);
|
|
343
|
+
return this.menuNode.run(this.effectiveMenuPath, ...args);
|
|
344
344
|
}
|
|
345
345
|
|
|
346
346
|
override get label(): string {
|
|
@@ -141,11 +141,11 @@ export class TabBarToolbarRegistry implements FrontendApplicationContribution {
|
|
|
141
141
|
const menu = this.menuRegistry.getMenu(delegate.menuPath);
|
|
142
142
|
if (menu) {
|
|
143
143
|
for (const child of menu.children) {
|
|
144
|
-
if (child.isVisible([...delegate.menuPath, child.id], this.contextKeyService, widget.node)) {
|
|
144
|
+
if (child.isVisible([...delegate.menuPath, child.id], this.contextKeyService, widget.node, widget)) {
|
|
145
145
|
if (CompoundMenuNode.is(child)) {
|
|
146
146
|
for (const grandchild of child.children) {
|
|
147
147
|
if (grandchild.isVisible([...delegate.menuPath, child.id, grandchild.id],
|
|
148
|
-
this.contextKeyService, widget.node) && RenderedMenuNode.is(grandchild)) {
|
|
148
|
+
this.contextKeyService, widget.node, widget) && RenderedMenuNode.is(grandchild)) {
|
|
149
149
|
if (CommandMenu.is(grandchild)) {
|
|
150
150
|
result.push(new CommandMenuAsToolbarItemWrapper([...delegate.menuPath, child.id, grandchild.id], this.commandRegistry,
|
|
151
151
|
this.menuRegistry, this.contextKeyService, this.contextMenuRenderer, grandchild, child.id));
|
|
@@ -18,7 +18,16 @@ import { enableJSDOM } from '../../test/jsdom';
|
|
|
18
18
|
|
|
19
19
|
let disableJSDOM = enableJSDOM();
|
|
20
20
|
import { expect } from 'chai';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
CommandMenu, CommandRegistry, CompoundMenuNode, Group, GroupImpl, MenuAction, MenuModelRegistry, MenuNode, MenuNodeFactory, MutableCompoundMenuNode,
|
|
23
|
+
Submenu, SubmenuImpl, SubMenuLink
|
|
24
|
+
} from '../../../common';
|
|
25
|
+
import { ContextKeyServiceDummyImpl } from '../../context-key-service';
|
|
26
|
+
import { ContextMenuRenderer } from '../../context-menu-renderer';
|
|
27
|
+
import { Widget } from '../../widgets';
|
|
28
|
+
import { TOOLBAR_WRAPPER_ID_SUFFIX } from './tab-bar-toolbar-menu-adapters';
|
|
29
|
+
import { TabBarToolbarRegistry } from './tab-bar-toolbar-registry';
|
|
30
|
+
import { TAB_BAR_TOOLBAR_CONTEXT_MENU, TabBarToolbarAction } from './tab-bar-toolbar-types';
|
|
22
31
|
|
|
23
32
|
disableJSDOM();
|
|
24
33
|
|
|
@@ -59,4 +68,153 @@ describe('tab-bar-toolbar', () => {
|
|
|
59
68
|
|
|
60
69
|
});
|
|
61
70
|
|
|
71
|
+
describe('menu delegates', () => {
|
|
72
|
+
|
|
73
|
+
const TEST_MENU_PATH = ['test-toolbar-delegate'];
|
|
74
|
+
const TEST_COMMAND = 'test.toolbar.command';
|
|
75
|
+
const TEST_SUBMENU_COMMAND = 'test.toolbar.submenu.command';
|
|
76
|
+
|
|
77
|
+
let contextKeyService: ContextKeyServiceDummyImpl;
|
|
78
|
+
|
|
79
|
+
before(() => {
|
|
80
|
+
disableJSDOM = enableJSDOM();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
beforeEach(() => {
|
|
84
|
+
contextKeyService = new ContextKeyServiceDummyImpl();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
after(() => {
|
|
88
|
+
disableJSDOM();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('passes the delegated widget to command visibility', () => {
|
|
92
|
+
const testWidget = new TestToolbarWidget();
|
|
93
|
+
const commands = createCommandRegistry();
|
|
94
|
+
commands.registerCommand({ id: TEST_COMMAND, label: 'Test Command' }, {
|
|
95
|
+
execute: () => { },
|
|
96
|
+
isVisible: widget => TestToolbarWidget.is(widget) && widget === testWidget
|
|
97
|
+
});
|
|
98
|
+
const menuRegistry = createMenuRegistry(commands);
|
|
99
|
+
menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other'], { commandId: TEST_COMMAND });
|
|
100
|
+
const registry = createToolbarRegistry(commands, menuRegistry, contextKeyService);
|
|
101
|
+
registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
|
|
102
|
+
|
|
103
|
+
const commandItem = registry.visibleItems(testWidget).find(item => item.id === `${TEST_COMMAND}${TOOLBAR_WRAPPER_ID_SUFFIX}`);
|
|
104
|
+
|
|
105
|
+
expect(commandItem).to.exist;
|
|
106
|
+
testWidget.dispose();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('preserves the widget for wrapped command menu visibility, enablement, toggled state, and execution', async () => {
|
|
110
|
+
const testWidget = new TestToolbarWidget();
|
|
111
|
+
let executedWith: unknown;
|
|
112
|
+
const commands = createCommandRegistry();
|
|
113
|
+
commands.registerCommand({ id: TEST_COMMAND, label: 'Test Command' }, {
|
|
114
|
+
execute: widget => executedWith = widget,
|
|
115
|
+
isVisible: widget => TestToolbarWidget.is(widget) && widget === testWidget,
|
|
116
|
+
isEnabled: widget => TestToolbarWidget.is(widget) && widget === testWidget,
|
|
117
|
+
isToggled: widget => TestToolbarWidget.is(widget) && widget === testWidget
|
|
118
|
+
});
|
|
119
|
+
const menuRegistry = createMenuRegistry(commands);
|
|
120
|
+
menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other'], { commandId: TEST_COMMAND });
|
|
121
|
+
const registry = createToolbarRegistry(commands, menuRegistry, contextKeyService);
|
|
122
|
+
registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
|
|
123
|
+
const commandItem = registry.visibleItems(testWidget).find(item => item.id === `${TEST_COMMAND}${TOOLBAR_WRAPPER_ID_SUFFIX}`);
|
|
124
|
+
const node = commandItem?.toMenuNode?.();
|
|
125
|
+
|
|
126
|
+
expect(CommandMenu.is(node)).to.be.true;
|
|
127
|
+
if (!CommandMenu.is(node)) {
|
|
128
|
+
throw new Error('Expected a command menu node.');
|
|
129
|
+
}
|
|
130
|
+
expect(node.isVisible(TAB_BAR_TOOLBAR_CONTEXT_MENU, contextKeyService, testWidget.node, testWidget)).to.be.true;
|
|
131
|
+
expect(node.isEnabled(TAB_BAR_TOOLBAR_CONTEXT_MENU, testWidget)).to.be.true;
|
|
132
|
+
expect(node.isToggled(TAB_BAR_TOOLBAR_CONTEXT_MENU, testWidget)).to.be.true;
|
|
133
|
+
await node.run(TAB_BAR_TOOLBAR_CONTEXT_MENU, testWidget);
|
|
134
|
+
expect(executedWith).to.equal(testWidget);
|
|
135
|
+
testWidget.dispose();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('preserves the widget for wrapped submenu emptiness checks', () => {
|
|
139
|
+
const testWidget = new TestToolbarWidget();
|
|
140
|
+
const commands = createCommandRegistry();
|
|
141
|
+
commands.registerCommand({ id: TEST_SUBMENU_COMMAND, label: 'Test Submenu Command' }, {
|
|
142
|
+
execute: () => { },
|
|
143
|
+
isVisible: widget => TestToolbarWidget.is(widget) && widget === testWidget
|
|
144
|
+
});
|
|
145
|
+
const menuRegistry = createMenuRegistry(commands);
|
|
146
|
+
menuRegistry.registerSubmenu([...TEST_MENU_PATH, 'other', 'test-submenu'], 'Test Submenu');
|
|
147
|
+
menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other', 'test-submenu'], { commandId: TEST_SUBMENU_COMMAND });
|
|
148
|
+
const registry = createToolbarRegistry(commands, menuRegistry, contextKeyService);
|
|
149
|
+
registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
|
|
150
|
+
const submenuItem = registry.visibleItems(testWidget).find(item => item.id === `test-submenu${TOOLBAR_WRAPPER_ID_SUFFIX}`);
|
|
151
|
+
const node = submenuItem?.toMenuNode?.();
|
|
152
|
+
|
|
153
|
+
expect(CompoundMenuNode.is(node)).to.be.true;
|
|
154
|
+
if (!CompoundMenuNode.is(node)) {
|
|
155
|
+
throw new Error('Expected a compound menu node.');
|
|
156
|
+
}
|
|
157
|
+
expect(node.isEmpty(TAB_BAR_TOOLBAR_CONTEXT_MENU, contextKeyService, testWidget.node, testWidget)).to.be.false;
|
|
158
|
+
testWidget.dispose();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
});
|
|
162
|
+
|
|
62
163
|
});
|
|
164
|
+
|
|
165
|
+
class TestToolbarWidget extends Widget {
|
|
166
|
+
static is(candidate?: Widget): candidate is TestToolbarWidget {
|
|
167
|
+
return candidate instanceof TestToolbarWidget;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
class TestMenuNodeFactory implements MenuNodeFactory {
|
|
172
|
+
|
|
173
|
+
constructor(protected readonly commands: CommandRegistry) { }
|
|
174
|
+
|
|
175
|
+
createGroup(id: string, orderString?: string, when?: string): Group & MutableCompoundMenuNode {
|
|
176
|
+
return new GroupImpl(id, orderString, when);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
createSubmenu(id: string, label: string, contextKeyOverlays: Record<string, string> | undefined, orderString?: string, icon?: string, when?: string):
|
|
180
|
+
Submenu & MutableCompoundMenuNode {
|
|
181
|
+
return new SubmenuImpl(id, label, contextKeyOverlays, orderString, icon, when);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
createSubmenuLink(delegate: Submenu, sortString?: string, when?: string): MenuNode {
|
|
185
|
+
return new SubMenuLink(delegate, sortString, when);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
createCommandMenu(item: MenuAction): CommandMenu {
|
|
189
|
+
return {
|
|
190
|
+
isVisible: (_path, _contextMatcher, _context, ...args) => this.commands.isVisible(item.commandId, ...args),
|
|
191
|
+
isEnabled: (_path, ...args) => this.commands.isEnabled(item.commandId, ...args),
|
|
192
|
+
isToggled: (_path, ...args) => this.commands.isToggled(item.commandId, ...args),
|
|
193
|
+
id: item.commandId,
|
|
194
|
+
label: item.label || this.commands.getCommand(item.commandId)?.label || '',
|
|
195
|
+
icon: item.icon,
|
|
196
|
+
when: item.when,
|
|
197
|
+
sortString: item.order || '',
|
|
198
|
+
run: async (_path, ...args) => { await this.commands.executeCommand(item.commandId, ...args); }
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function createCommandRegistry(): CommandRegistry {
|
|
204
|
+
return new CommandRegistry({ getContributions: () => [] });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function createMenuRegistry(commands: CommandRegistry): MenuModelRegistry {
|
|
208
|
+
return new MenuModelRegistry({ getContributions: () => [] }, commands, new TestMenuNodeFactory(commands));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function createToolbarRegistry(commands: CommandRegistry, menuRegistry: MenuModelRegistry, contextKeyService: ContextKeyServiceDummyImpl): TabBarToolbarRegistry {
|
|
212
|
+
const registry = new TabBarToolbarRegistry();
|
|
213
|
+
Reflect.set(registry, 'commandRegistry', commands);
|
|
214
|
+
Reflect.set(registry, 'contextKeyService', contextKeyService);
|
|
215
|
+
Reflect.set(registry, 'menuRegistry', menuRegistry);
|
|
216
|
+
Reflect.set(registry, 'keybindingRegistry', {});
|
|
217
|
+
Reflect.set(registry, 'labelParser', {});
|
|
218
|
+
Reflect.set(registry, 'contextMenuRenderer', { render: () => undefined } as unknown as ContextMenuRenderer);
|
|
219
|
+
return registry;
|
|
220
|
+
}
|
|
@@ -99,7 +99,7 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
|
|
|
99
99
|
protected internalSetColor(color?: string): void {
|
|
100
100
|
this.color = color;
|
|
101
101
|
}
|
|
102
|
-
protected render(): JSX.Element {
|
|
102
|
+
protected render(): React.JSX.Element {
|
|
103
103
|
const leftEntries = Array.from(this.viewModel.getLeft(), entry => this.renderElement(entry));
|
|
104
104
|
const rightEntries = Array.from(this.viewModel.getRight(), entry => this.renderElement(entry));
|
|
105
105
|
|
|
@@ -192,9 +192,9 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
|
|
|
192
192
|
return attrs;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
protected renderElement(entry: StatusBarViewEntry): JSX.Element {
|
|
195
|
+
protected renderElement(entry: StatusBarViewEntry): React.JSX.Element {
|
|
196
196
|
const childStrings = this.entryService.parse(entry.entry.text);
|
|
197
|
-
const children: JSX.Element[] = [];
|
|
197
|
+
const children: React.JSX.Element[] = [];
|
|
198
198
|
|
|
199
199
|
childStrings.forEach((val, key) => {
|
|
200
200
|
if (LabelIcon.is(val)) {
|
|
@@ -72,3 +72,21 @@ export function enableJSDOM(): () => void {
|
|
|
72
72
|
};
|
|
73
73
|
return disableJSDOM;
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Enables React's act test environment and restores the previous value when disposed.
|
|
78
|
+
*/
|
|
79
|
+
export function enableReactActEnvironment(): () => void {
|
|
80
|
+
const reactActEnvironment = globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean };
|
|
81
|
+
const hadReactActEnvironment = Object.prototype.hasOwnProperty.call(reactActEnvironment, 'IS_REACT_ACT_ENVIRONMENT');
|
|
82
|
+
const previousReactActEnvironment = reactActEnvironment.IS_REACT_ACT_ENVIRONMENT;
|
|
83
|
+
reactActEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
|
|
84
|
+
|
|
85
|
+
return () => {
|
|
86
|
+
if (hadReactActEnvironment) {
|
|
87
|
+
reactActEnvironment.IS_REACT_ACT_ENVIRONMENT = previousReactActEnvironment;
|
|
88
|
+
} else {
|
|
89
|
+
delete reactActEnvironment.IS_REACT_ACT_ENVIRONMENT;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -19,6 +19,8 @@ import { Container } from 'inversify';
|
|
|
19
19
|
import { createTreeContainer, isTreeServices } from './tree-container';
|
|
20
20
|
import { TreeSearch } from './tree-search';
|
|
21
21
|
import { defaultTreeProps, TreeProps } from './tree-widget';
|
|
22
|
+
import { ILogger } from '../../common/logger';
|
|
23
|
+
import { MockLogger } from '../../common/test/mock-logger';
|
|
22
24
|
|
|
23
25
|
describe('TreeContainer', () => {
|
|
24
26
|
describe('IsTreeServices should accurately distinguish TreeProps from TreeContainerProps', () => {
|
|
@@ -33,11 +35,15 @@ describe('TreeContainer', () => {
|
|
|
33
35
|
const nonDefault = { search: !defaultTreeProps.search, contextMenu: ['no-default-for-this'] };
|
|
34
36
|
it('should use props passed in as just props', () => {
|
|
35
37
|
const parent = new Container();
|
|
38
|
+
parent.bind(ILogger).to(MockLogger).inSingletonScope();
|
|
39
|
+
|
|
36
40
|
const child = createTreeContainer(parent, nonDefault);
|
|
37
41
|
assert.deepStrictEqual(child.get(TreeProps), { ...defaultTreeProps, ...nonDefault });
|
|
38
42
|
});
|
|
39
43
|
it('should use props passed in as part of TreeContainerProps', () => {
|
|
40
44
|
const parent = new Container();
|
|
45
|
+
parent.bind(ILogger).to(MockLogger).inSingletonScope();
|
|
46
|
+
|
|
41
47
|
const child = createTreeContainer(parent, { props: nonDefault });
|
|
42
48
|
assert.deepStrictEqual(child.get(TreeProps), { ...defaultTreeProps, ...nonDefault });
|
|
43
49
|
});
|
|
@@ -250,6 +250,10 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
|
|
|
250
250
|
return this.tree.validateNode(node);
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
removeNode(node: TreeNode | undefined): void {
|
|
254
|
+
this.tree.removeNode(node);
|
|
255
|
+
}
|
|
256
|
+
|
|
253
257
|
async refresh(parent?: Readonly<CompositeTreeNode>): Promise<CompositeTreeNode | undefined> {
|
|
254
258
|
if (parent) {
|
|
255
259
|
return this.tree.refresh(parent);
|