@@ -12,6 +12,8 @@ import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper';
12
12
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility' ;
13
13
import { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry' ;
14
14
import { IJSONSchema } from 'vs/base/common/jsonSchema' ;
15
+ import * as arrays from 'vs/base/common/arrays' ;
16
+ import * as objects from 'vs/base/common/objects' ;
15
17
16
18
//#region typed options
17
19
@@ -806,6 +808,11 @@ export interface IEditorOption<K1 extends EditorOption, V> {
806
808
* @internal
807
809
*/
808
810
compute ( env : IEnvironmentalOptions , options : IComputedEditorOptions , value : V ) : V ;
811
+
812
+ /**
813
+ * Might modify `value`.
814
+ */
815
+ applyUpdate ( value : V , update : V ) : ApplyUpdateResult < V > ;
809
816
}
810
817
811
818
type PossibleKeyName0 < V > = { [ K in keyof IEditorOptions ] : IEditorOptions [ K ] extends V | undefined ? K : never } [ keyof IEditorOptions ] ;
@@ -828,13 +835,45 @@ abstract class BaseEditorOption<K1 extends EditorOption, V> implements IEditorOp
828
835
this . schema = schema ;
829
836
}
830
837
838
+ public applyUpdate ( value : V , update : V ) : ApplyUpdateResult < V > {
839
+ return applyUpdate ( value , update ) ;
840
+ }
841
+
831
842
public abstract validate ( input : any ) : V ;
832
843
833
844
public compute ( env : IEnvironmentalOptions , options : IComputedEditorOptions , value : V ) : V {
834
845
return value ;
835
846
}
836
847
}
837
848
849
+ export class ApplyUpdateResult < T > {
850
+ constructor (
851
+ public readonly newValue : T ,
852
+ public readonly didChange : boolean
853
+ ) { }
854
+ }
855
+
856
+ function applyUpdate < T > ( value : T , update : T ) : ApplyUpdateResult < T > {
857
+ if ( typeof value !== 'object' || typeof update !== 'object' || ! value || ! update ) {
858
+ return new ApplyUpdateResult ( update , value !== update ) ;
859
+ }
860
+ if ( Array . isArray ( value ) || Array . isArray ( update ) ) {
861
+ const arrayEquals = Array . isArray ( value ) && Array . isArray ( update ) && arrays . equals ( value , update ) ;
862
+ return new ApplyUpdateResult ( update , arrayEquals ) ;
863
+ }
864
+ let didChange = false ;
865
+ for ( let key in update ) {
866
+ if ( ( update as T & object ) . hasOwnProperty ( key ) ) {
867
+ const result = applyUpdate ( value [ key ] , update [ key ] ) ;
868
+ if ( result . didChange ) {
869
+ value [ key ] = result . newValue ;
870
+ didChange = true ;
871
+ }
872
+ }
873
+ }
874
+ return new ApplyUpdateResult ( value , didChange ) ;
875
+ }
876
+
838
877
/**
839
878
* @internal
840
879
*/
@@ -853,6 +892,10 @@ abstract class ComputedEditorOption<K1 extends EditorOption, V> implements IEdit
853
892
this . deps = deps ;
854
893
}
855
894
895
+ public applyUpdate ( value : V , update : V ) : ApplyUpdateResult < V > {
896
+ return applyUpdate ( value , update ) ;
897
+ }
898
+
856
899
public validate ( input : any ) : V {
857
900
return this . defaultValue ;
858
901
}
@@ -874,6 +917,10 @@ class SimpleEditorOption<K1 extends EditorOption, V> implements IEditorOption<K1
874
917
this . schema = schema ;
875
918
}
876
919
920
+ public applyUpdate ( value : V , update : V ) : ApplyUpdateResult < V > {
921
+ return applyUpdate ( value , update ) ;
922
+ }
923
+
877
924
public validate ( input : any ) : V {
878
925
if ( typeof input === 'undefined' ) {
879
926
return this . defaultValue ;
@@ -3265,9 +3312,9 @@ export interface IUnicodeHighlightOptions {
3265
3312
ambiguousCharacters ?: boolean ;
3266
3313
includeComments ?: boolean | InUntrustedWorkspace ;
3267
3314
/**
3268
- * A list of allowed code points in a single string .
3315
+ * A map of allowed characters (true: allowed) .
3269
3316
*/
3270
- allowedCharacters ?: string ;
3317
+ allowedCharacters ?: Record < string , true > ;
3271
3318
}
3272
3319
3273
3320
/**
@@ -3293,7 +3340,7 @@ class UnicodeHighlight extends BaseEditorOption<EditorOption.unicodeHighlighting
3293
3340
invisibleCharacters : true ,
3294
3341
ambiguousCharacters : true ,
3295
3342
includeComments : inUntrustedWorkspace ,
3296
- allowedCharacters : '' ,
3343
+ allowedCharacters : { } ,
3297
3344
} ;
3298
3345
3299
3346
super (
@@ -3327,14 +3374,34 @@ class UnicodeHighlight extends BaseEditorOption<EditorOption.unicodeHighlighting
3327
3374
} ,
3328
3375
[ unicodeHighlightConfigKeys . allowedCharacters ] : {
3329
3376
restricted : true ,
3330
- type : 'string ' ,
3377
+ type : 'object ' ,
3331
3378
default : defaults . allowedCharacters ,
3332
- description : nls . localize ( 'unicodeHighlight.allowedCharacters' , "Defines allowed characters that are not being highlighted." )
3379
+ description : nls . localize ( 'unicodeHighlight.allowedCharacters' , "Defines allowed characters that are not being highlighted." ) ,
3380
+ additionalProperties : {
3381
+ type : 'boolean'
3382
+ }
3333
3383
} ,
3334
3384
}
3335
3385
) ;
3336
3386
}
3337
3387
3388
+ public override applyUpdate ( value : Required < Readonly < IUnicodeHighlightOptions > > , update : Required < Readonly < IUnicodeHighlightOptions > > ) : ApplyUpdateResult < Required < Readonly < IUnicodeHighlightOptions > > > {
3389
+ let didChange = false ;
3390
+ if ( update . allowedCharacters ) {
3391
+ // Treat allowedCharacters atomically
3392
+ if ( ! objects . equals ( value . allowedCharacters , update . allowedCharacters ) ) {
3393
+ value = { ...value , allowedCharacters : update . allowedCharacters } ;
3394
+ didChange = true ;
3395
+ }
3396
+ }
3397
+
3398
+ const result = super . applyUpdate ( value , update ) ;
3399
+ if ( didChange ) {
3400
+ return new ApplyUpdateResult ( result . newValue , true ) ;
3401
+ }
3402
+ return result ;
3403
+ }
3404
+
3338
3405
public validate ( _input : any ) : InternalUnicodeHighlightOptions {
3339
3406
if ( ! _input || typeof _input !== 'object' ) {
3340
3407
return this . defaultValue ;
@@ -3345,16 +3412,22 @@ class UnicodeHighlight extends BaseEditorOption<EditorOption.unicodeHighlighting
3345
3412
invisibleCharacters : boolean ( input . invisibleCharacters , this . defaultValue . invisibleCharacters ) ,
3346
3413
ambiguousCharacters : boolean ( input . ambiguousCharacters , this . defaultValue . ambiguousCharacters ) ,
3347
3414
includeComments : primitiveSet < boolean | InUntrustedWorkspace > ( input . includeComments , inUntrustedWorkspace , [ true , false , inUntrustedWorkspace ] ) ,
3348
- allowedCharacters : string ( input . allowedCharacters , '' ) ,
3415
+ allowedCharacters : this . validateAllowedCharacters ( _input . allowedCharacters , this . defaultValue . allowedCharacters ) ,
3349
3416
} ;
3350
3417
}
3351
- }
3352
3418
3353
- function string ( value : unknown , defaultValue : string ) : string {
3354
- if ( typeof value !== 'string' ) {
3355
- return defaultValue ;
3419
+ private validateAllowedCharacters ( map : unknown , defaultValue : Record < string , true > ) : Record < string , true > {
3420
+ if ( ( typeof map !== 'object' ) || ! map ) {
3421
+ return defaultValue ;
3422
+ }
3423
+ const result : Record < string , true > = { } ;
3424
+ for ( const [ key , value ] of Object . entries ( map ) ) {
3425
+ if ( value === true ) {
3426
+ result [ key ] = true ;
3427
+ }
3428
+ }
3429
+ return result ;
3356
3430
}
3357
- return value ;
3358
3431
}
3359
3432
3360
3433
//#endregion
0 commit comments