Skip to content

Commit

Permalink
Improve Documentation for PreferenceContribution and related types
Browse files Browse the repository at this point in the history
Fixes #8676
Contributed on behalf of STMicroelectronics
Signed-off-by: Tobias Ortmayr <tortmayr@eclipsesource.com>
  • Loading branch information
tortmayr committed Oct 30, 2020
1 parent c4f324a commit 85b652a
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 7 deletions.
44 changes: 43 additions & 1 deletion packages/core/src/browser/preferences/preference-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,31 @@ import { Mutable } from '../../common/types';
/* eslint-disable guard-for-in, @typescript-eslint/no-explicit-any */

export const PreferenceContribution = Symbol('PreferenceContribution');

/**
* A {@link PreferenceContribution} allows adding additional custom preferences.
* For this, the {@link PreferenceContribution} has to provide a valid JSON Schema specifying which preferences
* are available including their types and description.
*
* ### Example usage
* ```typescript
* const MyPreferencesSchema: PreferenceSchema = {
* 'type': 'object',
* 'properties': {
* 'myext.decorations.enabled': {
* 'type': 'boolean',
* 'description': 'Show file status',
* 'default': true
* },
* // [...]
* }
* }
* @injectable()
* export class MyPreferenceContribution implements PreferenceContribution{
* schema= MyPreferencesSchema;
* }
* ```
*/
export interface PreferenceContribution {
readonly schema: PreferenceSchema;
}
Expand All @@ -56,7 +81,10 @@ const OVERRIDE_PROPERTY = '\\[(.*)\\]$';
export const OVERRIDE_PROPERTY_PATTERN = new RegExp(OVERRIDE_PROPERTY);

const OVERRIDE_PATTERN_WITH_SUBSTITUTION = '\\[(${0})\\]$';

/**
* Specialized {@link FrontendApplicationConfig} to configure default
* preference values for the {@link PreferenceSchemaProvider}.
*/
export interface FrontendApplicationPreferenceConfig extends FrontendApplicationConfig {
preferences: {
[preferenceName: string]: any
Expand All @@ -68,6 +96,11 @@ export namespace FrontendApplicationPreferenceConfig {
}
}

/**
* The {@link PreferenceSchemaProvider} collects all {@link PreferenceContribution}s and combines
* the preference schema provided by these contributions into one collective schema. The preferences which
* are provided by this {@link PreferenceProvider} are derived from this combined schema.
*/
@injectable()
export class PreferenceSchemaProvider extends PreferenceProvider {

Expand Down Expand Up @@ -96,6 +129,15 @@ export class PreferenceSchemaProvider extends PreferenceProvider {
}

protected readonly overrideIdentifiers = new Set<string>();

/**
* Register a new overrideIdentifier. Existing identifiers are not replaced.
*
* Allows overriding existing values while keeping both values in store.
* For example to store different editor settings, e.g. "[markdown].editor.autoIndent",
* "[json].editor.autoIndent" and "editor.autoIndent"
* @param overrideIdentifier the new overrideIdentifier
*/
registerOverrideIdentifier(overrideIdentifier: string): void {
if (this.overrideIdentifiers.has(overrideIdentifier)) {
return;
Expand Down
47 changes: 42 additions & 5 deletions packages/core/src/browser/preferences/preference-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ export interface PreferenceResolveResult<T> {
configUri?: URI
value?: T
}

/**
* 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.
*/
@injectable()
export abstract class PreferenceProvider implements Disposable {

Expand Down Expand Up @@ -118,10 +122,29 @@ export abstract class PreferenceProvider implements Disposable {
return false;
}, 0);

/**
* 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<T>(preferenceName: string, resourceUri?: string): T | undefined {
return this.resolve<T>(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<T>(preferenceName: string, resourceUri?: string): PreferenceResolveResult<T> {
const value = this.getPreferences(resourceUri)[preferenceName];
if (value !== undefined) {
Expand All @@ -136,7 +159,12 @@ export abstract class PreferenceProvider implements Disposable {
abstract getPreferences(resourceUri?: string): { [p: string]: any };

/**
* Resolves only if all changes were delivered.
* Stores a new value for the given preference key in the provider.
* @param key the preference key (typically the name).
* @param value the new preference value.
* @param resourceUri the URI of the resource for which the preference is stored.
*
* @returns a promise that only resolves if all changes were delivered.
* If changes were made then implementation must either
* await on `this.emitPreferencesChangedEvent(...)` or
* `this.pendingChanges` if changes are fired indirectly.
Expand All @@ -152,21 +180,30 @@ export abstract class PreferenceProvider implements Disposable {
}

/**
* undefined if all belongs
* Retrieve the domain for this provider.
*
* @returns the domain or `undefined` if this provider is suitable for all domains.
*/
getDomain(): string[] | undefined {
return undefined;
}

/**
* Returns undefined if there is no valid config URI for the given resource URI.
* Retrieve the configuration URI for the given resource URI.
* @param resourceUri the uri of the resource or `undefined`.
*
* @returns the corresponding resource URI or `undefined` if there is no valid URI.
*/
getConfigUri(resourceUri?: string): URI | undefined {
return undefined;
}

/**
* Returns undefined if there is config URI at all for the given resource URI.
* Retrieves the first valid configuration URI contained by the given resource.
* @param resourceUri the uri of the container resource or `undefined`.
*
* @returns the first valid configuration URI contained by the given resource `undefined`
* if there is no valid configuration URI at all.
*/
getContainingConfigUri?(resourceUri?: string): URI | undefined;

Expand Down
24 changes: 23 additions & 1 deletion packages/core/src/browser/preferences/preference-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,31 @@ import { PreferenceConfigurations } from './preference-configurations';

export { PreferenceScope };

/**
* Representation of a preference change. A preference value can be set to `undefined` for a specific scope.
* This means that the value from a more general scope will be used.
*/
export interface PreferenceChange {
/**
* The name of the changed preference.
*/
readonly preferenceName: string;
/**
* The new value of the changed preference.
*/
readonly newValue?: any;
/**
* The old value of the changed preference.
*/
readonly oldValue?: any;
/**
* The {@link PreferenceScope} of the changed preference.
*/
readonly scope: PreferenceScope;
/**
* Tests wether the given resource is affected by the preference change.
* @param resourceUri the uri of the resource to test.
*/
affects(resourceUri?: string): boolean;
}

Expand Down Expand Up @@ -60,7 +80,9 @@ export class PreferenceChangeImpl implements PreferenceChange {
return !resourcePath || !domain || domain.some(uri => new URI(uri).path.relativity(resourcePath) >= 0);
}
}

/**
* A key-value storage for {@link PreferenceChange}s. Used to aggregate multiple simultaneous preference changes.
*/
export interface PreferenceChanges {
[preferenceName: string]: PreferenceChange
}
Expand Down

0 comments on commit 85b652a

Please sign in to comment.