Skip to content

Commit f593d2e

Browse files
authored
Joh/weird-mink (microsoft#199049)
* fix up wholerange with diff information once all edits are there * update summary when having changes across ranges
1 parent ae25f3a commit f593d2e

File tree

4 files changed

+44
-21
lines changed

4 files changed

+44
-21
lines changed

src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,10 @@ export class InlineChatController implements IEditorContribution {
745745
this._chatAccessibilityService.acceptResponse(a11yResponse, requestId);
746746
}
747747

748+
// todo@jrieken we can likely remove 'trackEdit'
749+
const diff = await this._editorWorkerService.computeDiff(this._activeSession.textModel0.uri, this._activeSession.textModelN.uri, { computeMoves: false, maxComputationTimeMs: Number.MAX_SAFE_INTEGER, ignoreTrimWhitespace: false }, 'advanced');
750+
this._activeSession.wholeRange.fixup(diff?.changes ?? []);
751+
748752
progressiveEditsCts.dispose(true);
749753
requestCts.dispose();
750754
msgListener.dispose();

src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { URI } from 'vs/base/common/uri';
77
import { Emitter, Event } from 'vs/base/common/event';
88
import { ResourceEdit, ResourceFileEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService';
99
import { IWorkspaceTextEdit, TextEdit, WorkspaceEdit } from 'vs/editor/common/languages';
10-
import { IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
10+
import { IModelDecorationOptions, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
1111
import { EditMode, IInlineChatSessionProvider, IInlineChatSession, IInlineChatBulkEditResponse, IInlineChatEditResponse, IInlineChatMessageResponse, IInlineChatResponse, IInlineChatService, InlineChatResponseType, InlineChateResponseTypes } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
1212
import { IRange, Range } from 'vs/editor/common/core/range';
1313
import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser';
@@ -16,15 +16,15 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
1616
import { IModelService } from 'vs/editor/common/services/model';
1717
import { ITextModelService } from 'vs/editor/common/services/resolverService';
1818
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
19-
import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel';
19+
import { ModelDecorationOptions, createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel';
2020
import { ILogService } from 'vs/platform/log/common/log';
2121
import { CancellationToken } from 'vs/base/common/cancellation';
2222
import { Iterable } from 'vs/base/common/iterator';
2323
import { toErrorMessage } from 'vs/base/common/errorMessage';
2424
import { isCancellationError } from 'vs/base/common/errors';
2525
import { EditOperation, ISingleEditOperation } from 'vs/editor/common/core/editOperation';
2626
import { raceCancellation } from 'vs/base/common/async';
27-
import { LineRangeMapping } from 'vs/editor/common/diff/rangeMapping';
27+
import { DetailedLineRangeMapping, LineRangeMapping } from 'vs/editor/common/diff/rangeMapping';
2828
import { IMarkdownString } from 'vs/base/common/htmlContent';
2929
import { IUntitledTextEditorModel } from 'vs/workbench/services/untitled/common/untitledTextEditorModel';
3030
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
@@ -71,12 +71,12 @@ export enum ExpansionState {
7171

7272
class SessionWholeRange {
7373

74-
private static readonly _options = { description: 'inlineChat/session/wholeRange' };
74+
private static readonly _options: IModelDecorationOptions = ModelDecorationOptions.register({ description: 'inlineChat/session/wholeRange' });
7575

7676
private readonly _onDidChange = new Emitter<this>();
7777
readonly onDidChange: Event<this> = this._onDidChange.event;
7878

79-
private readonly _decorationIds: string[] = [];
79+
private _decorationIds: string[] = [];
8080

8181
constructor(private readonly _textModel: ITextModel, wholeRange: IRange) {
8282
this._decorationIds = _textModel.deltaDecorations([], [{ range: wholeRange, options: SessionWholeRange._options }]);
@@ -98,6 +98,22 @@ class SessionWholeRange {
9898
this._onDidChange.fire(this);
9999
}
100100

101+
fixup(changes: readonly DetailedLineRangeMapping[]): void {
102+
103+
const newDeco: IModelDeltaDecoration[] = [];
104+
for (const { modified } of changes) {
105+
const modifiedRange = modified.isEmpty
106+
? new Range(modified.startLineNumber, 1, modified.startLineNumber, this._textModel.getLineLength(modified.startLineNumber))
107+
: new Range(modified.startLineNumber, 1, modified.endLineNumberExclusive - 1, this._textModel.getLineLength(modified.endLineNumberExclusive - 1));
108+
109+
newDeco.push({ range: modifiedRange, options: SessionWholeRange._options });
110+
}
111+
const [first, ...rest] = this._decorationIds; // first is the original whole range
112+
const newIds = this._textModel.deltaDecorations(rest, newDeco);
113+
this._decorationIds = [first].concat(newIds);
114+
this._onDidChange.fire(this);
115+
}
116+
101117
get value(): Range {
102118
let result: Range | undefined;
103119
for (const id of this._decorationIds) {

src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ export class LiveStrategy3 extends EditModeStrategy {
711711
}
712712

713713
private async _computeDiff(): Promise<IDocumentDiff> {
714-
const diff = await this._editorWorkerService.computeDiff(this._session.textModel0.uri, this._session.textModelN.uri, { ignoreTrimWhitespace: false, maxComputationTimeMs: 5000, computeMoves: false }, 'advanced');
714+
const diff = await this._editorWorkerService.computeDiff(this._session.textModel0.uri, this._session.textModelN.uri, { ignoreTrimWhitespace: false, maxComputationTimeMs: Number.MAX_SAFE_INTEGER, computeMoves: false }, 'advanced');
715715

716716
if (!diff || diff.changes.length === 0) {
717717
return { identical: false, quitEarly: false, changes: [], moves: [] };
@@ -750,8 +750,6 @@ export class LiveStrategy3 extends EditModeStrategy {
750750

751751
this._sessionStore.clear();
752752

753-
this._updateSummaryMessage(diff.changes);
754-
755753
if (diff.identical || diff.changes.length === 0) {
756754

757755
if (isAfterManualInteraction) {
@@ -767,10 +765,10 @@ export class LiveStrategy3 extends EditModeStrategy {
767765
const mightContainRTL = this._session.textModel0.mightContainRTL() ?? false;
768766
const renderOptions = RenderOptions.fromEditor(this._editor);
769767

770-
let widgetData: { distance: number; position: Position; actions: IAction[] } | undefined;
771-
772-
for (const { original, modified, innerChanges } of diff.changes) {
768+
let widgetData: { distance: number; position: Position; actions: IAction[]; mapping: LineRangeMapping } | undefined;
773769

770+
for (const mapping of diff.changes) {
771+
const { original, modified, innerChanges } = mapping;
774772
const modifiedRange: Range = modified.isEmpty
775773
? new Range(modified.startLineNumber, 1, modified.startLineNumber, this._session.textModelN.getLineLength(modified.startLineNumber))
776774
: new Range(modified.startLineNumber, 1, modified.endLineNumberExclusive - 1, this._session.textModelN.getLineLength(modified.endLineNumberExclusive - 1));
@@ -895,7 +893,7 @@ export class LiveStrategy3 extends EditModeStrategy {
895893
: zoneLineNumber - modifiedRange.endLineNumber;
896894

897895
if (!widgetData || widgetData.distance > myDistance) {
898-
widgetData = { distance: myDistance, position: modifiedRange.getStartPosition().delta(-1), actions };
896+
widgetData = { distance: myDistance, position: modifiedRange.getStartPosition().delta(-1), mapping, actions };
899897
}
900898
}
901899
}
@@ -904,6 +902,9 @@ export class LiveStrategy3 extends EditModeStrategy {
904902
this._zone.widget.setExtraButtons(widgetData.actions);
905903
this._zone.updatePositionAndHeight(widgetData.position);
906904
this._editor.revealPositionInCenterIfOutsideViewport(widgetData.position);
905+
906+
this._updateSummaryMessage(widgetData.mapping, diff.changes);
907+
907908
}
908909

909910
const decorations = this._editor.createDecorationsCollection(newDecorations);
@@ -940,18 +941,20 @@ export class LiveStrategy3 extends EditModeStrategy {
940941
}
941942
}
942943

943-
protected _updateSummaryMessage(mappings: readonly LineRangeMapping[]) {
944-
let linesChanged = 0;
945-
for (const change of mappings) {
946-
linesChanged += change.changedLineCount;
947-
}
944+
protected _updateSummaryMessage(current: LineRangeMapping, mappings: readonly LineRangeMapping[]) {
945+
const thisLinesChange = current.changedLineCount;
946+
const allLinesChanges = mappings.reduce((total, change) => total + change.changedLineCount, 0);
948947
let message: string;
949-
if (linesChanged === 0) {
948+
if (allLinesChanges === 0) {
950949
message = localize('lines.0', "Nothing changed");
951-
} else if (linesChanged === 1) {
950+
} else if (allLinesChanges === 1) {
952951
message = localize('lines.1', "Changed 1 line");
953952
} else {
954-
message = localize('lines.N', "Changed {0} lines", linesChanged);
953+
if (mappings.length === 1) {
954+
message = localize('lines.N', "Changed {0} lines", allLinesChanges);
955+
} else {
956+
message = localize('lines.NM', "{0} of {1} changed lines", thisLinesChange, allLinesChanges);
957+
}
955958
}
956959
this._zone.widget.updateStatus(message);
957960
}

src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ suite('InteractiveChatController', function () {
296296

297297
await ctrl.waitFor([State.MAKE_REQUEST, State.APPLY_RESPONSE, State.SHOW_RESPONSE, State.WAIT_FOR_INPUT]);
298298

299-
assert.deepStrictEqual(session.wholeRange.value, new Range(1, 1, 4, 12));
299+
assert.deepStrictEqual(session.wholeRange.value, new Range(4, 1, 4, 12));
300300

301301
await ctrl.cancelSession();
302302
await r;

0 commit comments

Comments
 (0)