<commit_before>
package com.intellij.openapi.command.impl;

import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.DocumentReferenceByDocument;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.VirtualFile;

class EditorChangeAction implements UndoableAction {
  private DocumentEx myDocument;
  private int myOffset;
  private CharSequence myOldString;
  private CharSequence myNewString;
  private long myTimeStamp;
  private final Project myProject;

  public EditorChangeAction(DocumentEx document, int offset,
                            CharSequence oldString, CharSequence newString,
                            long oldTimeStamp, Project project) {
    myDocument = document;
    myOffset = offset;
    myOldString = oldString;
    if (myOldString == null)
      myOldString = "";
    myNewString = newString;
    if (myNewString == null)
      myNewString = "";
    myTimeStamp = oldTimeStamp;
    myProject = project;
  }

  public void undo() {
    exchangeStrings(myNewString, myOldString);
    myDocument.setModificationStamp(myTimeStamp);
    fileFileStatusChanged();
  }

  private void fileFileStatusChanged() {
    if (myProject == null) return;
    VirtualFile file = FileDocumentManager.getInstance().getFile(myDocument);
    if (file == null) return;
    FileStatusManager.getInstance(myProject).fileStatusChanged(file);
  }

  private void exchangeStrings(CharSequence newString, CharSequence oldString) {
    if (newString.length() > 0 && oldString.length() == 0){
      myDocument.deleteString(myOffset, myOffset + newString.length());
    }
    else if (oldString.length() > 0 && newString.length() == 0){
      myDocument.insertString(myOffset, oldString);
    }
    else if (oldString.length() > 0 && newString.length() > 0){
      myDocument.replaceString(myOffset, myOffset + newString.length(), oldString);
    }
  }

  public void redo() {
    exchangeStrings(myOldString, myNewString);
  }

  public DocumentReference[] getAffectedDocuments() {
    return new DocumentReference[]{DocumentReferenceByDocument.createDocumentReference(myDocument)};
  }

  public boolean isComplex() {
    return false;
  }
}

<commit_msg>Undo no longer holds the document on a hard reference. Could be reloaded by VirtualFile if necessary (though I suspect it will not happen actually).<commit_after>
package com.intellij.openapi.command.impl;

import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.DocumentReferenceByDocument;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.PatchedWeakReference;

import java.lang.ref.Reference;

class EditorChangeAction implements UndoableAction {
  private Object myDocument; // DocumentEx or WeakReference<DocumentEx> or null
  private VirtualFile myDocumentFile;
  private int myOffset;
  private CharSequence myOldString;
  private CharSequence myNewString;
  private long myTimeStamp;
  private final Project myProject;

  public EditorChangeAction(DocumentEx document, int offset,
                            CharSequence oldString, CharSequence newString,
                            long oldTimeStamp, Project project) {
    myDocumentFile = FileDocumentManager.getInstance().getFile(document);
    if (myDocumentFile != null) {
      myDocument = new PatchedWeakReference(document);
    }
    else {
      myDocument = document;
    }

    myOffset = offset;
    myOldString = oldString;
    if (myOldString == null) {
      myOldString = "";
    }
    myNewString = newString;
    if (myNewString == null) {
      myNewString = "";
    }
    myTimeStamp = oldTimeStamp;
    myProject = project;
  }

  public void undo() {
    exchangeStrings(myNewString, myOldString);
    getDocument().setModificationStamp(myTimeStamp);
    fileFileStatusChanged();
  }

  private void fileFileStatusChanged() {
    if (myProject == null) return;
    VirtualFile file = FileDocumentManager.getInstance().getFile(getDocument());
    if (file == null) return;
    FileStatusManager.getInstance(myProject).fileStatusChanged(file);
  }

  private void exchangeStrings(CharSequence newString, CharSequence oldString) {
    if (newString.length() > 0 && oldString.length() == 0){
      getDocument().deleteString(myOffset, myOffset + newString.length());
    }
    else if (oldString.length() > 0 && newString.length() == 0){
      getDocument().insertString(myOffset, oldString);
    }
    else if (oldString.length() > 0 && newString.length() > 0){
      getDocument().replaceString(myOffset, myOffset + newString.length(), oldString);
    }
  }

  public void redo() {
    exchangeStrings(myOldString, myNewString);
  }

  public DocumentReference[] getAffectedDocuments() {
    return new DocumentReference[]{DocumentReferenceByDocument.createDocumentReference(getDocument())};
  }

  public boolean isComplex() {
    return false;
  }

  public DocumentEx getDocument() {
    if (myDocument instanceof DocumentEx) return (DocumentEx)myDocument;
    Reference ref = (PatchedWeakReference)myDocument;
    final DocumentEx doc = (DocumentEx)ref.get();
    if (doc != null) return doc;
    final DocumentEx document = (DocumentEx)FileDocumentManager.getInstance().getDocument(myDocumentFile);
    myDocument = new PatchedWeakReference(document);
    return document;
  }
}


{'fraction_non_alphanumeric': 0.09850950830906287, 'fraction_numerical': 0.002055850608189138, 'mean_word_length': 4.116564417177914, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '257304', 'n_tokens_mistral': 1685, 'n_tokens_neox': 1645, 'n_words': 365}