@@ -24,9 +24,55 @@ export enum LineAnnotationType {
2424 Hover = 'hover'
2525}
2626
27+ class AnnotationState {
28+
29+ constructor ( private _enabled : boolean , private _annotationType : LineAnnotationType ) { }
30+
31+ get annotationType ( ) : LineAnnotationType {
32+ return this . _annotationType ;
33+ }
34+
35+ get enabled ( ) : boolean {
36+ return this . suspended ? false : this . _enabled ;
37+ }
38+
39+ private _suspendReason ?: 'debugging' | 'dirty' ;
40+ get suspended ( ) : boolean {
41+ return this . _suspendReason !== undefined ;
42+ }
43+
44+ reset ( enabled : boolean , annotationType : LineAnnotationType ) : boolean {
45+ // returns whether or not a refresh is required
46+
47+ if ( this . _enabled === enabled && this . _annotationType === annotationType && ! this . suspended ) return false ;
48+
49+ this . _enabled = enabled ;
50+ this . _annotationType = annotationType ;
51+ this . _suspendReason = undefined ;
52+
53+ return true ;
54+ }
55+
56+ resume ( reason : 'debugging' | 'dirty' ) : boolean {
57+ // returns whether or not a refresh is required
58+
59+ const refresh = this . _suspendReason !== undefined ;
60+ this . _suspendReason = undefined ;
61+ return refresh ;
62+ }
63+
64+ suspend ( reason : 'debugging' | 'dirty' ) : boolean {
65+ // returns whether or not a refresh is required
66+
67+ const refresh = this . _suspendReason === undefined ;
68+ this . _suspendReason = reason ;
69+ return refresh ;
70+ }
71+ }
72+
2773export class CurrentLineController extends Disposable {
2874
29- private _blameAnnotationState : { enabled : boolean , annotationType : LineAnnotationType , reason : 'user' | 'debugging' | 'dirty' } | undefined ;
75+ private _blameAnnotationState : AnnotationState | undefined ;
3076 private _editor : TextEditor | undefined ;
3177 private _lineTracker : LineTracker < GitLineState > ;
3278 private _statusBarItem : StatusBarItem | undefined ;
@@ -149,11 +195,9 @@ export class CurrentLineController extends Disposable {
149195 }
150196
151197 private onDebugSessionStarted ( ) {
152- const state = this . getBlameAnnotationState ( ) ;
153- if ( ! state . enabled ) return ;
154-
155- this . _debugSessionEndDisposable = debug . onDidTerminateDebugSession ( this . onDebugSessionEnded , this ) ;
156- this . setBlameAnnotationState ( false , window . activeTextEditor , 'debugging' ) ;
198+ if ( this . suspendBlameAnnotations ( 'debugging' , window . activeTextEditor ) ) {
199+ this . _debugSessionEndDisposable = debug . onDidTerminateDebugSession ( this . onDebugSessionEnded , this ) ;
200+ }
157201 }
158202
159203 private onDebugSessionEnded ( ) {
@@ -162,18 +206,23 @@ export class CurrentLineController extends Disposable {
162206 this . _debugSessionEndDisposable = undefined ;
163207 }
164208
165- this . setBlameAnnotationState ( true , window . activeTextEditor , 'debugging' ) ;
209+ this . resumeBlameAnnotations ( 'debugging' , window . activeTextEditor ) ;
166210 }
167211
168212 private onDirtyIdleTriggered ( e : DocumentDirtyIdleTriggerEvent < GitDocumentState > ) {
169213 const maxLines = configuration . get < number > ( configuration . name ( 'advanced' ) ( 'blame' ) ( 'sizeThresholdAfterEdit' ) . value ) ;
170214 if ( maxLines > 0 && e . document . document . lineCount > maxLines ) return ;
171215
172- this . setBlameAnnotationState ( true , window . activeTextEditor , 'dirty' ) ;
216+ this . resumeBlameAnnotations ( 'dirty' , window . activeTextEditor ) ;
173217 }
174218
175219 private async onDirtyStateChanged ( e : DocumentDirtyStateChangeEvent < GitDocumentState > ) {
176- this . setBlameAnnotationState ( ! e . dirty , window . activeTextEditor , 'dirty' , { force : true } ) ;
220+ if ( e . dirty ) {
221+ this . suspendBlameAnnotations ( 'dirty' , window . activeTextEditor ) ;
222+ }
223+ else {
224+ this . resumeBlameAnnotations ( 'dirty' , window . activeTextEditor , { force : true } ) ;
225+ }
177226 }
178227
179228 private onFileAnnotationsToggled ( ) {
@@ -280,31 +329,56 @@ export class CurrentLineController extends Disposable {
280329 }
281330
282331 async showAnnotations ( editor : TextEditor | undefined , type : LineAnnotationType ) {
283- this . setBlameAnnotationState ( true , editor , 'user' , { type : type } ) ;
332+ this . setBlameAnnotationState ( true , type , editor ) ;
284333 }
285334
286335 async toggleAnnotations ( editor : TextEditor | undefined , type : LineAnnotationType ) {
287336 if ( editor === undefined ) return ;
288337
289338 const state = this . getBlameAnnotationState ( ) ;
290- this . setBlameAnnotationState ( ! state . enabled , editor , 'user' , { type : type } ) ;
339+ this . setBlameAnnotationState ( ! state . enabled , type , editor ) ;
291340 }
292341
293- private async setBlameAnnotationState ( enabled : boolean , editor : TextEditor | undefined , reason : 'user' | 'debugging' | 'dirty' , options : { force ?: boolean , type ?: LineAnnotationType } = { } ) {
294- if ( editor === undefined ) return ;
342+ private async resumeBlameAnnotations ( reason : 'debugging' | 'dirty' , editor : TextEditor | undefined , options : { force ?: boolean } = { } ) {
343+ if ( ! options . force && ( this . _blameAnnotationState === undefined || ! this . _blameAnnotationState . suspended ) ) return ;
344+
345+ let refresh = false ;
346+ if ( this . _blameAnnotationState !== undefined ) {
347+ refresh = this . _blameAnnotationState . resume ( reason ) ;
348+ }
295349
296- // If we are trying to turn annotations on, check if it was the user, or a matching reason
297- if ( enabled && reason !== 'user' && reason !== ( this . _blameAnnotationState && this . _blameAnnotationState . reason ) ) return ;
350+ if ( editor === undefined || ( ! options . force && ! refresh ) ) return ;
351+
352+ await this . refresh ( editor ) ;
353+ }
298354
355+ private async suspendBlameAnnotations ( reason : 'debugging' | 'dirty' , editor : TextEditor | undefined , options : { force ?: boolean } = { } ) {
299356 const state = this . getBlameAnnotationState ( ) ;
300- if ( options . type === undefined ) {
301- options . type = state . annotationType ;
357+
358+ // If we aren't enabled, suspend doesn't matter
359+ if ( this . _blameAnnotationState === undefined && ! state . enabled ) return false ;
360+
361+ if ( this . _blameAnnotationState === undefined ) {
362+ this . _blameAnnotationState = new AnnotationState ( state . enabled , state . annotationType ) ;
302363 }
364+ const refresh = this . _blameAnnotationState . suspend ( reason ) ;
365+
366+ if ( editor === undefined || ( ! options . force && ! refresh ) ) return ;
367+
368+ await this . refresh ( editor ) ;
369+ return true ;
370+ }
303371
304- // If we are off and want it off or we are on and want it on with matching annotation type
305- if ( ! options . force && state . enabled === enabled && ( ! enabled || state . annotationType === options . type ) ) return ;
372+ private async setBlameAnnotationState ( enabled : boolean , type : LineAnnotationType , editor : TextEditor | undefined ) {
373+ let refresh = true ;
374+ if ( this . _blameAnnotationState === undefined ) {
375+ this . _blameAnnotationState = new AnnotationState ( enabled , type ) ;
376+ }
377+ else {
378+ refresh = this . _blameAnnotationState . reset ( enabled , type ) ;
379+ }
306380
307- this . _blameAnnotationState = { enabled : enabled , annotationType : options . type , reason : reason } ;
381+ if ( editor === undefined || ! refresh ) return ;
308382
309383 await this . refresh ( editor ) ;
310384 }
0 commit comments