Repository: TabbyML/tabby
File: clients/tabby-agent/src/utils/diff.ts (TypeScript)

Code before:
  originRanges: Range[];
  modifiedRanges: Range[];
}

/**
 * Diff code and mapping the result range to editor range
 */
export function codeDiff(
  originCode: string[],
  originCodeRanges: Range[],
  modifiedCode: string[],
  modifiedCodeRanges: Range[],
): CodeDiffResult {
  const originRanges: Range[] = [];
  const modifiedRanges: Range[] = [];

  const diffResult = linesDiffComputers.getDefault().computeDiff(originCode, modifiedCode, {
    computeMoves: false,
    ignoreTrimWhitespace: true,
    maxComputationTimeMs: 100,
  });

  diffResult.changes.forEach((change) => {
    change.innerChanges?.forEach((innerChange) => {
      /**
       * In most case, stat line and end line are equal in diff change.
       * when start line and end line are different in change, it usually means a range that include a whole line.
       * {
       *   "startLineNumber": 2,
       *   "startColumn": 1,
       *   "endLineNumber": 3,
       *   "endColumn": 1
       * }
       *
       * In our case, the origin code and modified code are mixed tegather. so we should translate range to below to avoid wrong range mapping.
       * {
       *   "startLineNumber": 2,
       *   "startColumn": 1,
       *   "endLineNumber": 2,
       *   "endColumn": // end of line 2
       * }
       *
       */
      let originEndChar = innerChange.originalRange.endColumn - 1;
      if (innerChange.originalRange.endLineNumber !== innerChange.originalRange.startLineNumber) {
        originEndChar = originCodeRanges[innerChange.originalRange.startLineNumber - 1]?.end.character ?? 0;
      }
      originRanges.push({
        start: {
          line: originCodeRanges[innerChange.originalRange.startLineNumber - 1]?.start.line ?? 0,
          character: innerChange.originalRange.startColumn - 1,

Review comment (suggestion):
```suggestion
       * In most case, start line and end line are equal in diff change.
```

Code after:
  originRanges: Range[];
  modifiedRanges: Range[];
}

export function mapDiffRangeToEditorRange(diffRange: DiffRange, editorRanges: Range[]): Range | undefined {
  if (diffRange.isEmpty()) {
    return undefined;
  }

  const start: Position = {
    line: editorRanges[diffRange.startLineNumber - 1]?.start.line ?? 0,
    character: diffRange.startColumn - 1,
  };

  let end: Position;

  /**
   * In most case, start line and end line are equal in diff change.
   * when start line and end line are different in change, it usually means a range that include a whole line.
   * {
   *   "startLineNumber": 2,
   *   "startColumn": 1,
   *   "endLineNumber": 3,
   *   "endColumn": 1
   * }
   *
   * In our case, the origin code and modified code are mixed tegether. so we should translate range to below to avoid wrong range mapping.
   * {
   *   "startLineNumber": 2,
   *   "startColumn": 1,
   *   "endLineNumber": 2,
   *   "endColumn": // end of line 2
   * }
   *
   */
  if (diffRange.isSingleLine()) {
    end = {
      line: editorRanges[diffRange.startLineNumber - 1]?.start.line ?? 0,
      character: diffRange.endColumn - 1,
    };
  } else {
    end = {
      line: editorRanges[diffRange.startLineNumber - 1]?.start.line ?? 0,
      character: editorRanges[diffRange.startLineNumber - 1]?.end.character ?? 0,
    };
  }

  return {
    start,
    end,
  };