# All files / src/components/tools parseDiff.ts

97.05% Statements 33/34
94.73% Branches 18/19
100% Functions 3/3
97.05% Lines 33/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100

    5x
    5x

    5x
    95x
    10x

    85x

    10x

    75x
    5x
    70x
    40x
    30x

    30x
    20x
    10x

    10x

    5x

    36x
    36x
    36x

    36x
    78x

    36x
    123x

    36x

    41x
    41x
    41x
    276x
    163x

    276x
    78x

    41x

     /**
     * Lightweight diff parsing utilities for the FileEditCard.
     *
     * Handles two formats:
     * 1. Unified diff strings (from Copilot's `detailedContent` field)
     * 2. Old/new string pairs (from Claude Code's `Edit` tool args)
     */

    /** A single line in a parsed diff. */
    export interface DiffLine {
      /** Line classification. */
      type: "add" | "remove" | "context" | "header";
      /** Line content (without the leading +/- prefix). */
      content: string;
    }

    /** Addition/removal counts for a diff. */
    export interface DiffStats {
      added: number;
      removed: number;
    }

    /**
     * Parses a unified diff string into typed lines.
     *
     * Recognizes `@@` hunk headers, `+`/`-` prefixed lines, and context lines.
     * Skips `---`/`+++` file header lines and `diff --git` preamble.
     */
    export function parseUnifiedDiff(diff: string): DiffLine[] {
      const lines = diff.split("\n");
      const result: DiffLine[] = [];

      for (const line of lines) {
        if (line.startsWith("diff --git") || line.startsWith("index ")) {
          continue;
        }
        // Skip file header lines (--- a/file, +++ b/file) but not hunk content
        // lines that happen to start with "---" or "+++" (which appear as
        // "----..." or "++++..." in the diff and are handled by +/- rules below).
        if (
          (line.startsWith("--- ") || line.startsWith("+++ ")) &&
          !line.startsWith("---- ") &&
          !line.startsWith("++++ ")
        ) {
          continue;
        }
        if (line.startsWith("@@")) {
          result.push({ type: "header", content: line });
        } else if (line.startsWith("+")) {
          result.push({ type: "add", content: line.slice(1) });
        I} else if (line.startsWith("-")) {
          result.push({ type: "remove", content: line.slice(1) });
        } else if (line.startsWith(" ")) {
          result.push({ type: "context", content: line.slice(1) });
        } else if (line === "") {
          // Empty lines in unified diffs are context lines
          result.push({ type: "context", content: "" });
        }
      }

      return result;
    }

    /**
     * Constructs a minimal diff from old and new strings.
     *
     * This is a simple line-by-line comparison — not a true LCS diff algorithm.
     * Shows all old lines as removals followed by all new lines as additions.
     * Good enough for the small, targeted edits agents typically make.
     */
    export function diffFromOldNew(oldStr: string, newStr: string): DiffLine[] {
      const oldLines = oldStr.split("\n");
      const newLines = newStr.split("\n");
      const result: DiffLine[] = [];

      for (const line of oldLines) {
        result.push({ type: "remove", content: line });
      }
      for (const line of newLines) {
        result.push({ type: "add", content: line });
      }

      return result;
    }

    /** Counts additions and removals in a parsed diff. */
    export function diffStats(lines: DiffLine[]): DiffStats {
      let added = 0;
      let removed = 0;
      for (const line of lines) {
        if (line.type === "add") {
          added++;
        }
        if (line.type === "remove") {
          removed++;
        }
      }
      return { added, removed };
    }