Skip to content

Commit

Permalink
Warning dialog for converting changes to suggestions can be incorrect…
Browse files Browse the repository at this point in the history
… and vague (#6440)

Fixes #6263
  • Loading branch information
alexr00 authored Oct 30, 2024
1 parent ec5d189 commit 6401923
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 16 deletions.
79 changes: 68 additions & 11 deletions src/common/diffHunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,26 +179,83 @@ export function parsePatch(patch: string): DiffHunk[] {
let diffHunkIter = diffHunkReader.next();
const diffHunks: DiffHunk[] = [];

const right: string[] = [];
while (!diffHunkIter.done) {
const diffHunk = diffHunkIter.value;
diffHunks.push(diffHunk);
diffHunkIter = diffHunkReader.next();
}

for (let j = 0; j < diffHunk.diffLines.length; j++) {
const diffLine = diffHunk.diffLines[j];
if (diffLine.type === DiffChangeType.Delete || diffLine.type === DiffChangeType.Control) {
} else if (diffLine.type === DiffChangeType.Add) {
right.push(diffLine.text);
} else {
const codeInFirstLine = diffLine.text;
right.push(codeInFirstLine);
return diffHunks;
}

/**
* Split a hunk into smaller hunks based on the context lines. Position in hunk and control lines are not preserved.
*/
export function splitIntoSmallerHunks(hunk: DiffHunk): DiffHunk[] {
const splitHunks: DiffHunk[] = [];
const newHunk = (fromLine: DiffLine) => {
return {
diffLines: [],
newLength: 0,
oldLength: 0,
oldLineNumber: fromLine.oldLineNumber,
newLineNumber: fromLine.newLineNumber,
positionInHunk: 0
};
};

// Split hunk into smaller hunks on context lines.
// Context lines will be duplicated across the new smaller hunks
let currentHunk: DiffHunk | undefined;
let nextHunk: DiffHunk | undefined;

const addLineToHunk = (hunk: DiffHunk, line: DiffLine) => {
hunk.diffLines.push(line);
if (line.type === DiffChangeType.Delete) {
hunk.oldLength++;
} else if (line.type === DiffChangeType.Add) {
hunk.newLength++;
} else if (line.type === DiffChangeType.Context) {
hunk.oldLength++;
hunk.newLength++;
}
};
const hunkHasChanges = (hunk: DiffHunk) => {
return hunk.diffLines.some(line => line.type !== DiffChangeType.Context);
};
const hunkHasSandwichedChanges = (hunk: DiffHunk) => {
return hunkHasChanges(hunk) && hunk.diffLines[hunk.diffLines.length - 1].type === DiffChangeType.Context;
};

for (const line of hunk.diffLines) {
if (line.type === DiffChangeType.Context) {
if (!currentHunk) {
currentHunk = newHunk(line);
}
addLineToHunk(currentHunk, line);
if (hunkHasSandwichedChanges(currentHunk)) {
if (!nextHunk) {
nextHunk = newHunk(line);
}
addLineToHunk(nextHunk, line);
}
} else if (currentHunk) {
if (hunkHasSandwichedChanges(currentHunk)) {
splitHunks.push(currentHunk);
currentHunk = nextHunk!;
nextHunk = undefined;
}
if ((line.type === DiffChangeType.Delete) || (line.type === DiffChangeType.Add)) {
addLineToHunk(currentHunk, line);
}
}
}

diffHunkIter = diffHunkReader.next();
if (currentHunk) {
splitHunks.push(currentHunk);
}

return diffHunks;
return splitHunks;
}

export function getModifiedContentFromDiffHunk(originalContent: string, patch: string) {
Expand Down
12 changes: 7 additions & 5 deletions src/view/reviewManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as vscode from 'vscode';
import type { Branch, Repository } from '../api/api';
import { GitApiImpl, GitErrorCodes, Status } from '../api/api1';
import { openDescription } from '../commands';
import { DiffChangeType, DiffHunk, parsePatch } from '../common/diffHunk';
import { DiffChangeType, DiffHunk, parsePatch, splitIntoSmallerHunks } from '../common/diffHunk';
import { commands } from '../common/executeCommands';
import { GitChangeType, InMemFileChange, SlimFileChange } from '../common/file';
import Logger from '../common/logger';
Expand Down Expand Up @@ -723,10 +723,12 @@ export class ReviewManager {
let oldLineNumber = hunk.oldLineNumber;
let oldLength = hunk.oldLength;

// start at 1 to skip the control line
let i = 1;
let i = 0;
for (; i < hunk.diffLines.length; i++) {
const line = hunk.diffLines[i];
if (line.type === DiffChangeType.Control) {
continue;
}
if (line.type === DiffChangeType.Context) {
oldLineNumber++;
oldLength--;
Expand All @@ -749,7 +751,7 @@ export class ReviewManager {
// we have only inserted lines, so we need to include a context line so that
// there's a line to anchor the suggestion to
if (i > 1) {
// include from the begginning of the hunk
// include from the beginning of the hunk
i--;
oldLineNumber--;
oldLength++;
Expand Down Expand Up @@ -789,7 +791,7 @@ export class ReviewManager {
if (!resourceStrings.includes(changeFile.uri.toString()) || (changeFile.status !== Status.MODIFIED)) {
return;
}
diff = parsePatch(await this._folderRepoManager.repository.diffWithHEAD(changeFile.uri.fsPath));
diff = parsePatch(await this._folderRepoManager.repository.diffWithHEAD(changeFile.uri.fsPath)).map(hunk => splitIntoSmallerHunks(hunk)).flat();
await Promise.allSettled(diff.map(async hunk => {
try {
await this._reviewCommentController?.createSuggestionsFromChanges(changeFile.uri, this.convertDiffHunkToSuggestion(hunk));
Expand Down

0 comments on commit 6401923

Please sign in to comment.