applyEditsToFile function

String applyEditsToFile(
  1. String fileContents,
  2. List<FileEdit> edits
)

Apply a list of edits to file content and return the updated content. Throws if any edit fails or produces overlapping changes.

Implementation

String applyEditsToFile(String fileContents, List<FileEdit> edits) {
  var updatedFile = fileContents;
  final appliedNewStrings = <String>[];

  // Special case for empty files
  if (fileContents.isEmpty &&
      edits.length == 1 &&
      edits[0].oldString.isEmpty &&
      edits[0].newString.isEmpty) {
    return '';
  }

  for (final edit in edits) {
    // Strip trailing newlines from old_string before checking
    final oldStringToCheck = edit.oldString.replaceAll(RegExp(r'\n+$'), '');

    // Check if old_string is a substring of any previously applied new_string
    for (final previousNewString in appliedNewStrings) {
      if (oldStringToCheck.isNotEmpty &&
          previousNewString.contains(oldStringToCheck)) {
        throw StateError(
          'Cannot edit file: old_string is a substring of a new_string '
          'from a previous edit.',
        );
      }
    }

    final previousContent = updatedFile;
    updatedFile = edit.oldString.isEmpty
        ? edit.newString
        : applyEditToFile(
            updatedFile,
            edit.oldString,
            edit.newString,
            replaceAll: edit.replaceAll,
          );

    // If this edit did not change anything, throw
    if (updatedFile == previousContent) {
      throw StateError('String not found in file. Failed to apply edit.');
    }

    appliedNewStrings.add(edit.newString);
  }

  if (updatedFile == fileContents) {
    throw StateError(
      'Original and edited file match exactly. Failed to apply edit.',
    );
  }

  return updatedFile;
}