Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions tests/regression/diff-preview-block-grouping-regression.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,37 @@ const messageHandlerSource = readSource(
"messageHandler.ts",
);

const diffPreviewStepSource = readSource(
[joinFromRoot("webview", "shared", "src", "chat", "components", "activity-steps", "DiffPreviewStep.tsx")],
"DiffPreviewStep.tsx",
);

const activityDiffExcerptSource = readSource(
[joinFromRoot("webview", "shared", "src", "chat", "components", "ActivityDiffExcerpt.tsx")],
"ActivityDiffExcerpt.tsx",
);

test("diff preview keeps the complete patch instead of applying a fixed line cap", () => {
assert.match(
diffPreviewStepSource,
/const excerptLines = diffLines\.filter\(\(line, index\) => index !== firstHunkIndex\)/,
"the parser should retain context and all later hunks",
);
assert.doesNotMatch(
diffPreviewStepSource,
/slice\(0,\s*40\)/,
"the parser must not truncate patches at 40 lines",
);
});

test("diff excerpt resets line numbering for every hunk header", () => {
assert.match(
activityDiffExcerptSource,
/if \(line\.startsWith\("@@"\)\)[\s\S]*?parseHunkHeader\(line\)[\s\S]*?oldN = oldStart[\s\S]*?newN = newStart/s,
"each hunk header should reset old and new line counters",
);
});

// ── parseCentralizedSessionDiffEvent ─────────────────────────────────

test("parseCentralizedSessionDiffEvent handles both session.diff and message.updated event types", () => {
Expand Down
18 changes: 16 additions & 2 deletions webview/shared/src/chat/components/ActivityDiffExcerpt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,25 @@ function computeLineNumbers(
if (parsedHeader.length > 0) {
result.push({ old: null, new: null, line: parsedHeader, isHeader: true });
}
const { oldStart, newStart } =
let { oldStart, newStart } =
parsedHeader.length > 0 ? parseHunkHeader(parsedHeader) : { oldStart: 1, newStart: 1 };
let oldN = oldStart;
let newN = newStart;
for (const line of lines) {
for (const [index, line] of lines.entries()) {
if (line.startsWith("@@")) {
// A complete patch can contain multiple hunks. Reset numbering at each
// subsequent header instead of treating it as a source-code line.
({ oldStart, newStart } = parseHunkHeader(line));
oldN = oldStart;
newN = newStart;
result.push({ old: null, new: null, line, isHeader: true });
continue;
}
// Older callers may include the first header in `lines` as well as in
// `header`; avoid rendering that header twice.
if (index === 0 && parsedHeader.length > 0 && line === parsedHeader) {
continue;
}
if (line.startsWith("+") && !line.startsWith("+++")) {
result.push({ old: null, new: newN++, line, isHeader: false });
} else if (line.startsWith("-") && !line.startsWith("---")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,6 @@ function parsePatchTextToExcerpt(patchText?: string): DiffExcerpt | undefined {
return undefined;
}

const header = lines.find((line) => line.startsWith("@@")) || undefined;

const diffLines = lines.filter(
(line) =>
!line.startsWith("*** Begin Patch") &&
Expand All @@ -163,13 +161,19 @@ function parsePatchTextToExcerpt(patchText?: string): DiffExcerpt | undefined {
!line.startsWith("+++ "),
);

const previewLines = diffLines.slice(0, 40);
const firstHunkIndex = diffLines.findIndex((line) => line.startsWith("@@"));
const header = firstHunkIndex >= 0 ? diffLines[firstHunkIndex] : undefined;

// Keep the complete unified diff, including context and every hunk. The
// modal provides scrolling, so truncating here would hide later changes.
// The first hunk header is supplied separately through `header`.
const excerptLines = diffLines.filter((line, index) => index !== firstHunkIndex);
const added = diffLines.filter((line) => line.startsWith("+") && !line.startsWith("+++")).length;
const deleted = diffLines.filter((line) => line.startsWith("-") && !line.startsWith("---")).length;

return {
header,
lines: previewLines,
lines: excerptLines,
added,
deleted,
};
Expand Down
Loading