parseUnifiedDiff function

List<DiffHunk> parseUnifiedDiff(
  1. String diffText
)

Parse a unified diff string into hunks.

Implementation

List<DiffHunk> parseUnifiedDiff(String diffText) {
  final hunks = <DiffHunk>[];
  final lines = diffText.split('\n');

  int i = 0;

  // Skip file headers (--- / +++)
  while (i < lines.length &&
      !lines[i].startsWith('@@') &&
      !lines[i].startsWith('diff ')) {
    i++;
  }

  while (i < lines.length) {
    final line = lines[i];

    if (line.startsWith('@@')) {
      final hunkMatch = RegExp(
        r'^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@',
      ).firstMatch(line);

      if (hunkMatch == null) {
        i++;
        continue;
      }

      final oldStart = int.parse(hunkMatch.group(1)!);
      final oldLines = int.tryParse(hunkMatch.group(2) ?? '1') ?? 1;
      final newStart = int.parse(hunkMatch.group(3)!);
      final newLines = int.tryParse(hunkMatch.group(4) ?? '1') ?? 1;

      final hunkLines = <DiffLine>[];
      var oldLine = oldStart;
      var newLine = newStart;

      i++;
      while (i < lines.length && !lines[i].startsWith('@@')) {
        final l = lines[i];
        if (l.startsWith('+')) {
          hunkLines.add(
            DiffLine(
              type: DiffLineType.addition,
              content: l.substring(1),
              newLineNumber: newLine++,
            ),
          );
        } else if (l.startsWith('-')) {
          hunkLines.add(
            DiffLine(
              type: DiffLineType.removal,
              content: l.substring(1),
              oldLineNumber: oldLine++,
            ),
          );
        } else if (l.startsWith(' ') || l.isEmpty) {
          hunkLines.add(
            DiffLine(
              type: DiffLineType.context,
              content: l.isEmpty ? '' : l.substring(1),
              oldLineNumber: oldLine++,
              newLineNumber: newLine++,
            ),
          );
        } else if (l.startsWith('\\')) {
          // "\ No newline at end of file" — skip
        } else {
          break; // Next diff section
        }
        i++;
      }

      hunks.add(
        DiffHunk(
          oldStart: oldStart,
          oldLines: oldLines,
          newStart: newStart,
          newLines: newLines,
          lines: hunkLines,
        ),
      );
    } else {
      i++;
    }
  }

  return hunks;
}