@theia/core 1.74.0-next.10 → 1.74.0-next.17
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/lib/browser/catalog.json +27 -0
- package/lib/browser/preferences/preference-contribution.d.ts.map +1 -1
- package/lib/browser/preferences/preference-contribution.js +9 -1
- package/lib/browser/preferences/preference-contribution.js.map +1 -1
- package/lib/browser/preferences/preference-service.spec.js +63 -0
- package/lib/browser/preferences/preference-service.spec.js.map +1 -1
- package/lib/common/preferences/index.d.ts +1 -0
- package/lib/common/preferences/index.d.ts.map +1 -1
- package/lib/common/preferences/index.js +1 -0
- package/lib/common/preferences/index.js.map +1 -1
- package/lib/common/preferences/preference-scope.d.ts +6 -1
- package/lib/common/preferences/preference-scope.d.ts.map +1 -1
- package/lib/common/preferences/preference-scope.js +5 -0
- package/lib/common/preferences/preference-scope.js.map +1 -1
- package/lib/common/preferences/preference-scope.spec.js +5 -3
- package/lib/common/preferences/preference-scope.spec.js.map +1 -1
- package/lib/common/preferences/preference-service.d.ts +19 -0
- package/lib/common/preferences/preference-service.d.ts.map +1 -1
- package/lib/common/preferences/preference-service.js +34 -5
- package/lib/common/preferences/preference-service.js.map +1 -1
- package/lib/common/preferences/session-preference-provider.d.ts +17 -0
- package/lib/common/preferences/session-preference-provider.d.ts.map +1 -0
- package/lib/common/preferences/session-preference-provider.js +77 -0
- package/lib/common/preferences/session-preference-provider.js.map +1 -0
- package/lib/common/preferences/session-preference-provider.spec.d.ts +2 -0
- package/lib/common/preferences/session-preference-provider.spec.d.ts.map +1 -0
- package/lib/common/preferences/session-preference-provider.spec.js +71 -0
- package/lib/common/preferences/session-preference-provider.spec.js.map +1 -0
- package/package.json +4 -4
- package/src/browser/preferences/preference-contribution.ts +9 -1
- package/src/browser/preferences/preference-service.spec.ts +72 -0
- package/src/browser/style/status-bar.css +1 -1
- package/src/common/preferences/index.ts +1 -0
- package/src/common/preferences/preference-scope.spec.ts +5 -3
- package/src/common/preferences/preference-scope.ts +6 -1
- package/src/common/preferences/preference-service.ts +39 -5
- package/src/common/preferences/session-preference-provider.spec.ts +78 -0
- package/src/common/preferences/session-preference-provider.ts +69 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { JSONObject, JSONValue } from '@lumino/coreutils';
|
|
2
|
+
import { PreferenceProvider } from './preference-provider';
|
|
3
|
+
import { PreferenceProviderImpl } from './preference-provider-impl';
|
|
4
|
+
import { PreferenceScope } from './preference-scope';
|
|
5
|
+
/**
|
|
6
|
+
* In-memory preference provider used for process-lifetime overrides such as those
|
|
7
|
+
* supplied via the `--session-preference` CLI option. Values live in memory only
|
|
8
|
+
* and are dropped when the process exits.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SessionPreferenceProvider extends PreferenceProviderImpl implements PreferenceProvider {
|
|
11
|
+
protected readonly preferences: Map<string, JSONValue>;
|
|
12
|
+
protected init(): void;
|
|
13
|
+
canHandleScope(scope: PreferenceScope): boolean;
|
|
14
|
+
getPreferences(): JSONObject;
|
|
15
|
+
setPreference(key: string, value: JSONValue | undefined): Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=session-preference-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-preference-provider.d.ts","sourceRoot":"","sources":["../../../src/common/preferences/session-preference-provider.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAgC,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;GAIG;AACH,qBACa,yBAA0B,SAAQ,sBAAuB,YAAW,kBAAkB;IAE/F,SAAS,CAAC,QAAQ,CAAC,WAAW,yBAAgC;IAG9D,SAAS,CAAC,IAAI,IAAI,IAAI;IAIb,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO;IAIxD,cAAc,IAAI,UAAU;IAQtB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;CAmBnF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 EclipseSource and others.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.SessionPreferenceProvider = void 0;
|
|
19
|
+
const tslib_1 = require("tslib");
|
|
20
|
+
const inversify_1 = require("inversify");
|
|
21
|
+
const preference_provider_impl_1 = require("./preference-provider-impl");
|
|
22
|
+
const preference_scope_1 = require("./preference-scope");
|
|
23
|
+
/**
|
|
24
|
+
* In-memory preference provider used for process-lifetime overrides such as those
|
|
25
|
+
* supplied via the `--session-preference` CLI option. Values live in memory only
|
|
26
|
+
* and are dropped when the process exits.
|
|
27
|
+
*/
|
|
28
|
+
let SessionPreferenceProvider = class SessionPreferenceProvider extends preference_provider_impl_1.PreferenceProviderImpl {
|
|
29
|
+
constructor() {
|
|
30
|
+
super(...arguments);
|
|
31
|
+
this.preferences = new Map();
|
|
32
|
+
}
|
|
33
|
+
init() {
|
|
34
|
+
this._ready.resolve();
|
|
35
|
+
}
|
|
36
|
+
canHandleScope(scope) {
|
|
37
|
+
return scope === preference_scope_1.PreferenceScope.Session;
|
|
38
|
+
}
|
|
39
|
+
getPreferences() {
|
|
40
|
+
const result = {};
|
|
41
|
+
for (const [name, value] of this.preferences) {
|
|
42
|
+
result[name] = value;
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
async setPreference(key, value) {
|
|
47
|
+
const oldValue = this.preferences.get(key);
|
|
48
|
+
if (value === undefined) {
|
|
49
|
+
if (!this.preferences.has(key)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
this.preferences.delete(key);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
this.preferences.set(key, value);
|
|
56
|
+
}
|
|
57
|
+
const change = {
|
|
58
|
+
preferenceName: key,
|
|
59
|
+
newValue: value,
|
|
60
|
+
oldValue,
|
|
61
|
+
scope: preference_scope_1.PreferenceScope.Session
|
|
62
|
+
};
|
|
63
|
+
await this.emitPreferencesChangedEvent([change]);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
exports.SessionPreferenceProvider = SessionPreferenceProvider;
|
|
68
|
+
tslib_1.__decorate([
|
|
69
|
+
(0, inversify_1.postConstruct)(),
|
|
70
|
+
tslib_1.__metadata("design:type", Function),
|
|
71
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
72
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
73
|
+
], SessionPreferenceProvider.prototype, "init", null);
|
|
74
|
+
exports.SessionPreferenceProvider = SessionPreferenceProvider = tslib_1.__decorate([
|
|
75
|
+
(0, inversify_1.injectable)()
|
|
76
|
+
], SessionPreferenceProvider);
|
|
77
|
+
//# sourceMappingURL=session-preference-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-preference-provider.js","sourceRoot":"","sources":["../../../src/common/preferences/session-preference-provider.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,+CAA+C;AAC/C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAGhF,yCAAsD;AAEtD,yEAAoE;AACpE,yDAAqD;AAErD;;;;GAIG;AAEI,IAAM,yBAAyB,GAA/B,MAAM,yBAA0B,SAAQ,iDAAsB;IAA9D;;QAEgB,gBAAW,GAAG,IAAI,GAAG,EAAqB,CAAC;IAsClE,CAAC;IAnCa,IAAI;QACV,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC;IAEQ,cAAc,CAAC,KAAsB;QAC1C,OAAO,KAAK,KAAK,kCAAe,CAAC,OAAO,CAAC;IAC7C,CAAC;IAED,cAAc;QACV,MAAM,MAAM,GAAe,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACzB,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,KAA4B;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,OAAO,KAAK,CAAC;YACjB,CAAC;YACD,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,MAAM,MAAM,GAAiC;YACzC,cAAc,EAAE,GAAG;YACnB,QAAQ,EAAE,KAAK;YACf,QAAQ;YACR,KAAK,EAAE,kCAAe,CAAC,OAAO;SACjC,CAAC;QACF,MAAM,IAAI,CAAC,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ,CAAA;AAxCY,8DAAyB;AAKxB;IADT,IAAA,yBAAa,GAAE;;;;qDAGf;oCAPQ,yBAAyB;IADrC,IAAA,sBAAU,GAAE;GACA,yBAAyB,CAwCrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-preference-provider.spec.d.ts","sourceRoot":"","sources":["../../../src/common/preferences/session-preference-provider.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 EclipseSource and others.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const chai_1 = require("chai");
|
|
19
|
+
const session_preference_provider_1 = require("./session-preference-provider");
|
|
20
|
+
const preference_scope_1 = require("./preference-scope");
|
|
21
|
+
describe('SessionPreferenceProvider', () => {
|
|
22
|
+
let provider;
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
provider = new session_preference_provider_1.SessionPreferenceProvider();
|
|
25
|
+
// PostConstruct emulation
|
|
26
|
+
provider.init();
|
|
27
|
+
});
|
|
28
|
+
it('claims only the Session scope', () => {
|
|
29
|
+
(0, chai_1.expect)(provider.canHandleScope(preference_scope_1.PreferenceScope.Session)).to.be.true;
|
|
30
|
+
(0, chai_1.expect)(provider.canHandleScope(preference_scope_1.PreferenceScope.User)).to.be.false;
|
|
31
|
+
(0, chai_1.expect)(provider.canHandleScope(preference_scope_1.PreferenceScope.Workspace)).to.be.false;
|
|
32
|
+
(0, chai_1.expect)(provider.canHandleScope(preference_scope_1.PreferenceScope.Folder)).to.be.false;
|
|
33
|
+
(0, chai_1.expect)(provider.canHandleScope(preference_scope_1.PreferenceScope.Default)).to.be.false;
|
|
34
|
+
});
|
|
35
|
+
it('starts empty', () => {
|
|
36
|
+
(0, chai_1.expect)(provider.getPreferences()).to.deep.equal({});
|
|
37
|
+
});
|
|
38
|
+
it('stores set values in memory and exposes them via get/resolve', async () => {
|
|
39
|
+
const ok = await provider.setPreference('editor.fontSize', 18);
|
|
40
|
+
(0, chai_1.expect)(ok).to.be.true;
|
|
41
|
+
(0, chai_1.expect)(provider.get('editor.fontSize')).to.equal(18);
|
|
42
|
+
(0, chai_1.expect)(provider.resolve('editor.fontSize').value).to.equal(18);
|
|
43
|
+
(0, chai_1.expect)(provider.getPreferences()).to.deep.equal({ 'editor.fontSize': 18 });
|
|
44
|
+
});
|
|
45
|
+
it('emits a change event on set', async () => {
|
|
46
|
+
let received;
|
|
47
|
+
provider.onDidPreferencesChanged(changes => {
|
|
48
|
+
const key = Object.keys(changes)[0];
|
|
49
|
+
received = {
|
|
50
|
+
name: changes[key].preferenceName,
|
|
51
|
+
newValue: changes[key].newValue,
|
|
52
|
+
oldValue: changes[key].oldValue,
|
|
53
|
+
scope: changes[key].scope
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
await provider.setPreference('foo', 'bar');
|
|
57
|
+
(0, chai_1.expect)(received).to.deep.equal({ name: 'foo', newValue: 'bar', oldValue: undefined, scope: preference_scope_1.PreferenceScope.Session });
|
|
58
|
+
});
|
|
59
|
+
it('removes a value when set to undefined', async () => {
|
|
60
|
+
await provider.setPreference('foo', 'bar');
|
|
61
|
+
const removed = await provider.setPreference('foo', undefined);
|
|
62
|
+
(0, chai_1.expect)(removed).to.be.true;
|
|
63
|
+
(0, chai_1.expect)(provider.get('foo')).to.equal(undefined);
|
|
64
|
+
(0, chai_1.expect)(provider.getPreferences()).to.deep.equal({});
|
|
65
|
+
});
|
|
66
|
+
it('returns false when removing a key that was never set', async () => {
|
|
67
|
+
const removed = await provider.setPreference('missing', undefined);
|
|
68
|
+
(0, chai_1.expect)(removed).to.be.false;
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=session-preference-provider.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-preference-provider.spec.js","sourceRoot":"","sources":["../../../src/common/preferences/session-preference-provider.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/core",
|
|
3
|
-
"version": "1.74.0-next.
|
|
3
|
+
"version": "1.74.0-next.17+3351cf136",
|
|
4
4
|
"description": "Theia is a cloud & desktop IDE framework implemented in TypeScript.",
|
|
5
5
|
"main": "lib/common/index.js",
|
|
6
6
|
"typings": "lib/common/index.d.ts",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"@lumino/virtualdom": "^2.0.4",
|
|
18
18
|
"@lumino/widgets": "2.7.5",
|
|
19
19
|
"@parcel/watcher": "^2.5.6",
|
|
20
|
-
"@theia/application-package": "1.74.0-next.
|
|
21
|
-
"@theia/request": "1.74.0-next.
|
|
20
|
+
"@theia/application-package": "1.74.0-next.17+3351cf136",
|
|
21
|
+
"@theia/request": "1.74.0-next.17+3351cf136",
|
|
22
22
|
"@types/body-parser": "^1.19.6",
|
|
23
23
|
"@types/express": "^4.17.25",
|
|
24
24
|
"@types/fs-extra": "^4.0.15",
|
|
@@ -230,5 +230,5 @@
|
|
|
230
230
|
"nyc": {
|
|
231
231
|
"extends": "../../configs/nyc.json"
|
|
232
232
|
},
|
|
233
|
-
"gitHead": "
|
|
233
|
+
"gitHead": "3351cf1363eb15fad7088cfc9e6857377baf0acc"
|
|
234
234
|
}
|
|
@@ -22,16 +22,24 @@ import { isObject } from '../../common/types';
|
|
|
22
22
|
import { PreferenceSchemaServiceImpl } from '../../common/preferences/preference-schema-service';
|
|
23
23
|
import { PreferenceContribution, PreferenceSchemaService } from '../../common/preferences/preference-schema';
|
|
24
24
|
import { DefaultsPreferenceProvider } from '../../common/preferences/defaults-preference-provider';
|
|
25
|
+
import { SessionPreferenceProvider } from '../../common/preferences/session-preference-provider';
|
|
25
26
|
import { PreferenceLanguageOverrideService } from '../../common/preferences/preference-language-override-service';
|
|
26
27
|
import { FrontendConfigPreferenceContribution } from './frontend-config-preference-contributions';
|
|
27
28
|
import { bindPreferenceConfigurations } from '../../common/preferences/preference-configurations';
|
|
28
29
|
|
|
29
30
|
export function bindPreferenceSchemaProvider(bind: interfaces.Bind): void {
|
|
30
31
|
bindPreferenceConfigurations(bind);
|
|
31
|
-
bind(ValidPreferenceScopes).toConstantValue([
|
|
32
|
+
bind(ValidPreferenceScopes).toConstantValue([
|
|
33
|
+
PreferenceScope.Default,
|
|
34
|
+
PreferenceScope.User,
|
|
35
|
+
PreferenceScope.Workspace,
|
|
36
|
+
PreferenceScope.Folder,
|
|
37
|
+
PreferenceScope.Session
|
|
38
|
+
]);
|
|
32
39
|
bind(PreferenceSchemaServiceImpl).toSelf().inSingletonScope();
|
|
33
40
|
bind(PreferenceSchemaService).toService(PreferenceSchemaServiceImpl);
|
|
34
41
|
bind(PreferenceProvider).to(DefaultsPreferenceProvider).inSingletonScope().whenTargetNamed(PreferenceScope.Default);
|
|
42
|
+
bind(PreferenceProvider).to(SessionPreferenceProvider).inSingletonScope().whenTargetNamed(PreferenceScope.Session);
|
|
35
43
|
bind(PreferenceLanguageOverrideService).toSelf().inSingletonScope();
|
|
36
44
|
bindRootContributionProvider(bind, PreferenceContribution);
|
|
37
45
|
bind(PreferenceContribution).to(FrontendConfigPreferenceContribution).inSingletonScope();
|
|
@@ -262,6 +262,7 @@ describe('Preference Service', () => {
|
|
|
262
262
|
globalValue,
|
|
263
263
|
workspaceValue,
|
|
264
264
|
workspaceFolderValue,
|
|
265
|
+
sessionValue: undefined,
|
|
265
266
|
value,
|
|
266
267
|
};
|
|
267
268
|
const inspection = preferences.inspect(TAB_SIZE, DUMMY_URI);
|
|
@@ -374,6 +375,7 @@ describe('Preference Service', () => {
|
|
|
374
375
|
globalValue: undefined,
|
|
375
376
|
workspaceValue: undefined,
|
|
376
377
|
workspaceFolderValue: undefined,
|
|
378
|
+
sessionValue: undefined,
|
|
377
379
|
value: 4,
|
|
378
380
|
};
|
|
379
381
|
assert.deepStrictEqual(expected, preferences.inspect('editor.tabSize'));
|
|
@@ -397,6 +399,7 @@ describe('Preference Service', () => {
|
|
|
397
399
|
globalValue: 2,
|
|
398
400
|
workspaceValue: undefined,
|
|
399
401
|
workspaceFolderValue: undefined,
|
|
402
|
+
sessionValue: undefined,
|
|
400
403
|
value: 2
|
|
401
404
|
};
|
|
402
405
|
preferences.set('editor.tabSize', 2, PreferenceScope.User);
|
|
@@ -422,6 +425,7 @@ describe('Preference Service', () => {
|
|
|
422
425
|
globalValue: undefined,
|
|
423
426
|
workspaceValue: undefined,
|
|
424
427
|
workspaceFolderValue: undefined,
|
|
428
|
+
sessionValue: undefined,
|
|
425
429
|
value: 4
|
|
426
430
|
};
|
|
427
431
|
assert.deepStrictEqual(expected, preferences.inspect('editor.tabSize'));
|
|
@@ -537,4 +541,72 @@ describe('Preference Service', () => {
|
|
|
537
541
|
});
|
|
538
542
|
});
|
|
539
543
|
|
|
544
|
+
describe('session-scope overrides', () => {
|
|
545
|
+
function getSessionProvider(): PreferenceProvider {
|
|
546
|
+
return testContainer.getNamed<PreferenceProvider>(PreferenceProvider, PreferenceScope.Session);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
beforeEach(() => {
|
|
550
|
+
prefSchema.addSchema({
|
|
551
|
+
scope: PreferenceScope.Folder,
|
|
552
|
+
properties: {
|
|
553
|
+
'test.session': { type: 'number' }
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
it('takes precedence over the user scope', async () => {
|
|
559
|
+
getProvider(PreferenceScope.User).setPreference('test.session', 1);
|
|
560
|
+
await prefService.set('test.session', 99, PreferenceScope.Session);
|
|
561
|
+
expect(prefService.get('test.session')).equals(99);
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
it('is dropped when the same key is written to a persistent scope', async () => {
|
|
565
|
+
const sessionProvider = getSessionProvider();
|
|
566
|
+
getProvider(PreferenceScope.User).setPreference('test.session', 1);
|
|
567
|
+
await prefService.set('test.session', 99, PreferenceScope.Session);
|
|
568
|
+
expect(prefService.get('test.session')).equals(99);
|
|
569
|
+
|
|
570
|
+
// An explicit user edit must win over the session override and clear it.
|
|
571
|
+
await prefService.set('test.session', 2, PreferenceScope.User);
|
|
572
|
+
expect(sessionProvider.get('test.session')).to.equal(undefined);
|
|
573
|
+
expect(prefService.get('test.session')).equals(2);
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
it('is reported via inspect().sessionValue', async () => {
|
|
577
|
+
await prefService.set('test.session', 42, PreferenceScope.Session);
|
|
578
|
+
expect(prefService.inspect('test.session')?.sessionValue).equals(42);
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
it('emits a Session-scope change event when evicted by a persistent write', async () => {
|
|
582
|
+
// Status bar listeners rely on this: an eviction must surface as an
|
|
583
|
+
// onPreferenceChanged event whose `scope` is Session, otherwise the
|
|
584
|
+
// status bar would never clear after the override is dropped.
|
|
585
|
+
await prefService.set('test.session', 99, PreferenceScope.Session);
|
|
586
|
+
|
|
587
|
+
const sessionScopeEvents: PreferenceScope[] = [];
|
|
588
|
+
const listener = prefService.onPreferenceChanged(e => {
|
|
589
|
+
if (e.preferenceName === 'test.session') {
|
|
590
|
+
sessionScopeEvents.push(e.scope);
|
|
591
|
+
}
|
|
592
|
+
});
|
|
593
|
+
try {
|
|
594
|
+
await prefService.set('test.session', 2, PreferenceScope.User);
|
|
595
|
+
} finally {
|
|
596
|
+
listener.dispose();
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
expect(sessionScopeEvents).to.include(PreferenceScope.Session);
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
it('is left alone when writing to the Session scope itself', async () => {
|
|
603
|
+
const sessionProvider = getSessionProvider();
|
|
604
|
+
await prefService.set('test.session', 7, PreferenceScope.Session);
|
|
605
|
+
expect(sessionProvider.get('test.session')).to.equal(7);
|
|
606
|
+
// A second write to Session must not trigger eviction of itself.
|
|
607
|
+
await prefService.set('test.session', 8, PreferenceScope.Session);
|
|
608
|
+
expect(sessionProvider.get('test.session')).to.equal(8);
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
|
|
540
612
|
});
|
|
@@ -63,7 +63,7 @@ body.theia-no-open-workspace #theia-statusBar {
|
|
|
63
63
|
padding-inline: var(--theia-ui-padding);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
#theia-statusBar .area.left .element.has-background {
|
|
66
|
+
#theia-statusBar .area.left .element.has-background:not(#session-preference-status) {
|
|
67
67
|
margin-left: calc(-1 * var(--theia-ui-padding));
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
export * from './defaults-preference-provider';
|
|
18
18
|
export * from './preference-language-override-service';
|
|
19
|
+
export * from './session-preference-provider';
|
|
19
20
|
export * from './preference-provider-impl';
|
|
20
21
|
export * from './preference-provider';
|
|
21
22
|
export * from './preference-schema-service';
|
|
@@ -20,11 +20,11 @@ import { PreferenceScope } from './preference-scope';
|
|
|
20
20
|
describe('PreferenceScope', () => {
|
|
21
21
|
|
|
22
22
|
it('getScopes() should return numbers from broadest to narrowest', () => {
|
|
23
|
-
expect(PreferenceScope.getScopes()).deep.equal([0, 1, 2, 3]);
|
|
23
|
+
expect(PreferenceScope.getScopes()).deep.equal([0, 1, 2, 3, 4]);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
it('getReversedScopes() should return numbers from narrowest to broadest', () => {
|
|
27
|
-
expect(PreferenceScope.getReversedScopes()).deep.equal([3, 2, 1, 0]);
|
|
27
|
+
expect(PreferenceScope.getReversedScopes()).deep.equal([4, 3, 2, 1, 0]);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
it('getScopeNames() should return the names of scopes broader than the current one', () => {
|
|
@@ -36,11 +36,13 @@ describe('PreferenceScope', () => {
|
|
|
36
36
|
expect(PreferenceScope.is(PreferenceScope.User)).to.be.true;
|
|
37
37
|
expect(PreferenceScope.is(PreferenceScope.Workspace)).to.be.true;
|
|
38
38
|
expect(PreferenceScope.is(PreferenceScope.Folder)).to.be.true;
|
|
39
|
+
expect(PreferenceScope.is(PreferenceScope.Session)).to.be.true;
|
|
39
40
|
expect(PreferenceScope.is(0)).to.be.true;
|
|
40
41
|
expect(PreferenceScope.is(1)).to.be.true;
|
|
41
42
|
expect(PreferenceScope.is(2)).to.be.true;
|
|
42
43
|
expect(PreferenceScope.is(3)).to.be.true;
|
|
43
|
-
expect(PreferenceScope.is(4)).to.be.
|
|
44
|
+
expect(PreferenceScope.is(4)).to.be.true;
|
|
45
|
+
expect(PreferenceScope.is(5)).to.be.false;
|
|
44
46
|
expect(PreferenceScope.is(-1)).to.be.false;
|
|
45
47
|
expect(PreferenceScope.is({})).to.be.false;
|
|
46
48
|
expect(PreferenceScope.is('Default')).to.be.false;
|
|
@@ -23,7 +23,12 @@ export enum PreferenceScope {
|
|
|
23
23
|
Default,
|
|
24
24
|
User,
|
|
25
25
|
Workspace,
|
|
26
|
-
Folder
|
|
26
|
+
Folder,
|
|
27
|
+
/**
|
|
28
|
+
* Process-lifetime, in-memory scope used by `--session-preference` CLI overrides.
|
|
29
|
+
* Has the highest precedence and is never persisted to disk.
|
|
30
|
+
*/
|
|
31
|
+
Session
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
export namespace PreferenceScope {
|
|
@@ -254,6 +254,10 @@ export interface PreferenceInspection<T = JSONValue> {
|
|
|
254
254
|
* Value in folder scope.
|
|
255
255
|
*/
|
|
256
256
|
workspaceFolderValue: T | undefined,
|
|
257
|
+
/**
|
|
258
|
+
* Value in session scope (in-memory, set via `--session-preference`).
|
|
259
|
+
*/
|
|
260
|
+
sessionValue?: T | undefined,
|
|
257
261
|
/**
|
|
258
262
|
* The value that is active, i.e. the value set in the lowest scope available.
|
|
259
263
|
*/
|
|
@@ -453,11 +457,37 @@ export class PreferenceServiceImpl implements PreferenceService {
|
|
|
453
457
|
}
|
|
454
458
|
const provider = this.getProvider(resolvedScope);
|
|
455
459
|
if (provider && await provider.setPreference(preferenceName, value, resourceUri)) {
|
|
460
|
+
await this.evictSessionOverride(preferenceName, resolvedScope);
|
|
456
461
|
return;
|
|
457
462
|
}
|
|
458
463
|
throw new Error(`Unable to write to ${PreferenceScope[resolvedScope]} Settings.`);
|
|
459
464
|
}
|
|
460
465
|
|
|
466
|
+
/**
|
|
467
|
+
* When a preference is written to a persistent scope, drop any in-memory session
|
|
468
|
+
* override (set via `--session-preference`) for the same key so that the explicit
|
|
469
|
+
* change takes effect for the remainder of the session. Without this, the session
|
|
470
|
+
* scope would keep shadowing the user's change because it has higher precedence.
|
|
471
|
+
*
|
|
472
|
+
* Note: this fires for any write to a persistent scope, including programmatic
|
|
473
|
+
* writes from extensions. Extensions that race with startup CLI overrides will
|
|
474
|
+
* therefore clear them. This is intentional: a programmatic write is "explicit"
|
|
475
|
+
* from the preference system's point of view, but consumers should be aware.
|
|
476
|
+
*
|
|
477
|
+
* Session preferences are global (no per-resource scoping), so `resourceUri` is
|
|
478
|
+
* not threaded through.
|
|
479
|
+
*/
|
|
480
|
+
protected async evictSessionOverride(preferenceName: string, writtenScope: PreferenceScope): Promise<void> {
|
|
481
|
+
if (writtenScope === PreferenceScope.Session || writtenScope === PreferenceScope.Default) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const sessionProvider = this.getProvider(PreferenceScope.Session);
|
|
485
|
+
if (sessionProvider && sessionProvider.get(preferenceName) !== undefined) {
|
|
486
|
+
// Passing `undefined` clears the value in the session provider.
|
|
487
|
+
await sessionProvider.setPreference(preferenceName, undefined as unknown as JSONValue);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
461
491
|
getBoolean(preferenceName: string): boolean | undefined;
|
|
462
492
|
getBoolean(preferenceName: string, defaultValue: boolean): boolean;
|
|
463
493
|
getBoolean(preferenceName: string, defaultValue: boolean, resourceUri: string): boolean;
|
|
@@ -499,10 +529,11 @@ export class PreferenceServiceImpl implements PreferenceService {
|
|
|
499
529
|
const globalValue = this.inspectInScope<T>(preferenceName, PreferenceScope.User, resourceUri, forceLanguageOverride);
|
|
500
530
|
const workspaceValue = this.inspectInScope<T>(preferenceName, PreferenceScope.Workspace, resourceUri, forceLanguageOverride);
|
|
501
531
|
const workspaceFolderValue = this.inspectInScope<T>(preferenceName, PreferenceScope.Folder, resourceUri, forceLanguageOverride);
|
|
532
|
+
const sessionValue = this.inspectInScope<T>(preferenceName, PreferenceScope.Session, resourceUri, forceLanguageOverride);
|
|
502
533
|
|
|
503
|
-
const valueApplied = workspaceFolderValue ?? workspaceValue ?? globalValue ?? defaultValue;
|
|
534
|
+
const valueApplied = sessionValue ?? workspaceFolderValue ?? workspaceValue ?? globalValue ?? defaultValue;
|
|
504
535
|
|
|
505
|
-
return { preferenceName, defaultValue, globalValue, workspaceValue, workspaceFolderValue, value: valueApplied };
|
|
536
|
+
return { preferenceName, defaultValue, globalValue, workspaceValue, workspaceFolderValue, sessionValue, value: valueApplied };
|
|
506
537
|
}
|
|
507
538
|
|
|
508
539
|
inspectInScope<T extends JSONValue>(preferenceName: string, scope: PreferenceScope, resourceUri?: string, forceLanguageOverride?: boolean): T | undefined {
|
|
@@ -526,6 +557,8 @@ export class PreferenceServiceImpl implements PreferenceService {
|
|
|
526
557
|
return inspection.workspaceValue;
|
|
527
558
|
case PreferenceScope.Folder:
|
|
528
559
|
return inspection.workspaceFolderValue;
|
|
560
|
+
case PreferenceScope.Session:
|
|
561
|
+
return inspection.sessionValue;
|
|
529
562
|
}
|
|
530
563
|
unreachable(scope, 'Not all PreferenceScope enum variants handled.');
|
|
531
564
|
}
|
|
@@ -551,9 +584,10 @@ export class PreferenceServiceImpl implements PreferenceService {
|
|
|
551
584
|
}
|
|
552
585
|
|
|
553
586
|
// Scopes in ascending order of scope breadth.
|
|
554
|
-
const allScopes = [...this.schemaService.validScopes].reverse()
|
|
555
|
-
|
|
556
|
-
|
|
587
|
+
const allScopes = [...this.schemaService.validScopes].reverse()
|
|
588
|
+
// Default is read-only, and Session is populated only by `--session-preference`,
|
|
589
|
+
// so neither is a valid target for a regular user edit.
|
|
590
|
+
.filter(scope => scope !== PreferenceScope.Default && scope !== PreferenceScope.Session);
|
|
557
591
|
|
|
558
592
|
const isScopeDefined = (scope: PreferenceScope) => this.getScopedValueFromInspection(inspection, scope) !== undefined;
|
|
559
593
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 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 { expect } from 'chai';
|
|
18
|
+
import { SessionPreferenceProvider } from './session-preference-provider';
|
|
19
|
+
import { PreferenceScope } from './preference-scope';
|
|
20
|
+
|
|
21
|
+
describe('SessionPreferenceProvider', () => {
|
|
22
|
+
|
|
23
|
+
let provider: SessionPreferenceProvider;
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
provider = new SessionPreferenceProvider();
|
|
27
|
+
// PostConstruct emulation
|
|
28
|
+
(provider as unknown as { init(): void }).init();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('claims only the Session scope', () => {
|
|
32
|
+
expect(provider.canHandleScope(PreferenceScope.Session)).to.be.true;
|
|
33
|
+
expect(provider.canHandleScope(PreferenceScope.User)).to.be.false;
|
|
34
|
+
expect(provider.canHandleScope(PreferenceScope.Workspace)).to.be.false;
|
|
35
|
+
expect(provider.canHandleScope(PreferenceScope.Folder)).to.be.false;
|
|
36
|
+
expect(provider.canHandleScope(PreferenceScope.Default)).to.be.false;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('starts empty', () => {
|
|
40
|
+
expect(provider.getPreferences()).to.deep.equal({});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('stores set values in memory and exposes them via get/resolve', async () => {
|
|
44
|
+
const ok = await provider.setPreference('editor.fontSize', 18);
|
|
45
|
+
expect(ok).to.be.true;
|
|
46
|
+
expect(provider.get('editor.fontSize')).to.equal(18);
|
|
47
|
+
expect(provider.resolve('editor.fontSize').value).to.equal(18);
|
|
48
|
+
expect(provider.getPreferences()).to.deep.equal({ 'editor.fontSize': 18 });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('emits a change event on set', async () => {
|
|
52
|
+
let received: { name: string; newValue: unknown; oldValue: unknown; scope: PreferenceScope } | undefined;
|
|
53
|
+
provider.onDidPreferencesChanged(changes => {
|
|
54
|
+
const key = Object.keys(changes)[0];
|
|
55
|
+
received = {
|
|
56
|
+
name: changes[key].preferenceName,
|
|
57
|
+
newValue: changes[key].newValue,
|
|
58
|
+
oldValue: changes[key].oldValue,
|
|
59
|
+
scope: changes[key].scope
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
await provider.setPreference('foo', 'bar');
|
|
63
|
+
expect(received).to.deep.equal({ name: 'foo', newValue: 'bar', oldValue: undefined, scope: PreferenceScope.Session });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('removes a value when set to undefined', async () => {
|
|
67
|
+
await provider.setPreference('foo', 'bar');
|
|
68
|
+
const removed = await provider.setPreference('foo', undefined as never);
|
|
69
|
+
expect(removed).to.be.true;
|
|
70
|
+
expect(provider.get('foo')).to.equal(undefined);
|
|
71
|
+
expect(provider.getPreferences()).to.deep.equal({});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('returns false when removing a key that was never set', async () => {
|
|
75
|
+
const removed = await provider.setPreference('missing', undefined as never);
|
|
76
|
+
expect(removed).to.be.false;
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 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 { JSONObject, JSONValue } from '@lumino/coreutils';
|
|
18
|
+
import { injectable, postConstruct } from 'inversify';
|
|
19
|
+
import { PreferenceProvider, PreferenceProviderDataChange } from './preference-provider';
|
|
20
|
+
import { PreferenceProviderImpl } from './preference-provider-impl';
|
|
21
|
+
import { PreferenceScope } from './preference-scope';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* In-memory preference provider used for process-lifetime overrides such as those
|
|
25
|
+
* supplied via the `--session-preference` CLI option. Values live in memory only
|
|
26
|
+
* and are dropped when the process exits.
|
|
27
|
+
*/
|
|
28
|
+
@injectable()
|
|
29
|
+
export class SessionPreferenceProvider extends PreferenceProviderImpl implements PreferenceProvider {
|
|
30
|
+
|
|
31
|
+
protected readonly preferences = new Map<string, JSONValue>();
|
|
32
|
+
|
|
33
|
+
@postConstruct()
|
|
34
|
+
protected init(): void {
|
|
35
|
+
this._ready.resolve();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override canHandleScope(scope: PreferenceScope): boolean {
|
|
39
|
+
return scope === PreferenceScope.Session;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getPreferences(): JSONObject {
|
|
43
|
+
const result: JSONObject = {};
|
|
44
|
+
for (const [name, value] of this.preferences) {
|
|
45
|
+
result[name] = value;
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async setPreference(key: string, value: JSONValue | undefined): Promise<boolean> {
|
|
51
|
+
const oldValue = this.preferences.get(key);
|
|
52
|
+
if (value === undefined) {
|
|
53
|
+
if (!this.preferences.has(key)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
this.preferences.delete(key);
|
|
57
|
+
} else {
|
|
58
|
+
this.preferences.set(key, value);
|
|
59
|
+
}
|
|
60
|
+
const change: PreferenceProviderDataChange = {
|
|
61
|
+
preferenceName: key,
|
|
62
|
+
newValue: value,
|
|
63
|
+
oldValue,
|
|
64
|
+
scope: PreferenceScope.Session
|
|
65
|
+
};
|
|
66
|
+
await this.emitPreferencesChangedEvent([change]);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|