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

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditReadOnlyListener;
import com.intellij.openapi.editor.ex.EditorHighlighter;
import com.intellij.openapi.editor.ex.LineIterator;
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.containers.CoModifiableList;
import com.intellij.util.containers.WeakList;
import com.intellij.util.text.CharArrayUtil;
import gnu.trove.THashMap;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.*;

public class DocumentImpl implements DocumentEx {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.DocumentImpl");

  private ArrayList<DocumentListener> myDocumentListeners = new ArrayList<DocumentListener>();
  private CoModifiableList<RangeMarkerImpl> myRangeMarkers = new CoModifiableList<RangeMarkerImpl>(new WeakList<RangeMarkerImpl>());
  private List<RangeMarker> myGuardedBlocks = new ArrayList<RangeMarker>();

  private LineSet myLineSet = new LineSet();
  private CharArray myText;

  private boolean myIsReadOnly = false;
  private final THashMap<Object, Object> myUserDataMap = new THashMap<Object, Object>(4);
  private boolean isStripTrailingSpacesEnabled = true;
  private long myModificationStamp;
  private HashMap<Project, MarkupModel> myProjectToMarkupModelMap = new HashMap<Project, MarkupModel>();
  private PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this);

  private MarkupModelImpl myMarkupModel;
  private DocumentListener[] myCachedDocumentListeners;
  private List<EditReadOnlyListener> myReadOnlyListeners = new ArrayList<EditReadOnlyListener>(1);

  private static final Comparator<? super DocumentListener> ourListenersComparator = new Comparator<Object>() {
    public int compare(Object o1, Object o2) {
      return getPriority(o1) - getPriority(o2);
    }

    private int getPriority(Object o) {
      if (o instanceof FoldingModel) return 1;
      if (o instanceof EditorHighlighter) return 2;
      if (o instanceof CaretModel) return 3;
      if (o instanceof SelectionModel) return 4;
      if (o instanceof EditorImpl.EditorDocumentAdapter) return 5;

      return 6;
    }
  };
  private int myCheckGuardedBlocks = 0;
  private boolean myGuardsSuppressed = false;

  private DocumentImpl() {
    setCyclicBufferSize(0);
    setModificationStamp(LocalTimeCounter.currentTime());
  }

  public DocumentImpl(String text) {
    this();
    LOG.assertTrue(text.indexOf("\r") < 0, "Wrong line separators in Document");

    setChars(text);
    setModificationStamp(LocalTimeCounter.currentTime());
  }

  public DocumentImpl(CharSequence chars) {
    this();
    setChars(chars);
  }

  public char[] getChars() {
    return CharArrayUtil.fromSequence(getCharsSequence());
  }

  private void setChars(CharSequence chars) {
    myText.replaceText(chars);
    DocumentEvent event = new DocumentEventImpl(this, 0, null, null, -1);
    myLineSet.documentCreated(event);
  }

  public MarkupModel getMarkupModel() {
    if (myMarkupModel == null) myMarkupModel = new MarkupModelImpl(this);
    return myMarkupModel;
  }

  public void setStripTrailingSpacesEnabled(boolean isEnabled) {
    isStripTrailingSpacesEnabled = isEnabled;
  }

  public void stripTrailingSpaces(boolean inChangedLinesOnly) {
    Editor[] editors = EditorFactory.getInstance().getEditors(this, null);
    VisualPosition[] visualCarets = new VisualPosition[editors.length];
    int[] caretLines = new int[editors.length];
    for (int i = 0; i < editors.length; i++) {
      visualCarets[i] = editors[i].getCaretModel().getVisualPosition();
      caretLines[i] = editors[i].getCaretModel().getLogicalPosition().line;
    }

    if (!isStripTrailingSpacesEnabled) {
      return;
    }

    boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode();

    lines:
        for (int i = 0; i < myLineSet.getLineCount(); i++) {
          if (!isTestMode) {
            for (int j = 0; j < caretLines.length; j++) {
              if (caretLines[j] == i) continue lines;
            }
          }

          if (!inChangedLinesOnly || myLineSet.isModified(i)) {
            int start = -1;
            int lineEnd = myLineSet.getLineEnd(i) - myLineSet.getSeparatorLength(i);
            int lineStart = myLineSet.getLineStart(i);
            CharSequence text = myText.getCharArray();
            for (int offset = lineEnd - 1; offset >= lineStart; offset--) {
              char c = text.charAt(offset);
              if (c != ' ' && c != '\t') {
                break;
              }
              start = offset;
            }
            if (start != -1) {
              deleteString(start, lineEnd);
            }
          }
        }

    for (int i = 0; i < editors.length; i++) {
      editors[i].getCaretModel().moveToVisualPosition(visualCarets[i]);
    }
  }

  public <T> void putUserData(Key<T> key, T value) {
    synchronized (myUserDataMap) {
      if (value != null) {
        myUserDataMap.put(key, value);
      }
      else {
        myUserDataMap.remove(key);
      }
    }
  }

  public <T> T getUserData(Key<T> key) {
    synchronized (myUserDataMap) {
      return (T)myUserDataMap.get(key);
    }
  }
<commit_msg>DocumentImpl now extends UserDataHolderBase thus inheriting correct synchronized access to user data map.<commit_after>package com.intellij.openapi.editor.impl;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditReadOnlyListener;
import com.intellij.openapi.editor.ex.EditorHighlighter;
import com.intellij.openapi.editor.ex.LineIterator;
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.containers.CoModifiableList;
import com.intellij.util.containers.WeakList;
import com.intellij.util.text.CharArrayUtil;
import gnu.trove.THashMap;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.*;

public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.DocumentImpl");

  private ArrayList<DocumentListener> myDocumentListeners = new ArrayList<DocumentListener>();
  private CoModifiableList<RangeMarkerImpl> myRangeMarkers = new CoModifiableList<RangeMarkerImpl>(new WeakList<RangeMarkerImpl>());
  private List<RangeMarker> myGuardedBlocks = new ArrayList<RangeMarker>();

  private LineSet myLineSet = new LineSet();
  private CharArray myText;

  private boolean myIsReadOnly = false;
  private boolean isStripTrailingSpacesEnabled = true;
  private long myModificationStamp;
  private HashMap<Project, MarkupModel> myProjectToMarkupModelMap = new HashMap<Project, MarkupModel>();
  private PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this);

  private MarkupModelImpl myMarkupModel;
  private DocumentListener[] myCachedDocumentListeners;
  private List<EditReadOnlyListener> myReadOnlyListeners = new ArrayList<EditReadOnlyListener>(1);

  private static final Comparator<? super DocumentListener> ourListenersComparator = new Comparator<Object>() {
    public int compare(Object o1, Object o2) {
      return getPriority(o1) - getPriority(o2);
    }

    private int getPriority(Object o) {
      if (o instanceof FoldingModel) return 1;
      if (o instanceof EditorHighlighter) return 2;
      if (o instanceof CaretModel) return 3;
      if (o instanceof SelectionModel) return 4;
      if (o instanceof EditorImpl.EditorDocumentAdapter) return 5;

      return 6;
    }
  };
  private int myCheckGuardedBlocks = 0;
  private boolean myGuardsSuppressed = false;

  private DocumentImpl() {
    setCyclicBufferSize(0);
    setModificationStamp(LocalTimeCounter.currentTime());
  }

  public DocumentImpl(String text) {
    this();
    LOG.assertTrue(text.indexOf("\r") < 0, "Wrong line separators in Document");

    setChars(text);
    setModificationStamp(LocalTimeCounter.currentTime());
  }

  public DocumentImpl(CharSequence chars) {
    this();
    setChars(chars);
  }

  public char[] getChars() {
    return CharArrayUtil.fromSequence(getCharsSequence());
  }

  private void setChars(CharSequence chars) {
    myText.replaceText(chars);
    DocumentEvent event = new DocumentEventImpl(this, 0, null, null, -1);
    myLineSet.documentCreated(event);
  }

  public MarkupModel getMarkupModel() {
    if (myMarkupModel == null) myMarkupModel = new MarkupModelImpl(this);
    return myMarkupModel;
  }

  public void setStripTrailingSpacesEnabled(boolean isEnabled) {
    isStripTrailingSpacesEnabled = isEnabled;
  }

  public void stripTrailingSpaces(boolean inChangedLinesOnly) {
    Editor[] editors = EditorFactory.getInstance().getEditors(this, null);
    VisualPosition[] visualCarets = new VisualPosition[editors.length];
    int[] caretLines = new int[editors.length];
    for (int i = 0; i < editors.length; i++) {
      visualCarets[i] = editors[i].getCaretModel().getVisualPosition();
      caretLines[i] = editors[i].getCaretModel().getLogicalPosition().line;
    }

    if (!isStripTrailingSpacesEnabled) {
      return;
    }

    boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode();

    lines:
        for (int i = 0; i < myLineSet.getLineCount(); i++) {
          if (!isTestMode) {
            for (int j = 0; j < caretLines.length; j++) {
              if (caretLines[j] == i) continue lines;
            }
          }

          if (!inChangedLinesOnly || myLineSet.isModified(i)) {
            int start = -1;
            int lineEnd = myLineSet.getLineEnd(i) - myLineSet.getSeparatorLength(i);
            int lineStart = myLineSet.getLineStart(i);
            CharSequence text = myText.getCharArray();
            for (int offset = lineEnd - 1; offset >= lineStart; offset--) {
              char c = text.charAt(offset);
              if (c != ' ' && c != '\t') {
                break;
              }
              start = offset;
            }
            if (start != -1) {
              deleteString(start, lineEnd);
            }
          }
        }

    for (int i = 0; i < editors.length; i++) {
      editors[i].getCaretModel().moveToVisualPosition(visualCarets[i]);
    }
  }

{'fraction_non_alphanumeric': 0.10470305526948163, 'fraction_numerical': 0.004033642293168555, 'mean_word_length': 3.811312964492155, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 37, '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': '1369002', 'n_tokens_mistral': 3500, 'n_tokens_neox': 3425, 'n_words': 731}