diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DocumentsSynchonizer.java b/platform/platform-api/src/com/intellij/openapi/diff/DocumentsSynchronizer.java similarity index 79% rename from platform/platform-api/src/com/intellij/openapi/diff/DocumentsSynchonizer.java rename to platform/platform-api/src/com/intellij/openapi/diff/DocumentsSynchronizer.java index 5204ddfcaeb3..b0e48b756184 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DocumentsSynchonizer.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DocumentsSynchronizer.java @@ -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); } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java index 608a40c548f6..6c40b3797efb 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java @@ -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 ORIGINAL_DOCUMENT = new Key("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;