@@ -71,14 +71,25 @@ export function formatSnapshot(
71
71
externalSymbolTable . set ( externalSymbol . symbol , externalSymbol ) ;
72
72
}
73
73
74
+ const enclosingRanges : { range : Range ; symbol : string } [ ] = [ ] ;
74
75
const symbolsWithDefinitions : Set < string > = new Set ( ) ;
76
+
75
77
for ( let occurrence of doc . occurrences ) {
76
78
const isDefinition = ( occurrence . symbol_roles & scip . SymbolRole . Definition ) > 0 ;
77
79
if ( isDefinition ) {
78
80
symbolsWithDefinitions . add ( occurrence . symbol ) ;
79
81
}
82
+
83
+ if ( occurrence . enclosing_range . length > 0 ) {
84
+ enclosingRanges . push ( {
85
+ range : Range . fromLsif ( occurrence . enclosing_range ) ,
86
+ symbol : occurrence . symbol ,
87
+ } ) ;
88
+ }
80
89
}
81
90
91
+ enclosingRanges . sort ( enclosingRangesByLine ) ;
92
+
82
93
const emittedDocstrings : Set < string > = new Set ( ) ;
83
94
const pushDoc = ( range : Range , symbol : string , isDefinition : boolean , isStartOfLine : boolean ) => {
84
95
// Only emit docstrings once
@@ -157,8 +168,33 @@ export function formatSnapshot(
157
168
out . push ( '\n' ) ;
158
169
} ;
159
170
171
+ const pushEnclosingRange = (
172
+ enclosingRange : {
173
+ range : Range ;
174
+ symbol : string ;
175
+ } ,
176
+ end : boolean = false
177
+ ) => {
178
+ if ( ! formatOptions . showRanges ) {
179
+ return ;
180
+ }
181
+
182
+ out . push ( commentSyntax ) ;
183
+ out . push ( ' ' . repeat ( Math . max ( 1 , enclosingRange . range . start . character - 1 ) ) ) ;
184
+ if ( end ) {
185
+ out . push ( '⌃ end ' ) ;
186
+ } else {
187
+ out . push ( '⌄ start ' ) ;
188
+ }
189
+ out . push ( 'enclosing_range ' ) ;
190
+ out . push ( enclosingRange . symbol ) ;
191
+ out . push ( '\n' ) ;
192
+ } ;
193
+
160
194
doc . occurrences . sort ( occurrencesByLine ) ;
161
195
let occurrenceIndex = 0 ;
196
+ const openEnclosingRanges = [ ] ;
197
+
162
198
for ( const [ lineNumber , line ] of input . lines . entries ( ) ) {
163
199
// Write 0,0 items ABOVE the first line.
164
200
// This is the only case where we would need to do this.
@@ -182,6 +218,26 @@ export function formatSnapshot(
182
218
}
183
219
}
184
220
221
+ // Check if any enclosing ranges start on this line
222
+ for ( let rangeIndex = 0 ; rangeIndex < enclosingRanges . length ; rangeIndex ++ ) {
223
+ const enclosingRange = enclosingRanges [ rangeIndex ] ;
224
+
225
+ if ( enclosingRange . range . start . line == lineNumber ) {
226
+ // Switch the range to the open list
227
+ enclosingRanges . splice ( rangeIndex , 1 ) ;
228
+ openEnclosingRanges . push ( enclosingRange ) ;
229
+
230
+ // Decrement the counter as an item was removed
231
+ rangeIndex -= 1 ;
232
+
233
+ pushEnclosingRange ( enclosingRange ) ;
234
+
235
+ continue ;
236
+ }
237
+
238
+ break ;
239
+ }
240
+
185
241
out . push ( '' ) ;
186
242
out . push ( line ) ;
187
243
out . push ( '\n' ) ;
@@ -226,6 +282,21 @@ export function formatSnapshot(
226
282
227
283
pushDoc ( range , occurrence . symbol , isDefinition , isStartOfLine ) ;
228
284
}
285
+
286
+ for ( let openRangeIndex = openEnclosingRanges . length - 1 ; openRangeIndex >= 0 ; openRangeIndex -- ) {
287
+ const enclosingRange = openEnclosingRanges [ openRangeIndex ] ;
288
+
289
+ if ( enclosingRange . range . end . line == lineNumber ) {
290
+ // Switch the range to the open list
291
+ openEnclosingRanges . splice ( openRangeIndex , 1 ) ;
292
+
293
+ pushEnclosingRange ( enclosingRange , true ) ;
294
+
295
+ continue ;
296
+ }
297
+
298
+ break ;
299
+ }
229
300
}
230
301
return out . join ( '' ) ;
231
302
}
@@ -261,3 +332,14 @@ export function diffSnapshot(outputPath: string, obtained: string): void {
261
332
function occurrencesByLine ( a : scip . Occurrence , b : scip . Occurrence ) : number {
262
333
return Range . fromLsif ( a . range ) . compare ( Range . fromLsif ( b . range ) ) ;
263
334
}
335
+
336
+ function enclosingRangesByLine ( a : { range : Range ; symbol : string } , b : { range : Range ; symbol : string } ) : number {
337
+ // Return the range that starts first, and if they start at the same line, the one that ends last (enclosing).
338
+ const rangeCompare = a . range . compare ( b . range ) ;
339
+
340
+ if ( rangeCompare !== 0 ) {
341
+ return rangeCompare ;
342
+ }
343
+
344
+ return b . range . end . line - a . range . end . line ;
345
+ }
0 commit comments