@@ -7,8 +7,7 @@ import { Sequencer } from '../../../../base/common/async.js';
7
7
import { Codicon } from '../../../../base/common/codicons.js' ;
8
8
import { BugIndicatingError } from '../../../../base/common/errors.js' ;
9
9
import { Emitter } from '../../../../base/common/event.js' ;
10
- import { Disposable , IReference } from '../../../../base/common/lifecycle.js' ;
11
- import { ResourceSet } from '../../../../base/common/map.js' ;
10
+ import { Disposable , IReference , MutableDisposable } from '../../../../base/common/lifecycle.js' ;
12
11
import { Schemas } from '../../../../base/common/network.js' ;
13
12
import { derived , IObservable , ITransaction , observableValue , ValueWithChangeEventFromObservable } from '../../../../base/common/observable.js' ;
14
13
import { URI } from '../../../../base/common/uri.js' ;
@@ -52,6 +51,7 @@ export class ChatEditingService extends Disposable implements IChatEditingServic
52
51
_serviceBrand : undefined ;
53
52
54
53
private readonly _currentSessionObs = observableValue < ChatEditingSession | null > ( this , null ) ;
54
+ private readonly _currentSessionDisposeListener = this . _register ( new MutableDisposable ( ) ) ;
55
55
56
56
get currentEditingSession ( ) : IChatEditingSession | null {
57
57
return this . _currentSessionObs . get ( ) ;
@@ -62,11 +62,6 @@ export class ChatEditingService extends Disposable implements IChatEditingServic
62
62
return this . _onDidCreateEditingSession . event ;
63
63
}
64
64
65
- private readonly _onDidDisposeEditingSession = new Emitter < IChatEditingSession > ( ) ;
66
- get onDidDisposeEditingSession ( ) {
67
- return this . _onDidDisposeEditingSession . event ;
68
- }
69
-
70
65
constructor (
71
66
@IEditorGroupsService private readonly _editorGroupsService : IEditorGroupsService ,
72
67
@IInstantiationService private readonly _instantiationService : IInstantiationService ,
@@ -90,11 +85,16 @@ export class ChatEditingService extends Disposable implements IChatEditingServic
90
85
} ) ) ;
91
86
this . _register ( this . _chatService . onDidDisposeSession ( ( e ) => {
92
87
if ( e . reason === 'cleared' && this . _currentSessionObs . get ( ) ?. chatSessionId === e . sessionId ) {
93
- this . _killCurrentEditingSession ( ) ;
88
+ void this . _currentSessionObs . get ( ) ?. stop ( ) ;
94
89
}
95
90
} ) ) ;
96
91
}
97
92
93
+ override dispose ( ) : void {
94
+ this . _currentSessionObs . get ( ) ?. dispose ( ) ;
95
+ super . dispose ( ) ;
96
+ }
97
+
98
98
async startOrContinueEditingSession ( chatSessionId : string , builder ?: ( stream : IChatEditingSessionStream ) => Promise < void > , options ?: { silent : boolean } ) : Promise < void > {
99
99
const session = this . _currentSessionObs . get ( ) ;
100
100
if ( session ) {
@@ -121,12 +121,10 @@ export class ChatEditingService extends Disposable implements IChatEditingServic
121
121
const editorPane = options ?. silent ? undefined : await this . _editorGroupsService . activeGroup . openEditor ( input , { pinned : true , activation : EditorActivation . ACTIVATE } ) as MultiDiffEditor | undefined ;
122
122
123
123
const session = this . _instantiationService . createInstance ( ChatEditingSession , chatSessionId , editorPane ) ;
124
- const disposeListener = session . onDidDispose ( ( ) => {
124
+ this . _currentSessionDisposeListener . value = session . onDidDispose ( ( ) => {
125
+ this . _currentSessionDisposeListener . clear ( ) ;
125
126
this . _currentSessionObs . set ( null , undefined ) ;
126
- this . _onDidDisposeEditingSession . fire ( session ) ;
127
- disposeListener . dispose ( ) ;
128
127
} ) ;
129
- this . _register ( disposeListener ) ;
130
128
131
129
this . _currentSessionObs . set ( session , undefined ) ;
132
130
this . _onDidCreateEditingSession . fire ( session ) ;
@@ -179,15 +177,6 @@ export class ChatEditingService extends Disposable implements IChatEditingServic
179
177
}
180
178
}
181
179
182
- private _killCurrentEditingSession ( ) {
183
- const currentSession = this . _currentSessionObs . get ( ) ;
184
- if ( currentSession ) {
185
- this . _onDidDisposeEditingSession . fire ( currentSession ) ;
186
- currentSession . dispose ( ) ;
187
- this . _currentSessionObs . set ( null , undefined ) ;
188
- }
189
- }
190
-
191
180
private _findGroupedEditors ( ) {
192
181
const editors : [ IEditorGroup , EditorInput ] [ ] = [ ] ;
193
182
for ( const group of this . _editorGroupsService . groups ) {
@@ -495,7 +484,7 @@ export class ChatEditingStopSessionAction extends Action2 {
495
484
496
485
async run ( accessor : ServicesAccessor , ...args : any [ ] ) : Promise < void > {
497
486
const chatEditingService = accessor . get ( IChatEditingService ) ;
498
- chatEditingService . currentEditingSession ?. dispose ( ) ;
487
+ await chatEditingService . currentEditingSession ?. stop ( ) ;
499
488
}
500
489
}
501
490
registerAction2 ( ChatEditingStopSessionAction ) ;
@@ -572,28 +561,32 @@ class ChatEditingSession extends Disposable implements IChatEditingSession {
572
561
private readonly _state = observableValue < ChatEditingSessionState > ( this , ChatEditingSessionState . Initial ) ;
573
562
private readonly _entriesObs = observableValue < readonly ModifiedFileEntry [ ] > ( this , [ ] ) ;
574
563
public get entries ( ) : IObservable < readonly ModifiedFileEntry [ ] > {
564
+ this . _assertNotDisposed ( ) ;
575
565
return this . _entriesObs ;
576
566
}
577
567
private readonly _sequencer = new Sequencer ( ) ;
578
568
579
569
private _entries : ModifiedFileEntry [ ] = [ ] ;
580
570
581
571
get state ( ) : IObservable < ChatEditingSessionState > {
572
+ this . _assertNotDisposed ( ) ;
582
573
return this . _state ;
583
574
}
584
575
585
- private readonly _editedResources = new ResourceSet ( ) ;
586
576
private readonly _onDidChange = new Emitter < void > ( ) ;
587
577
get onDidChange ( ) {
578
+ this . _assertNotDisposed ( ) ;
588
579
return this . _onDidChange . event ;
589
580
}
590
581
591
582
private readonly _onDidDispose = new Emitter < void > ( ) ;
592
583
get onDidDispose ( ) {
584
+ this . _assertNotDisposed ( ) ;
593
585
return this . _onDidDispose . event ;
594
586
}
595
587
596
588
get isVisible ( ) : boolean {
589
+ this . _assertNotDisposed ( ) ;
597
590
return Boolean ( this . editorPane && this . editorPane . isVisible ( ) ) ;
598
591
}
599
592
@@ -608,10 +601,14 @@ class ChatEditingSession extends Disposable implements IChatEditingSession {
608
601
super ( ) ;
609
602
}
610
603
611
- async accept ( ... uris : URI [ ] ) : Promise < void > {
612
- if ( this . state . get ( ) === ChatEditingSessionState . Disposed ) {
613
- return ;
604
+ private _assertNotDisposed ( ) : void {
605
+ if ( this . _state . get ( ) === ChatEditingSessionState . Disposed ) {
606
+ throw new BugIndicatingError ( `Cannot access a disposed editing session` ) ;
614
607
}
608
+ }
609
+
610
+ async accept ( ...uris : URI [ ] ) : Promise < void > {
611
+ this . _assertNotDisposed ( ) ;
615
612
616
613
if ( uris . length === 0 ) {
617
614
await Promise . all ( this . _entries . map ( entry => entry . accept ( undefined ) ) ) ;
@@ -628,9 +625,7 @@ class ChatEditingSession extends Disposable implements IChatEditingSession {
628
625
}
629
626
630
627
async reject ( ...uris : URI [ ] ) : Promise < void > {
631
- if ( this . state . get ( ) === ChatEditingSessionState . Disposed ) {
632
- return ;
633
- }
628
+ this . _assertNotDisposed ( ) ;
634
629
635
630
if ( uris . length === 0 ) {
636
631
await Promise . all ( this . _entries . map ( entry => entry . reject ( undefined ) ) ) ;
@@ -647,6 +642,8 @@ class ChatEditingSession extends Disposable implements IChatEditingSession {
647
642
}
648
643
649
644
async show ( ) : Promise < void > {
645
+ this . _assertNotDisposed ( ) ;
646
+
650
647
if ( this . editorPane ?. isVisible ( ) ) {
651
648
return ;
652
649
} else if ( this . editorPane ?. input ) {
@@ -663,28 +660,39 @@ class ChatEditingSession extends Disposable implements IChatEditingSession {
663
660
this . editorPane = editorPane ;
664
661
}
665
662
666
- override dispose ( ) {
663
+ async stop ( ) : Promise < void > {
664
+ this . _assertNotDisposed ( ) ;
665
+
667
666
// Close out all open files
668
- this . _editorGroupsService . groups . forEach ( ( g ) => {
669
- g . editors . forEach ( ( e ) => {
667
+ await Promise . allSettled ( this . _editorGroupsService . groups . map ( async ( g ) => {
668
+ return Promise . allSettled ( g . editors . map ( async ( e ) => {
670
669
if ( e instanceof MultiDiffEditorInput || e instanceof DiffEditorInput && ( e . original . resource ?. scheme === ModifiedFileEntry . scheme || e . original . resource ?. scheme === ChatEditingTextModelContentProvider . scheme ) ) {
671
- g . closeEditor ( e ) ;
670
+ await g . closeEditor ( e ) ;
672
671
}
673
- } ) ;
674
- } ) ;
672
+ } ) ) ;
673
+ } ) ) ;
674
+
675
+ this . dispose ( ) ;
676
+ }
677
+
678
+ override dispose ( ) {
679
+ this . _assertNotDisposed ( ) ;
675
680
676
681
super . dispose ( ) ;
677
682
this . _state . set ( ChatEditingSessionState . Disposed , undefined ) ;
678
683
this . _onDidDispose . fire ( ) ;
679
684
}
680
685
681
686
getVirtualModel ( documentId : string ) : ITextModel | null {
687
+ this . _assertNotDisposed ( ) ;
688
+
682
689
const entry = this . _entries . find ( e => e . entryId === documentId ) ;
683
690
return entry ?. docSnapshot ?? null ;
684
691
}
685
692
686
693
acceptStreamingEditsStart ( ) : void {
687
- if ( this . state . get ( ) === ChatEditingSessionState . Disposed ) {
694
+ if ( this . _state . get ( ) === ChatEditingSessionState . Disposed ) {
695
+ // we don't throw in this case because there could be a builder still connected to a disposed session
688
696
return ;
689
697
}
690
698
@@ -693,7 +701,8 @@ class ChatEditingSession extends Disposable implements IChatEditingSession {
693
701
}
694
702
695
703
acceptTextEdits ( resource : URI , textEdits : TextEdit [ ] ) : void {
696
- if ( this . state . get ( ) === ChatEditingSessionState . Disposed ) {
704
+ if ( this . _state . get ( ) === ChatEditingSessionState . Disposed ) {
705
+ // we don't throw in this case because there could be a builder still connected to a disposed session
697
706
return ;
698
707
}
699
708
@@ -702,7 +711,8 @@ class ChatEditingSession extends Disposable implements IChatEditingSession {
702
711
}
703
712
704
713
resolve ( ) : void {
705
- if ( this . state . get ( ) === ChatEditingSessionState . Disposed ) {
714
+ if ( this . _state . get ( ) === ChatEditingSessionState . Disposed ) {
715
+ // we don't throw in this case because there could be a builder still connected to a disposed session
706
716
return ;
707
717
}
708
718
@@ -734,7 +744,6 @@ class ChatEditingSession extends Disposable implements IChatEditingSession {
734
744
this . _register ( entry ) ;
735
745
this . _entries = [ ...this . _entries , entry ] ;
736
746
this . _entriesObs . set ( this . _entries , undefined ) ;
737
- this . _editedResources . add ( resource ) ;
738
747
this . _onDidChange . fire ( ) ;
739
748
740
749
return entry ;
0 commit comments