Skip to content

Commit 25ab7b2

Browse files
authored
fix: delete files created by chat editing that were subsequently reverted (microsoft#232196)
1 parent 1c39d75 commit 25ab7b2

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingModifiedFileEntry.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { RunOnceScheduler, timeout } from '../../../../../base/common/async.js';
7+
import { Emitter } from '../../../../../base/common/event.js';
78
import { Disposable, IReference, toDisposable } from '../../../../../base/common/lifecycle.js';
89
import { IObservable, ITransaction, observableValue, transaction } from '../../../../../base/common/observable.js';
910
import { themeColorFromId } from '../../../../../base/common/themables.js';
@@ -24,10 +25,11 @@ import { IModelService } from '../../../../../editor/common/services/model.js';
2425
import { IResolvedTextEditorModel, ITextModelService } from '../../../../../editor/common/services/resolverService.js';
2526
import { IModelContentChange, IModelContentChangedEvent } from '../../../../../editor/common/textModelEvents.js';
2627
import { localize } from '../../../../../nls.js';
28+
import { IFileService } from '../../../../../platform/files/common/files.js';
2729
import { editorSelectionBackground } from '../../../../../platform/theme/common/colorRegistry.js';
2830
import { IUndoRedoService } from '../../../../../platform/undoRedo/common/undoRedo.js';
2931
import { IChatAgentResult } from '../../common/chatAgents.js';
30-
import { IModifiedFileEntry, WorkingSetEntryState } from '../../common/chatEditingService.js';
32+
import { ChatEditKind, IModifiedFileEntry, WorkingSetEntryState } from '../../common/chatEditingService.js';
3133
import { IChatService } from '../../common/chatService.js';
3234
import { ChatEditingSnapshotTextModelContentProvider, ChatEditingTextModelContentProvider } from './chatEditingTextModelContentProviders.js';
3335

@@ -40,6 +42,11 @@ export class ChatEditingModifiedFileEntry extends Disposable implements IModifie
4042
public readonly docSnapshot: ITextModel;
4143
private readonly doc: ITextModel;
4244

45+
private readonly _onDidDelete = this._register(new Emitter<void>());
46+
public get onDidDelete() {
47+
return this._onDidDelete.event;
48+
}
49+
4350
get originalURI(): URI {
4451
return this.docSnapshot.uri;
4552
}
@@ -95,6 +102,8 @@ export class ChatEditingModifiedFileEntry extends Disposable implements IModifie
95102
return this._telemetryInfo;
96103
}
97104

105+
readonly createdInRequestId: string | undefined;
106+
98107
get lastModifyingRequestId() {
99108
return this._telemetryInfo.requestId;
100109
}
@@ -104,15 +113,20 @@ export class ChatEditingModifiedFileEntry extends Disposable implements IModifie
104113
resourceRef: IReference<IResolvedTextEditorModel>,
105114
private readonly _multiDiffEntryDelegate: { collapse: (transaction: ITransaction | undefined) => void },
106115
private _telemetryInfo: IModifiedEntryTelemetryInfo,
116+
kind: ChatEditKind,
107117
@IModelService modelService: IModelService,
108118
@ITextModelService textModelService: ITextModelService,
109119
@ILanguageService languageService: ILanguageService,
110120
@IBulkEditService public readonly bulkEditService: IBulkEditService,
111121
@IChatService private readonly _chatService: IChatService,
112122
@IEditorWorkerService private readonly _editorWorkerService: IEditorWorkerService,
113-
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService
123+
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService,
124+
@IFileService private readonly _fileService: IFileService,
114125
) {
115126
super();
127+
if (kind === ChatEditKind.Created) {
128+
this.createdInRequestId = this._telemetryInfo.requestId;
129+
}
116130
this.doc = resourceRef.object.textEditorModel;
117131
const docSnapshot = this.docSnapshot = this._register(
118132
modelService.createModel(
@@ -316,11 +330,16 @@ export class ChatEditingModifiedFileEntry extends Disposable implements IModifie
316330
return;
317331
}
318332

319-
this._setDocValue(this.docSnapshot.getValue());
320-
321333
this._stateObs.set(WorkingSetEntryState.Rejected, transaction);
322-
await this.collapse(transaction);
323334
this._notifyAction('rejected');
335+
if (this.createdInRequestId === this._telemetryInfo.requestId) {
336+
await this._fileService.del(this.resource);
337+
this._onDidDelete.fire();
338+
this.dispose();
339+
} else {
340+
this._setDocValue(this.docSnapshot.getValue());
341+
await this.collapse(transaction);
342+
}
324343
}
325344

326345
private _setDocValue(value: string): void {

src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { IEditorService } from '../../../../services/editor/common/editorService
3030
import { MultiDiffEditor } from '../../../multiDiffEditor/browser/multiDiffEditor.js';
3131
import { MultiDiffEditorInput } from '../../../multiDiffEditor/browser/multiDiffEditorInput.js';
3232
import { ChatAgentLocation, IChatAgentService } from '../../common/chatAgents.js';
33-
import { ChatEditingSessionState, IChatEditingSession, WorkingSetEntryState } from '../../common/chatEditingService.js';
33+
import { ChatEditingSessionState, ChatEditKind, IChatEditingSession, WorkingSetEntryState } from '../../common/chatEditingService.js';
3434
import { IChatResponseModel } from '../../common/chatModel.js';
3535
import { IChatWidgetService } from '../chat.js';
3636
import { ChatEditingMultiDiffSourceResolver } from './chatEditingService.js';
@@ -566,6 +566,15 @@ export class ChatEditingSession extends Disposable implements IChatEditingSessio
566566
if (!this._initialFileContents.has(resource)) {
567567
this._initialFileContents.set(resource, entry.modifiedModel.getValue());
568568
}
569+
// If an entry is deleted e.g. reverting a created file,
570+
// remove it from the entries and don't show it in the working set anymore
571+
// so that it can be recreated e.g. through retry
572+
this._register(entry.onDidDelete(() => {
573+
const newEntries = this._entriesObs.get().filter(e => e.modifiedURI.toString() !== entry.modifiedURI.toString());
574+
this._entriesObs.set(newEntries, undefined);
575+
this._workingSet.delete(entry.modifiedURI);
576+
this._onDidChange.fire();
577+
}));
569578
const entriesArr = [...this._entriesObs.get(), entry];
570579
this._entriesObs.set(entriesArr, undefined);
571580
this._onDidChange.fire();
@@ -576,7 +585,8 @@ export class ChatEditingSession extends Disposable implements IChatEditingSessio
576585
private async _createModifiedFileEntry(resource: URI, responseModel: IModifiedEntryTelemetryInfo, mustExist = false): Promise<ChatEditingModifiedFileEntry> {
577586
try {
578587
const ref = await this._textModelService.createModelReference(resource);
579-
return this._instantiationService.createInstance(ChatEditingModifiedFileEntry, resource, ref, { collapse: (transaction: ITransaction | undefined) => this._collapse(resource, transaction) }, responseModel);
588+
589+
return this._instantiationService.createInstance(ChatEditingModifiedFileEntry, resource, ref, { collapse: (transaction: ITransaction | undefined) => this._collapse(resource, transaction) }, responseModel, mustExist ? ChatEditKind.Created : ChatEditKind.Modified);
580590
} catch (err) {
581591
if (mustExist) {
582592
throw err;

src/vs/workbench/contrib/chat/common/chatEditingService.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,8 @@ export const hasAppliedChatEditsContextKey = new RawContextKey<boolean | undefin
111111

112112
export const chatEditingMaxFileAssignmentName = 'chatEditingSessionFileLimit';
113113
export const defaultChatEditingMaxFileLimit = 10;
114+
115+
export const enum ChatEditKind {
116+
Created,
117+
Modified,
118+
}

0 commit comments

Comments
 (0)