@@ -69,6 +69,16 @@ interface OutputNotificationBody {
69
69
output : string ;
70
70
}
71
71
72
+ interface InactiveRegionParams {
73
+ uri : string ;
74
+ ranges : vscode . Range [ ] ;
75
+ }
76
+
77
+ interface DecorationRangesPair {
78
+ decoration : vscode . TextEditorDecorationType ;
79
+ ranges : vscode . Range [ ] ;
80
+ }
81
+
72
82
// Requests
73
83
const NavigationListRequest : RequestType < TextDocumentIdentifier , string , void , void > = new RequestType < TextDocumentIdentifier , string , void , void > ( 'cpptools/requestNavigationList' ) ;
74
84
const GoToDeclarationRequest : RequestType < void , void , void , void > = new RequestType < void , void , void , void > ( 'cpptools/goToDeclaration' ) ;
@@ -97,6 +107,7 @@ const ReportTagParseStatusNotification: NotificationType<ReportStatusNotificatio
97
107
const ReportStatusNotification : NotificationType < ReportStatusNotificationBody , void > = new NotificationType < ReportStatusNotificationBody , void > ( 'cpptools/reportStatus' ) ;
98
108
const DebugProtocolNotification : NotificationType < OutputNotificationBody , void > = new NotificationType < OutputNotificationBody , void > ( 'cpptools/debugProtocol' ) ;
99
109
const DebugLogNotification : NotificationType < OutputNotificationBody , void > = new NotificationType < OutputNotificationBody , void > ( 'cpptools/debugLog' ) ;
110
+ const InactiveRegionNotification : NotificationType < InactiveRegionParams , void > = new NotificationType < InactiveRegionParams , void > ( 'cpptools/inactiveRegions' ) ;
100
111
101
112
const maxSettingLengthForTelemetry : number = 50 ;
102
113
let previousCppSettings : { [ key : string ] : any } = { } ;
@@ -159,6 +170,7 @@ export interface Client {
159
170
Name : string ;
160
171
TrackedDocuments : Set < vscode . TextDocument > ;
161
172
onDidChangeSettings ( ) : void ;
173
+ onDidChangeVisibleTextEditors ( editors : vscode . TextEditor [ ] ) : void ;
162
174
takeOwnership ( document : vscode . TextDocument ) : void ;
163
175
requestGoToDeclaration ( ) : Thenable < void > ;
164
176
requestSwitchHeaderSource ( rootPath : string , fileName : string ) : Thenable < string > ;
@@ -198,6 +210,7 @@ class DefaultClient implements Client {
198
210
private crashTimes : number [ ] = [ ] ;
199
211
private failureMessageShown = new PersistentState < boolean > ( "DefaultClient.failureMessageShown" , false ) ;
200
212
private isSupported : boolean = true ;
213
+ private inactiveRegionsDecorations = new Map < string , DecorationRangesPair > ( ) ;
201
214
202
215
// The "model" that is displayed via the UI (status bar).
203
216
private model : ClientModel = {
@@ -382,6 +395,16 @@ class DefaultClient implements Client {
382
395
}
383
396
}
384
397
398
+ public onDidChangeVisibleTextEditors ( editors : vscode . TextEditor [ ] ) : void {
399
+ //Apply text decorations to inactive regions
400
+ for ( let e of editors ) {
401
+ let valuePair : DecorationRangesPair = this . inactiveRegionsDecorations . get ( e . document . uri . toString ( ) ) ;
402
+ if ( valuePair ) {
403
+ e . setDecorations ( valuePair . decoration , valuePair . ranges ) ; // VSCode clears the decorations when the text editor becomes invisible
404
+ }
405
+ }
406
+ }
407
+
385
408
/**
386
409
* Take ownership of a document that was previously serviced by another client.
387
410
* This process involves sending a textDocument/didOpen message to the server so
@@ -434,6 +457,7 @@ class DefaultClient implements Client {
434
457
this . languageClient . onNotification ( ReportNavigationNotification , ( e ) => this . navigate ( e ) ) ;
435
458
this . languageClient . onNotification ( ReportStatusNotification , ( e ) => this . updateStatus ( e ) ) ;
436
459
this . languageClient . onNotification ( ReportTagParseStatusNotification , ( e ) => this . updateTagParseStatus ( e ) ) ;
460
+ this . languageClient . onNotification ( InactiveRegionNotification , ( e ) => this . updateInactiveRegions ( e ) ) ;
437
461
this . setupOutputHandlers ( ) ;
438
462
}
439
463
@@ -620,6 +644,55 @@ class DefaultClient implements Client {
620
644
this . model . tagParserStatus . Value = notificationBody . status ;
621
645
}
622
646
647
+ private updateInactiveRegions ( params : InactiveRegionParams ) : void {
648
+ let renderOptions : vscode . DecorationRenderOptions = {
649
+ light : { color : "rgba(175,175,175,1.0)" } ,
650
+ dark : { color : "rgba(155,155,155,1.0)" }
651
+ } ;
652
+ let decoration : vscode . TextEditorDecorationType = vscode . window . createTextEditorDecorationType ( renderOptions ) ;
653
+
654
+ // Recycle the active text decorations when we receive a new set of inactive regions
655
+ let valuePair : DecorationRangesPair = this . inactiveRegionsDecorations . get ( params . uri ) ;
656
+ if ( valuePair ) {
657
+ // The language server will send notifications regardless of whether the ranges have changed
658
+ if ( ! this . areRangesEqual ( valuePair . ranges , params . ranges ) ) {
659
+ // Disposing of and resetting the decoration will undo previously applied text decorations
660
+ valuePair . decoration . dispose ( ) ;
661
+ valuePair . decoration = decoration ;
662
+
663
+ // As vscode.TextEditor.setDecorations only applies to visible editors, we must cache the range for when another editor becomes visible
664
+ valuePair . ranges = params . ranges ;
665
+ }
666
+ } else { // The entry does not exist. Make a new one
667
+ let toInsert : DecorationRangesPair = {
668
+ decoration : decoration ,
669
+ ranges : params . ranges
670
+ } ;
671
+ this . inactiveRegionsDecorations . set ( params . uri , toInsert ) ;
672
+ }
673
+
674
+ // Apply the decorations to all *visible* text editors
675
+ let editors : vscode . TextEditor [ ] = vscode . window . visibleTextEditors . filter ( e => e . document . uri . toString ( ) === params . uri ) ;
676
+ for ( let e of editors ) {
677
+ e . setDecorations ( decoration , params . ranges ) ;
678
+ }
679
+ }
680
+
681
+ // Helper method to compare two ranges arrays for equality
682
+ private areRangesEqual ( r1 : vscode . Range [ ] , r2 : vscode . Range [ ] ) : boolean {
683
+ if ( r1 . length !== r2 . length ) {
684
+ return false ;
685
+ }
686
+
687
+ for ( let i : number = 0 ; i < r1 . length ; ++ i ) {
688
+ if ( ! r1 [ i ] . isEqual ( r2 [ i ] ) ) {
689
+ return false ;
690
+ }
691
+ }
692
+
693
+ return true ;
694
+ }
695
+
623
696
/*********************************************
624
697
* requests to the language server
625
698
*********************************************/
@@ -809,6 +882,7 @@ class NullClient implements Client {
809
882
Name : string = "(empty)" ;
810
883
TrackedDocuments = new Set < vscode . TextDocument > ( ) ;
811
884
onDidChangeSettings ( ) : void { }
885
+ onDidChangeVisibleTextEditors ( editors : vscode . TextEditor [ ] ) : void { }
812
886
takeOwnership ( document : vscode . TextDocument ) : void { }
813
887
requestGoToDeclaration ( ) : Thenable < void > { return Promise . resolve ( ) ; }
814
888
requestSwitchHeaderSource ( rootPath : string , fileName : string ) : Thenable < string > { return Promise . resolve ( "" ) ; }
0 commit comments