@@ -82,61 +82,14 @@ export class CollectionItemTextualScopeHandler extends BaseScopeHandler {
8282 direction : Direction ,
8383 hints : ScopeIteratorRequirements ,
8484 ) : Iterable < TargetScope > {
85- const { document } = editor ;
8685 const isEveryScope = hints . containment == null && hints . skipAncestorScopes ;
87- const separatorRanges = getSeparatorOccurrences ( document ) ;
88-
86+ const separatorRanges = getSeparatorOccurrences ( editor . document ) ;
8987 const interiorRanges = this . getInteriorRanges ( editor , "collectionBoundary" ) ;
9088 const stringRanges = this . getInteriorRanges ( editor , "string" ) ;
91-
9289 const scopes : TargetScope [ ] = [ ] ;
9390 const usedInteriors = new Set < Range > ( ) ;
9491 const iterationStatesStack : IterationState [ ] = [ ] ;
9592
96- function addScopes ( state : IterationState ) {
97- const { delimiters, iterationRange : iterationRange } = state ;
98-
99- if ( delimiters . length === 0 ) {
100- return ;
101- }
102-
103- const itemRanges : Range [ ] = [ ] ;
104-
105- for ( let i = 0 ; i < delimiters . length ; ++ i ) {
106- const current = delimiters [ i ] ;
107-
108- const previous = delimiters [ i - 1 ] ?. end ?? iterationRange . start ;
109- itemRanges . push ( new Range ( previous , current . start ) ) ;
110- }
111-
112- const lastDelimiter = delimiters [ delimiters . length - 1 ] ;
113- itemRanges . push ( new Range ( lastDelimiter . end , iterationRange . end ) ) ;
114-
115- const trimmedRanges = itemRanges . map ( ( range ) =>
116- shrinkRangeToFitContent ( editor , range ) ,
117- ) ;
118-
119- for ( let i = 0 ; i < trimmedRanges . length ; ++ i ) {
120- // Handle trailing delimiter
121- if (
122- i === trimmedRanges . length - 1 &&
123- document . getText ( trimmedRanges [ i ] ) . trim ( ) === ""
124- ) {
125- continue ;
126- }
127- scopes . push (
128- createTargetScope (
129- isEveryScope ,
130- editor ,
131- iterationRange ,
132- trimmedRanges [ i ] ,
133- trimmedRanges [ i - 1 ] ,
134- trimmedRanges [ i + 1 ] ,
135- ) ,
136- ) ;
137- }
138- }
139-
14093 // TODO: fixed performance on large files
14194 for ( const separator of separatorRanges ) {
14295 // Separators in a string are not considered
@@ -154,7 +107,8 @@ export class CollectionItemTextualScopeHandler extends BaseScopeHandler {
154107
155108 // The contain range is either the interior or the line containing the separator
156109 const containingIterationRange =
157- containingInteriorRange ?? document . lineAt ( separator . start . line ) . range ;
110+ containingInteriorRange ??
111+ editor . document . lineAt ( separator . start . line ) . range ;
158112
159113 if ( currentIterationState != null ) {
160114 // The current containing iteration range is the same as the previous one. Just append delimiter.
@@ -169,7 +123,7 @@ export class CollectionItemTextualScopeHandler extends BaseScopeHandler {
169123
170124 // The current containing range does not intersect previous one. Add scopes and remove state.
171125 if ( ! currentIterationState . iterationRange . contains ( separator ) ) {
172- addScopes ( currentIterationState ) ;
126+ this . addScopes ( scopes , currentIterationState ) ;
173127 // Remove already added state
174128 iterationStatesStack . pop ( ) ;
175129 }
@@ -188,13 +142,15 @@ export class CollectionItemTextualScopeHandler extends BaseScopeHandler {
188142 usedInteriors . add ( containingInteriorRange ) ;
189143
190144 iterationStatesStack . push ( {
145+ editor,
146+ isEveryScope,
191147 iterationRange : containingIterationRange ,
192148 delimiters : [ separator ] ,
193149 } ) ;
194150 }
195151
196152 for ( const state of iterationStatesStack ) {
197- addScopes ( state ) ;
153+ this . addScopes ( scopes , state ) ;
198154 }
199155
200156 // Add interior ranges without a delimiter in them. eg: `[foo]`
@@ -211,9 +167,55 @@ export class CollectionItemTextualScopeHandler extends BaseScopeHandler {
211167
212168 yield * scopes ;
213169 }
170+
171+ private addScopes ( scopes : TargetScope [ ] , state : IterationState ) {
172+ const { editor, iterationRange, isEveryScope, delimiters } = state ;
173+
174+ if ( delimiters . length === 0 ) {
175+ return ;
176+ }
177+
178+ const itemRanges : Range [ ] = [ ] ;
179+
180+ for ( let i = 0 ; i < delimiters . length ; ++ i ) {
181+ const current = delimiters [ i ] ;
182+
183+ const previous = delimiters [ i - 1 ] ?. end ?? iterationRange . start ;
184+ itemRanges . push ( new Range ( previous , current . start ) ) ;
185+ }
186+
187+ const lastDelimiter = delimiters [ delimiters . length - 1 ] ;
188+ itemRanges . push ( new Range ( lastDelimiter . end , iterationRange . end ) ) ;
189+
190+ const trimmedRanges = itemRanges . map ( ( range ) =>
191+ shrinkRangeToFitContent ( editor , range ) ,
192+ ) ;
193+
194+ for ( let i = 0 ; i < trimmedRanges . length ; ++ i ) {
195+ // Handle trailing delimiter
196+ if (
197+ i === trimmedRanges . length - 1 &&
198+ editor . document . getText ( trimmedRanges [ i ] ) . trim ( ) === ""
199+ ) {
200+ continue ;
201+ }
202+ scopes . push (
203+ createTargetScope (
204+ isEveryScope ,
205+ editor ,
206+ iterationRange ,
207+ trimmedRanges [ i ] ,
208+ trimmedRanges [ i - 1 ] ,
209+ trimmedRanges [ i + 1 ] ,
210+ ) ,
211+ ) ;
212+ }
213+ }
214214}
215215
216216interface IterationState {
217+ editor : TextEditor ;
217218 iterationRange : Range ;
219+ isEveryScope : boolean ;
218220 delimiters : Range [ ] ;
219221}
0 commit comments