33/* @internal */
44namespace ts . formatting {
55 export class RulesMap {
6+ // This array is used during construction & updating of the rules buckets in the map
7+ private rulesBucketConstructionStateList : RulesBucketConstructionState [ ] ;
8+ private readonly lowPriorityCommonRules : Rule [ ] ;
9+
610 public map : RulesBucket [ ] ;
711 public mapRowLength : number ;
812
9- constructor ( ) {
13+ constructor ( lowPriorityCommonRules : Rule [ ] ) {
1014 this . map = [ ] ;
1115 this . mapRowLength = 0 ;
16+ this . lowPriorityCommonRules = lowPriorityCommonRules ;
1217 }
1318
14- static create ( rules : Rule [ ] ) : RulesMap {
15- const result = new RulesMap ( ) ;
16- result . Initialize ( rules ) ;
19+ static create ( highPriorityCommonRules : Rule [ ] , lowPriorityCommonRules : Rule [ ] ) : RulesMap {
20+ const result = new RulesMap ( lowPriorityCommonRules ) ;
21+ result . Initialize ( highPriorityCommonRules ) ;
1722 return result ;
1823 }
1924
25+ public Update ( oldRules : Rule [ ] , newRules : Rule [ ] ) : void {
26+ const addRules = filter ( newRules , r => oldRules . indexOf ( r ) < 0 ) ;
27+ const deleteRules = filter ( oldRules , r => newRules . indexOf ( r ) < 0 ) ;
28+
29+ if ( addRules . length === 0 && deleteRules . length === 0 ) {
30+ return ;
31+ }
32+
33+ this . RemoveRules ( deleteRules . concat ( this . lowPriorityCommonRules ) ) ;
34+ this . FillRules ( addRules . concat ( this . lowPriorityCommonRules ) ) ;
35+ }
36+
2037 public Initialize ( rules : Rule [ ] ) {
2138 this . mapRowLength = SyntaxKind . LastToken + 1 ;
2239 this . map = < any > new Array ( this . mapRowLength * this . mapRowLength ) ; // new Array<RulesBucket>(this.mapRowLength * this.mapRowLength);
40+ this . rulesBucketConstructionStateList = new Array ( this . map . length ) ; // new Array<RulesBucketConstructionState>(this.map.length);
2341
24- // This array is used only during construction of the rulesbucket in the map
25- const rulesBucketConstructionStateList : RulesBucketConstructionState [ ] = < any > new Array ( this . map . length ) ; // new Array<RulesBucketConstructionState>(this.map.length);
26-
27- this . FillRules ( rules , rulesBucketConstructionStateList ) ;
42+ this . FillRules ( rules ) ;
2843 return this . map ;
2944 }
3045
31- public FillRules ( rules : Rule [ ] , rulesBucketConstructionStateList : RulesBucketConstructionState [ ] ) : void {
46+ public FillRules ( rules : Rule [ ] ) : void {
47+ rules . forEach ( ( rule ) => {
48+ this . AddOrRemoveRule ( rule , RulesAction . Add ) ;
49+ } ) ;
50+ }
51+
52+ public RemoveRules ( rules : Rule [ ] ) : void {
3253 rules . forEach ( ( rule ) => {
33- this . FillRule ( rule , rulesBucketConstructionStateList ) ;
54+ this . AddOrRemoveRule ( rule , RulesAction . Remove ) ;
3455 } ) ;
3556 }
3657
@@ -40,7 +61,7 @@ namespace ts.formatting {
4061 return rulesBucketIndex ;
4162 }
4263
43- private FillRule ( rule : Rule , rulesBucketConstructionStateList : RulesBucketConstructionState [ ] ) : void {
64+ private AddOrRemoveRule ( rule : Rule , action : RulesAction ) : void {
4465 const specificRule = rule . Descriptor . LeftTokenRange !== Shared . TokenRange . Any &&
4566 rule . Descriptor . RightTokenRange !== Shared . TokenRange . Any ;
4667
@@ -49,11 +70,19 @@ namespace ts.formatting {
4970 const rulesBucketIndex = this . GetRuleBucketIndex ( left , right ) ;
5071
5172 let rulesBucket = this . map [ rulesBucketIndex ] ;
52- if ( rulesBucket === undefined ) {
53- rulesBucket = this . map [ rulesBucketIndex ] = new RulesBucket ( ) ;
73+ if ( action === RulesAction . Add ) {
74+ if ( rulesBucket === undefined ) {
75+ rulesBucket = this . map [ rulesBucketIndex ] = new RulesBucket ( ) ;
76+ }
77+ rulesBucket . AddRule ( rule , specificRule , this . rulesBucketConstructionStateList , rulesBucketIndex ) ;
78+ }
79+ else {
80+ if ( rulesBucket === undefined ) {
81+ // The rules bucket does not exist for this rule
82+ return ;
83+ }
84+ rulesBucket . RemoveRule ( rule , specificRule , this . rulesBucketConstructionStateList , rulesBucketIndex ) ;
5485 }
55-
56- rulesBucket . AddRule ( rule , specificRule , rulesBucketConstructionStateList , rulesBucketIndex ) ;
5786 } ) ;
5887 } ) ;
5988 }
@@ -75,6 +104,11 @@ namespace ts.formatting {
75104 const MaskBitSize = 5 ;
76105 const Mask = 0x1f ;
77106
107+ enum RulesAction {
108+ Add ,
109+ Remove
110+ }
111+
78112 export enum RulesPosition {
79113 IgnoreRulesSpecific = 0 ,
80114 IgnoreRulesAny = MaskBitSize * 1 ,
@@ -121,10 +155,17 @@ namespace ts.formatting {
121155 return index ;
122156 }
123157
124- public IncreaseInsertionIndex ( maskPosition : RulesPosition ) : void {
158+ public SetInsertionIndex ( maskPosition : RulesPosition , action : RulesAction ) : void {
125159 let value = ( this . rulesInsertionIndexBitmap >> maskPosition ) & Mask ;
126- value ++ ;
127- Debug . assert ( ( value & Mask ) === value , "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules." ) ;
160+
161+ if ( action === RulesAction . Add ) {
162+ value ++ ;
163+ Debug . assert ( ( value & Mask ) === value , "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules." ) ;
164+ }
165+ else {
166+ value -- ;
167+ Debug . assert ( value >= 0 , "Index should never be less than 0." ) ;
168+ }
128169
129170 let temp = this . rulesInsertionIndexBitmap & ~ ( Mask << maskPosition ) ;
130171 temp |= value << maskPosition ;
@@ -145,6 +186,30 @@ namespace ts.formatting {
145186 }
146187
147188 public AddRule ( rule : Rule , specificTokens : boolean , constructionState : RulesBucketConstructionState [ ] , rulesBucketIndex : number ) : void {
189+ const position = this . GetMaskPosition ( rule , specificTokens ) ;
190+ let state = constructionState [ rulesBucketIndex ] ;
191+ if ( state === undefined ) {
192+ state = constructionState [ rulesBucketIndex ] = new RulesBucketConstructionState ( ) ;
193+ }
194+ const index = state . GetInsertionIndex ( position ) ;
195+ this . rules . splice ( index , 0 , rule ) ;
196+ state . SetInsertionIndex ( position , RulesAction . Add ) ;
197+ }
198+
199+ public RemoveRule ( rule : Rule , specificTokens : boolean , constructionState : RulesBucketConstructionState [ ] , rulesBucketIndex : number ) : void {
200+ const position = this . GetMaskPosition ( rule , specificTokens ) ;
201+ const state = constructionState [ rulesBucketIndex ] ;
202+ if ( state === undefined ) {
203+ return ;
204+ }
205+ const index = this . rules . indexOf ( rule ) ;
206+ if ( index > - 1 ) {
207+ this . rules . splice ( index , 1 ) ;
208+ state . SetInsertionIndex ( position , RulesAction . Remove ) ;
209+ }
210+ }
211+
212+ private GetMaskPosition ( rule : Rule , specificTokens : boolean ) : RulesPosition {
148213 let position : RulesPosition ;
149214
150215 if ( rule . Operation . Action === RuleAction . Ignore ) {
@@ -163,13 +228,7 @@ namespace ts.formatting {
163228 RulesPosition . NoContextRulesAny ;
164229 }
165230
166- let state = constructionState [ rulesBucketIndex ] ;
167- if ( state === undefined ) {
168- state = constructionState [ rulesBucketIndex ] = new RulesBucketConstructionState ( ) ;
169- }
170- const index = state . GetInsertionIndex ( position ) ;
171- this . rules . splice ( index , 0 , rule ) ;
172- state . IncreaseInsertionIndex ( position ) ;
231+ return position ;
173232 }
174233 }
175234}
0 commit comments