EA-45865 - assert: DocumentImpl.a

This commit is contained in:
Alexey Kudravtsev
2013-04-24 17:52:45 +04:00
parent b3391e85d5
commit bfe130acae
2 changed files with 55 additions and 32 deletions
@@ -15,26 +15,29 @@
*/
package com.intellij.openapi.diff;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
abstract class DocumentsSynchonizer {
abstract class DocumentsSynchronizer {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.DocumentsSynchonizer");
private Document myOriginal = null;
private Document myCopy = null;
private final Project myProject;
private boolean myDuringModification = false;
private volatile boolean myDuringModification = false;
private int myAssignedCount = 0;
private final DocumentAdapter myOriginalListener = new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
if (myDuringModification) return;
onOriginalChanged(e, getCopy());
@@ -42,39 +45,47 @@ abstract class DocumentsSynchonizer {
};
private final DocumentAdapter myCopyListener = new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
if (myDuringModification) return;
onCopyChanged(e, getOriginal());
}
};
private final PropertyChangeListener myROListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (Document.PROP_WRITABLE.equals(evt.getPropertyName())) getCopy().setReadOnly(!getOriginal().isWritable());
}
};
protected DocumentsSynchonizer(Project project) {
protected DocumentsSynchronizer(Project project) {
myProject = project;
}
protected abstract void onCopyChanged(DocumentEvent event, Document original);
protected abstract void onCopyChanged(@NotNull DocumentEvent event, @NotNull Document original);
protected abstract void onOriginalChanged(DocumentEvent event, Document copy);
protected abstract void onOriginalChanged(@NotNull DocumentEvent event, @NotNull Document copy);
protected abstract void beforeListenersAttached(Document original, Document copy);
protected abstract void beforeListenersAttached(@NotNull Document original, @NotNull Document copy);
protected abstract Document createOriginal();
protected abstract Document createCopy();
protected void replaceString(final Document document, final int startOffset, final int endOffset, final String newText) {
protected void replaceString(@NotNull final Document document, final int startOffset, final int endOffset, @NotNull final String newText) {
LOG.assertTrue(!myDuringModification);
try {
myDuringModification = true;
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
@Override
public void run() {
LOG.assertTrue(endOffset <= document.getTextLength());
document.replaceString(startOffset, endOffset, newText);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
document.replaceString(startOffset, endOffset, newText);
}
});
}
}, DiffBundle.message("save.merge.result.command.name"), document);
}
@@ -23,11 +23,11 @@ import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
@@ -39,19 +39,16 @@ public class FragmentContent extends DiffContent {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.FragmentContent");
private final DiffContent myOriginal;
private final FileType myType;
private final MyDocumentsSynchonizer mySynchonizer;
private final MyDocumentsSynchronizer mySynchonizer;
public static final Key<Document> ORIGINAL_DOCUMENT = new Key<Document>("ORIGINAL_DOCUMENT");
public FragmentContent(DiffContent original, TextRange range, Project project, VirtualFile file) {
public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, VirtualFile file) {
this(original, range, project, file != null ? DiffContentUtil.getContentType(file) : null);
}
public FragmentContent(DiffContent original, TextRange range, Project project, FileType type) {
this(original.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true), original, type, project);
}
private FragmentContent(RangeMarker rangeMarker, DiffContent original, FileType fileType, Project project) {
mySynchonizer = new MyDocumentsSynchonizer(project, rangeMarker);
public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, FileType fileType) {
RangeMarker rangeMarker = original.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true);
mySynchonizer = new MyDocumentsSynchronizer(project, rangeMarker);
myOriginal = original;
myType = fileType;
}
@@ -65,27 +62,35 @@ public class FragmentContent extends DiffContent {
}
@Override
public void onAssigned(boolean isAssigned) {
myOriginal.onAssigned(isAssigned);
mySynchonizer.listenDocuments(isAssigned);
super.onAssigned(isAssigned);
}
@Override
public Document getDocument() {
return mySynchonizer.getCopy();
}
@Override
public OpenFileDescriptor getOpenFileDescriptor(int offset) {
return myOriginal.getOpenFileDescriptor(offset + mySynchonizer.getStartOffset());
}
public VirtualFile getFile() { return null; }
@Override
public VirtualFile getFile() {
return null;
}
@Override
@Nullable
public FileType getContentType() {
return myType != null ? myType : myOriginal.getContentType();
}
@Override
public byte[] getBytes() throws IOException {
return getDocument().getText().getBytes();
}
@@ -97,52 +102,59 @@ public class FragmentContent extends DiffContent {
return new FragmentContent(new DocumentContent(project, document), TextRange.create(rangeMarker), project, type);
}
private class MyDocumentsSynchonizer extends DocumentsSynchonizer {
private class MyDocumentsSynchronizer extends DocumentsSynchronizer {
private final RangeMarker myRangeMarker;
public MyDocumentsSynchonizer(Project project, RangeMarker originalRange) {
public MyDocumentsSynchronizer(Project project, @NotNull RangeMarker originalRange) {
super(project);
myRangeMarker = originalRange;
}
public int getStartOffset() { return myRangeMarker.getStartOffset(); }
public int getStartOffset() {
return myRangeMarker.getStartOffset();
}
protected void onOriginalChanged(DocumentEvent event, Document copy) {
@Override
protected void onOriginalChanged(@NotNull DocumentEvent event, @NotNull Document copy) {
if (!myRangeMarker.isValid()) {
fireContentInvalid();
return;
}
replaceString(copy, 0, copy.getTextLength(),
subText(event.getDocument(), myRangeMarker.getStartOffset(), getLength()));
replaceString(copy, 0, copy.getTextLength(), subText(event.getDocument(), myRangeMarker.getStartOffset(), getLength()));
}
protected void beforeListenersAttached(Document original, Document copy) {
@Override
protected void beforeListenersAttached(@NotNull Document original, @NotNull Document copy) {
boolean writable = copy.isWritable();
Document copyEx = copy;
if (!writable) copyEx.setReadOnly(false);
replaceString(copy, 0, copy.getTextLength(),
subText(original, myRangeMarker.getStartOffset(), getLength()));
copyEx.setReadOnly(!writable);
if (!writable) {
copy.setReadOnly(false);
}
replaceString(copy, 0, copy.getTextLength(), subText(original, myRangeMarker.getStartOffset(), getLength()));
copy.setReadOnly(!writable);
}
private int getLength() {
return myRangeMarker.getEndOffset() - myRangeMarker.getStartOffset();
}
@Override
protected Document createOriginal() {
return myRangeMarker.getDocument();
}
@Override
protected Document createCopy() {
final Document originalDocument = myRangeMarker.getDocument();
String textInRange = originalDocument.getCharsSequence().subSequence(myRangeMarker.getStartOffset(), myRangeMarker.getEndOffset()).toString();
String textInRange =
originalDocument.getCharsSequence().subSequence(myRangeMarker.getStartOffset(), myRangeMarker.getEndOffset()).toString();
final Document result = EditorFactory.getInstance().createDocument(textInRange);
result.setReadOnly(!originalDocument.isWritable());
result.putUserData(ORIGINAL_DOCUMENT, originalDocument);
return result;
}
protected void onCopyChanged(DocumentEvent event, Document original) {
@Override
protected void onCopyChanged(@NotNull DocumentEvent event, @NotNull Document original) {
final int originalOffset = event.getOffset() + myRangeMarker.getStartOffset();
LOG.assertTrue(originalOffset >= 0);
if (!original.isWritable()) return;