mirror of
https://github.com/microsoft/vscode.git
synced 2026-10-07 09:50:12 +01:00
Allows editor options to override how new config updates are applied.
This commit is contained in:
4 files changed
+84
-33
No files matched your search
@@ -112,12 +112,15 @@ class EditorConfiguration2 {
|
||||
}
|
||||
|
||||
private static _deepEquals<T>(a: T, b: T): boolean {
|
||||
if (typeof a !== 'object' || typeof b !== 'object') {
|
||||
return (a === b);
|
||||
if (typeof a !== 'object' || typeof b !== 'object' || !a || !b) {
|
||||
return a === b;
|
||||
}
|
||||
if (Array.isArray(a) || Array.isArray(b)) {
|
||||
return (Array.isArray(a) && Array.isArray(b) ? arrays.equals(a, b) : false);
|
||||
}
|
||||
if (Object.keys(a).length !== Object.keys(b).length) {
|
||||
return false;
|
||||
}
|
||||
for (let key in a) {
|
||||
if (!EditorConfiguration2._deepEquals(a[key], b[key])) {
|
||||
return false;
|
||||
@@ -138,6 +141,22 @@ class EditorConfiguration2 {
|
||||
}
|
||||
return (somethingChanged ? new ConfigurationChangedEvent(result) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if something changed.
|
||||
* Modifies `options`.
|
||||
*/
|
||||
public static applyUpdate(options: IEditorOptions, update: Readonly<IEditorOptions>): boolean {
|
||||
let changed = false;
|
||||
for (const editorOption of editorOptionsRegistry) {
|
||||
if (update.hasOwnProperty(editorOption.name)) {
|
||||
const result = editorOption.applyUpdate((options as any)[editorOption.name], (update as any)[editorOption.name]);
|
||||
(options as any)[editorOption.name] = result.newValue;
|
||||
changed = changed || result.didChange;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,43 +401,17 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
||||
return EditorConfiguration2.computeOptions(this._validatedOptions, env);
|
||||
}
|
||||
|
||||
private static _subsetEquals(base: { [key: string]: any }, subset: { [key: string]: any }): boolean {
|
||||
for (const key in subset) {
|
||||
if (hasOwnProperty.call(subset, key)) {
|
||||
const subsetValue = subset[key];
|
||||
const baseValue = base[key];
|
||||
|
||||
if (baseValue === subsetValue) {
|
||||
continue;
|
||||
}
|
||||
if (Array.isArray(baseValue) && Array.isArray(subsetValue)) {
|
||||
if (!arrays.equals(baseValue, subsetValue)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (baseValue && typeof baseValue === 'object' && subsetValue && typeof subsetValue === 'object') {
|
||||
if (!this._subsetEquals(baseValue, subsetValue)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public updateOptions(_newOptions: Readonly<IEditorOptions>): void {
|
||||
if (typeof _newOptions === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const newOptions = deepCloneAndMigrateOptions(_newOptions);
|
||||
if (CommonEditorConfiguration._subsetEquals(this._rawOptions, newOptions)) {
|
||||
|
||||
const didChange = EditorConfiguration2.applyUpdate(this._rawOptions, newOptions);
|
||||
if (!didChange) {
|
||||
return;
|
||||
}
|
||||
this._rawOptions = objects.mixin(this._rawOptions, newOptions || {});
|
||||
|
||||
this._readOptions = EditorConfiguration2.readOptions(this._rawOptions);
|
||||
this._validatedOptions = EditorConfiguration2.validateOptions(this._readOptions);
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper';
|
||||
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
|
||||
//#region typed options
|
||||
|
||||
@@ -806,6 +808,11 @@ export interface IEditorOption<K1 extends EditorOption, V> {
|
||||
* @internal
|
||||
*/
|
||||
compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V;
|
||||
|
||||
/**
|
||||
* Might modify `value`.
|
||||
*/
|
||||
applyUpdate(value: V, update: V): ApplyUpdateResult<V>;
|
||||
}
|
||||
|
||||
type PossibleKeyName0<V> = { [K in keyof IEditorOptions]: IEditorOptions[K] extends V | undefined ? K : never }[keyof IEditorOptions];
|
||||
@@ -828,6 +835,10 @@ abstract class BaseEditorOption<K1 extends EditorOption, V> implements IEditorOp
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
public applyUpdate(value: V, update: V): ApplyUpdateResult<V> {
|
||||
return applyUpdate(value, update);
|
||||
}
|
||||
|
||||
public abstract validate(input: any): V;
|
||||
|
||||
public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, value: V): V {
|
||||
@@ -835,6 +846,34 @@ abstract class BaseEditorOption<K1 extends EditorOption, V> implements IEditorOp
|
||||
}
|
||||
}
|
||||
|
||||
export class ApplyUpdateResult<T> {
|
||||
constructor(
|
||||
public readonly newValue: T,
|
||||
public readonly didChange: boolean
|
||||
) { }
|
||||
}
|
||||
|
||||
function applyUpdate<T>(value: T, update: T): ApplyUpdateResult<T> {
|
||||
if (typeof value !== 'object' || typeof update !== 'object') {
|
||||
return new ApplyUpdateResult(update, value === update);
|
||||
}
|
||||
if (Array.isArray(value) || Array.isArray(update)) {
|
||||
const arrayEquals = Array.isArray(value) && Array.isArray(update) && arrays.equals(value, update);
|
||||
return new ApplyUpdateResult(update, arrayEquals);
|
||||
}
|
||||
let didChange = false;
|
||||
for (let key in update) {
|
||||
if ((value as T & object).hasOwnProperty(key)) {
|
||||
const result = applyUpdate(value[key], update[key]);
|
||||
if (result.didChange) {
|
||||
value[key] = result.newValue;
|
||||
didChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ApplyUpdateResult(value, didChange);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -853,6 +892,10 @@ abstract class ComputedEditorOption<K1 extends EditorOption, V> implements IEdit
|
||||
this.deps = deps;
|
||||
}
|
||||
|
||||
public applyUpdate(value: V, update: V): ApplyUpdateResult<V> {
|
||||
return applyUpdate(value, update);
|
||||
}
|
||||
|
||||
public validate(input: any): V {
|
||||
return this.defaultValue;
|
||||
}
|
||||
@@ -874,6 +917,10 @@ class SimpleEditorOption<K1 extends EditorOption, V> implements IEditorOption<K1
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
public applyUpdate(value: V, update: V): ApplyUpdateResult<V> {
|
||||
return applyUpdate(value, update);
|
||||
}
|
||||
|
||||
public validate(input: any): V {
|
||||
if (typeof input === 'undefined') {
|
||||
return this.defaultValue;
|
||||
|
||||
@@ -10,7 +10,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { OpenerService } from 'vs/editor/browser/services/openerService';
|
||||
import { DiffNavigator, IDiffNavigator } from 'vs/editor/browser/widget/diffNavigator';
|
||||
import { EditorOptions, ConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
|
||||
import { EditorOptions, ConfigurationChangedEvent, ApplyUpdateResult } from 'vs/editor/common/config/editorOptions';
|
||||
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
import { Token } from 'vs/editor/common/core/token';
|
||||
import { IEditor, EditorType } from 'vs/editor/common/editorCommon';
|
||||
@@ -393,6 +393,7 @@ export function createMonacoEditorAPI(): typeof monaco.editor {
|
||||
FontInfo: <any>FontInfo,
|
||||
TextModelResolvedOptions: <any>TextModelResolvedOptions,
|
||||
FindMatch: <any>FindMatch,
|
||||
ApplyUpdateResult: <any>ApplyUpdateResult,
|
||||
|
||||
// vars
|
||||
EditorType: EditorType,
|
||||
|
||||
Vendored
+10
@@ -3378,6 +3378,16 @@ declare namespace monaco.editor {
|
||||
readonly id: K1;
|
||||
readonly name: string;
|
||||
defaultValue: V;
|
||||
/**
|
||||
* Might modify `value`.
|
||||
*/
|
||||
applyUpdate(value: V, update: V): ApplyUpdateResult<V>;
|
||||
}
|
||||
|
||||
export class ApplyUpdateResult<T> {
|
||||
readonly newValue: T;
|
||||
readonly didChange: boolean;
|
||||
constructor(newValue: T, didChange: boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user