@@ -69,6 +69,16 @@ interface OutputNotificationBody {
6969 output : string ;
7070}
7171
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+
7282// Requests
7383const NavigationListRequest : RequestType < TextDocumentIdentifier , string , void , void > = new RequestType < TextDocumentIdentifier , string , void , void > ( 'cpptools/requestNavigationList' ) ;
7484const GoToDeclarationRequest : RequestType < void , void , void , void > = new RequestType < void , void , void , void > ( 'cpptools/goToDeclaration' ) ;
@@ -97,6 +107,7 @@ const ReportTagParseStatusNotification: NotificationType<ReportStatusNotificatio
97107const ReportStatusNotification : NotificationType < ReportStatusNotificationBody , void > = new NotificationType < ReportStatusNotificationBody , void > ( 'cpptools/reportStatus' ) ;
98108const DebugProtocolNotification : NotificationType < OutputNotificationBody , void > = new NotificationType < OutputNotificationBody , void > ( 'cpptools/debugProtocol' ) ;
99109const DebugLogNotification : NotificationType < OutputNotificationBody , void > = new NotificationType < OutputNotificationBody , void > ( 'cpptools/debugLog' ) ;
110+ const InactiveRegionNotification : NotificationType < InactiveRegionParams , void > = new NotificationType < InactiveRegionParams , void > ( 'cpptools/inactiveRegions' ) ;
100111
101112const maxSettingLengthForTelemetry : number = 50 ;
102113let previousCppSettings : { [ key : string ] : any } = { } ;
@@ -159,6 +170,7 @@ export interface Client {
159170 Name : string ;
160171 TrackedDocuments : Set < vscode . TextDocument > ;
161172 onDidChangeSettings ( ) : void ;
173+ onDidChangeVisibleTextEditors ( editors : vscode . TextEditor [ ] ) : void ;
162174 takeOwnership ( document : vscode . TextDocument ) : void ;
163175 requestGoToDeclaration ( ) : Thenable < void > ;
164176 requestSwitchHeaderSource ( rootPath : string , fileName : string ) : Thenable < string > ;
@@ -198,6 +210,7 @@ class DefaultClient implements Client {
198210 private crashTimes : number [ ] = [ ] ;
199211 private failureMessageShown = new PersistentState < boolean > ( "DefaultClient.failureMessageShown" , false ) ;
200212 private isSupported : boolean = true ;
213+ private inactiveRegionsDecorations = new Map < string , DecorationRangesPair > ( ) ;
201214
202215 // The "model" that is displayed via the UI (status bar).
203216 private model : ClientModel = {
@@ -382,6 +395,16 @@ class DefaultClient implements Client {
382395 }
383396 }
384397
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+
385408 /**
386409 * Take ownership of a document that was previously serviced by another client.
387410 * This process involves sending a textDocument/didOpen message to the server so
@@ -434,6 +457,7 @@ class DefaultClient implements Client {
434457 this . languageClient . onNotification ( ReportNavigationNotification , ( e ) => this . navigate ( e ) ) ;
435458 this . languageClient . onNotification ( ReportStatusNotification , ( e ) => this . updateStatus ( e ) ) ;
436459 this . languageClient . onNotification ( ReportTagParseStatusNotification , ( e ) => this . updateTagParseStatus ( e ) ) ;
460+ this . languageClient . onNotification ( InactiveRegionNotification , ( e ) => this . updateInactiveRegions ( e ) ) ;
437461 this . setupOutputHandlers ( ) ;
438462 }
439463
@@ -620,6 +644,55 @@ class DefaultClient implements Client {
620644 this . model . tagParserStatus . Value = notificationBody . status ;
621645 }
622646
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+
623696 /*********************************************
624697 * requests to the language server
625698 *********************************************/
@@ -809,6 +882,7 @@ class NullClient implements Client {
809882 Name : string = "(empty)" ;
810883 TrackedDocuments = new Set < vscode . TextDocument > ( ) ;
811884 onDidChangeSettings ( ) : void { }
885+ onDidChangeVisibleTextEditors ( editors : vscode . TextEditor [ ] ) : void { }
812886 takeOwnership ( document : vscode . TextDocument ) : void { }
813887 requestGoToDeclaration ( ) : Thenable < void > { return Promise . resolve ( ) ; }
814888 requestSwitchHeaderSource ( rootPath : string , fileName : string ) : Thenable < string > { return Promise . resolve ( "" ) ; }
0 commit comments