(text: string)
| 22 | } |
| 23 | |
| 24 | export function parseUnifiedPatch(text: string): SplitDiffFile[] | null { |
| 25 | const files: SplitDiffFile[] = []; |
| 26 | let current: SplitDiffFile | null = null; |
| 27 | let pendingOldPath: string | undefined; |
| 28 | let oldLineNo = 0; |
| 29 | let newLineNo = 0; |
| 30 | let removed: PendingChangeLine[] = []; |
| 31 | let added: PendingChangeLine[] = []; |
| 32 | |
| 33 | const emptyCell = (): SplitDiffCell => ({ lineNo: null, text: "", type: "empty" }); |
| 34 | const flushChanges = () => { |
| 35 | if (!current) { |
| 36 | removed = []; |
| 37 | added = []; |
| 38 | return; |
| 39 | } |
| 40 | const count = Math.max(removed.length, added.length); |
| 41 | for (let i = 0; i < count; i++) { |
| 42 | const left = removed[i] |
| 43 | ? { lineNo: removed[i].lineNo, text: removed[i].text, type: "removed" as const } |
| 44 | : emptyCell(); |
| 45 | const right = added[i] |
| 46 | ? { lineNo: added[i].lineNo, text: added[i].text, type: "added" as const } |
| 47 | : emptyCell(); |
| 48 | current.rows.push({ type: "line", left, right }); |
| 49 | } |
| 50 | removed = []; |
| 51 | added = []; |
| 52 | }; |
| 53 | |
| 54 | for (const line of text.split(/\r?\n/)) { |
| 55 | if (line.startsWith("--- ")) { |
| 56 | flushChanges(); |
| 57 | pendingOldPath = cleanPatchPath(line.slice(4)); |
| 58 | continue; |
| 59 | } |
| 60 | |
| 61 | if (line.startsWith("+++ ")) { |
| 62 | flushChanges(); |
| 63 | current = { oldPath: pendingOldPath, newPath: cleanPatchPath(line.slice(4)), rows: [] }; |
| 64 | files.push(current); |
| 65 | continue; |
| 66 | } |
| 67 | |
| 68 | const hunk = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/); |
| 69 | if (hunk) { |
| 70 | if (!current) { |
| 71 | current = { rows: [] }; |
| 72 | files.push(current); |
| 73 | } |
| 74 | flushChanges(); |
| 75 | oldLineNo = Number(hunk[1]); |
| 76 | newLineNo = Number(hunk[2]); |
| 77 | current.rows.push({ type: "hunk", text: line }); |
| 78 | continue; |
| 79 | } |
| 80 | |
| 81 | if (!current) continue; |
no test coverage detected