@pierre/diffs 1.3.0-beta.3 → 1.3.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/File.d.ts +2 -2
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +11 -11
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +7 -4
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +56 -47
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +1 -1
- package/dist/components/VirtualizedFile.d.ts +1 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +7 -3
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +2 -1
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +14 -0
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
- package/dist/editor/editStack.d.ts +1 -1
- package/dist/editor/editor.d.ts +10 -8
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +386 -339
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/editor2.js.map +1 -1
- package/dist/editor/lineAnnotations.d.ts +2 -1
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +111 -1
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +33 -0
- package/dist/editor/marker.d.ts.map +1 -0
- package/dist/editor/marker.js +185 -0
- package/dist/editor/marker.js.map +1 -0
- package/dist/editor/pieceTable.d.ts +2 -2
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +42 -11
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/searchPanel.js +2 -2
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +19 -3
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +188 -37
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/{quickEdit.d.ts → selectionAction.d.ts} +8 -8
- package/dist/editor/selectionAction.d.ts.map +1 -0
- package/dist/editor/{quickEdit.js → selectionAction.js} +18 -18
- package/dist/editor/selectionAction.js.map +1 -0
- package/dist/editor/sprite.d.ts +3 -2
- package/dist/editor/sprite.d.ts.map +1 -1
- package/dist/editor/sprite.js +9 -2
- package/dist/editor/sprite.js.map +1 -1
- package/dist/editor/textDocument.d.ts +4 -4
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +7 -7
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/tokenzier.js +11 -3
- package/dist/editor/tokenzier.js.map +1 -1
- package/dist/editor/utils.d.ts +3 -1
- package/dist/editor/utils.d.ts.map +1 -1
- package/dist/editor/utils.js +16 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/highlighter/shared_highlighter.js +3 -29
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.js +4 -3
- package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.js +3 -2
- package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/constants.d.ts +1 -7
- package/dist/highlighter/themes/constants.d.ts.map +1 -1
- package/dist/highlighter/themes/constants.js +1 -4
- package/dist/highlighter/themes/constants.js.map +1 -1
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js +2 -2
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.js +2 -8
- package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.js +2 -3
- package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +1 -1
- package/dist/highlighter/themes/registerCustomTheme.d.ts +5 -3
- package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.js +15 -5
- package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveTheme.js +6 -27
- package/dist/highlighter/themes/resolveTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveThemes.js +5 -12
- package/dist/highlighter/themes/resolveThemes.js.map +1 -1
- package/dist/highlighter/themes/themeResolution.d.ts +8 -0
- package/dist/highlighter/themes/themeResolution.d.ts.map +1 -0
- package/dist/highlighter/themes/themeResolution.js +22 -0
- package/dist/highlighter/themes/themeResolution.js.map +1 -0
- package/dist/highlighter/themes/themeResolver.d.ts +8 -0
- package/dist/highlighter/themes/themeResolver.d.ts.map +1 -0
- package/dist/highlighter/themes/themeResolver.js +8 -0
- package/dist/highlighter/themes/themeResolver.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/react/index.d.ts +2 -2
- package/dist/react/jsx.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +1 -0
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +4 -1
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +134 -10
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +2 -2
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +5 -5
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/types.d.ts +9 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.js +16 -12
- package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
- package/dist/utils/parsePatchFiles.js +93 -4
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +13 -0
- package/dist/utils/updateDiffHunks.d.ts.map +1 -0
- package/dist/utils/updateDiffHunks.js +171 -0
- package/dist/utils/updateDiffHunks.js.map +1 -0
- package/dist/utils/virtualDiffLayout.d.ts +2 -1
- package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
- package/dist/utils/virtualDiffLayout.js +9 -1
- package/dist/utils/virtualDiffLayout.js.map +1 -1
- package/dist/worker/worker-portable.js +727 -22
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +23 -15
- package/dist/worker/worker.js.map +1 -1
- package/package.json +2 -1
- package/dist/editor/quickEdit.d.ts.map +0 -1
- package/dist/editor/quickEdit.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ALTERNATE_FILE_NAMES_GIT, COMMIT_METADATA_SPLIT, FILENAME_HEADER_REGEX, FILENAME_HEADER_REGEX_GIT, GIT_DIFF_FILE_BREAK_REGEX, INDEX_LINE_METADATA
|
|
1
|
+
import { ALTERNATE_FILE_NAMES_GIT, COMMIT_METADATA_SPLIT, FILENAME_HEADER_REGEX, FILENAME_HEADER_REGEX_GIT, GIT_DIFF_FILE_BREAK_REGEX, INDEX_LINE_METADATA } from "../constants.js";
|
|
2
2
|
import { cleanLastNewline } from "./cleanLastNewline.js";
|
|
3
3
|
import { detachString, releaseStringDetachBuffer } from "./detachString.js";
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ function processPatch(data, cacheKeyPrefix, throwOnError) {
|
|
|
12
12
|
}
|
|
13
13
|
function _processPatch(data, cacheKeyPrefix, throwOnError = false) {
|
|
14
14
|
const isGitDiff = isGitDiffPatch(data);
|
|
15
|
-
const rawFiles = isGitDiff ?
|
|
15
|
+
const rawFiles = isGitDiff ? splitGitDiffFiles(data) : splitUnifiedDiffFiles(data);
|
|
16
16
|
let patchMetadata;
|
|
17
17
|
const files = [];
|
|
18
18
|
for (const fileOrPatchMetadata of rawFiles) {
|
|
@@ -21,7 +21,7 @@ function _processPatch(data, cacheKeyPrefix, throwOnError = false) {
|
|
|
21
21
|
else if (throwOnError) throw Error("parsePatchContent: unknown file blob");
|
|
22
22
|
else console.error("parsePatchContent: unknown file blob:", fileOrPatchMetadata);
|
|
23
23
|
continue;
|
|
24
|
-
} else if (!isGitDiff && !
|
|
24
|
+
} else if (!isGitDiff && !startsWithUnifiedDiffFileHeader(fileOrPatchMetadata)) {
|
|
25
25
|
if (patchMetadata == null) patchMetadata = detachString(fileOrPatchMetadata);
|
|
26
26
|
else if (throwOnError) throw Error("parsePatchContent: unknown file blob");
|
|
27
27
|
else console.error("parsePatchContent: unknown file blob:", fileOrPatchMetadata);
|
|
@@ -160,15 +160,20 @@ function _processFile(fileDiffString, { cacheKey, isGitDiff = GIT_DIFF_FILE_BREA
|
|
|
160
160
|
let parsedDeletionLines = 0;
|
|
161
161
|
for (let lineIndex = 1; lineIndex < lines.length; lineIndex++) {
|
|
162
162
|
const rawLine = lines[lineIndex];
|
|
163
|
-
if (parsedAdditionLines >= hunkData.additionCount && parsedDeletionLines >= hunkData.deletionCount && !rawLine.startsWith("\\"))
|
|
163
|
+
if (parsedAdditionLines >= hunkData.additionCount && parsedDeletionLines >= hunkData.deletionCount && !rawLine.startsWith("\\")) {
|
|
164
|
+
if (throwOnError && isHunkBodyLine(rawLine) && !isFormatPatchVersionSeparator(rawLine)) throw Error("parsePatchContent: hunk has more lines than expected");
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
164
167
|
const firstChar = rawLine[0];
|
|
165
168
|
if (firstChar !== "+" && firstChar !== "-" && firstChar !== " " && firstChar !== "\\") {
|
|
169
|
+
if (throwOnError) throw Error("parsePatchContent: invalid hunk line");
|
|
166
170
|
console.error(`parseLineType: Invalid firstChar: "${firstChar}", full line: "${rawLine}"`);
|
|
167
171
|
console.error("processFile: invalid rawLine:", rawLine);
|
|
168
172
|
continue;
|
|
169
173
|
}
|
|
170
174
|
const type = parseRawLineType(firstChar);
|
|
171
175
|
if (type === "addition") {
|
|
176
|
+
if (throwOnError && parsedAdditionLines >= hunkData.additionCount) throw Error("parsePatchContent: hunk has too many addition lines");
|
|
172
177
|
const line = getParsedLineContent(rawLine);
|
|
173
178
|
if (currentContent == null || currentContent.type !== "change") {
|
|
174
179
|
currentContent = createContentGroup("change", deletionLineIndex, additionLineIndex);
|
|
@@ -181,6 +186,7 @@ function _processFile(fileDiffString, { cacheKey, isGitDiff = GIT_DIFF_FILE_BREA
|
|
|
181
186
|
additionLines++;
|
|
182
187
|
lastLineType = "addition";
|
|
183
188
|
} else if (type === "deletion") {
|
|
189
|
+
if (throwOnError && parsedDeletionLines >= hunkData.deletionCount) throw Error("parsePatchContent: hunk has too many deletion lines");
|
|
184
190
|
const line = getParsedLineContent(rawLine);
|
|
185
191
|
if (currentContent == null || currentContent.type !== "change") {
|
|
186
192
|
currentContent = createContentGroup("change", deletionLineIndex, additionLineIndex);
|
|
@@ -193,6 +199,7 @@ function _processFile(fileDiffString, { cacheKey, isGitDiff = GIT_DIFF_FILE_BREA
|
|
|
193
199
|
deletionLines++;
|
|
194
200
|
lastLineType = "deletion";
|
|
195
201
|
} else if (type === "context") {
|
|
202
|
+
if (throwOnError && (parsedDeletionLines >= hunkData.deletionCount || parsedAdditionLines >= hunkData.additionCount)) throw Error("parsePatchContent: hunk has too many context lines");
|
|
196
203
|
const line = getParsedLineContent(rawLine);
|
|
197
204
|
if (currentContent == null || currentContent.type !== "context") {
|
|
198
205
|
currentContent = createContentGroup("context", deletionLineIndex, additionLineIndex);
|
|
@@ -224,6 +231,7 @@ function _processFile(fileDiffString, { cacheKey, isGitDiff = GIT_DIFF_FILE_BREA
|
|
|
224
231
|
}
|
|
225
232
|
}
|
|
226
233
|
}
|
|
234
|
+
if (throwOnError && (parsedAdditionLines !== hunkData.additionCount || parsedDeletionLines !== hunkData.deletionCount)) throw Error("parsePatchContent: hunk line count mismatch");
|
|
227
235
|
hunkData.additionLines = additionLines;
|
|
228
236
|
hunkData.deletionLines = deletionLines;
|
|
229
237
|
hunkData.collapsedBefore = Math.max(hunkData.additionStart - 1 - lastHunkEnd, 0);
|
|
@@ -242,6 +250,7 @@ function _processFile(fileDiffString, { cacheKey, isGitDiff = GIT_DIFF_FILE_BREA
|
|
|
242
250
|
currentFile.unifiedLineCount += hunkData.collapsedBefore + hunkData.unifiedLineCount;
|
|
243
251
|
}
|
|
244
252
|
if (currentFile == null) return;
|
|
253
|
+
if (throwOnError && isPartial && !isGitDiff && currentFile.hunks.length === 0) throw Error("parsePatchContent: unified file has no hunks");
|
|
245
254
|
if (currentFile.hunks.length > 0 && !isPartial && currentFile.additionLines.length > 0 && currentFile.deletionLines.length > 0) {
|
|
246
255
|
const lastHunk = currentFile.hunks[currentFile.hunks.length - 1];
|
|
247
256
|
const lastHunkEnd$1 = lastHunk.additionStart + lastHunk.additionCount - 1;
|
|
@@ -299,6 +308,86 @@ function splitWithNewlines(contents) {
|
|
|
299
308
|
if (startIndex < contents.length) lines.push(contents.slice(startIndex));
|
|
300
309
|
return lines;
|
|
301
310
|
}
|
|
311
|
+
function splitGitDiffFiles(contents) {
|
|
312
|
+
return splitAtLinePrefix(contents, "diff --git");
|
|
313
|
+
}
|
|
314
|
+
function splitUnifiedDiffFiles(contents) {
|
|
315
|
+
if (contents.length === 0) return [""];
|
|
316
|
+
const parts = [];
|
|
317
|
+
let partStartIndex = 0;
|
|
318
|
+
let lineStartIndex = 0;
|
|
319
|
+
let remainingDeletionLines = 0;
|
|
320
|
+
let remainingAdditionLines = 0;
|
|
321
|
+
let hasOpenedUnifiedFile = false;
|
|
322
|
+
while (lineStartIndex < contents.length) {
|
|
323
|
+
const nextLineStartIndex = getNextLineStartIndex(contents, lineStartIndex);
|
|
324
|
+
if (remainingDeletionLines <= 0 && remainingAdditionLines <= 0) {
|
|
325
|
+
if (isUnifiedDiffFileHeaderAt(contents, lineStartIndex)) {
|
|
326
|
+
if (lineStartIndex > partStartIndex) parts.push(contents.slice(partStartIndex, lineStartIndex));
|
|
327
|
+
partStartIndex = lineStartIndex;
|
|
328
|
+
hasOpenedUnifiedFile = true;
|
|
329
|
+
lineStartIndex = getNextLineStartIndex(contents, nextLineStartIndex);
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (hasOpenedUnifiedFile && contents.startsWith("@@ -", lineStartIndex)) {
|
|
333
|
+
const fileHeader = parseHunkHeader(contents.slice(lineStartIndex, nextLineStartIndex));
|
|
334
|
+
if (fileHeader != null) {
|
|
335
|
+
remainingDeletionLines = fileHeader.deletionCount;
|
|
336
|
+
remainingAdditionLines = fileHeader.additionCount;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
lineStartIndex = nextLineStartIndex;
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const firstChar = contents[lineStartIndex];
|
|
343
|
+
if (firstChar === "\\") {
|
|
344
|
+
lineStartIndex = nextLineStartIndex;
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (firstChar === " ") {
|
|
348
|
+
remainingDeletionLines = Math.max(remainingDeletionLines - 1, 0);
|
|
349
|
+
remainingAdditionLines = Math.max(remainingAdditionLines - 1, 0);
|
|
350
|
+
} else if (firstChar === "-") remainingDeletionLines = Math.max(remainingDeletionLines - 1, 0);
|
|
351
|
+
else if (firstChar === "+") remainingAdditionLines = Math.max(remainingAdditionLines - 1, 0);
|
|
352
|
+
lineStartIndex = nextLineStartIndex;
|
|
353
|
+
}
|
|
354
|
+
parts.push(contents.slice(partStartIndex));
|
|
355
|
+
return parts;
|
|
356
|
+
}
|
|
357
|
+
function startsWithUnifiedDiffFileHeader(contents) {
|
|
358
|
+
return isUnifiedDiffFileHeaderAt(contents, 0);
|
|
359
|
+
}
|
|
360
|
+
function isUnifiedDiffFileHeaderAt(contents, lineStartIndex) {
|
|
361
|
+
const nextLineStartIndex = getNextLineStartIndex(contents, lineStartIndex);
|
|
362
|
+
return isUnifiedDiffHeaderLineAt(contents, lineStartIndex, "---") && isUnifiedDiffHeaderLineAt(contents, nextLineStartIndex, "+++");
|
|
363
|
+
}
|
|
364
|
+
function isUnifiedDiffHeaderLineAt(contents, lineStartIndex, prefix) {
|
|
365
|
+
if (!contents.startsWith(prefix, lineStartIndex)) return false;
|
|
366
|
+
const separator = contents[lineStartIndex + prefix.length];
|
|
367
|
+
if (separator !== " " && separator !== " ") return false;
|
|
368
|
+
for (let index = lineStartIndex + prefix.length + 1; index < contents.length; index++) {
|
|
369
|
+
const char = contents[index];
|
|
370
|
+
if (char === "\n" || char === "\r") break;
|
|
371
|
+
if (char !== " " && char !== " ") return true;
|
|
372
|
+
}
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
function getNextLineStartIndex(contents, lineStartIndex) {
|
|
376
|
+
const newlineIndex = contents.indexOf("\n", lineStartIndex);
|
|
377
|
+
return newlineIndex === -1 ? contents.length : newlineIndex + 1;
|
|
378
|
+
}
|
|
379
|
+
function isHunkBodyLine(line) {
|
|
380
|
+
const firstChar = line[0];
|
|
381
|
+
return firstChar === "+" || firstChar === "-" || firstChar === " ";
|
|
382
|
+
}
|
|
383
|
+
function isFormatPatchVersionSeparator(line) {
|
|
384
|
+
if (!line.startsWith("--")) return false;
|
|
385
|
+
for (let index = 2; index < line.length; index++) {
|
|
386
|
+
const char = line[index];
|
|
387
|
+
if (char !== " " && char !== " " && char !== "\n" && char !== "\r") return false;
|
|
388
|
+
}
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
302
391
|
function parseHunkHeader(line) {
|
|
303
392
|
if (!line.startsWith("@@ -")) return;
|
|
304
393
|
let index = 4;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsePatchFiles.js","names":["patchMetadata: string | undefined","files: FileDiffMetadata[]","currentFile: FileDiffMetadata | undefined","filenameMatch","currentContent: ContextContent | ChangeContent | undefined","lastLineType: 'context' | 'addition' | 'deletion' | undefined","hunkData: Hunk","lastHunkEnd","patches: ParsedPatch[]","lines: string[]","hunkContext: string | undefined","parts: string[]"],"sources":["../../src/utils/parsePatchFiles.ts"],"sourcesContent":["import {\n ALTERNATE_FILE_NAMES_GIT,\n COMMIT_METADATA_SPLIT,\n FILENAME_HEADER_REGEX,\n FILENAME_HEADER_REGEX_GIT,\n GIT_DIFF_FILE_BREAK_REGEX,\n INDEX_LINE_METADATA,\n UNIFIED_DIFF_FILE_BREAK_REGEX,\n} from '../constants';\nimport type {\n ChangeContent,\n ContextContent,\n FileContents,\n FileDiffMetadata,\n Hunk,\n HunkLineType,\n ParsedPatch,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { detachString, releaseStringDetachBuffer } from './detachString';\n\ninterface ParsedHunkHeader {\n additionCount: number;\n additionStart: number;\n deletionCount: number;\n deletionStart: number;\n hunkContext?: string;\n}\n\nexport function processPatch(\n data: string,\n cacheKeyPrefix?: string,\n throwOnError?: boolean\n): ParsedPatch {\n try {\n return _processPatch(data, cacheKeyPrefix, throwOnError);\n } finally {\n releaseStringDetachBuffer();\n }\n}\n\nfunction _processPatch(\n data: string,\n cacheKeyPrefix?: string,\n throwOnError = false\n): ParsedPatch {\n const isGitDiff = isGitDiffPatch(data);\n const rawFiles = isGitDiff\n ? splitAtLinePrefix(data, 'diff --git')\n : data.split(UNIFIED_DIFF_FILE_BREAK_REGEX);\n let patchMetadata: string | undefined;\n const files: FileDiffMetadata[] = [];\n for (const fileOrPatchMetadata of rawFiles) {\n if (isGitDiff && !GIT_DIFF_FILE_BREAK_REGEX.test(fileOrPatchMetadata)) {\n if (patchMetadata == null) {\n patchMetadata = detachString(fileOrPatchMetadata);\n } else {\n if (throwOnError) {\n throw Error('parsePatchContent: unknown file blob');\n } else {\n console.error(\n 'parsePatchContent: unknown file blob:',\n fileOrPatchMetadata\n );\n }\n }\n // If we get in here, it's most likely the introductory metadata from the\n // patch, or something is fucked with the diff format\n continue;\n } else if (\n !isGitDiff &&\n !UNIFIED_DIFF_FILE_BREAK_REGEX.test(fileOrPatchMetadata)\n ) {\n if (patchMetadata == null) {\n patchMetadata = detachString(fileOrPatchMetadata);\n } else {\n if (throwOnError) {\n throw Error('parsePatchContent: unknown file blob');\n } else {\n console.error(\n 'parsePatchContent: unknown file blob:',\n fileOrPatchMetadata\n );\n }\n }\n continue;\n }\n const currentFile = _processFile(fileOrPatchMetadata, {\n cacheKey:\n cacheKeyPrefix != null\n ? `${cacheKeyPrefix}-${files.length}`\n : undefined,\n isGitDiff,\n throwOnError,\n });\n if (currentFile != null) {\n files.push(currentFile);\n }\n }\n return { patchMetadata, files };\n}\n\ninterface ProcessFileOptions {\n cacheKey?: string;\n isGitDiff?: boolean;\n oldFile?: FileContents;\n newFile?: FileContents;\n throwOnError?: boolean;\n}\n\nexport function processFile(\n fileDiffString: string,\n options?: ProcessFileOptions\n): FileDiffMetadata | undefined {\n try {\n return _processFile(fileDiffString, options);\n } finally {\n releaseStringDetachBuffer();\n }\n}\n\nfunction _processFile(\n fileDiffString: string,\n {\n cacheKey,\n isGitDiff = GIT_DIFF_FILE_BREAK_REGEX.test(fileDiffString),\n oldFile,\n newFile,\n throwOnError = false,\n }: ProcessFileOptions = {}\n): FileDiffMetadata | undefined {\n let lastHunkEnd = 0;\n const hunks = splitAtLinePrefix(fileDiffString, '@@ ');\n let currentFile: FileDiffMetadata | undefined;\n const isPartial = oldFile == null || newFile == null;\n let deletionLineIndex = 0;\n let additionLineIndex = 0;\n for (const hunk of hunks) {\n const lines = splitWithNewlines(hunk);\n const firstLine = lines[0];\n if (firstLine == null) {\n if (throwOnError) {\n throw Error('parsePatchContent: invalid hunk');\n } else {\n console.error('parsePatchContent: invalid hunk', hunk);\n }\n continue;\n }\n const fileHeader = parseHunkHeader(firstLine);\n let additionLines = 0;\n let deletionLines = 0;\n // Setup currentFile, this should be the first iteration of our hunks, and\n // technically not a hunk\n if (fileHeader == null || currentFile == null) {\n if (currentFile != null) {\n if (throwOnError) {\n throw Error('parsePatchContent: Invalid hunk');\n } else {\n console.error('parsePatchContent: Invalid hunk', hunk);\n }\n continue;\n }\n currentFile = {\n name: '',\n type: 'change',\n hunks: [],\n splitLineCount: 0,\n unifiedLineCount: 0,\n isPartial,\n additionLines:\n !isPartial && oldFile != null && newFile != null\n ? splitFileContents(newFile.contents)\n : [],\n deletionLines:\n !isPartial && oldFile != null && newFile != null\n ? splitFileContents(oldFile.contents)\n : [],\n cacheKey: maybeDetachOptionalString(cacheKey),\n };\n // If either file is technically empty, then we should empty the\n // arrays respectively\n if (currentFile.additionLines.length === 1 && newFile?.contents === '') {\n currentFile.additionLines.length = 0;\n }\n if (currentFile.deletionLines.length === 1 && oldFile?.contents === '') {\n currentFile.deletionLines.length = 0;\n }\n\n for (const line of lines) {\n if (line.startsWith('diff --git')) {\n const filenameMatch = line.trim().match(ALTERNATE_FILE_NAMES_GIT);\n const prevName = filenameMatch?.[1] ?? filenameMatch?.[2];\n const name = filenameMatch?.[3] ?? filenameMatch?.[4];\n if (prevName == null || name == null) {\n if (throwOnError) {\n throw Error('parsePatchContent: invalid git diff header');\n } else {\n console.error('parsePatchContent: invalid git diff header', line);\n }\n continue;\n }\n currentFile.name = detachString(name.trim());\n if (prevName !== name) {\n currentFile.prevName = detachString(prevName.trim());\n }\n continue;\n }\n\n const filenameMatch =\n line.startsWith('---') || line.startsWith('+++')\n ? line.match(\n isGitDiff ? FILENAME_HEADER_REGEX_GIT : FILENAME_HEADER_REGEX\n )\n : null;\n if (filenameMatch != null) {\n const [, type, fileName] = filenameMatch;\n if (type === '---' && fileName !== '/dev/null') {\n const detachedFileName = detachString(fileName.trim());\n currentFile.prevName = detachedFileName;\n currentFile.name = detachedFileName;\n } else if (type === '+++' && fileName !== '/dev/null') {\n currentFile.name = detachString(fileName.trim());\n }\n }\n // Git diffs have a bunch of additional metadata we can pull from\n else if (isGitDiff) {\n if (line.startsWith('new mode ')) {\n currentFile.mode = detachString(\n line.slice('new mode'.length).trim()\n );\n }\n if (line.startsWith('old mode ')) {\n currentFile.prevMode = detachString(\n line.slice('old mode'.length).trim()\n );\n }\n if (line.startsWith('new file mode')) {\n currentFile.type = 'new';\n currentFile.mode = detachString(\n line.slice('new file mode'.length).trim()\n );\n }\n if (line.startsWith('deleted file mode')) {\n currentFile.type = 'deleted';\n currentFile.mode = detachString(\n line.slice('deleted file mode'.length).trim()\n );\n }\n if (line.startsWith('similarity index')) {\n if (line.startsWith('similarity index 100%')) {\n currentFile.type = 'rename-pure';\n } else {\n currentFile.type = 'rename-changed';\n }\n }\n if (line.startsWith('index ')) {\n const [, prevObjectId, newObjectId, mode] =\n line.trim().match(INDEX_LINE_METADATA) ?? [];\n if (prevObjectId != null) {\n currentFile.prevObjectId = detachString(prevObjectId);\n }\n if (newObjectId != null) {\n currentFile.newObjectId = detachString(newObjectId);\n }\n if (mode != null) {\n currentFile.mode = detachString(mode);\n }\n }\n // We have to handle these for pure renames because there won't be\n // --- and +++ lines\n if (line.startsWith('rename from ')) {\n currentFile.prevName = detachString(\n line.slice('rename from '.length).trim()\n );\n }\n if (line.startsWith('rename to ')) {\n currentFile.name = detachString(\n line.slice('rename to '.length).trim()\n );\n }\n }\n }\n continue;\n }\n\n // Otherwise, time to start parsing out the hunk\n let currentContent: ContextContent | ChangeContent | undefined;\n let lastLineType: 'context' | 'addition' | 'deletion' | undefined;\n\n // Strip trailing bare newlines (format-patch separators between commits)\n // if needed\n while (\n lines.length > 0 &&\n (lines[lines.length - 1] === '\\n' ||\n lines[lines.length - 1] === '\\r' ||\n lines[lines.length - 1] === '\\r\\n' ||\n lines[lines.length - 1] === '')\n ) {\n lines.pop();\n }\n\n const { additionStart, deletionStart } = fileHeader;\n deletionLineIndex = isPartial ? deletionLineIndex : deletionStart - 1;\n additionLineIndex = isPartial ? additionLineIndex : additionStart - 1;\n\n const hunkData: Hunk = {\n collapsedBefore: 0,\n\n splitLineCount: 0,\n splitLineStart: 0,\n\n unifiedLineCount: 0,\n unifiedLineStart: 0,\n\n additionCount: fileHeader.additionCount,\n additionStart,\n additionLines,\n\n deletionCount: fileHeader.deletionCount,\n deletionStart,\n deletionLines,\n\n deletionLineIndex,\n additionLineIndex,\n\n hunkContent: [],\n hunkContext: maybeDetachOptionalString(fileHeader.hunkContext),\n hunkSpecs: detachString(firstLine),\n\n noEOFCRAdditions: false,\n noEOFCRDeletions: false,\n };\n\n // Now we process each line of the hunk\n let parsedAdditionLines = 0;\n let parsedDeletionLines = 0;\n for (let lineIndex = 1; lineIndex < lines.length; lineIndex++) {\n const rawLine = lines[lineIndex];\n if (\n parsedAdditionLines >= hunkData.additionCount &&\n parsedDeletionLines >= hunkData.deletionCount &&\n !rawLine.startsWith('\\\\')\n ) {\n break;\n }\n\n const firstChar = rawLine[0];\n // If we can't properly process the line, well, lets just try to salvage\n // things and continue... It's possible an AI generated diff might have\n // some stray blank lines or something in there\n if (\n firstChar !== '+' &&\n firstChar !== '-' &&\n firstChar !== ' ' &&\n firstChar !== '\\\\'\n ) {\n console.error(\n `parseLineType: Invalid firstChar: \"${firstChar}\", full line: \"${rawLine}\"`\n );\n console.error('processFile: invalid rawLine:', rawLine);\n continue;\n }\n\n const type = parseRawLineType(firstChar);\n if (type === 'addition') {\n const line = getParsedLineContent(rawLine);\n if (currentContent == null || currentContent.type !== 'change') {\n currentContent = createContentGroup(\n 'change',\n deletionLineIndex,\n additionLineIndex\n );\n hunkData.hunkContent.push(currentContent);\n }\n additionLineIndex++;\n parsedAdditionLines++;\n if (isPartial) {\n currentFile.additionLines.push(line);\n }\n currentContent.additions++;\n additionLines++;\n lastLineType = 'addition';\n } else if (type === 'deletion') {\n const line = getParsedLineContent(rawLine);\n if (currentContent == null || currentContent.type !== 'change') {\n currentContent = createContentGroup(\n 'change',\n deletionLineIndex,\n additionLineIndex\n );\n hunkData.hunkContent.push(currentContent);\n }\n deletionLineIndex++;\n parsedDeletionLines++;\n if (isPartial) {\n currentFile.deletionLines.push(line);\n }\n currentContent.deletions++;\n deletionLines++;\n lastLineType = 'deletion';\n } else if (type === 'context') {\n const line = getParsedLineContent(rawLine);\n if (currentContent == null || currentContent.type !== 'context') {\n currentContent = createContentGroup(\n 'context',\n deletionLineIndex,\n additionLineIndex\n );\n hunkData.hunkContent.push(currentContent);\n }\n additionLineIndex++;\n deletionLineIndex++;\n parsedAdditionLines++;\n parsedDeletionLines++;\n if (isPartial) {\n currentFile.deletionLines.push(line);\n currentFile.additionLines.push(line);\n }\n currentContent.lines++;\n lastLineType = 'context';\n } else if (type === 'metadata' && currentContent != null) {\n if (currentContent.type === 'context') {\n hunkData.noEOFCRAdditions = true;\n hunkData.noEOFCRDeletions = true;\n } else if (lastLineType === 'deletion') {\n hunkData.noEOFCRDeletions = true;\n } else if (lastLineType === 'addition') {\n hunkData.noEOFCRAdditions = true;\n }\n // If we're dealing with partial content from a diff, we need to strip\n // newlines manually from the content\n if (\n isPartial &&\n (lastLineType === 'addition' || lastLineType === 'context')\n ) {\n const lastIndex = currentFile.additionLines.length - 1;\n if (lastIndex >= 0) {\n currentFile.additionLines[lastIndex] = cleanLastNewline(\n currentFile.additionLines[lastIndex]\n );\n }\n }\n if (\n isPartial &&\n (lastLineType === 'deletion' || lastLineType === 'context')\n ) {\n const lastIndex = currentFile.deletionLines.length - 1;\n if (lastIndex >= 0) {\n currentFile.deletionLines[lastIndex] = cleanLastNewline(\n currentFile.deletionLines[lastIndex]\n );\n }\n }\n }\n }\n\n hunkData.additionLines = additionLines;\n hunkData.deletionLines = deletionLines;\n\n hunkData.collapsedBefore = Math.max(\n hunkData.additionStart - 1 - lastHunkEnd,\n 0\n );\n currentFile.hunks.push(hunkData);\n lastHunkEnd = hunkData.additionStart + hunkData.additionCount - 1;\n for (const content of hunkData.hunkContent) {\n if (content.type === 'context') {\n hunkData.splitLineCount += content.lines;\n hunkData.unifiedLineCount += content.lines;\n } else {\n hunkData.splitLineCount += Math.max(\n content.additions,\n content.deletions\n );\n hunkData.unifiedLineCount += content.deletions + content.additions;\n }\n }\n hunkData.splitLineStart =\n currentFile.splitLineCount + hunkData.collapsedBefore;\n hunkData.unifiedLineStart =\n currentFile.unifiedLineCount + hunkData.collapsedBefore;\n\n currentFile.splitLineCount +=\n hunkData.collapsedBefore + hunkData.splitLineCount;\n currentFile.unifiedLineCount +=\n hunkData.collapsedBefore + hunkData.unifiedLineCount;\n }\n if (currentFile == null) {\n return undefined;\n }\n\n // Account for collapsed lines after the final hunk and increment the\n // split/unified counts properly\n if (\n currentFile.hunks.length > 0 &&\n !isPartial &&\n currentFile.additionLines.length > 0 &&\n currentFile.deletionLines.length > 0\n ) {\n const lastHunk = currentFile.hunks[currentFile.hunks.length - 1];\n const lastHunkEnd = lastHunk.additionStart + lastHunk.additionCount - 1;\n const totalFileLines = currentFile.additionLines.length;\n const collapsedAfter = Math.max(totalFileLines - lastHunkEnd, 0);\n currentFile.splitLineCount += collapsedAfter;\n currentFile.unifiedLineCount += collapsedAfter;\n }\n\n // If this isn't a git diff style patch, then we'll need to sus out some\n // additional metadata manually\n if (!isGitDiff) {\n if (\n currentFile.prevName != null &&\n currentFile.name !== currentFile.prevName\n ) {\n if (currentFile.hunks.length > 0) {\n currentFile.type = 'rename-changed';\n } else {\n currentFile.type = 'rename-pure';\n }\n }\n // Sort of a hack for detecting deleted/added files...\n else if (\n (oldFile == null || oldFile.contents === '') &&\n newFile != null &&\n newFile.contents !== ''\n ) {\n currentFile.type = 'new';\n } else if (\n oldFile != null &&\n oldFile.contents !== '' &&\n (newFile == null || newFile.contents === '')\n ) {\n currentFile.type = 'deleted';\n }\n }\n if (\n currentFile.type !== 'rename-pure' &&\n currentFile.type !== 'rename-changed'\n ) {\n currentFile.prevName = undefined;\n }\n return currentFile;\n}\n\n/**\n * Parses a patch file string into an array of parsed patches.\n *\n * @param data - The raw patch file content (supports multi-commit patches)\n * @param cacheKeyPrefix - Optional prefix for generating cache keys. When provided,\n * each file in the patch will get a cache key in the format `prefix-patchIndex-fileIndex`.\n * This enables caching of rendered diff results in the worker pool.\n */\nexport function parsePatchFiles(\n data: string,\n cacheKeyPrefix?: string,\n throwOnError = false\n): ParsedPatch[] {\n // NOTE(amadeus): This function is pretty forgiving in that it can accept a\n // patch file that includes commit metdata, multiple commits, or not\n const patches: ParsedPatch[] = [];\n const rawPatches = hasCommitMetadataBoundary(data)\n ? data.split(COMMIT_METADATA_SPLIT)\n : [data];\n for (const patch of rawPatches) {\n try {\n patches.push(\n processPatch(\n patch,\n cacheKeyPrefix != null\n ? `${cacheKeyPrefix}-${patches.length}`\n : undefined,\n throwOnError\n )\n );\n } catch (error) {\n if (throwOnError) {\n throw error;\n } else {\n console.error(error);\n }\n }\n }\n return patches;\n}\n\nfunction hasCommitMetadataBoundary(data: string): boolean {\n return data.startsWith('From ') || data.includes('\\nFrom ');\n}\n\nfunction splitFileContents(contents: string): string[] {\n const lines = splitWithNewlines(contents);\n for (let index = 0; index < lines.length; index++) {\n lines[index] = detachString(lines[index]);\n }\n return lines;\n}\n\nfunction splitWithNewlines(contents: string): string[] {\n if (contents.length === 0) {\n return [''];\n }\n\n const lines: string[] = [];\n let startIndex = 0;\n for (;;) {\n const newlineIndex = contents.indexOf('\\n', startIndex);\n if (newlineIndex === -1) {\n break;\n }\n\n lines.push(contents.slice(startIndex, newlineIndex + 1));\n startIndex = newlineIndex + 1;\n }\n\n if (startIndex < contents.length) {\n lines.push(contents.slice(startIndex));\n }\n return lines;\n}\n\nfunction parseHunkHeader(line: string): ParsedHunkHeader | undefined {\n if (!line.startsWith('@@ -')) {\n return undefined;\n }\n\n let index = 4;\n const deletionStartResult = readPositiveInteger(line, index);\n if (deletionStartResult == null) {\n return undefined;\n }\n const deletionStart = deletionStartResult.value;\n index = deletionStartResult.endIndex;\n\n let deletionCount = 1;\n if (line[index] === ',') {\n const deletionCountResult = readPositiveInteger(line, index + 1);\n if (deletionCountResult == null) {\n return undefined;\n }\n deletionCount = deletionCountResult.value;\n index = deletionCountResult.endIndex;\n }\n\n if (line[index] !== ' ' || line[index + 1] !== '+') {\n return undefined;\n }\n index += 2;\n\n const additionStartResult = readPositiveInteger(line, index);\n if (additionStartResult == null) {\n return undefined;\n }\n const additionStart = additionStartResult.value;\n index = additionStartResult.endIndex;\n\n let additionCount = 1;\n if (line[index] === ',') {\n const additionCountResult = readPositiveInteger(line, index + 1);\n if (additionCountResult == null) {\n return undefined;\n }\n additionCount = additionCountResult.value;\n index = additionCountResult.endIndex;\n }\n\n if (\n line[index] !== ' ' ||\n line[index + 1] !== '@' ||\n line[index + 2] !== '@'\n ) {\n return undefined;\n }\n\n let hunkContext: string | undefined;\n const contextStartIndex = index + 3;\n if (line[contextStartIndex] === ' ') {\n hunkContext = trimLineEnd(line.slice(contextStartIndex + 1));\n }\n\n return {\n additionCount,\n additionStart,\n deletionCount,\n deletionStart,\n hunkContext,\n };\n}\n\nfunction readPositiveInteger(\n value: string,\n startIndex: number\n): { value: number; endIndex: number } | undefined {\n let index = startIndex;\n let parsedValue = 0;\n for (; index < value.length; index++) {\n const digit = value.charCodeAt(index) - 48;\n if (digit < 0 || digit > 9) {\n break;\n }\n parsedValue = parsedValue * 10 + digit;\n }\n\n if (index === startIndex) {\n return undefined;\n }\n return { value: parsedValue, endIndex: index };\n}\n\nfunction trimLineEnd(value: string): string {\n if (value.endsWith('\\r\\n')) {\n return value.slice(0, -2);\n }\n if (value.endsWith('\\n')) {\n return value.slice(0, -1);\n }\n return value;\n}\n\nfunction isGitDiffPatch(data: string): boolean {\n return data.startsWith('diff --git') || data.includes('\\ndiff --git');\n}\n\nfunction splitAtLinePrefix(contents: string, prefix: string): string[] {\n if (contents.length === 0) {\n return [''];\n }\n\n const newlinePrefix = `\\n${prefix}`;\n const firstBoundaryIndex = contents.startsWith(prefix)\n ? 0\n : findLinePrefixIndex(contents, newlinePrefix, 0);\n if (firstBoundaryIndex === -1) {\n return [contents];\n }\n\n const parts: string[] = [];\n if (firstBoundaryIndex > 0) {\n parts.push(contents.slice(0, firstBoundaryIndex));\n }\n\n let startIndex = firstBoundaryIndex;\n for (;;) {\n const nextBoundaryIndex = findLinePrefixIndex(\n contents,\n newlinePrefix,\n startIndex + 1\n );\n if (nextBoundaryIndex === -1) {\n break;\n }\n\n parts.push(contents.slice(startIndex, nextBoundaryIndex));\n startIndex = nextBoundaryIndex;\n }\n parts.push(contents.slice(startIndex));\n return parts;\n}\n\nfunction findLinePrefixIndex(\n contents: string,\n newlinePrefix: string,\n fromIndex: number\n): number {\n const index = contents.indexOf(newlinePrefix, fromIndex);\n return index === -1 ? -1 : index + 1;\n}\n\nfunction maybeDetachOptionalString<T extends string | undefined>(value: T): T {\n return (value == null ? value : detachString(value)) as T;\n}\n\nfunction parseRawLineType(\n firstChar: string | undefined\n): Exclude<HunkLineType, 'expanded'> {\n return firstChar === ' '\n ? 'context'\n : firstChar === '\\\\'\n ? 'metadata'\n : firstChar === '+'\n ? 'addition'\n : 'deletion';\n}\n\nfunction getParsedLineContent(rawLine: string): string {\n const processedLine = rawLine.slice(1);\n return detachString(processedLine === '' ? '\\n' : processedLine);\n}\n\nfunction createContentGroup(\n type: 'change',\n deletionLineIndex: number,\n additionLineIndex: number\n): ChangeContent;\nfunction createContentGroup(\n type: 'context',\n deletionLineIndex: number,\n additionLineIndex: number\n): ContextContent;\nfunction createContentGroup(\n type: 'change' | 'context',\n deletionLineIndex: number,\n additionLineIndex: number\n): ChangeContent | ContextContent {\n if (type === 'change') {\n return {\n type: 'change',\n additions: 0,\n deletions: 0,\n additionLineIndex,\n deletionLineIndex,\n };\n }\n return {\n type: 'context',\n lines: 0,\n additionLineIndex,\n deletionLineIndex,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parsePatchFiles.js","names":["patchMetadata: string | undefined","files: FileDiffMetadata[]","currentFile: FileDiffMetadata | undefined","filenameMatch","currentContent: ContextContent | ChangeContent | undefined","lastLineType: 'context' | 'addition' | 'deletion' | undefined","hunkData: Hunk","lastHunkEnd","patches: ParsedPatch[]","lines: string[]","parts: string[]","hunkContext: string | undefined"],"sources":["../../src/utils/parsePatchFiles.ts"],"sourcesContent":["import {\n ALTERNATE_FILE_NAMES_GIT,\n COMMIT_METADATA_SPLIT,\n FILENAME_HEADER_REGEX,\n FILENAME_HEADER_REGEX_GIT,\n GIT_DIFF_FILE_BREAK_REGEX,\n INDEX_LINE_METADATA,\n} from '../constants';\nimport type {\n ChangeContent,\n ContextContent,\n FileContents,\n FileDiffMetadata,\n Hunk,\n HunkLineType,\n ParsedPatch,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { detachString, releaseStringDetachBuffer } from './detachString';\n\ninterface ParsedHunkHeader {\n additionCount: number;\n additionStart: number;\n deletionCount: number;\n deletionStart: number;\n hunkContext?: string;\n}\n\nexport function processPatch(\n data: string,\n cacheKeyPrefix?: string,\n throwOnError?: boolean\n): ParsedPatch {\n try {\n return _processPatch(data, cacheKeyPrefix, throwOnError);\n } finally {\n releaseStringDetachBuffer();\n }\n}\n\nfunction _processPatch(\n data: string,\n cacheKeyPrefix?: string,\n throwOnError = false\n): ParsedPatch {\n const isGitDiff = isGitDiffPatch(data);\n const rawFiles = isGitDiff\n ? splitGitDiffFiles(data)\n : splitUnifiedDiffFiles(data);\n let patchMetadata: string | undefined;\n const files: FileDiffMetadata[] = [];\n for (const fileOrPatchMetadata of rawFiles) {\n if (isGitDiff && !GIT_DIFF_FILE_BREAK_REGEX.test(fileOrPatchMetadata)) {\n if (patchMetadata == null) {\n patchMetadata = detachString(fileOrPatchMetadata);\n } else {\n if (throwOnError) {\n throw Error('parsePatchContent: unknown file blob');\n } else {\n console.error(\n 'parsePatchContent: unknown file blob:',\n fileOrPatchMetadata\n );\n }\n }\n // If we get in here, it's most likely the introductory metadata from the\n // patch, or something is fucked with the diff format\n continue;\n } else if (\n !isGitDiff &&\n !startsWithUnifiedDiffFileHeader(fileOrPatchMetadata)\n ) {\n if (patchMetadata == null) {\n patchMetadata = detachString(fileOrPatchMetadata);\n } else {\n if (throwOnError) {\n throw Error('parsePatchContent: unknown file blob');\n } else {\n console.error(\n 'parsePatchContent: unknown file blob:',\n fileOrPatchMetadata\n );\n }\n }\n continue;\n }\n const currentFile = _processFile(fileOrPatchMetadata, {\n cacheKey:\n cacheKeyPrefix != null\n ? `${cacheKeyPrefix}-${files.length}`\n : undefined,\n isGitDiff,\n throwOnError,\n });\n if (currentFile != null) {\n files.push(currentFile);\n }\n }\n return { patchMetadata, files };\n}\n\ninterface ProcessFileOptions {\n cacheKey?: string;\n isGitDiff?: boolean;\n oldFile?: FileContents;\n newFile?: FileContents;\n throwOnError?: boolean;\n}\n\nexport function processFile(\n fileDiffString: string,\n options?: ProcessFileOptions\n): FileDiffMetadata | undefined {\n try {\n return _processFile(fileDiffString, options);\n } finally {\n releaseStringDetachBuffer();\n }\n}\n\nfunction _processFile(\n fileDiffString: string,\n {\n cacheKey,\n isGitDiff = GIT_DIFF_FILE_BREAK_REGEX.test(fileDiffString),\n oldFile,\n newFile,\n throwOnError = false,\n }: ProcessFileOptions = {}\n): FileDiffMetadata | undefined {\n let lastHunkEnd = 0;\n const hunks = splitAtLinePrefix(fileDiffString, '@@ ');\n let currentFile: FileDiffMetadata | undefined;\n const isPartial = oldFile == null || newFile == null;\n let deletionLineIndex = 0;\n let additionLineIndex = 0;\n for (const hunk of hunks) {\n const lines = splitWithNewlines(hunk);\n const firstLine = lines[0];\n if (firstLine == null) {\n if (throwOnError) {\n throw Error('parsePatchContent: invalid hunk');\n } else {\n console.error('parsePatchContent: invalid hunk', hunk);\n }\n continue;\n }\n const fileHeader = parseHunkHeader(firstLine);\n let additionLines = 0;\n let deletionLines = 0;\n // Setup currentFile, this should be the first iteration of our hunks, and\n // technically not a hunk\n if (fileHeader == null || currentFile == null) {\n if (currentFile != null) {\n if (throwOnError) {\n throw Error('parsePatchContent: Invalid hunk');\n } else {\n console.error('parsePatchContent: Invalid hunk', hunk);\n }\n continue;\n }\n currentFile = {\n name: '',\n type: 'change',\n hunks: [],\n splitLineCount: 0,\n unifiedLineCount: 0,\n isPartial,\n additionLines:\n !isPartial && oldFile != null && newFile != null\n ? splitFileContents(newFile.contents)\n : [],\n deletionLines:\n !isPartial && oldFile != null && newFile != null\n ? splitFileContents(oldFile.contents)\n : [],\n cacheKey: maybeDetachOptionalString(cacheKey),\n };\n // If either file is technically empty, then we should empty the\n // arrays respectively\n if (currentFile.additionLines.length === 1 && newFile?.contents === '') {\n currentFile.additionLines.length = 0;\n }\n if (currentFile.deletionLines.length === 1 && oldFile?.contents === '') {\n currentFile.deletionLines.length = 0;\n }\n\n for (const line of lines) {\n if (line.startsWith('diff --git')) {\n const filenameMatch = line.trim().match(ALTERNATE_FILE_NAMES_GIT);\n const prevName = filenameMatch?.[1] ?? filenameMatch?.[2];\n const name = filenameMatch?.[3] ?? filenameMatch?.[4];\n if (prevName == null || name == null) {\n if (throwOnError) {\n throw Error('parsePatchContent: invalid git diff header');\n } else {\n console.error('parsePatchContent: invalid git diff header', line);\n }\n continue;\n }\n currentFile.name = detachString(name.trim());\n if (prevName !== name) {\n currentFile.prevName = detachString(prevName.trim());\n }\n continue;\n }\n\n const filenameMatch =\n line.startsWith('---') || line.startsWith('+++')\n ? line.match(\n isGitDiff ? FILENAME_HEADER_REGEX_GIT : FILENAME_HEADER_REGEX\n )\n : null;\n if (filenameMatch != null) {\n const [, type, fileName] = filenameMatch;\n if (type === '---' && fileName !== '/dev/null') {\n const detachedFileName = detachString(fileName.trim());\n currentFile.prevName = detachedFileName;\n currentFile.name = detachedFileName;\n } else if (type === '+++' && fileName !== '/dev/null') {\n currentFile.name = detachString(fileName.trim());\n }\n }\n // Git diffs have a bunch of additional metadata we can pull from\n else if (isGitDiff) {\n if (line.startsWith('new mode ')) {\n currentFile.mode = detachString(\n line.slice('new mode'.length).trim()\n );\n }\n if (line.startsWith('old mode ')) {\n currentFile.prevMode = detachString(\n line.slice('old mode'.length).trim()\n );\n }\n if (line.startsWith('new file mode')) {\n currentFile.type = 'new';\n currentFile.mode = detachString(\n line.slice('new file mode'.length).trim()\n );\n }\n if (line.startsWith('deleted file mode')) {\n currentFile.type = 'deleted';\n currentFile.mode = detachString(\n line.slice('deleted file mode'.length).trim()\n );\n }\n if (line.startsWith('similarity index')) {\n if (line.startsWith('similarity index 100%')) {\n currentFile.type = 'rename-pure';\n } else {\n currentFile.type = 'rename-changed';\n }\n }\n if (line.startsWith('index ')) {\n const [, prevObjectId, newObjectId, mode] =\n line.trim().match(INDEX_LINE_METADATA) ?? [];\n if (prevObjectId != null) {\n currentFile.prevObjectId = detachString(prevObjectId);\n }\n if (newObjectId != null) {\n currentFile.newObjectId = detachString(newObjectId);\n }\n if (mode != null) {\n currentFile.mode = detachString(mode);\n }\n }\n // We have to handle these for pure renames because there won't be\n // --- and +++ lines\n if (line.startsWith('rename from ')) {\n currentFile.prevName = detachString(\n line.slice('rename from '.length).trim()\n );\n }\n if (line.startsWith('rename to ')) {\n currentFile.name = detachString(\n line.slice('rename to '.length).trim()\n );\n }\n }\n }\n continue;\n }\n\n // Otherwise, time to start parsing out the hunk\n let currentContent: ContextContent | ChangeContent | undefined;\n let lastLineType: 'context' | 'addition' | 'deletion' | undefined;\n\n // Strip trailing bare newlines (format-patch separators between commits)\n // if needed\n while (\n lines.length > 0 &&\n (lines[lines.length - 1] === '\\n' ||\n lines[lines.length - 1] === '\\r' ||\n lines[lines.length - 1] === '\\r\\n' ||\n lines[lines.length - 1] === '')\n ) {\n lines.pop();\n }\n\n const { additionStart, deletionStart } = fileHeader;\n deletionLineIndex = isPartial ? deletionLineIndex : deletionStart - 1;\n additionLineIndex = isPartial ? additionLineIndex : additionStart - 1;\n\n const hunkData: Hunk = {\n collapsedBefore: 0,\n\n splitLineCount: 0,\n splitLineStart: 0,\n\n unifiedLineCount: 0,\n unifiedLineStart: 0,\n\n additionCount: fileHeader.additionCount,\n additionStart,\n additionLines,\n\n deletionCount: fileHeader.deletionCount,\n deletionStart,\n deletionLines,\n\n deletionLineIndex,\n additionLineIndex,\n\n hunkContent: [],\n hunkContext: maybeDetachOptionalString(fileHeader.hunkContext),\n hunkSpecs: detachString(firstLine),\n\n noEOFCRAdditions: false,\n noEOFCRDeletions: false,\n };\n\n // Now we process each line of the hunk\n let parsedAdditionLines = 0;\n let parsedDeletionLines = 0;\n for (let lineIndex = 1; lineIndex < lines.length; lineIndex++) {\n const rawLine = lines[lineIndex];\n if (\n parsedAdditionLines >= hunkData.additionCount &&\n parsedDeletionLines >= hunkData.deletionCount &&\n !rawLine.startsWith('\\\\')\n ) {\n if (\n throwOnError &&\n isHunkBodyLine(rawLine) &&\n !isFormatPatchVersionSeparator(rawLine)\n ) {\n throw Error('parsePatchContent: hunk has more lines than expected');\n }\n break;\n }\n\n const firstChar = rawLine[0];\n // If we can't properly process the line, well, lets just try to salvage\n // things and continue... It's possible an AI generated diff might have\n // some stray blank lines or something in there\n if (\n firstChar !== '+' &&\n firstChar !== '-' &&\n firstChar !== ' ' &&\n firstChar !== '\\\\'\n ) {\n if (throwOnError) {\n throw Error('parsePatchContent: invalid hunk line');\n }\n console.error(\n `parseLineType: Invalid firstChar: \"${firstChar}\", full line: \"${rawLine}\"`\n );\n console.error('processFile: invalid rawLine:', rawLine);\n continue;\n }\n\n const type = parseRawLineType(firstChar);\n if (type === 'addition') {\n if (throwOnError && parsedAdditionLines >= hunkData.additionCount) {\n throw Error('parsePatchContent: hunk has too many addition lines');\n }\n const line = getParsedLineContent(rawLine);\n if (currentContent == null || currentContent.type !== 'change') {\n currentContent = createContentGroup(\n 'change',\n deletionLineIndex,\n additionLineIndex\n );\n hunkData.hunkContent.push(currentContent);\n }\n additionLineIndex++;\n parsedAdditionLines++;\n if (isPartial) {\n currentFile.additionLines.push(line);\n }\n currentContent.additions++;\n additionLines++;\n lastLineType = 'addition';\n } else if (type === 'deletion') {\n if (throwOnError && parsedDeletionLines >= hunkData.deletionCount) {\n throw Error('parsePatchContent: hunk has too many deletion lines');\n }\n const line = getParsedLineContent(rawLine);\n if (currentContent == null || currentContent.type !== 'change') {\n currentContent = createContentGroup(\n 'change',\n deletionLineIndex,\n additionLineIndex\n );\n hunkData.hunkContent.push(currentContent);\n }\n deletionLineIndex++;\n parsedDeletionLines++;\n if (isPartial) {\n currentFile.deletionLines.push(line);\n }\n currentContent.deletions++;\n deletionLines++;\n lastLineType = 'deletion';\n } else if (type === 'context') {\n if (\n throwOnError &&\n (parsedDeletionLines >= hunkData.deletionCount ||\n parsedAdditionLines >= hunkData.additionCount)\n ) {\n throw Error('parsePatchContent: hunk has too many context lines');\n }\n const line = getParsedLineContent(rawLine);\n if (currentContent == null || currentContent.type !== 'context') {\n currentContent = createContentGroup(\n 'context',\n deletionLineIndex,\n additionLineIndex\n );\n hunkData.hunkContent.push(currentContent);\n }\n additionLineIndex++;\n deletionLineIndex++;\n parsedAdditionLines++;\n parsedDeletionLines++;\n if (isPartial) {\n currentFile.deletionLines.push(line);\n currentFile.additionLines.push(line);\n }\n currentContent.lines++;\n lastLineType = 'context';\n } else if (type === 'metadata' && currentContent != null) {\n if (currentContent.type === 'context') {\n hunkData.noEOFCRAdditions = true;\n hunkData.noEOFCRDeletions = true;\n } else if (lastLineType === 'deletion') {\n hunkData.noEOFCRDeletions = true;\n } else if (lastLineType === 'addition') {\n hunkData.noEOFCRAdditions = true;\n }\n // If we're dealing with partial content from a diff, we need to strip\n // newlines manually from the content\n if (\n isPartial &&\n (lastLineType === 'addition' || lastLineType === 'context')\n ) {\n const lastIndex = currentFile.additionLines.length - 1;\n if (lastIndex >= 0) {\n currentFile.additionLines[lastIndex] = cleanLastNewline(\n currentFile.additionLines[lastIndex]\n );\n }\n }\n if (\n isPartial &&\n (lastLineType === 'deletion' || lastLineType === 'context')\n ) {\n const lastIndex = currentFile.deletionLines.length - 1;\n if (lastIndex >= 0) {\n currentFile.deletionLines[lastIndex] = cleanLastNewline(\n currentFile.deletionLines[lastIndex]\n );\n }\n }\n }\n }\n\n if (\n throwOnError &&\n (parsedAdditionLines !== hunkData.additionCount ||\n parsedDeletionLines !== hunkData.deletionCount)\n ) {\n throw Error('parsePatchContent: hunk line count mismatch');\n }\n\n hunkData.additionLines = additionLines;\n hunkData.deletionLines = deletionLines;\n\n hunkData.collapsedBefore = Math.max(\n hunkData.additionStart - 1 - lastHunkEnd,\n 0\n );\n currentFile.hunks.push(hunkData);\n lastHunkEnd = hunkData.additionStart + hunkData.additionCount - 1;\n for (const content of hunkData.hunkContent) {\n if (content.type === 'context') {\n hunkData.splitLineCount += content.lines;\n hunkData.unifiedLineCount += content.lines;\n } else {\n hunkData.splitLineCount += Math.max(\n content.additions,\n content.deletions\n );\n hunkData.unifiedLineCount += content.deletions + content.additions;\n }\n }\n hunkData.splitLineStart =\n currentFile.splitLineCount + hunkData.collapsedBefore;\n hunkData.unifiedLineStart =\n currentFile.unifiedLineCount + hunkData.collapsedBefore;\n\n currentFile.splitLineCount +=\n hunkData.collapsedBefore + hunkData.splitLineCount;\n currentFile.unifiedLineCount +=\n hunkData.collapsedBefore + hunkData.unifiedLineCount;\n }\n if (currentFile == null) {\n return undefined;\n }\n if (\n throwOnError &&\n isPartial &&\n !isGitDiff &&\n currentFile.hunks.length === 0\n ) {\n throw Error('parsePatchContent: unified file has no hunks');\n }\n\n // Account for collapsed lines after the final hunk and increment the\n // split/unified counts properly\n if (\n currentFile.hunks.length > 0 &&\n !isPartial &&\n currentFile.additionLines.length > 0 &&\n currentFile.deletionLines.length > 0\n ) {\n const lastHunk = currentFile.hunks[currentFile.hunks.length - 1];\n const lastHunkEnd = lastHunk.additionStart + lastHunk.additionCount - 1;\n const totalFileLines = currentFile.additionLines.length;\n const collapsedAfter = Math.max(totalFileLines - lastHunkEnd, 0);\n currentFile.splitLineCount += collapsedAfter;\n currentFile.unifiedLineCount += collapsedAfter;\n }\n\n // If this isn't a git diff style patch, then we'll need to sus out some\n // additional metadata manually\n if (!isGitDiff) {\n if (\n currentFile.prevName != null &&\n currentFile.name !== currentFile.prevName\n ) {\n if (currentFile.hunks.length > 0) {\n currentFile.type = 'rename-changed';\n } else {\n currentFile.type = 'rename-pure';\n }\n }\n // Sort of a hack for detecting deleted/added files...\n else if (\n (oldFile == null || oldFile.contents === '') &&\n newFile != null &&\n newFile.contents !== ''\n ) {\n currentFile.type = 'new';\n } else if (\n oldFile != null &&\n oldFile.contents !== '' &&\n (newFile == null || newFile.contents === '')\n ) {\n currentFile.type = 'deleted';\n }\n }\n if (\n currentFile.type !== 'rename-pure' &&\n currentFile.type !== 'rename-changed'\n ) {\n currentFile.prevName = undefined;\n }\n return currentFile;\n}\n\n/**\n * Parses a patch file string into an array of parsed patches.\n *\n * @param data - The raw patch file content (supports multi-commit patches)\n * @param cacheKeyPrefix - Optional prefix for generating cache keys. When provided,\n * each file in the patch will get a cache key in the format `prefix-patchIndex-fileIndex`.\n * This enables caching of rendered diff results in the worker pool.\n */\nexport function parsePatchFiles(\n data: string,\n cacheKeyPrefix?: string,\n throwOnError = false\n): ParsedPatch[] {\n // NOTE(amadeus): This function is pretty forgiving in that it can accept a\n // patch file that includes commit metdata, multiple commits, or not\n const patches: ParsedPatch[] = [];\n const rawPatches = hasCommitMetadataBoundary(data)\n ? data.split(COMMIT_METADATA_SPLIT)\n : [data];\n for (const patch of rawPatches) {\n try {\n patches.push(\n processPatch(\n patch,\n cacheKeyPrefix != null\n ? `${cacheKeyPrefix}-${patches.length}`\n : undefined,\n throwOnError\n )\n );\n } catch (error) {\n if (throwOnError) {\n throw error;\n } else {\n console.error(error);\n }\n }\n }\n return patches;\n}\n\nfunction hasCommitMetadataBoundary(data: string): boolean {\n return data.startsWith('From ') || data.includes('\\nFrom ');\n}\n\nfunction splitFileContents(contents: string): string[] {\n const lines = splitWithNewlines(contents);\n for (let index = 0; index < lines.length; index++) {\n lines[index] = detachString(lines[index]);\n }\n return lines;\n}\n\nfunction splitWithNewlines(contents: string): string[] {\n if (contents.length === 0) {\n return [''];\n }\n\n const lines: string[] = [];\n let startIndex = 0;\n for (;;) {\n const newlineIndex = contents.indexOf('\\n', startIndex);\n if (newlineIndex === -1) {\n break;\n }\n\n lines.push(contents.slice(startIndex, newlineIndex + 1));\n startIndex = newlineIndex + 1;\n }\n\n if (startIndex < contents.length) {\n lines.push(contents.slice(startIndex));\n }\n return lines;\n}\n\nfunction splitGitDiffFiles(contents: string): string[] {\n return splitAtLinePrefix(contents, 'diff --git');\n}\n\nfunction splitUnifiedDiffFiles(contents: string): string[] {\n if (contents.length === 0) {\n return [''];\n }\n\n const parts: string[] = [];\n let partStartIndex = 0;\n let lineStartIndex = 0;\n let remainingDeletionLines = 0;\n let remainingAdditionLines = 0;\n let hasOpenedUnifiedFile = false;\n\n while (lineStartIndex < contents.length) {\n const nextLineStartIndex = getNextLineStartIndex(contents, lineStartIndex);\n if (remainingDeletionLines <= 0 && remainingAdditionLines <= 0) {\n if (isUnifiedDiffFileHeaderAt(contents, lineStartIndex)) {\n if (lineStartIndex > partStartIndex) {\n parts.push(contents.slice(partStartIndex, lineStartIndex));\n }\n partStartIndex = lineStartIndex;\n hasOpenedUnifiedFile = true;\n lineStartIndex = getNextLineStartIndex(contents, nextLineStartIndex);\n continue;\n }\n\n if (hasOpenedUnifiedFile && contents.startsWith('@@ -', lineStartIndex)) {\n const fileHeader = parseHunkHeader(\n contents.slice(lineStartIndex, nextLineStartIndex)\n );\n if (fileHeader != null) {\n remainingDeletionLines = fileHeader.deletionCount;\n remainingAdditionLines = fileHeader.additionCount;\n }\n }\n lineStartIndex = nextLineStartIndex;\n continue;\n }\n\n const firstChar = contents[lineStartIndex];\n if (firstChar === '\\\\') {\n lineStartIndex = nextLineStartIndex;\n continue;\n }\n\n if (firstChar === ' ') {\n remainingDeletionLines = Math.max(remainingDeletionLines - 1, 0);\n remainingAdditionLines = Math.max(remainingAdditionLines - 1, 0);\n } else if (firstChar === '-') {\n remainingDeletionLines = Math.max(remainingDeletionLines - 1, 0);\n } else if (firstChar === '+') {\n remainingAdditionLines = Math.max(remainingAdditionLines - 1, 0);\n }\n lineStartIndex = nextLineStartIndex;\n }\n\n parts.push(contents.slice(partStartIndex));\n return parts;\n}\n\nfunction startsWithUnifiedDiffFileHeader(contents: string): boolean {\n return isUnifiedDiffFileHeaderAt(contents, 0);\n}\n\nfunction isUnifiedDiffFileHeaderAt(contents: string, lineStartIndex: number) {\n const nextLineStartIndex = getNextLineStartIndex(contents, lineStartIndex);\n return (\n isUnifiedDiffHeaderLineAt(contents, lineStartIndex, '---') &&\n isUnifiedDiffHeaderLineAt(contents, nextLineStartIndex, '+++')\n );\n}\n\nfunction isUnifiedDiffHeaderLineAt(\n contents: string,\n lineStartIndex: number,\n prefix: '---' | '+++'\n): boolean {\n if (!contents.startsWith(prefix, lineStartIndex)) {\n return false;\n }\n\n const separator = contents[lineStartIndex + prefix.length];\n if (separator !== ' ' && separator !== '\\t') {\n return false;\n }\n\n for (\n let index = lineStartIndex + prefix.length + 1;\n index < contents.length;\n index++\n ) {\n const char = contents[index];\n if (char === '\\n' || char === '\\r') {\n break;\n }\n if (char !== ' ' && char !== '\\t') {\n return true;\n }\n }\n return false;\n}\n\nfunction getNextLineStartIndex(\n contents: string,\n lineStartIndex: number\n): number {\n const newlineIndex = contents.indexOf('\\n', lineStartIndex);\n return newlineIndex === -1 ? contents.length : newlineIndex + 1;\n}\n\nfunction isHunkBodyLine(line: string): boolean {\n const firstChar = line[0];\n return firstChar === '+' || firstChar === '-' || firstChar === ' ';\n}\n\nfunction isFormatPatchVersionSeparator(line: string): boolean {\n if (!line.startsWith('--')) {\n return false;\n }\n\n for (let index = 2; index < line.length; index++) {\n const char = line[index];\n if (char !== ' ' && char !== '\\t' && char !== '\\n' && char !== '\\r') {\n return false;\n }\n }\n return true;\n}\n\nfunction parseHunkHeader(line: string): ParsedHunkHeader | undefined {\n if (!line.startsWith('@@ -')) {\n return undefined;\n }\n\n let index = 4;\n const deletionStartResult = readPositiveInteger(line, index);\n if (deletionStartResult == null) {\n return undefined;\n }\n const deletionStart = deletionStartResult.value;\n index = deletionStartResult.endIndex;\n\n let deletionCount = 1;\n if (line[index] === ',') {\n const deletionCountResult = readPositiveInteger(line, index + 1);\n if (deletionCountResult == null) {\n return undefined;\n }\n deletionCount = deletionCountResult.value;\n index = deletionCountResult.endIndex;\n }\n\n if (line[index] !== ' ' || line[index + 1] !== '+') {\n return undefined;\n }\n index += 2;\n\n const additionStartResult = readPositiveInteger(line, index);\n if (additionStartResult == null) {\n return undefined;\n }\n const additionStart = additionStartResult.value;\n index = additionStartResult.endIndex;\n\n let additionCount = 1;\n if (line[index] === ',') {\n const additionCountResult = readPositiveInteger(line, index + 1);\n if (additionCountResult == null) {\n return undefined;\n }\n additionCount = additionCountResult.value;\n index = additionCountResult.endIndex;\n }\n\n if (\n line[index] !== ' ' ||\n line[index + 1] !== '@' ||\n line[index + 2] !== '@'\n ) {\n return undefined;\n }\n\n let hunkContext: string | undefined;\n const contextStartIndex = index + 3;\n if (line[contextStartIndex] === ' ') {\n hunkContext = trimLineEnd(line.slice(contextStartIndex + 1));\n }\n\n return {\n additionCount,\n additionStart,\n deletionCount,\n deletionStart,\n hunkContext,\n };\n}\n\nfunction readPositiveInteger(\n value: string,\n startIndex: number\n): { value: number; endIndex: number } | undefined {\n let index = startIndex;\n let parsedValue = 0;\n for (; index < value.length; index++) {\n const digit = value.charCodeAt(index) - 48;\n if (digit < 0 || digit > 9) {\n break;\n }\n parsedValue = parsedValue * 10 + digit;\n }\n\n if (index === startIndex) {\n return undefined;\n }\n return { value: parsedValue, endIndex: index };\n}\n\nfunction trimLineEnd(value: string): string {\n if (value.endsWith('\\r\\n')) {\n return value.slice(0, -2);\n }\n if (value.endsWith('\\n')) {\n return value.slice(0, -1);\n }\n return value;\n}\n\nfunction isGitDiffPatch(data: string): boolean {\n return data.startsWith('diff --git') || data.includes('\\ndiff --git');\n}\n\nfunction splitAtLinePrefix(contents: string, prefix: string): string[] {\n if (contents.length === 0) {\n return [''];\n }\n\n const newlinePrefix = `\\n${prefix}`;\n const firstBoundaryIndex = contents.startsWith(prefix)\n ? 0\n : findLinePrefixIndex(contents, newlinePrefix, 0);\n if (firstBoundaryIndex === -1) {\n return [contents];\n }\n\n const parts: string[] = [];\n if (firstBoundaryIndex > 0) {\n parts.push(contents.slice(0, firstBoundaryIndex));\n }\n\n let startIndex = firstBoundaryIndex;\n for (;;) {\n const nextBoundaryIndex = findLinePrefixIndex(\n contents,\n newlinePrefix,\n startIndex + 1\n );\n if (nextBoundaryIndex === -1) {\n break;\n }\n\n parts.push(contents.slice(startIndex, nextBoundaryIndex));\n startIndex = nextBoundaryIndex;\n }\n parts.push(contents.slice(startIndex));\n return parts;\n}\n\nfunction findLinePrefixIndex(\n contents: string,\n newlinePrefix: string,\n fromIndex: number\n): number {\n const index = contents.indexOf(newlinePrefix, fromIndex);\n return index === -1 ? -1 : index + 1;\n}\n\nfunction maybeDetachOptionalString<T extends string | undefined>(value: T): T {\n return (value == null ? value : detachString(value)) as T;\n}\n\nfunction parseRawLineType(\n firstChar: string | undefined\n): Exclude<HunkLineType, 'expanded'> {\n return firstChar === ' '\n ? 'context'\n : firstChar === '\\\\'\n ? 'metadata'\n : firstChar === '+'\n ? 'addition'\n : 'deletion';\n}\n\nfunction getParsedLineContent(rawLine: string): string {\n const processedLine = rawLine.slice(1);\n return detachString(processedLine === '' ? '\\n' : processedLine);\n}\n\nfunction createContentGroup(\n type: 'change',\n deletionLineIndex: number,\n additionLineIndex: number\n): ChangeContent;\nfunction createContentGroup(\n type: 'context',\n deletionLineIndex: number,\n additionLineIndex: number\n): ContextContent;\nfunction createContentGroup(\n type: 'change' | 'context',\n deletionLineIndex: number,\n additionLineIndex: number\n): ChangeContent | ContextContent {\n if (type === 'change') {\n return {\n type: 'change',\n additions: 0,\n deletions: 0,\n additionLineIndex,\n deletionLineIndex,\n };\n }\n return {\n type: 'context',\n lines: 0,\n additionLineIndex,\n deletionLineIndex,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FileDiffMetadata } from "../types.js";
|
|
2
|
+
import { CreatePatchOptionsNonabortable } from "diff";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/updateDiffHunks.d.ts
|
|
5
|
+
type HunkMetadataUpdate = Pick<FileDiffMetadata, 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'type'>;
|
|
6
|
+
type FullDiffHunkUpdate = HunkMetadataUpdate & Pick<FileDiffMetadata, 'additionLines' | 'deletionLines'>;
|
|
7
|
+
/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */
|
|
8
|
+
declare function recomputeDiffHunks(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
|
|
9
|
+
/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */
|
|
10
|
+
declare function updateDiffHunks(diff: FileDiffMetadata, changedAdditionLineIndexes: Iterable<number>, parseDiffOptions?: CreatePatchOptionsNonabortable): HunkMetadataUpdate;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { recomputeDiffHunks, updateDiffHunks };
|
|
13
|
+
//# sourceMappingURL=updateDiffHunks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateDiffHunks.d.ts","names":["CreatePatchOptionsNonabortable","FileDiffMetadata","HunkMetadataUpdate","Pick","FullDiffHunkUpdate","recomputeDiffHunks","updateDiffHunks","Iterable"],"sources":["../../src/utils/updateDiffHunks.d.ts"],"sourcesContent":["import type { CreatePatchOptionsNonabortable } from 'diff';\nimport type { FileDiffMetadata } from '../types';\ntype HunkMetadataUpdate = Pick<FileDiffMetadata, 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'type'>;\ntype FullDiffHunkUpdate = HunkMetadataUpdate & Pick<FileDiffMetadata, 'additionLines' | 'deletionLines'>;\n/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */\nexport declare function recomputeDiffHunks(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;\n/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */\nexport declare function updateDiffHunks(diff: FileDiffMetadata, changedAdditionLineIndexes: Iterable<number>, parseDiffOptions?: CreatePatchOptionsNonabortable): HunkMetadataUpdate;\nexport {};\n//# sourceMappingURL=updateDiffHunks.d.ts.map"],"mappings":";;;;KAEKE,kBAAAA,GAAqBC,KAAKF;KAC1BG,kBAAAA,GAAqBF,qBAAqBC,KAAKF;AAFH;AAE5CG,iBAEmBC,kBAAAA,CAFD,IAAA,EAE0BJ,gBAF1B,EAAA,gBAAA,CAAA,EAE+DD,8BAF/D,CAAA,EAEgGI,kBAFhG;;AAA6BH,iBAI5BK,eAAAA,CAJ4BL,IAAAA,EAINA,gBAJMA,EAAAA,0BAAAA,EAIwCM,QAJxCN,CAAAA,MAAAA,CAAAA,EAAAA,gBAAAA,CAAAA,EAI6ED,8BAJ7EC,CAAAA,EAI8GC,kBAJ9GD"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { hasTrailingContextMismatch } from "./virtualDiffLayout.js";
|
|
2
|
+
import { cleanLastNewline } from "./cleanLastNewline.js";
|
|
3
|
+
import { parseDiffFromFile } from "./parseDiffFromFile.js";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/updateDiffHunks.ts
|
|
6
|
+
/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */
|
|
7
|
+
function recomputeDiffHunks(diff, parseDiffOptions) {
|
|
8
|
+
const recomputed = parseDiffFromFile({
|
|
9
|
+
name: diff.prevName ?? diff.name,
|
|
10
|
+
contents: diff.deletionLines.join("")
|
|
11
|
+
}, {
|
|
12
|
+
name: diff.name,
|
|
13
|
+
contents: diff.additionLines.join(""),
|
|
14
|
+
lang: diff.lang
|
|
15
|
+
}, parseDiffOptions);
|
|
16
|
+
return {
|
|
17
|
+
hunks: recomputed.hunks,
|
|
18
|
+
splitLineCount: recomputed.splitLineCount,
|
|
19
|
+
unifiedLineCount: recomputed.unifiedLineCount,
|
|
20
|
+
additionLines: recomputed.additionLines,
|
|
21
|
+
deletionLines: recomputed.deletionLines,
|
|
22
|
+
type: recomputed.type
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */
|
|
26
|
+
function updateDiffHunks(diff, changedAdditionLineIndexes, parseDiffOptions) {
|
|
27
|
+
if (diff.isPartial) return applyHunkUpdateResult(diff, recomputeDiffHunks(diff, parseDiffOptions));
|
|
28
|
+
if (diff.deletionLines.length !== diff.additionLines.length) return applyHunkUpdateResult(diff, recomputeDiffHunks(diff, parseDiffOptions));
|
|
29
|
+
const changedLines = Array.from(changedAdditionLineIndexes);
|
|
30
|
+
if (changedLines.length === 0) return applyHunkUpdateResult(diff, {
|
|
31
|
+
hunks: diff.hunks,
|
|
32
|
+
splitLineCount: diff.splitLineCount,
|
|
33
|
+
unifiedLineCount: diff.unifiedLineCount,
|
|
34
|
+
type: diff.type
|
|
35
|
+
});
|
|
36
|
+
for (const line of changedLines) {
|
|
37
|
+
const additionLine = diff.additionLines[line];
|
|
38
|
+
const deletionLine = diff.deletionLines[line];
|
|
39
|
+
if (additionLine == null || deletionLine == null) return applyHunkUpdateResult(diff, recomputeDiffHunks(diff, parseDiffOptions));
|
|
40
|
+
if (cleanLastNewline(additionLine) === cleanLastNewline(deletionLine)) return applyHunkUpdateResult(diff, recomputeDiffHunks(diff, parseDiffOptions));
|
|
41
|
+
}
|
|
42
|
+
const affectedHunkIndexes = getAffectedHunkIndexes(diff, changedLines);
|
|
43
|
+
if (affectedHunkIndexes.size === 0) return applyHunkUpdateResult(diff, recomputeDiffHunks(diff, parseDiffOptions));
|
|
44
|
+
for (const hunkIndex of affectedHunkIndexes) if (!reparseHunkRegion(diff, hunkIndex, parseDiffOptions)) return applyHunkUpdateResult(diff, recomputeDiffHunks(diff, parseDiffOptions));
|
|
45
|
+
recomputeDiffRenderLineCounts(diff);
|
|
46
|
+
if (hasTrailingContextMismatch(diff)) return applyHunkUpdateResult(diff, recomputeDiffHunks(diff, parseDiffOptions));
|
|
47
|
+
return applyHunkUpdateResult(diff, {
|
|
48
|
+
hunks: diff.hunks,
|
|
49
|
+
splitLineCount: diff.splitLineCount,
|
|
50
|
+
unifiedLineCount: diff.unifiedLineCount,
|
|
51
|
+
type: diff.type
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function applyHunkUpdateResult(diff, result) {
|
|
55
|
+
Object.assign(diff, result);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
function getAffectedHunkIndexes(diff, changedAdditionLineIndexes) {
|
|
59
|
+
const indexes = /* @__PURE__ */ new Set();
|
|
60
|
+
for (const line of changedAdditionLineIndexes) {
|
|
61
|
+
const hunkIndex = findHunkIndexForAdditionLine(diff, line);
|
|
62
|
+
if (hunkIndex == null) return /* @__PURE__ */ new Set();
|
|
63
|
+
indexes.add(hunkIndex);
|
|
64
|
+
}
|
|
65
|
+
return indexes;
|
|
66
|
+
}
|
|
67
|
+
function findHunkIndexForAdditionLine(diff, line) {
|
|
68
|
+
for (const [hunkIndex, hunk] of diff.hunks.entries()) {
|
|
69
|
+
const end = hunk.additionLineIndex + hunk.additionCount;
|
|
70
|
+
if (line >= hunk.additionLineIndex && line < end) return hunkIndex;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function reparseHunkRegion(diff, hunkIndex, parseDiffOptions) {
|
|
74
|
+
const hunk = diff.hunks[hunkIndex];
|
|
75
|
+
if (hunk == null) return false;
|
|
76
|
+
const deletionSlice = diff.deletionLines.slice(hunk.deletionLineIndex, hunk.deletionLineIndex + hunk.deletionCount);
|
|
77
|
+
const additionSlice = diff.additionLines.slice(hunk.additionLineIndex, hunk.additionLineIndex + hunk.additionCount);
|
|
78
|
+
const reparsed = parseDiffFromFile({
|
|
79
|
+
name: diff.prevName ?? diff.name,
|
|
80
|
+
contents: deletionSlice.join("")
|
|
81
|
+
}, {
|
|
82
|
+
name: diff.name,
|
|
83
|
+
contents: additionSlice.join(""),
|
|
84
|
+
lang: diff.lang
|
|
85
|
+
}, {
|
|
86
|
+
...parseDiffOptions,
|
|
87
|
+
context: 0
|
|
88
|
+
});
|
|
89
|
+
const reparsedHunk = reparsed.hunks[0];
|
|
90
|
+
if (reparsedHunk == null || reparsed.hunks.length !== 1) return false;
|
|
91
|
+
applyReparsedHunk(hunk, reparsedHunk);
|
|
92
|
+
syncHunkNoEOFCRFromFullFile(diff, hunkIndex);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
function syncHunkNoEOFCRFromFullFile(diff, hunkIndex) {
|
|
96
|
+
const hunk = diff.hunks[hunkIndex];
|
|
97
|
+
if (hunk == null) return;
|
|
98
|
+
if (!(hunkIndex === diff.hunks.length - 1)) {
|
|
99
|
+
hunk.noEOFCRAdditions = false;
|
|
100
|
+
hunk.noEOFCRDeletions = false;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const lastAdditionLine = diff.additionLines.at(-1);
|
|
104
|
+
const lastDeletionLine = diff.deletionLines.at(-1);
|
|
105
|
+
hunk.noEOFCRAdditions = lastAdditionLine != null && lastAdditionLine !== "" && !lastAdditionLine.endsWith("\n");
|
|
106
|
+
hunk.noEOFCRDeletions = lastDeletionLine != null && lastDeletionLine !== "" && !lastDeletionLine.endsWith("\n");
|
|
107
|
+
}
|
|
108
|
+
function applyReparsedHunk(target, parsed) {
|
|
109
|
+
const additionOffset = target.additionLineIndex;
|
|
110
|
+
const deletionOffset = target.deletionLineIndex;
|
|
111
|
+
target.hunkContent = parsed.hunkContent.map((content) => offsetHunkContent(content, additionOffset, deletionOffset));
|
|
112
|
+
target.additionLineIndex = additionOffset + parsed.additionLineIndex;
|
|
113
|
+
target.additionStart = target.additionStart + parsed.additionLineIndex;
|
|
114
|
+
target.additionCount = parsed.additionCount;
|
|
115
|
+
target.additionLines = parsed.additionLines;
|
|
116
|
+
if (parsed.deletionLineIndex >= 0) {
|
|
117
|
+
target.deletionLineIndex = deletionOffset + parsed.deletionLineIndex;
|
|
118
|
+
target.deletionStart = target.deletionStart + parsed.deletionLineIndex;
|
|
119
|
+
}
|
|
120
|
+
target.deletionCount = parsed.deletionCount;
|
|
121
|
+
target.deletionLines = parsed.deletionLines;
|
|
122
|
+
target.noEOFCRAdditions = parsed.noEOFCRAdditions;
|
|
123
|
+
target.noEOFCRDeletions = parsed.noEOFCRDeletions;
|
|
124
|
+
recomputeHunkRenderLineCounts(target);
|
|
125
|
+
}
|
|
126
|
+
function offsetHunkContent(content, additionOffset, deletionOffset) {
|
|
127
|
+
return {
|
|
128
|
+
...content,
|
|
129
|
+
additionLineIndex: content.additionLineIndex + additionOffset,
|
|
130
|
+
deletionLineIndex: content.deletionLineIndex + deletionOffset
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function recomputeHunkRenderLineCounts(hunk) {
|
|
134
|
+
let splitLineCount = 0;
|
|
135
|
+
let unifiedLineCount = 0;
|
|
136
|
+
for (const content of hunk.hunkContent) if (content.type === "context") {
|
|
137
|
+
splitLineCount += content.lines;
|
|
138
|
+
unifiedLineCount += content.lines;
|
|
139
|
+
} else {
|
|
140
|
+
splitLineCount += Math.max(content.additions, content.deletions);
|
|
141
|
+
unifiedLineCount += content.additions + content.deletions;
|
|
142
|
+
}
|
|
143
|
+
hunk.splitLineCount = splitLineCount;
|
|
144
|
+
hunk.unifiedLineCount = unifiedLineCount;
|
|
145
|
+
}
|
|
146
|
+
function recomputeDiffRenderLineCounts(diff) {
|
|
147
|
+
let splitTotal = 0;
|
|
148
|
+
let unifiedTotal = 0;
|
|
149
|
+
let lastHunkAdditionEnd = 0;
|
|
150
|
+
for (const hunk of diff.hunks) {
|
|
151
|
+
hunk.collapsedBefore = Math.max(hunk.additionStart - 1 - lastHunkAdditionEnd, 0);
|
|
152
|
+
hunk.splitLineStart = splitTotal + hunk.collapsedBefore;
|
|
153
|
+
hunk.unifiedLineStart = unifiedTotal + hunk.collapsedBefore;
|
|
154
|
+
recomputeHunkRenderLineCounts(hunk);
|
|
155
|
+
splitTotal += hunk.collapsedBefore + hunk.splitLineCount;
|
|
156
|
+
unifiedTotal += hunk.collapsedBefore + hunk.unifiedLineCount;
|
|
157
|
+
lastHunkAdditionEnd = hunk.additionStart + hunk.additionCount - 1;
|
|
158
|
+
}
|
|
159
|
+
if (diff.hunks.length > 0) {
|
|
160
|
+
const lastHunk = diff.hunks[diff.hunks.length - 1];
|
|
161
|
+
const collapsedAfter = Math.max(diff.additionLines.length - (lastHunk.additionLineIndex + lastHunk.additionCount), 0);
|
|
162
|
+
splitTotal += collapsedAfter;
|
|
163
|
+
unifiedTotal += collapsedAfter;
|
|
164
|
+
}
|
|
165
|
+
diff.splitLineCount = splitTotal;
|
|
166
|
+
diff.unifiedLineCount = unifiedTotal;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
//#endregion
|
|
170
|
+
export { recomputeDiffHunks, updateDiffHunks };
|
|
171
|
+
//# sourceMappingURL=updateDiffHunks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateDiffHunks.js","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"sourcesContent":["import type { CreatePatchOptionsNonabortable } from 'diff';\n\nimport type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { parseDiffFromFile } from './parseDiffFromFile';\nimport { hasTrailingContextMismatch } from './virtualDiffLayout';\n\ntype HunkContent = ContextContent | ChangeContent;\n\ntype HunkMetadataUpdate = Pick<\n FileDiffMetadata,\n 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'type'\n>;\n\ntype FullDiffHunkUpdate = HunkMetadataUpdate &\n Pick<FileDiffMetadata, 'additionLines' | 'deletionLines'>;\n\n/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */\nexport function recomputeDiffHunks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: diff.deletionLines.join(''),\n },\n {\n name: diff.name,\n contents: diff.additionLines.join(''),\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines: recomputed.additionLines,\n deletionLines: recomputed.deletionLines,\n type: recomputed.type,\n };\n}\n\n/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */\nexport function updateDiffHunks(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): HunkMetadataUpdate {\n if (diff.isPartial) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n if (diff.deletionLines.length !== diff.additionLines.length) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n const changedLines = Array.from(changedAdditionLineIndexes);\n if (changedLines.length === 0) {\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n }\n for (const line of changedLines) {\n const additionLine = diff.additionLines[line];\n const deletionLine = diff.deletionLines[line];\n if (additionLine == null || deletionLine == null) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n // Restoring a line to the old side can merge/split hunks across context windows.\n if (cleanLastNewline(additionLine) === cleanLastNewline(deletionLine)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n const affectedHunkIndexes = getAffectedHunkIndexes(diff, changedLines);\n if (affectedHunkIndexes.size === 0) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n for (const hunkIndex of affectedHunkIndexes) {\n const updated = reparseHunkRegion(diff, hunkIndex, parseDiffOptions);\n if (!updated) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n recomputeDiffRenderLineCounts(diff);\n\n if (hasTrailingContextMismatch(diff)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n}\n\nfunction applyHunkUpdateResult<T extends HunkMetadataUpdate>(\n diff: FileDiffMetadata,\n result: T\n): T {\n Object.assign(diff, result);\n return result;\n}\n\nfunction getAffectedHunkIndexes(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>\n): Set<number> {\n const indexes = new Set<number>();\n for (const line of changedAdditionLineIndexes) {\n const hunkIndex = findHunkIndexForAdditionLine(diff, line);\n if (hunkIndex == null) {\n return new Set();\n }\n indexes.add(hunkIndex);\n }\n return indexes;\n}\n\nfunction findHunkIndexForAdditionLine(\n diff: FileDiffMetadata,\n line: number\n): number | undefined {\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const end = hunk.additionLineIndex + hunk.additionCount;\n if (line >= hunk.additionLineIndex && line < end) {\n return hunkIndex;\n }\n }\n return undefined;\n}\n\nfunction reparseHunkRegion(\n diff: FileDiffMetadata,\n hunkIndex: number,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): boolean {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return false;\n }\n\n const deletionSlice = diff.deletionLines.slice(\n hunk.deletionLineIndex,\n hunk.deletionLineIndex + hunk.deletionCount\n );\n const additionSlice = diff.additionLines.slice(\n hunk.additionLineIndex,\n hunk.additionLineIndex + hunk.additionCount\n );\n\n const reparsed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionSlice.join(''),\n },\n {\n name: diff.name,\n contents: additionSlice.join(''),\n lang: diff.lang,\n },\n { ...parseDiffOptions, context: 0 }\n );\n\n const reparsedHunk = reparsed.hunks[0];\n if (reparsedHunk == null || reparsed.hunks.length !== 1) {\n return false;\n }\n\n applyReparsedHunk(hunk, reparsedHunk);\n syncHunkNoEOFCRFromFullFile(diff, hunkIndex);\n return true;\n}\n\nfunction syncHunkNoEOFCRFromFullFile(\n diff: FileDiffMetadata,\n hunkIndex: number\n): void {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return;\n }\n\n const isLastHunk = hunkIndex === diff.hunks.length - 1;\n if (!isLastHunk) {\n hunk.noEOFCRAdditions = false;\n hunk.noEOFCRDeletions = false;\n return;\n }\n\n const lastAdditionLine = diff.additionLines.at(-1);\n const lastDeletionLine = diff.deletionLines.at(-1);\n hunk.noEOFCRAdditions =\n lastAdditionLine != null &&\n lastAdditionLine !== '' &&\n !lastAdditionLine.endsWith('\\n');\n hunk.noEOFCRDeletions =\n lastDeletionLine != null &&\n lastDeletionLine !== '' &&\n !lastDeletionLine.endsWith('\\n');\n}\n\nfunction applyReparsedHunk(target: Hunk, parsed: Hunk): void {\n const additionOffset = target.additionLineIndex;\n const deletionOffset = target.deletionLineIndex;\n\n target.hunkContent = parsed.hunkContent.map((content) =>\n offsetHunkContent(content, additionOffset, deletionOffset)\n );\n target.additionLineIndex = additionOffset + parsed.additionLineIndex;\n target.additionStart = target.additionStart + parsed.additionLineIndex;\n target.additionCount = parsed.additionCount;\n target.additionLines = parsed.additionLines;\n if (parsed.deletionLineIndex >= 0) {\n target.deletionLineIndex = deletionOffset + parsed.deletionLineIndex;\n target.deletionStart = target.deletionStart + parsed.deletionLineIndex;\n }\n target.deletionCount = parsed.deletionCount;\n target.deletionLines = parsed.deletionLines;\n target.noEOFCRAdditions = parsed.noEOFCRAdditions;\n target.noEOFCRDeletions = parsed.noEOFCRDeletions;\n\n recomputeHunkRenderLineCounts(target);\n}\n\nfunction offsetHunkContent(\n content: HunkContent,\n additionOffset: number,\n deletionOffset: number\n): HunkContent {\n return {\n ...content,\n additionLineIndex: content.additionLineIndex + additionOffset,\n deletionLineIndex: content.deletionLineIndex + deletionOffset,\n };\n}\n\nfunction recomputeHunkRenderLineCounts(hunk: Hunk): void {\n let splitLineCount = 0;\n let unifiedLineCount = 0;\n\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n splitLineCount += content.lines;\n unifiedLineCount += content.lines;\n } else {\n splitLineCount += Math.max(content.additions, content.deletions);\n unifiedLineCount += content.additions + content.deletions;\n }\n }\n\n hunk.splitLineCount = splitLineCount;\n hunk.unifiedLineCount = unifiedLineCount;\n}\n\nfunction recomputeDiffRenderLineCounts(diff: FileDiffMetadata): void {\n let splitTotal = 0;\n let unifiedTotal = 0;\n let lastHunkAdditionEnd = 0;\n\n for (const hunk of diff.hunks) {\n hunk.collapsedBefore = Math.max(\n hunk.additionStart - 1 - lastHunkAdditionEnd,\n 0\n );\n hunk.splitLineStart = splitTotal + hunk.collapsedBefore;\n hunk.unifiedLineStart = unifiedTotal + hunk.collapsedBefore;\n\n recomputeHunkRenderLineCounts(hunk);\n\n splitTotal += hunk.collapsedBefore + hunk.splitLineCount;\n unifiedTotal += hunk.collapsedBefore + hunk.unifiedLineCount;\n lastHunkAdditionEnd = hunk.additionStart + hunk.additionCount - 1;\n }\n\n if (diff.hunks.length > 0) {\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n const collapsedAfter = Math.max(\n diff.additionLines.length -\n (lastHunk.additionLineIndex + lastHunk.additionCount),\n 0\n );\n splitTotal += collapsedAfter;\n unifiedTotal += collapsedAfter;\n }\n\n diff.splitLineCount = splitTotal;\n diff.unifiedLineCount = unifiedTotal;\n}\n"],"mappings":"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"}
|
|
@@ -46,6 +46,7 @@ declare function getExpandedRegion({
|
|
|
46
46
|
collapsedContextThreshold
|
|
47
47
|
}: GetExpandedRegionProps): ExpandedRegionResult;
|
|
48
48
|
declare function hasTrailingContext(fileDiff: FileDiffMetadata): boolean;
|
|
49
|
+
declare function hasTrailingContextMismatch(fileDiff: FileDiffMetadata): boolean;
|
|
49
50
|
declare function getTrailingContextRangeSize({
|
|
50
51
|
fileDiff,
|
|
51
52
|
errorPrefix
|
|
@@ -82,5 +83,5 @@ declare function getTrailingHunkSeparatorLayout({
|
|
|
82
83
|
metrics
|
|
83
84
|
}: HunkSeparatorBaseProps): HunkSeparatorLayout | undefined;
|
|
84
85
|
//#endregion
|
|
85
|
-
export { ExpandedRegionResult, GetExpandedRegionProps, GetTrailingContextRangeSizeProps, GetTrailingExpandedRegionProps, HunkSeparatorLayout, getExpandedRegion, getHunkSeparatorGap, getHunkSeparatorHeight, getLeadingHunkSeparatorLayout, getTrailingContextRangeSize, getTrailingExpandedRegion, getTrailingHunkSeparatorLayout, hasLeadingHunkSeparator, hasTrailingContext, hasTrailingHunkSeparator };
|
|
86
|
+
export { ExpandedRegionResult, GetExpandedRegionProps, GetTrailingContextRangeSizeProps, GetTrailingExpandedRegionProps, HunkSeparatorLayout, getExpandedRegion, getHunkSeparatorGap, getHunkSeparatorHeight, getLeadingHunkSeparatorLayout, getTrailingContextRangeSize, getTrailingExpandedRegion, getTrailingHunkSeparatorLayout, hasLeadingHunkSeparator, hasTrailingContext, hasTrailingContextMismatch, hasTrailingHunkSeparator };
|
|
86
87
|
//# sourceMappingURL=virtualDiffLayout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualDiffLayout.d.ts","names":["FileDiffMetadata","HunkExpansionRegion","HunkSeparators","VirtualFileMetrics","ExpandedRegionResult","GetExpandedRegionProps","Map","GetTrailingContextRangeSizeProps","GetTrailingExpandedRegionProps","HunkSeparatorLayout","HunkSeparatorBaseProps","LeadingHunkSeparatorLayoutProps","getExpandedRegion","isPartial","rangeSize","expandedHunks","hunkIndex","collapsedContextThreshold","hasTrailingContext","getTrailingContextRangeSize","fileDiff","errorPrefix","getTrailingExpandedRegion","getHunkSeparatorHeight","type","metrics","getHunkSeparatorGap","hasLeadingHunkSeparator","hunkSpecs","Omit","hasTrailingHunkSeparator","getLeadingHunkSeparatorLayout","getTrailingHunkSeparatorLayout"],"sources":["../../src/utils/virtualDiffLayout.d.ts"],"sourcesContent":["import type { FileDiffMetadata, HunkExpansionRegion, HunkSeparators, VirtualFileMetrics } from '../types';\nexport interface ExpandedRegionResult {\n fromStart: number;\n fromEnd: number;\n rangeSize: number;\n collapsedLines: number;\n renderAll: boolean;\n}\nexport interface GetExpandedRegionProps {\n isPartial: boolean;\n rangeSize: number;\n expandedHunks: Map<number, HunkExpansionRegion> | true | undefined;\n hunkIndex: number;\n collapsedContextThreshold: number;\n}\nexport interface GetTrailingContextRangeSizeProps {\n fileDiff: FileDiffMetadata;\n errorPrefix: string;\n}\nexport interface GetTrailingExpandedRegionProps extends GetTrailingContextRangeSizeProps {\n hunkIndex: number;\n expandedHunks: GetExpandedRegionProps['expandedHunks'];\n collapsedContextThreshold: number;\n}\nexport interface HunkSeparatorLayout {\n height: number;\n gapBefore: number;\n gapAfter: number;\n totalHeight: number;\n}\ninterface HunkSeparatorBaseProps {\n type: HunkSeparators;\n metrics: VirtualFileMetrics;\n}\ninterface LeadingHunkSeparatorLayoutProps extends HunkSeparatorBaseProps {\n hunkIndex: number;\n hunkSpecs: string | undefined;\n}\nexport declare function getExpandedRegion({ isPartial, rangeSize, expandedHunks, hunkIndex, collapsedContextThreshold }: GetExpandedRegionProps): ExpandedRegionResult;\nexport declare function hasTrailingContext(fileDiff: FileDiffMetadata): boolean;\nexport declare function getTrailingContextRangeSize({ fileDiff, errorPrefix }: GetTrailingContextRangeSizeProps): number;\nexport declare function getTrailingExpandedRegion({ fileDiff, hunkIndex, expandedHunks, collapsedContextThreshold, errorPrefix }: GetTrailingExpandedRegionProps): ExpandedRegionResult | undefined;\nexport declare function getHunkSeparatorHeight({ type, metrics }: HunkSeparatorBaseProps): number;\nexport declare function getHunkSeparatorGap({ type, metrics }: HunkSeparatorBaseProps): number;\nexport declare function hasLeadingHunkSeparator({ type, hunkIndex, hunkSpecs }: Omit<LeadingHunkSeparatorLayoutProps, 'metrics'>): boolean;\nexport declare function hasTrailingHunkSeparator(type: HunkSeparators): boolean;\nexport declare function getLeadingHunkSeparatorLayout({ type, metrics, hunkIndex, hunkSpecs }: LeadingHunkSeparatorLayoutProps): HunkSeparatorLayout | undefined;\nexport declare function getTrailingHunkSeparatorLayout({ type, metrics }: HunkSeparatorBaseProps): HunkSeparatorLayout | undefined;\nexport {};\n//# sourceMappingURL=virtualDiffLayout.d.ts.map"],"mappings":";;;UACiBI,oBAAAA;;EAAAA,OAAAA,EAAAA,MAAAA;EAOAC,SAAAA,EAAAA,MAAAA;EAOAE,cAAAA,EAAAA,MAAAA;EAIAC,SAAAA,EAAAA,OAAAA;AAKjB;AAMUE,UAtBOL,sBAAAA,CAsBe;EAItBM,SAAAA,EAAAA,OAAAA;EAIcC,SAAAA,EAAAA,MAAAA;EAAoBC,aAAAA,EA3BzBP,GA2ByBO,CAAAA,MAAAA,EA3BbZ,mBA2BaY,CAAAA,GAAAA,IAAAA,GAAAA,SAAAA;EAAWC,SAAAA,EAAAA,MAAAA;EAAWC,yBAAAA,EAAAA,MAAAA;;AAA0BE,UAvB3EV,gCAAAA,CAuB2EU;EAA6BZ,QAAAA,EAtB3GL,gBAsB2GK;EAAyBD,WAAAA,EAAAA,MAAAA;;AAC1Hc,UApBPV,8BAAAA,SAAuCD,gCAoBa,CAAA;EAC7CY,SAAAA,EAAAA,MAAAA;
|
|
1
|
+
{"version":3,"file":"virtualDiffLayout.d.ts","names":["FileDiffMetadata","HunkExpansionRegion","HunkSeparators","VirtualFileMetrics","ExpandedRegionResult","GetExpandedRegionProps","Map","GetTrailingContextRangeSizeProps","GetTrailingExpandedRegionProps","HunkSeparatorLayout","HunkSeparatorBaseProps","LeadingHunkSeparatorLayoutProps","getExpandedRegion","isPartial","rangeSize","expandedHunks","hunkIndex","collapsedContextThreshold","hasTrailingContext","hasTrailingContextMismatch","getTrailingContextRangeSize","fileDiff","errorPrefix","getTrailingExpandedRegion","getHunkSeparatorHeight","type","metrics","getHunkSeparatorGap","hasLeadingHunkSeparator","hunkSpecs","Omit","hasTrailingHunkSeparator","getLeadingHunkSeparatorLayout","getTrailingHunkSeparatorLayout"],"sources":["../../src/utils/virtualDiffLayout.d.ts"],"sourcesContent":["import type { FileDiffMetadata, HunkExpansionRegion, HunkSeparators, VirtualFileMetrics } from '../types';\nexport interface ExpandedRegionResult {\n fromStart: number;\n fromEnd: number;\n rangeSize: number;\n collapsedLines: number;\n renderAll: boolean;\n}\nexport interface GetExpandedRegionProps {\n isPartial: boolean;\n rangeSize: number;\n expandedHunks: Map<number, HunkExpansionRegion> | true | undefined;\n hunkIndex: number;\n collapsedContextThreshold: number;\n}\nexport interface GetTrailingContextRangeSizeProps {\n fileDiff: FileDiffMetadata;\n errorPrefix: string;\n}\nexport interface GetTrailingExpandedRegionProps extends GetTrailingContextRangeSizeProps {\n hunkIndex: number;\n expandedHunks: GetExpandedRegionProps['expandedHunks'];\n collapsedContextThreshold: number;\n}\nexport interface HunkSeparatorLayout {\n height: number;\n gapBefore: number;\n gapAfter: number;\n totalHeight: number;\n}\ninterface HunkSeparatorBaseProps {\n type: HunkSeparators;\n metrics: VirtualFileMetrics;\n}\ninterface LeadingHunkSeparatorLayoutProps extends HunkSeparatorBaseProps {\n hunkIndex: number;\n hunkSpecs: string | undefined;\n}\nexport declare function getExpandedRegion({ isPartial, rangeSize, expandedHunks, hunkIndex, collapsedContextThreshold }: GetExpandedRegionProps): ExpandedRegionResult;\nexport declare function hasTrailingContext(fileDiff: FileDiffMetadata): boolean;\nexport declare function hasTrailingContextMismatch(fileDiff: FileDiffMetadata): boolean;\nexport declare function getTrailingContextRangeSize({ fileDiff, errorPrefix }: GetTrailingContextRangeSizeProps): number;\nexport declare function getTrailingExpandedRegion({ fileDiff, hunkIndex, expandedHunks, collapsedContextThreshold, errorPrefix }: GetTrailingExpandedRegionProps): ExpandedRegionResult | undefined;\nexport declare function getHunkSeparatorHeight({ type, metrics }: HunkSeparatorBaseProps): number;\nexport declare function getHunkSeparatorGap({ type, metrics }: HunkSeparatorBaseProps): number;\nexport declare function hasLeadingHunkSeparator({ type, hunkIndex, hunkSpecs }: Omit<LeadingHunkSeparatorLayoutProps, 'metrics'>): boolean;\nexport declare function hasTrailingHunkSeparator(type: HunkSeparators): boolean;\nexport declare function getLeadingHunkSeparatorLayout({ type, metrics, hunkIndex, hunkSpecs }: LeadingHunkSeparatorLayoutProps): HunkSeparatorLayout | undefined;\nexport declare function getTrailingHunkSeparatorLayout({ type, metrics }: HunkSeparatorBaseProps): HunkSeparatorLayout | undefined;\nexport {};\n//# sourceMappingURL=virtualDiffLayout.d.ts.map"],"mappings":";;;UACiBI,oBAAAA;;EAAAA,OAAAA,EAAAA,MAAAA;EAOAC,SAAAA,EAAAA,MAAAA;EAOAE,cAAAA,EAAAA,MAAAA;EAIAC,SAAAA,EAAAA,OAAAA;AAKjB;AAMUE,UAtBOL,sBAAAA,CAsBe;EAItBM,SAAAA,EAAAA,OAAAA;EAIcC,SAAAA,EAAAA,MAAAA;EAAoBC,aAAAA,EA3BzBP,GA2ByBO,CAAAA,MAAAA,EA3BbZ,mBA2BaY,CAAAA,GAAAA,IAAAA,GAAAA,SAAAA;EAAWC,SAAAA,EAAAA,MAAAA;EAAWC,yBAAAA,EAAAA,MAAAA;;AAA0BE,UAvB3EV,gCAAAA,CAuB2EU;EAA6BZ,QAAAA,EAtB3GL,gBAsB2GK;EAAyBD,WAAAA,EAAAA,MAAAA;;AAC1Hc,UApBPV,8BAAAA,SAAuCD,gCAoBa,CAAA;EAC7CY,SAAAA,EAAAA,MAAAA;EACAC,aAAAA,EApBLf,sBAoBgC,CAAA,eAAA,CAAA;EAAGgB,yBAAAA,EAAAA,MAAAA;;AAAyBd,UAjB9DE,mBAAAA,CAiB8DF;EAAgC,MAAA,EAAA,MAAA;EACvFgB,SAAAA,EAAAA,MAAAA;EAA4BF,QAAAA,EAAAA,MAAAA;EAAUL,WAAAA,EAAAA,MAAAA;;UAZpDN,sBAAAA,CAY8EO;EAA2BK,IAAAA,EAXzGpB,cAWyGoB;EAAed,OAAAA,EAVrHL,kBAUqHK;;UARxHG,+BAAAA,SAAwCD,sBAQqI,CAAA;EAC/Jc,SAAAA,EAAAA,MAAAA;EAAyBC,SAAAA,EAAAA,MAAAA,GAAAA,SAAAA;;AAAiBf,iBAL1CE,iBAAAA,CAK0CF;EAAAA,SAAAA;EAAAA,SAAAA;EAAAA,aAAAA;EAAAA,SAAAA;EAAAA;AAAAA,CAAAA,EALuDL,sBAKvDK,CAAAA,EALgFN,oBAKhFM;AAAsB,iBAJhEQ,kBAAAA,CAIgE,QAAA,EAJnClB,gBAImC,CAAA,EAAA,OAAA;AAChE2B,iBAJAR,0BAAAA,CAImB,QAAA,EAJkBnB,gBAIlB,CAAA,EAAA,OAAA;AAAGyB,iBAHtBL,2BAAAA,CAGsBK;EAAAA,QAAAA;EAAAA;AAAAA,CAAAA,EAHiClB,gCAGjCkB,CAAAA,EAAAA,MAAAA;AAAMC,iBAF5BH,yBAAAA,CAE4BG;EAAAA,QAAAA;EAAAA,SAAAA;EAAAA,aAAAA;EAAAA,yBAAAA;EAAAA;AAAAA,CAAAA,EAF8ElB,8BAE9EkB,CAAAA,EAF+GtB,oBAE/GsB,GAAAA,SAAAA;AAAWhB,iBADvCc,sBAAAA,CACuCd;EAAAA,IAAAA;EAAAA;AAAAA,CAAAA,EADGA,sBACHA,CAAAA,EAAAA,MAAAA;AAAsB,iBAA7DiB,mBAAAA,CAA6D;EAAA,IAAA;EAAA;AAAA,CAAA,EAAtBjB,sBAAsB,CAAA,EAAA,MAAA;AAC7DkB,iBAAAA,uBAAAA,CAAuB;EAAA,IAAA;EAAA,SAAA;EAAA;AAAA,CAAA,EAAiCE,IAAjC,CAAsCnB,+BAAtC,EAAA,SAAA,CAAA,CAAA,EAAA,OAAA;AAAGc,iBAC1BM,wBAAAA,CAD0BN,IAAAA,EACKvB,cADLuB,CAAAA,EAAAA,OAAAA;AAAMT,iBAEhCgB,6BAAAA,CAFgChB;EAAAA,IAAAA;EAAAA,OAAAA;EAAAA,SAAAA;EAAAA;AAAAA,CAAAA,EAEuCL,+BAFvCK,CAAAA,EAEyEP,mBAFzEO,GAAAA,SAAAA;AAAWa,iBAG3CI,8BAAAA,CAH2CJ;EAAAA,IAAAA;EAAAA;AAAAA,CAAAA,EAGOnB,sBAHPmB,CAAAA,EAGgCpB,mBAHhCoB,GAAAA,SAAAA"}
|