@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
221 lines • 9.74 kB
JavaScript
// *****************************************************************************
// Copyright (C) 2018 Ericsson and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PreferenceProvider = exports.PreferenceProviderDataChange = void 0;
/* eslint-disable @typescript-eslint/no-explicit-any */
const debounce = require("p-debounce");
const inversify_1 = require("inversify");
const coreutils_1 = require("@phosphor/coreutils");
const uri_1 = require("../../common/uri");
const common_1 = require("../../common");
const promise_util_1 = require("../../common/promise-util");
const preference_language_override_service_1 = require("./preference-language-override-service");
var PreferenceProviderDataChange;
(function (PreferenceProviderDataChange) {
function affects(change, resourceUri) {
const resourcePath = resourceUri && new uri_1.default(resourceUri).path;
const domain = change.domain;
return !resourcePath || !domain || domain.some(uri => new uri_1.default(uri).path.relativity(resourcePath) >= 0);
}
PreferenceProviderDataChange.affects = affects;
})(PreferenceProviderDataChange = exports.PreferenceProviderDataChange || (exports.PreferenceProviderDataChange = {}));
/**
* The {@link PreferenceProvider} is used to store and retrieve preference values. A {@link PreferenceProvider} does not operate in a global scope but is
* configured for one or more {@link PreferenceScope}s. The (default implementation for the) {@link PreferenceService} aggregates all {@link PreferenceProvider}s and
* serves as a common facade for manipulating preference values.
*/
let PreferenceProvider = class PreferenceProvider {
constructor() {
this.onDidPreferencesChangedEmitter = new common_1.Emitter();
this.onDidPreferencesChanged = this.onDidPreferencesChangedEmitter.event;
this.toDispose = new common_1.DisposableCollection();
this._ready = new promise_util_1.Deferred();
this.fireDidPreferencesChanged = debounce(() => {
const changes = this.deferredChanges;
this.deferredChanges = undefined;
if (changes && Object.keys(changes).length) {
this.onDidPreferencesChangedEmitter.fire(changes);
return true;
}
return false;
}, 0);
this.toDispose.push(this.onDidPreferencesChangedEmitter);
}
dispose() {
this.toDispose.dispose();
}
/**
* Informs the listeners that one or more preferences of this provider are changed.
* The listeners are able to find what was changed from the emitted event.
*/
emitPreferencesChangedEvent(changes) {
if (Array.isArray(changes)) {
for (const change of changes) {
this.mergePreferenceProviderDataChange(change);
}
}
else {
for (const preferenceName of Object.keys(changes)) {
this.mergePreferenceProviderDataChange(changes[preferenceName]);
}
}
return this.fireDidPreferencesChanged();
}
mergePreferenceProviderDataChange(change) {
if (!this.deferredChanges) {
this.deferredChanges = {};
}
const current = this.deferredChanges[change.preferenceName];
const { newValue, scope, domain } = change;
if (!current) {
// new
this.deferredChanges[change.preferenceName] = change;
}
else if (current.oldValue === newValue) {
// delete
delete this.deferredChanges[change.preferenceName];
}
else {
// update
Object.assign(current, { newValue, scope, domain });
}
}
/**
* Retrieve the stored value for the given preference and resource URI.
*
* @param preferenceName the preference identifier.
* @param resourceUri the uri of the resource for which the preference is stored. This is used to retrieve
* a potentially different value for the same preference for different resources, for example `files.encoding`.
*
* @returns the value stored for the given preference and resourceUri if it exists, otherwise `undefined`.
*/
get(preferenceName, resourceUri) {
return this.resolve(preferenceName, resourceUri).value;
}
/**
* Resolve the value for the given preference and resource URI.
*
* @param preferenceName the preference identifier.
* @param resourceUri the URI of the resource for which this provider should resolve the preference. This is used to retrieve
* a potentially different value for the same preference for different resources, for example `files.encoding`.
*
* @returns an object containing the value stored for the given preference and resourceUri if it exists,
* otherwise `undefined`.
*/
resolve(preferenceName, resourceUri) {
const value = this.getPreferences(resourceUri)[preferenceName];
if (value !== undefined) {
return {
value,
configUri: this.getConfigUri(resourceUri)
};
}
return {};
}
/**
* Resolved when the preference provider is ready to provide preferences
* It should be resolved by subclasses.
*/
get ready() {
return this._ready.promise;
}
/**
* Retrieve the domain for this provider.
*
* @returns the domain or `undefined` if this provider is suitable for all domains.
*/
getDomain() {
return undefined;
}
/**
* Retrieve the configuration URI for the given resource URI.
* @param resourceUri the uri of the resource or `undefined`.
* @param sectionName the section to return the URI for, e.g. `tasks` or `launch`. Defaults to settings.
*
* @returns the corresponding resource URI or `undefined` if there is no valid URI.
*/
getConfigUri(resourceUri, sectionName) {
return undefined;
}
static merge(source, target) {
if (source === undefined || !coreutils_1.JSONExt.isObject(source)) {
return coreutils_1.JSONExt.deepCopy(target);
}
if (coreutils_1.JSONExt.isPrimitive(target)) {
return {};
}
for (const key of Object.keys(target)) {
const value = target[key];
if (key in source) {
if (coreutils_1.JSONExt.isObject(source[key]) && coreutils_1.JSONExt.isObject(value)) {
this.merge(source[key], value);
continue;
}
}
source[key] = coreutils_1.JSONExt.deepCopy(value);
}
return source;
}
/**
* Handles deep equality with the possibility of `undefined`
*/
static deepEqual(a, b) {
if (a === b) {
return true;
}
if (a === undefined || b === undefined) {
return false;
}
return coreutils_1.JSONExt.deepEqual(a, b);
}
getParsedContent(jsonData) {
const preferences = {};
if (!(0, common_1.isObject)(jsonData)) {
return preferences;
}
for (const [preferenceName, preferenceValue] of Object.entries(jsonData)) {
if (this.preferenceOverrideService.testOverrideValue(preferenceName, preferenceValue)) {
for (const [overriddenPreferenceName, overriddenValue] of Object.entries(preferenceValue)) {
preferences[`${preferenceName}.${overriddenPreferenceName}`] = overriddenValue;
}
}
else {
preferences[preferenceName] = preferenceValue;
}
}
return preferences;
}
};
__decorate([
(0, inversify_1.inject)(preference_language_override_service_1.PreferenceLanguageOverrideService),
__metadata("design:type", preference_language_override_service_1.PreferenceLanguageOverrideService)
], PreferenceProvider.prototype, "preferenceOverrideService", void 0);
PreferenceProvider = __decorate([
(0, inversify_1.injectable)(),
__metadata("design:paramtypes", [])
], PreferenceProvider);
exports.PreferenceProvider = PreferenceProvider;
//# sourceMappingURL=preference-provider.js.map
;