@@ -13,6 +13,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
13
13
import { Range } from 'vs/editor/common/core/range' ;
14
14
import { Emitter } from 'vs/base/common/event' ;
15
15
import { binarySearch } from 'vs/base/common/arrays' ;
16
+ import { Iterable } from 'vs/base/common/iterator' ;
16
17
import { FoldingController } from 'vs/editor/contrib/folding/browser/folding' ;
17
18
import { FoldingModel } from 'vs/editor/contrib/folding/browser/foldingModel' ;
18
19
@@ -44,6 +45,7 @@ export class StickyLineCandidateProvider extends Disposable {
44
45
private _outlineModel : StickyOutlineElement | undefined ;
45
46
private readonly _sessionStore : DisposableStore = new DisposableStore ( ) ;
46
47
private _modelVersionId : number = 0 ;
48
+ private _providerID : string | undefined = undefined ;
47
49
48
50
constructor (
49
51
editor : ICodeEditor ,
@@ -67,10 +69,16 @@ export class StickyLineCandidateProvider extends Disposable {
67
69
this . _sessionStore . clear ( ) ;
68
70
return ;
69
71
} else {
70
- this . _sessionStore . add ( this . _editor . onDidChangeModel ( ( ) => this . update ( ) ) ) ;
72
+ this . _sessionStore . add ( this . _editor . onDidChangeModel ( ( ) => {
73
+ this . _providerID = undefined ;
74
+ this . update ( ) ;
75
+ } ) ) ;
71
76
this . _sessionStore . add ( this . _editor . onDidChangeHiddenAreas ( ( ) => this . update ( ) ) ) ;
72
77
this . _sessionStore . add ( this . _editor . onDidChangeModelContent ( ( ) => this . _updateSoon . schedule ( ) ) ) ;
73
- this . _sessionStore . add ( this . _languageFeaturesService . documentSymbolProvider . onDidChange ( ( ) => this . update ( ) ) ) ;
78
+ this . _sessionStore . add ( this . _languageFeaturesService . documentSymbolProvider . onDidChange ( ( ) => {
79
+ this . _providerID = undefined ;
80
+ this . update ( ) ;
81
+ } ) ) ;
74
82
this . update ( ) ;
75
83
}
76
84
}
@@ -95,7 +103,9 @@ export class StickyLineCandidateProvider extends Disposable {
95
103
return ;
96
104
}
97
105
if ( outlineModel . children . size !== 0 ) {
98
- this . _outlineModel = StickyOutlineElement . fromOutlineModel ( outlineModel , - 1 ) ;
106
+ const { stickyOutlineElement, providerID } = StickyOutlineElement . fromOutlineModel ( outlineModel , this . _providerID ) ;
107
+ this . _outlineModel = stickyOutlineElement ;
108
+ this . _providerID = providerID ;
99
109
} else {
100
110
const foldingController = FoldingController . get ( this . _editor ) ;
101
111
const foldingModel = await foldingController ?. getFoldingModel ( ) ;
@@ -177,18 +187,16 @@ export class StickyLineCandidateProvider extends Disposable {
177
187
}
178
188
179
189
class StickyOutlineElement {
180
- public static fromOutlineModel ( outlineModel : OutlineModel | OutlineElement | OutlineGroup , previousStartLine : number ) : StickyOutlineElement {
181
190
191
+ public static fromOutlineElement ( outlineElement : OutlineElement , previousStartLine : number ) : StickyOutlineElement {
182
192
const children : StickyOutlineElement [ ] = [ ] ;
183
- for ( const child of outlineModel . children . values ( ) ) {
184
- if ( child instanceof OutlineGroup || child instanceof OutlineModel ) {
185
- children . push ( StickyOutlineElement . fromOutlineModel ( child , previousStartLine ) ) ;
186
- } else if ( child instanceof OutlineElement && child . symbol . selectionRange . startLineNumber !== child . symbol . range . endLineNumber ) {
193
+ for ( const child of outlineElement . children . values ( ) ) {
194
+ if ( child . symbol . selectionRange . startLineNumber !== child . symbol . range . endLineNumber ) {
187
195
if ( child . symbol . selectionRange . startLineNumber !== previousStartLine ) {
188
- children . push ( StickyOutlineElement . fromOutlineModel ( child , child . symbol . selectionRange . startLineNumber ) ) ;
196
+ children . push ( StickyOutlineElement . fromOutlineElement ( child , child . symbol . selectionRange . startLineNumber ) ) ;
189
197
} else {
190
198
for ( const subchild of child . children . values ( ) ) {
191
- children . push ( StickyOutlineElement . fromOutlineModel ( subchild , child . symbol . selectionRange . startLineNumber ) ) ;
199
+ children . push ( StickyOutlineElement . fromOutlineElement ( subchild , child . symbol . selectionRange . startLineNumber ) ) ;
192
200
}
193
201
}
194
202
}
@@ -202,17 +210,59 @@ class StickyOutlineElement {
202
210
return child2 . range . endLineNumber - child1 . range . endLineNumber ;
203
211
}
204
212
} ) ;
205
- let range : StickyRange | undefined ;
206
- if ( outlineModel instanceof OutlineElement ) {
207
- range = new StickyRange ( outlineModel . symbol . selectionRange . startLineNumber , outlineModel . symbol . range . endLineNumber ) ;
213
+ const range = new StickyRange ( outlineElement . symbol . selectionRange . startLineNumber , outlineElement . symbol . range . endLineNumber ) ;
214
+ return new StickyOutlineElement ( range , children , undefined ) ;
215
+ }
216
+
217
+ public static fromOutlineModel ( outlineModel : OutlineModel , providerID : string | undefined ) : { stickyOutlineElement : StickyOutlineElement ; providerID : string | undefined } {
218
+
219
+ let ID : string | undefined = providerID ;
220
+ let outlineElements : Map < string , OutlineElement > ;
221
+ // When several possible outline providers
222
+ if ( Iterable . first ( outlineModel . children . values ( ) ) instanceof OutlineGroup ) {
223
+ const provider = Iterable . find ( outlineModel . children . values ( ) , outlineGroupOfModel => outlineGroupOfModel . id === providerID ) ;
224
+ if ( provider ) {
225
+ outlineElements = provider . children ;
226
+ } else {
227
+ let tempID = '' ;
228
+ let maxTotalSumOfRanges = 0 ;
229
+ let optimalOutlineGroup = undefined ;
230
+ for ( const [ _key , outlineGroup ] of outlineModel . children . entries ( ) ) {
231
+ const totalSumRanges = StickyOutlineElement . findSumOfRangesOfGroup ( outlineGroup ) ;
232
+ if ( totalSumRanges > maxTotalSumOfRanges ) {
233
+ optimalOutlineGroup = outlineGroup ;
234
+ maxTotalSumOfRanges = totalSumRanges ;
235
+ tempID = outlineGroup . id ;
236
+ }
237
+ }
238
+ ID = tempID ;
239
+ outlineElements = optimalOutlineGroup ! . children ;
240
+ }
208
241
} else {
209
- range = undefined ;
242
+ outlineElements = outlineModel . children as Map < string , OutlineElement > ;
243
+ }
244
+ const stickyChildren : StickyOutlineElement [ ] = [ ] ;
245
+ for ( const outlineElement of outlineElements . values ( ) ) {
246
+ stickyChildren . push ( StickyOutlineElement . fromOutlineElement ( outlineElement , outlineElement . symbol . selectionRange . startLineNumber ) ) ;
247
+ }
248
+ const stickyOutlineElement = new StickyOutlineElement ( undefined , stickyChildren , undefined ) ;
249
+
250
+ return {
251
+ stickyOutlineElement : stickyOutlineElement ,
252
+ providerID : ID
253
+ } ;
254
+ }
255
+
256
+ private static findSumOfRangesOfGroup ( outline : OutlineGroup | OutlineElement ) : number {
257
+ let res = 0 ;
258
+ for ( const child of outline . children . values ( ) ) {
259
+ res += this . findSumOfRangesOfGroup ( child ) ;
260
+ }
261
+ if ( outline instanceof OutlineElement ) {
262
+ return res + outline . symbol . range . endLineNumber - outline . symbol . selectionRange . startLineNumber ;
263
+ } else {
264
+ return res ;
210
265
}
211
- return new StickyOutlineElement (
212
- range ,
213
- children ,
214
- undefined
215
- ) ;
216
266
}
217
267
218
268
public static fromFoldingModel ( foldingModel : FoldingModel ) : StickyOutlineElement {
0 commit comments