3
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
- import { ArrayQueue , findLast } from 'vs/base/common/arrays' ;
6
+ import { findLast } from 'vs/base/common/arrays' ;
7
7
import * as strings from 'vs/base/common/strings' ;
8
8
import { CursorColumns } from 'vs/editor/common/core/cursorColumns' ;
9
9
import { IPosition , Position } from 'vs/editor/common/core/position' ;
10
10
import { Range } from 'vs/editor/common/core/range' ;
11
- import { BracketPairInfo } from 'vs/editor/common/textModelBracketPairs' ;
12
11
import type { TextModel } from 'vs/editor/common/model/textModel' ;
13
12
import { TextModelPart } from 'vs/editor/common/model/textModelPart' ;
14
13
import { computeIndentLevel } from 'vs/editor/common/model/utils' ;
@@ -278,6 +277,13 @@ export class GuidesTextModelPart extends TextModelPart implements IGuidesTextMod
278
277
options : BracketGuideOptions
279
278
) : IndentGuide [ ] [ ] {
280
279
const result : IndentGuide [ ] [ ] = [ ] ;
280
+ for ( let lineNumber = startLineNumber ; lineNumber <= endLineNumber ; lineNumber ++ ) {
281
+ result . push ( [ ] ) ;
282
+ }
283
+
284
+ // If requested, this could be made configurable.
285
+ const includeSingleLinePairs = true ;
286
+
281
287
const bracketPairs =
282
288
this . textModel . bracketPairs . getBracketPairsInRangeWithMinIndentation (
283
289
new Range (
@@ -302,205 +308,151 @@ export class GuidesTextModelPart extends TextModelPart implements IGuidesTextMod
302
308
303
309
activeBracketPairRange = findLast (
304
310
bracketsContainingActivePosition ,
305
- /* Exclude single line bracket pairs for cases such as
306
- * ```
307
- * function test() {
308
- * if (true) { | }
309
- * }
310
- * ```
311
- */
312
- ( i ) => i . range . startLineNumber !== i . range . endLineNumber
311
+ ( i ) => includeSingleLinePairs || i . range . startLineNumber !== i . range . endLineNumber
313
312
) ?. range ;
314
313
}
315
314
316
- const queue = new ArrayQueue ( bracketPairs ) ;
317
- /** Indexed by nesting level */
318
- const activeGuides = new Array < {
319
- nestingLevel : number ;
320
- nestingLevelOfEqualBracketType : number ;
321
- guideVisibleColumn : number ;
322
- start : Position ;
323
- visibleStartColumn : number ;
324
- end : Position ;
325
- visibleEndColumn : number ;
326
- bracketPair : BracketPairInfo ;
327
- renderHorizontalEndLineAtTheBottom : boolean ;
328
- } | null > ( ) ;
329
- const nextGuides = new Array < IndentGuide > ( ) ;
315
+ const independentColorPoolPerBracketType = this . textModel . getOptions ( ) . bracketPairColorizationOptions . independentColorPoolPerBracketType ;
330
316
const colorProvider = new BracketPairGuidesClassNames ( ) ;
331
- const independentColorPoolPerBracketType = this . textModel . getOptions ( ) . bracketPairColorizationOptions
332
- . independentColorPoolPerBracketType ;
333
317
334
- for (
335
- let lineNumber = startLineNumber ;
336
- lineNumber <= endLineNumber ;
337
- lineNumber ++
338
- ) {
339
- let guides = new Array < IndentGuide > ( ) ;
340
- if ( nextGuides . length > 0 ) {
341
- guides = guides . concat ( nextGuides ) ;
342
- nextGuides . length = 0 ;
318
+ for ( const pair of bracketPairs ) {
319
+ /*
320
+
321
+
322
+ {
323
+ |
324
+ }
325
+
326
+ {
327
+ |
328
+ ----}
329
+
330
+ ____{
331
+ |test
332
+ ----}
333
+
334
+ renderHorizontalEndLineAtTheBottom:
335
+ {
336
+ |
337
+ |x}
338
+ --
339
+ renderHorizontalEndLineAtTheBottom:
340
+ ____{
341
+ |test
342
+ | x }
343
+ ----
344
+ */
345
+
346
+ const isActive = activeBracketPairRange && pair . range . equalsRange ( activeBracketPairRange ) ;
347
+
348
+ if ( ! isActive && ! options . includeInactive ) {
349
+ continue ;
343
350
}
344
- result . push ( guides ) ;
345
-
346
- // Update activeGuides
347
- for ( const pair of queue . takeWhile (
348
- ( b ) => b . openingBracketRange . startLineNumber <= lineNumber
349
- ) || [ ] ) {
350
- if ( pair . range . startLineNumber === pair . range . endLineNumber ) {
351
- // ignore single line brackets
352
- continue ;
353
- }
354
- const guideVisibleColumn = Math . min (
355
- this . getVisibleColumnFromPosition (
356
- pair . openingBracketRange . getStartPosition ( )
357
- ) ,
358
- this . getVisibleColumnFromPosition (
359
- pair . closingBracketRange ?. getStartPosition ( ) ??
360
- pair . range . getEndPosition ( )
361
- ) ,
362
- pair . minVisibleColumnIndentation + 1
363
- ) ;
364
- let renderHorizontalEndLineAtTheBottom = false ;
365
- if ( pair . closingBracketRange ) {
366
- const firstNonWsIndex = strings . firstNonWhitespaceIndex (
367
- this . textModel . getLineContent (
368
- pair . closingBracketRange . startLineNumber
351
+
352
+ const className =
353
+ colorProvider . getInlineClassName ( pair . nestingLevel , pair . nestingLevelOfEqualBracketType , independentColorPoolPerBracketType ) +
354
+ ( options . highlightActive && isActive
355
+ ? ' ' + colorProvider . activeClassName
356
+ : '' ) ;
357
+
358
+
359
+ const start = pair . openingBracketRange . getStartPosition ( ) ;
360
+ const end =
361
+ pair . closingBracketRange ?. getStartPosition ( ) ??
362
+ pair . range . getEndPosition ( ) ;
363
+
364
+ const horizontalGuides = options . horizontalGuides === HorizontalGuidesState . Enabled || ( options . horizontalGuides === HorizontalGuidesState . EnabledForActive && isActive ) ;
365
+
366
+ if ( pair . range . startLineNumber === pair . range . endLineNumber ) {
367
+ if ( includeSingleLinePairs && horizontalGuides ) {
368
+
369
+ result [ pair . range . startLineNumber - startLineNumber ] . push (
370
+ new IndentGuide (
371
+ - 1 ,
372
+ pair . openingBracketRange . getEndPosition ( ) . column ,
373
+ className ,
374
+ new IndentGuideHorizontalLine ( false , end . column ) ,
375
+ - 1 ,
376
+ - 1 ,
369
377
)
370
378
) ;
371
- if ( firstNonWsIndex < pair . closingBracketRange . startColumn - 1 ) {
372
- renderHorizontalEndLineAtTheBottom = true ;
373
- }
374
- }
375
379
376
- const start = pair . openingBracketRange . getStartPosition ( ) ;
377
- const end =
378
- pair . closingBracketRange ?. getStartPosition ( ) ??
379
- pair . range . getEndPosition ( ) ;
380
-
381
- if ( pair . closingBracketRange === undefined ) {
382
- // Don't show guides for bracket pairs that are not balanced.
383
- // See #135125.
384
- activeGuides [ pair . nestingLevel ] = null ;
385
- } else {
386
- activeGuides [ pair . nestingLevel ] = {
387
- nestingLevel : pair . nestingLevel ,
388
- nestingLevelOfEqualBracketType : pair . nestingLevelOfEqualBracketType ,
389
- guideVisibleColumn,
390
- start,
391
- visibleStartColumn : this . getVisibleColumnFromPosition ( start ) ,
392
- end,
393
- visibleEndColumn : this . getVisibleColumnFromPosition ( end ) ,
394
- bracketPair : pair ,
395
- renderHorizontalEndLineAtTheBottom,
396
- } ;
397
380
}
381
+ continue ;
398
382
}
399
383
400
- for ( const line of activeGuides ) {
401
- if ( ! line ) {
402
- continue ;
403
- }
404
- const isActive =
405
- activeBracketPairRange &&
406
- line . bracketPair . range . equalsRange ( activeBracketPairRange ) ;
407
-
408
- const className =
409
- colorProvider . getInlineClassName ( line . nestingLevel , line . nestingLevelOfEqualBracketType , independentColorPoolPerBracketType ) +
410
- ( options . highlightActive && isActive
411
- ? ' ' + colorProvider . activeClassName
412
- : '' ) ;
384
+ const endVisibleColumn = this . getVisibleColumnFromPosition ( end ) ;
385
+ const startVisibleColumn = this . getVisibleColumnFromPosition (
386
+ pair . openingBracketRange . getStartPosition ( )
387
+ ) ;
388
+ const guideVisibleColumn = Math . min ( startVisibleColumn , endVisibleColumn , pair . minVisibleColumnIndentation + 1 ) ;
413
389
414
- if (
415
- ( isActive &&
416
- options . horizontalGuides !==
417
- HorizontalGuidesState . Disabled ) ||
418
- ( options . includeInactive &&
419
- options . horizontalGuides === HorizontalGuidesState . Enabled )
420
- ) {
421
- if ( line . start . lineNumber === lineNumber ) {
422
- if ( line . guideVisibleColumn < line . visibleStartColumn ) {
423
- guides . push (
424
- new IndentGuide (
425
- line . guideVisibleColumn ,
426
- className ,
427
- new IndentGuideHorizontalLine ( false , line . start . column )
428
- )
429
- ) ;
430
- }
431
- }
432
- if ( line . end . lineNumber === lineNumber + 1 ) {
433
- // The next line might have horizontal guides.
434
- // However, the next line might also have a new bracket pair with the same indentation,
435
- // so the current bracket pair might get replaced. That's why we push the guide to nextGuides one line ahead.
436
- if ( line . guideVisibleColumn < line . visibleEndColumn ) {
437
- nextGuides . push (
438
- new IndentGuide (
439
- line . guideVisibleColumn ,
440
- className ,
441
- new IndentGuideHorizontalLine (
442
- ! line . renderHorizontalEndLineAtTheBottom ,
443
- line . end . column
444
- )
445
- )
446
- ) ;
447
- }
448
- }
390
+ let renderHorizontalEndLineAtTheBottom = false ;
391
+ if ( pair . closingBracketRange ) {
392
+ const firstNonWsIndex = strings . firstNonWhitespaceIndex (
393
+ this . textModel . getLineContent (
394
+ pair . closingBracketRange . startLineNumber
395
+ )
396
+ ) ;
397
+ const hasTextBeforeClosingBracket = firstNonWsIndex < pair . closingBracketRange . startColumn - 1 ;
398
+ if ( hasTextBeforeClosingBracket ) {
399
+ renderHorizontalEndLineAtTheBottom = true ;
449
400
}
450
401
}
451
402
452
- let lastVisibleColumnCount = Number . MAX_SAFE_INTEGER ;
453
- // Going backwards, so the last guide potentially replaces others
454
- for ( let i = activeGuides . length - 1 ; i >= 0 ; i -- ) {
455
- const line = activeGuides [ i ] ;
456
- if ( ! line ) {
457
- continue ;
458
- }
459
- const isActive =
460
- options . highlightActive &&
461
- activeBracketPairRange &&
462
- line . bracketPair . range . equalsRange ( activeBracketPairRange ) ;
463
-
464
- const className =
465
- colorProvider . getInlineClassName (
466
- line . nestingLevel ,
467
- line . nestingLevelOfEqualBracketType ,
468
- independentColorPoolPerBracketType
469
- ) + ( isActive ? ' ' + colorProvider . activeClassName : '' ) ;
470
-
471
- if ( isActive || options . includeInactive ) {
472
- if (
473
- line . renderHorizontalEndLineAtTheBottom &&
474
- line . end . lineNumber === lineNumber + 1
475
- ) {
476
- nextGuides . push (
477
- new IndentGuide ( line . guideVisibleColumn , className , null )
478
- ) ;
479
- }
480
- }
481
403
482
- if (
483
- line . end . lineNumber <= lineNumber ||
484
- line . start . lineNumber >= lineNumber
485
- ) {
486
- continue ;
487
- }
404
+ const visibleGuideStartLineNumber = Math . max ( start . lineNumber , startLineNumber ) ;
405
+ const visibleGuideEndLineNumber = Math . min ( end . lineNumber , endLineNumber ) ;
488
406
489
- if ( line . guideVisibleColumn >= lastVisibleColumnCount && ! isActive ) {
490
- // Don't render a guide on top of an existing guide, unless it is active.
491
- continue ;
407
+ const offset = renderHorizontalEndLineAtTheBottom ? 1 : 0 ;
408
+
409
+ for ( let l = visibleGuideStartLineNumber ; l < visibleGuideEndLineNumber + offset ; l ++ ) {
410
+ result [ l - startLineNumber ] . push (
411
+ new IndentGuide (
412
+ guideVisibleColumn ,
413
+ - 1 ,
414
+ className ,
415
+ null ,
416
+ l === start . lineNumber ? start . column : - 1 ,
417
+ // TODO: Investigate if this is correct
418
+ l === end . lineNumber ? end . column : - 1
419
+ )
420
+ ) ;
421
+ }
422
+
423
+ if ( horizontalGuides ) {
424
+ if ( start . lineNumber >= startLineNumber && startVisibleColumn > guideVisibleColumn ) {
425
+ result [ start . lineNumber - startLineNumber ] . push (
426
+ new IndentGuide (
427
+ guideVisibleColumn ,
428
+ - 1 ,
429
+ className ,
430
+ new IndentGuideHorizontalLine ( false , start . column ) ,
431
+ - 1 ,
432
+ - 1 ,
433
+ )
434
+ ) ;
492
435
}
493
- lastVisibleColumnCount = line . guideVisibleColumn ;
494
436
495
- if ( isActive || options . includeInactive ) {
496
- guides . push (
497
- new IndentGuide ( line . guideVisibleColumn , className , null )
437
+ if ( end . lineNumber <= endLineNumber && endVisibleColumn > guideVisibleColumn ) {
438
+ result [ end . lineNumber - startLineNumber ] . push (
439
+ new IndentGuide (
440
+ guideVisibleColumn ,
441
+ - 1 ,
442
+ className ,
443
+ new IndentGuideHorizontalLine ( ! renderHorizontalEndLineAtTheBottom , end . column ) ,
444
+ - 1 ,
445
+ - 1 ,
446
+ )
498
447
) ;
499
448
}
500
449
}
450
+ }
501
451
452
+ for ( const guides of result ) {
502
453
guides . sort ( ( a , b ) => a . visibleColumn - b . visibleColumn ) ;
503
454
}
455
+
504
456
return result ;
505
457
}
506
458
0 commit comments