Skip to content

Commit

Permalink
Add API Documentation in core package
Browse files Browse the repository at this point in the history
* Document 'BackendContribution'
* Document 'MessageService' and related message interfaces
* Extend documentation of MenuContribution and related menu interfaces
and classes
* Document 'PreferenceService', 'PreferenceProxy' and related
interfaces, classes and functions

Signed-off-by: Stefan Dirix <sdirix@eclipsesource.com>
Contributed on behalf of STMicroelectronics
  • Loading branch information
sdirix committed Oct 5, 2020
1 parent 2d86390 commit 7c03a68
Show file tree
Hide file tree
Showing 6 changed files with 532 additions and 28 deletions.
83 changes: 83 additions & 0 deletions packages/core/src/browser/preferences/preference-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,104 @@ export interface PreferenceEventEmitter<T> {
readonly ready: Promise<void>;
}

/**
* Generic interface to declare a typesafe get function based on the given
* configuration type.
*
* ### Example
*
* ```typescript
* interface PreferenceConfiguration {
* 'myext.decorations.enabled': boolean,
* 'myext.debug': boolean,
* 'myext.editor.previewtype': string
* }
* const prefs : PreferenceRetrieval<PreferenceConfiguration> = createPreferenceProxy(...);
* const enabled : boolean = prefs.get('myext.decorations.enabled'); // valid
* const debug : string = prefs.get('myext.debug'); // invalid
* prefs.get('foobar'); // invalid
* ```
*/
export interface PreferenceRetrieval<T> {
get<K extends keyof T>(preferenceName: K | {
preferenceName: K,
overrideIdentifier?: string
}, defaultValue?: T[K], resourceUri?: string): T[K];
}

/**
* Typesafe schema-based preferences utility based on the {@link PreferenceService}.
*
* Can be used to set and get preferences as well as listen to preference changes.
*
* ### Example usage
*
* ``` typescript
* const MyPreferencesSchema: PreferenceSchema = {
* 'type': 'object',
* 'properties': {
* 'myext.decorations.enabled': {
* 'type': 'boolean',
* 'description': 'Show file status',
* 'default': true
* },
* // [...]
* }
* }
*
* interface MyPrefConfiguration {
* 'myext.decorations.enabled': boolean;
* }
*
* type MyPreferences = PreferenceProxy<MyPrefConfiguration>;
*
* const preferences : MyPreferences = createPreferenceProxy(preferenceService, MyPreferenceSchema);
*
* preferences.onPreferenceChanged(({ preferenceName, newValue }) => { console.log(preferenceName, newValue) });
* const enabled = preferences['myext.decorations.enabled'];
* ```
*
*/
export type PreferenceProxy<T> = Readonly<T> & Disposable & PreferenceEventEmitter<T> & PreferenceRetrieval<T>;
/**
* Proxy configuration parameters.
*/
export interface PreferenceProxyOptions {
/**
* Prefix which is transparently added to all preference identifiers.
*/
prefix?: string;
/**
* The default resourceUri to use if none was specified when calling "set" or "get".
*/
resourceUri?: string;
/**
* The overrideIdentifier to use with the underlying preferenceService.
* Useful to potentially override 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"
*/
overrideIdentifier?: string;
/**
* Indicates whether '.' in schema properties shall be interpreted as regular names (flat),
* as declaring nested objects (deep) or both. Default is flat.
*
* When 'deep' or 'both' is given, nested preference proxies can be retrieved.
*/
style?: 'flat' | 'deep' | 'both';
}

/**
* Creates a preference proxy for typesafe preference handling.
*
* @param preferences the underlying preference service to use for preference handling.
* @param schema the JSON Schema which describes which preferences are available including types and descriptions.
* @param options configuration options.
*
* @returns the created preference proxy.
*
*/
export function createPreferenceProxy<T>(preferences: PreferenceService, schema: PreferenceSchema, options?: PreferenceProxyOptions): PreferenceProxy<T> {
const opts = options || {};
const prefix = opts.prefix || '';
Expand Down
156 changes: 141 additions & 15 deletions packages/core/src/browser/preferences/preference-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,34 +66,163 @@ export interface PreferenceChanges {
}

export const PreferenceService = Symbol('PreferenceService');
/**
* Service to store and retrieve preference values.
*
* Depending on your use case you might also want to look at `createPreferenceProxy` with which
* you can easily create a typesafe schema-based interface for your preferences. Internally the proxy
* uses the PreferenceService so both approaches are compatible.
*/
export interface PreferenceService extends Disposable {
readonly ready: Promise<void>;
/**
* Retrieve the stored value for the given preference.
*
* @param preferenceName the preference identifier.
*
* @returns the value stored for the given preference when it exists, `undefined` otherwise.
*/
get<T>(preferenceName: string): T | undefined;
/**
* Retrieve the stored value for the given preference.
*
* @param preferenceName the preference identifier.
* @param defaultValue the value to return when no value for the given preference is stored.
*
* @returns the value stored for the given preference when it exists, otherwise the given default value.
*/
get<T>(preferenceName: string, defaultValue: T): T;
/**
* Retrieve the stored value for the given preference and resourceUri.
*
* @param preferenceName the preference identifier.
* @param defaultValue the value to return when no value for the given preference is stored.
* @param resourceUri the uri of the resource for which the preference is stored. This 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 when it exists, otherwise the given
* default value.
*/
get<T>(preferenceName: string, defaultValue: T, resourceUri?: string): T;
/**
* Retrieve the stored value for the given preference and resourceUri.
*
* @param preferenceName the preference identifier.
* @param defaultValue the value to return when no value for the given preference is stored.
* @param resourceUri the uri of the resource for which the preference is stored. This 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 when it exists, otherwise the given
* default value.
*/
get<T>(preferenceName: string, defaultValue?: T, resourceUri?: string): T | undefined;
/**
* Sets the given preference to the given value.
*
* @param preferenceName the preference identifier.
* @param value the new value of the preference.
* @param scope the scope for which the value shall be set, i.e. user, workspace etc.
* When the folder scope is specified a resourceUri must be provided.
* @param resourceUri the uri of the resource for which the preference is stored. This used to store
* a potentially different value for the same preference for different resources, for example `files.encoding`.
*
* @returns a promise which resolves to `undefined` when setting the preference was successful. Otherwise it rejects
* with an error.
*/
set(preferenceName: string, value: any, scope?: PreferenceScope, resourceUri?: string): Promise<void>;
/**
* Registers a callback which will be called whenever a preference is changed.
*/
onPreferenceChanged: Event<PreferenceChange>;
/**
* Registers a callback which will be called whenever one or more preferences are changed.
*/
onPreferencesChanged: Event<PreferenceChanges>;

inspect<T>(preferenceName: string, resourceUri?: string): {
preferenceName: string,
defaultValue: T | undefined,
globalValue: T | undefined, // User Preference
workspaceValue: T | undefined, // Workspace Preference
workspaceFolderValue: T | undefined // Folder Preference
} | undefined;

/**
* Retrieve the stored value for the given preference and resourceUri in all available scopes.
*
* @param preferenceName the preference identifier.
* @param resourceUri the uri of the resource for which the preference is stored.
*
* @return an object containing the value of the given preference for all scopes.
*/
inspect<T>(preferenceName: string, resourceUri?: string): PreferenceInspection<T> | undefined;
/**
* Returns a new preference identifier based on the given OverridePreferenceName.
*
* @param options the override specification.
*
* @returns the calculated string based on the given OverridePreferenceName.
*/
overridePreferenceName(options: OverridePreferenceName): string;
/**
* Tries to split the given preference identifier into the original OverridePreferenceName attributes
* with which this identifier was created. Returns `undefined` if this is not possible, for example
* when the given preference identifier was not generated by `overridePreferenceName`.
*
* This method is checked when resolving preferences. Therefore together with "overridePreferenceName"
* this can be used to handle specialized preferences, e.g. "[markdown].editor.autoIndent" and "editor.autoIndent".
*
* @param preferenceName the preferenceName which might have been created via {@link PreferenceService.overridePreferenceName}.
*
* @returns the OverridePreferenceName which was used to create the given `preferenceName` if this was the case,
* `undefined` otherwise.
*/
overriddenPreferenceName(preferenceName: string): OverridePreferenceName | undefined;

/**
* Retrieve the stored value for the given preference and resourceUri.
*
* @param preferenceName the preference identifier.
* @param defaultValue the value to return when no value for the given preference is stored.
* @param resourceUri the uri of the resource for which the preference is stored. This 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 when it exists,
* otherwise the given default value. If determinable the object will also contain the uri of the configuration
* resource in which the preference was stored.
*/
resolve<T>(preferenceName: string, defaultValue?: T, resourceUri?: string): PreferenceResolveResult<T>;
/**
* Returns the uri of the configuration resource for the given scope and optional resource uri.
*
* @param scope the PreferenceScope to query for.
* @param resourceUri the optional uri of the resource-specific preference handling
*
* @returns the uri of the configuration resource for the given scope and optional resource uri it it exists,
* `undefined` otherwise.
*/
getConfigUri(scope: PreferenceScope, resourceUri?: string): URI | undefined;
}

/**
* Return type of the {@link PreferenceService.inspect} call.
*/
export interface PreferenceInspection<T> {
/**
* The preference identifier.
*/
preferenceName: string,
/**
* Value in default scope.
*/
defaultValue: T | undefined,
/**
* Value in user scope.
*/
globalValue: T | undefined,
/**
* Value in workspace scope.
*/
workspaceValue: T | undefined,
/**
* Value in folder scope.
*/
workspaceFolderValue: T | undefined
}

/**
* We cannot load providers directly in the case if they depend on `PreferenceService` somehow.
* It allows to load them lazilly after DI is configured.
* It allows to load them lazily after DI is configured.
*/
export const PreferenceProviderProvider = Symbol('PreferenceProviderProvider');
export type PreferenceProviderProvider = (scope: PreferenceScope, uri?: URI) => PreferenceProvider;
Expand Down Expand Up @@ -233,10 +362,7 @@ export class PreferenceServiceImpl implements PreferenceService {
return this.resolve<T>(preferenceName, defaultValue, resourceUri).value;
}

resolve<T>(preferenceName: string, defaultValue?: T, resourceUri?: string): {
configUri?: URI,
value?: T
} {
resolve<T>(preferenceName: string, defaultValue?: T, resourceUri?: string): PreferenceResolveResult<T> {
const { value, configUri } = this.doResolve(preferenceName, defaultValue, resourceUri);
if (value === undefined) {
const overridden = this.overriddenPreferenceName(preferenceName);
Expand Down
Loading

0 comments on commit 7c03a68

Please sign in to comment.