Source: eval/diff_adapters/CpeeDiffAdapter.js

import {Dsl} from '../../config/Dsl.js';
import {DiffAdapter} from './DiffAdapter.js';
import {EvalConfig} from '../../config/EvalConfig.js';
import fs from 'fs';
import {execFileSync} from 'child_process';
import {EditScript} from '../../diff/delta/EditScript.js';
import {MatchPipeline} from '../../diff/match/MatchPipeline.js';

/**
 * Diff adapter for CpeeDiff that starts the algorithm in a separate process.
 */
export class CpeeDiffAdapter extends DiffAdapter {
  /**
   * The matching mode to use.
   * @type {String}
   * @private
   * @const
   */
  #mode;

  /**
   * Construct a new CpeeDiffAdapter instance.
   * @param {String} mode The matching mode to use. "quality" by default.
   */
  constructor(mode = MatchPipeline.MATCH_MODES.QUALITY) {
    super(
        EvalConfig.DIFFS.CPEEDIFF.path,
        EvalConfig.DIFFS.CPEEDIFF.displayName + '_' + mode,
    );
    this.#mode = mode;
  }

  /**
   * @inheritDoc
   * @override
   */
  parseOutput(output) {
    let updates = 0;
    let insertions = 0;
    let moves = 0;
    let deletions = 0;

    const delta = EditScript.fromXmlString(output);
    for (const change of delta) {
      switch (change.type) {
        case Dsl.CHANGE_MODEL.INSERTION.label:
          insertions++;
          break;
        case Dsl.CHANGE_MODEL.DELETION.label:
          deletions++;
          break;
        case Dsl.CHANGE_MODEL.MOVE.label:
          moves++;
          break;
        case Dsl.CHANGE_MODEL.UPDATE.label:
          updates++;
          break;
      }
    }
    return [
      insertions,
      moves,
      updates,
      deletions,
      delta.cost,
    ];
  }

  /**
   * @inheritDoc
   * @override
   */
  run(oldTree, newTree) {
    const oldTreeString = oldTree.toXmlString();
    const newTreeString = newTree.toXmlString();

    const oldFilePath = EvalConfig.FILENAMES.OLD_TREE;
    const newFilePath = EvalConfig.FILENAMES.NEW_TREE;

    fs.writeFileSync(oldFilePath, oldTreeString);
    fs.writeFileSync(newFilePath, newTreeString);

    const time = new Date().getTime();
    return {
      output: execFileSync(
          this.path,
          [
            'diff',
            '--mode',
            this.#mode,
            oldFilePath,
            newFilePath,
          ],
          EvalConfig.EXECUTION_OPTIONS,
      ).toString(),
      runtime: new Date().getTime() - time,
    };
  }
}