@@ -61,7 +61,7 @@ class LeanFileTaskGutter implements Disposable {
6161 }
6262
6363 onDidUpdateState ( newDecorationStates : DecorationState [ ] ) {
64- this . scheduleUpdate ( newDecorationStates , 20 )
64+ this . scheduleUpdate ( newDecorationStates , 100 )
6565 }
6666
6767 clear ( clearedDecorationTypes : TextEditorDecorationType [ ] ) {
@@ -84,13 +84,11 @@ class LeanFileTaskGutter implements Disposable {
8484 this . displayDecorations ( 'Instantaneous' )
8585 } , ms )
8686 }
87- if ( this . editDelayTimeout !== undefined ) {
88- clearTimeout ( this . editDelayTimeout )
89- }
87+ clearTimeout ( this . editDelayTimeout )
9088 const remainingDelayMs =
9189 this . lastEditTimestampMs !== undefined
92- ? Math . max ( 0 , this . editDelayMs - ( Date . now ( ) - this . lastEditTimestampMs ) )
93- : 0
90+ ? Math . max ( ms , this . editDelayMs - ( Date . now ( ) - this . lastEditTimestampMs ) )
91+ : ms
9492 this . editDelayTimeout = setTimeout ( ( ) => {
9593 this . editDelayTimeout = undefined
9694 this . displayDecorations ( 'EditDelayed' )
@@ -214,19 +212,7 @@ function mergeDiagnosticGutterDecos(a: DiagnosticGutterDeco, b: DiagnosticGutter
214212}
215213
216214function isGoalsAccomplishedDiagnostic ( d : LeanDiagnostic ) : boolean {
217- return (
218- d . leanTags !== undefined &&
219- d . leanTags . some ( t => t === LeanTag . GoalsAccomplished ) &&
220- goalsAccomplishedDecorationKind ( ) !== 'Off'
221- )
222- }
223-
224- function isGutterDecoDiagnostic ( d : LeanDiagnostic ) : boolean {
225- return (
226- d . severity === DiagnosticSeverity . Error ||
227- d . severity === DiagnosticSeverity . Warning ||
228- isGoalsAccomplishedDiagnostic ( d )
229- )
215+ return d . leanTags !== undefined && d . leanTags . some ( t => t === LeanTag . GoalsAccomplished )
230216}
231217
232218function determineDiagStart ( d : LeanDiagnostic , startLine : number , endLine : number , line : number ) : DiagStart {
@@ -276,29 +262,14 @@ function determineDiagnosticGutterDeco(
276262 }
277263}
278264
279- function computeDiagnosticGutterDecos ( diagnostics : LeanDiagnostic [ ] ) : DiagnosticGutterDeco [ ] {
280- const decos : Map < number , DiagnosticGutterDeco > = new Map ( )
281- for ( const d of diagnostics ) {
282- if ( ! isGutterDecoDiagnostic ( d ) ) {
283- continue
284- }
285- const range = diagRange ( d )
286- const startLine = range . start . line
287- const endLine = inclusiveEndLine ( range )
288- for ( let line = startLine ; line <= endLine ; line ++ ) {
289- const deco = determineDiagnosticGutterDeco ( d , startLine , endLine , line )
290- const oldDeco = decos . get ( deco . line )
291- if ( oldDeco === undefined ) {
292- decos . set ( deco . line , deco )
293- } else {
294- const mergedDeco = mergeDiagnosticGutterDecos ( oldDeco , deco )
295- decos . set ( deco . line , mergedDeco )
296- }
297- }
265+ function updateDecos ( decos : Map < number , DiagnosticGutterDeco > , deco : DiagnosticGutterDeco ) {
266+ const oldDeco = decos . get ( deco . line )
267+ if ( oldDeco === undefined ) {
268+ decos . set ( deco . line , deco )
269+ } else {
270+ const mergedDeco = mergeDiagnosticGutterDecos ( oldDeco , deco )
271+ decos . set ( deco . line , mergedDeco )
298272 }
299- const result : DiagnosticGutterDeco [ ] = [ ...decos . values ( ) ]
300- result . sort ( ( a , b ) => a . line - b . line )
301- return result
302273}
303274
304275const diagnosticGutterDecoKinds = [
@@ -333,103 +304,6 @@ const diagnosticGutterDecoKinds = [
333304] as const
334305type DiagnosticGutterDecoKind = ( typeof diagnosticGutterDecoKinds ) [ number ]
335306
336- function getGoalsAccomplishedDiagnosticGutterDecoKindName ( ) : string {
337- const configName = goalsAccomplishedDecorationKind ( )
338- if ( configName === 'Double Checkmark' ) {
339- return 'goals-accomplished-checkmark'
340- }
341- if ( configName === 'Circled Checkmark' ) {
342- return 'goals-accomplished-circled-checkmark'
343- }
344- if ( configName === 'Octopus' ) {
345- return 'goals-accomplished-octopus'
346- }
347- if ( configName === 'Tada' ) {
348- return 'goals-accomplished-tada'
349- }
350- return 'goals-accomplished-checkmark'
351- }
352-
353- function determineSingleLineDiagnosticGutterDecoKind ( d : DiagnosticGutterDeco , name : string ) : DiagnosticGutterDecoKind {
354- const c = d . isPreviousDiagContinue
355- const e = d . isPreviousDiagEnd
356- if ( ! c && ! e ) {
357- return name as DiagnosticGutterDecoKind
358- }
359- if ( ! c && e ) {
360- return `${ name } -l-passthrough` as DiagnosticGutterDecoKind
361- }
362- if ( c && ! e ) {
363- return `${ name } -i-passthrough` as DiagnosticGutterDecoKind
364- }
365- if ( c && e ) {
366- return `${ name } -t-passthrough` as DiagnosticGutterDecoKind
367- }
368- assert ( false )
369- }
370-
371- function determineDiagnosticGutterDecoKind ( d : DiagnosticGutterDeco ) : DiagnosticGutterDecoKind | undefined {
372- const s = d . diagStart
373- const c = d . isPreviousDiagContinue
374- const e = d . isPreviousDiagEnd
375- if ( s !== 'None' ) {
376- const k = s . kind
377- const r = s . range
378- if ( k === 'Error' ) {
379- if ( ! c && ! e ) {
380- if ( r === 'SingleLine' ) {
381- return 'error'
382- }
383- if ( r === 'MultiLine' ) {
384- return 'error-init'
385- }
386- r satisfies never
387- }
388- if ( ! c && e ) {
389- if ( r === 'SingleLine' ) {
390- return 'error-l-passthrough'
391- }
392- if ( r === 'MultiLine' ) {
393- return 'error-t-passthrough'
394- }
395- r satisfies never
396- }
397- if ( c && ! e ) {
398- // All designs I can think of that would distinguish `SingleLine` and `MultiLine` in this case
399- // have too much visual complexity for the small gutter.
400- return 'error-i-passthrough'
401- }
402- if ( c && e ) {
403- // All designs I can think of that would distinguish `SingleLine` and `MultiLine` in this case
404- // have too much visual complexity for the small gutter.
405- return 'error-t-passthrough'
406- }
407- assert ( false )
408- }
409- if ( k === 'Warning' ) {
410- return determineSingleLineDiagnosticGutterDecoKind ( d , 'warning' )
411- }
412- if ( k === 'GoalsAccomplished' ) {
413- return determineSingleLineDiagnosticGutterDecoKind ( d , getGoalsAccomplishedDiagnosticGutterDecoKindName ( ) )
414- }
415- k satisfies never
416- }
417- assert ( s === 'None' )
418- if ( ! c && ! e ) {
419- return undefined
420- }
421- if ( ! c && e ) {
422- return 'error-l'
423- }
424- if ( c && ! e ) {
425- return 'error-i'
426- }
427- if ( c && e ) {
428- return 'error-t'
429- }
430- assert ( false )
431- }
432-
433307export class LeanTaskGutter implements Disposable {
434308 private processingDecorationType : TextEditorDecorationType
435309 private fatalErrorDecorationType : TextEditorDecorationType
@@ -439,6 +313,7 @@ export class LeanTaskGutter implements Disposable {
439313 private gutters : Map < string , LeanFileTaskGutter > = new Map ( )
440314 private subscriptions : Disposable [ ] = [ ]
441315 private showDiagnosticGutterDecorations : boolean = true
316+ private goalsAccomplishedDecorationKind : string
442317 private showUnsolvedGoalsDecoration : boolean = true
443318
444319 constructor (
@@ -542,6 +417,7 @@ export class LeanTaskGutter implements Disposable {
542417 errorLensExtensions . isActive &&
543418 workspace . getConfiguration ( 'errorLens' ) . get ( 'gutterIconsEnabled' , false )
544419 this . showDiagnosticGutterDecorations = ! isErrorLensGutterEnabled && showDiagnosticGutterDecorations ( )
420+ this . goalsAccomplishedDecorationKind = goalsAccomplishedDecorationKind ( )
545421 this . showUnsolvedGoalsDecoration = showUnsolvedGoalsDecoration ( )
546422 if ( ! this . showDiagnosticGutterDecorations ) {
547423 for ( const gutter of this . gutters . values ( ) ) {
@@ -622,9 +498,9 @@ export class LeanTaskGutter implements Disposable {
622498 decos : [ ] ,
623499 } )
624500 }
625- const decos = computeDiagnosticGutterDecos ( diagnostics )
501+ const decos = this . computeDiagnosticGutterDecos ( diagnostics )
626502 for ( const deco of decos ) {
627- const kind = determineDiagnosticGutterDecoKind ( deco )
503+ const kind = this . determineDiagnosticGutterDecoKind ( deco )
628504 if ( kind === undefined ) {
629505 continue
630506 }
@@ -635,6 +511,138 @@ export class LeanTaskGutter implements Disposable {
635511 return [ ...decoStates . values ( ) ]
636512 }
637513
514+ computeDiagnosticGutterDecos ( diagnostics : LeanDiagnostic [ ] ) : DiagnosticGutterDeco [ ] {
515+ const decos : Map < number , DiagnosticGutterDeco > = new Map ( )
516+ for ( const d of diagnostics ) {
517+ if ( ! this . isGutterDecoDiagnostic ( d ) ) {
518+ continue
519+ }
520+ const range = diagRange ( d )
521+ const startLine = range . start . line
522+ const endLine = inclusiveEndLine ( range )
523+ const startDeco = determineDiagnosticGutterDeco ( d , startLine , endLine , startLine )
524+ updateDecos ( decos , startDeco )
525+ if ( startDeco . diagStart !== 'None' && startDeco . diagStart . range === 'SingleLine' ) {
526+ continue
527+ }
528+ for ( let line = startLine + 1 ; line <= endLine ; line ++ ) {
529+ const deco = determineDiagnosticGutterDeco ( d , startLine , endLine , line )
530+ updateDecos ( decos , deco )
531+ }
532+ }
533+ const result : DiagnosticGutterDeco [ ] = [ ...decos . values ( ) ]
534+ result . sort ( ( a , b ) => a . line - b . line )
535+ return result
536+ }
537+
538+ isGutterDecoDiagnostic ( d : LeanDiagnostic ) : boolean {
539+ return (
540+ d . severity === DiagnosticSeverity . Error ||
541+ d . severity === DiagnosticSeverity . Warning ||
542+ ( isGoalsAccomplishedDiagnostic ( d ) && this . goalsAccomplishedDecorationKind !== 'Off' )
543+ )
544+ }
545+
546+ getGoalsAccomplishedDiagnosticGutterDecoKindName ( ) : string {
547+ const configName = this . goalsAccomplishedDecorationKind
548+ if ( configName === 'Double Checkmark' ) {
549+ return 'goals-accomplished-checkmark'
550+ }
551+ if ( configName === 'Circled Checkmark' ) {
552+ return 'goals-accomplished-circled-checkmark'
553+ }
554+ if ( configName === 'Octopus' ) {
555+ return 'goals-accomplished-octopus'
556+ }
557+ if ( configName === 'Tada' ) {
558+ return 'goals-accomplished-tada'
559+ }
560+ return 'goals-accomplished-checkmark'
561+ }
562+
563+ determineSingleLineDiagnosticGutterDecoKind ( d : DiagnosticGutterDeco , name : string ) : DiagnosticGutterDecoKind {
564+ const c = d . isPreviousDiagContinue
565+ const e = d . isPreviousDiagEnd
566+ if ( ! c && ! e ) {
567+ return name as DiagnosticGutterDecoKind
568+ }
569+ if ( ! c && e ) {
570+ return `${ name } -l-passthrough` as DiagnosticGutterDecoKind
571+ }
572+ if ( c && ! e ) {
573+ return `${ name } -i-passthrough` as DiagnosticGutterDecoKind
574+ }
575+ if ( c && e ) {
576+ return `${ name } -t-passthrough` as DiagnosticGutterDecoKind
577+ }
578+ assert ( false )
579+ }
580+
581+ determineDiagnosticGutterDecoKind ( d : DiagnosticGutterDeco ) : DiagnosticGutterDecoKind | undefined {
582+ const s = d . diagStart
583+ const c = d . isPreviousDiagContinue
584+ const e = d . isPreviousDiagEnd
585+ if ( s !== 'None' ) {
586+ const k = s . kind
587+ const r = s . range
588+ if ( k === 'Error' ) {
589+ if ( ! c && ! e ) {
590+ if ( r === 'SingleLine' ) {
591+ return 'error'
592+ }
593+ if ( r === 'MultiLine' ) {
594+ return 'error-init'
595+ }
596+ r satisfies never
597+ }
598+ if ( ! c && e ) {
599+ if ( r === 'SingleLine' ) {
600+ return 'error-l-passthrough'
601+ }
602+ if ( r === 'MultiLine' ) {
603+ return 'error-t-passthrough'
604+ }
605+ r satisfies never
606+ }
607+ if ( c && ! e ) {
608+ // All designs I can think of that would distinguish `SingleLine` and `MultiLine` in this case
609+ // have too much visual complexity for the small gutter.
610+ return 'error-i-passthrough'
611+ }
612+ if ( c && e ) {
613+ // All designs I can think of that would distinguish `SingleLine` and `MultiLine` in this case
614+ // have too much visual complexity for the small gutter.
615+ return 'error-t-passthrough'
616+ }
617+ assert ( false )
618+ }
619+ if ( k === 'Warning' ) {
620+ return this . determineSingleLineDiagnosticGutterDecoKind ( d , 'warning' )
621+ }
622+ if ( k === 'GoalsAccomplished' ) {
623+ return this . determineSingleLineDiagnosticGutterDecoKind (
624+ d ,
625+ this . getGoalsAccomplishedDiagnosticGutterDecoKindName ( ) ,
626+ )
627+ }
628+ k satisfies never
629+ }
630+ assert ( s === 'None' )
631+ if ( ! c && ! e ) {
632+ return undefined
633+ }
634+ if ( ! c && e ) {
635+ return 'error-l'
636+ }
637+ if ( c && ! e ) {
638+ return 'error-i'
639+ }
640+ if ( c && e ) {
641+ return 'error-t'
642+ }
643+ assert ( false )
644+ }
645+
638646 private computeUnsolvedGoalsDecoState ( diagnostics : LeanDiagnostic [ ] ) : DecorationState {
639647 const unsolvedGoalsLines = diagnostics
640648 . filter ( d => {
0 commit comments