IDEA-91514 Idea freezes due to high CPU usage when pasting XML file (one long line)

This commit is contained in:
Denis.Zhdanov
2012-10-25 15:43:04 +04:00
parent 9e25eaa0b3
commit 78131bbce4
5 changed files with 76 additions and 25 deletions
@@ -29,8 +29,15 @@ public class DocumentUtil {
private DocumentUtil() {
}
// TODO den add doc
/**
* Ensures that given task is executed when given document is at the given 'in bulk' mode.
*
* @param document target document
* @param executeInBulk <code>true</code> to force given document to be in bulk mode when given task is executed;
* <code>false</code> to force given document to be <b>not</b> in bulk mode when given task is executed
* @param task task to execute
*/
public static void executeInBulk(@NotNull Document document, final boolean executeInBulk, @NotNull Runnable task) {
if (!(document instanceof DocumentEx)) {
task.run();
@@ -28,6 +28,7 @@ import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.EditorTextInsertHandler;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
@@ -39,6 +40,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.DocumentUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Producer;
import com.intellij.util.containers.HashMap;
@@ -365,15 +367,23 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser
}
}
private static void reformatBlock(Project project, Editor editor, int startOffset, int endOffset) {
private static void reformatBlock(final Project project, final Editor editor, final int startOffset, final int endOffset) {
PsiDocumentManager.getInstance(project).commitAllDocuments();
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
Runnable task = new Runnable() {
@Override
public void run() {
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
try {
CodeStyleManager.getInstance(project).reformatRange(file, startOffset, endOffset, true);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
};
try {
CodeStyleManager.getInstance(project).reformatRange(file, startOffset, endOffset, true);
}
catch (IncorrectOperationException e) {
LOG.error(e);
if (endOffset - startOffset > 1000) {
DocumentUtil.executeInBulk(editor.getDocument(), true, task);
}
}
@@ -321,8 +321,9 @@ class FormatProcessor {
* <code>false</code> otherwise
*/
@SuppressWarnings({"deprecation"})
private boolean applyChangesAtBulkMode(final List<LeafBlockWrapper> blocksToModify, final FormattingModel model,
@NotNull CommonCodeStyleSettings.IndentOptions indentOption)
private boolean applyChangesAtRewriteMode(@NotNull final List<LeafBlockWrapper> blocksToModify,
@NotNull final FormattingModel model,
@NotNull CommonCodeStyleSettings.IndentOptions indentOption)
{
FormattingDocumentModel documentModel = model.getDocumentModel();
Document document = documentModel.getDocument();
@@ -366,14 +367,13 @@ class FormatProcessor {
@Nullable
private static DocumentEx getAffectedDocument(final FormattingModel model) {
if (model instanceof DocumentBasedFormattingModel) {
final Document document = ((DocumentBasedFormattingModel)model).getDocument();
if (document instanceof DocumentEx) return (DocumentEx)document;
}/* else if (false) { // till issue with persistent range markers dropped fixed
Document document = model.getDocumentModel().getDocument();
if (document instanceof DocumentEx) return (DocumentEx)document;
}*/
return null;
final Document document = model.getDocumentModel().getDocument();
if (document instanceof DocumentEx) {
return (DocumentEx)document;
}
else {
return null;
}
}
private static int replaceWhiteSpace(final FormattingModel model,
@@ -1397,7 +1397,7 @@ class FormatProcessor {
myResetBulkUpdateState = true;
}
if (blocksToModifyCount > BULK_REPLACE_OPTIMIZATION_CRITERIA
&& applyChangesAtBulkMode(myBlocksToModify, myModel, myDefaultIndentOption))
&& applyChangesAtRewriteMode(myBlocksToModify, myModel, myDefaultIndentOption))
{
setDone(true);
}
@@ -715,6 +715,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myMousePressedEvent = null;
myMouseMovedEvent = null;
Disposer.dispose(myCaretModel);
Disposer.dispose(mySoftWrapModel);
clearCaretThread();
myFocusListeners.clear();
@@ -16,6 +16,7 @@
package com.intellij.openapi.editor.impl;
import com.intellij.diagnostic.Dumpable;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -52,7 +53,9 @@ import java.util.List;
* @author Denis Zhdanov
* @since Jun 8, 2010 12:47:32 PM
*/
public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentListener, FoldingListener, PropertyChangeListener, Dumpable {
public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentListener, DocumentBulkUpdateListener, FoldingListener,
PropertyChangeListener, Dumpable, Disposable
{
/**
* Holds name of JVM property which presence should trigger debug-aware soft wraps processing.
@@ -109,6 +112,8 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
* Current field serves as a flag that indicates if all preliminary actions necessary for successful soft wraps processing is done.
*/
private boolean myUpdateInProgress;
private boolean myBulkUpdateInProgress;
/**
* There is a possible case that target document is changed while its editor is inactive (e.g. user opens two editors for classes
@@ -169,6 +174,8 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
myUseSoftWraps = settings.isUseSoftWraps();
editor.addPropertyChangeListener(this);
ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(DocumentBulkUpdateListener.TOPIC, this);
}
/**
@@ -370,7 +377,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
@NotNull
@Override
public LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visual) {
if (myUpdateInProgress || !prepareToMapping()) {
if (myBulkUpdateInProgress || myUpdateInProgress || !prepareToMapping()) {
return myEditor.visualToLogicalPosition(visual, false);
}
myActive++;
@@ -386,7 +393,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
@NotNull
@Override
public LogicalPosition offsetToLogicalPosition(int offset) {
if (myUpdateInProgress || !prepareToMapping()) {
if (myBulkUpdateInProgress || myUpdateInProgress || !prepareToMapping()) {
return myEditor.offsetToLogicalPosition(offset, false);
}
myActive++;
@@ -401,7 +408,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
@NotNull
public LogicalPosition adjustLogicalPosition(LogicalPosition defaultLogical, int offset) {
if (myUpdateInProgress || !prepareToMapping()) {
if (myBulkUpdateInProgress || myUpdateInProgress || !prepareToMapping()) {
return defaultLogical;
}
@@ -418,7 +425,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
@Override
@NotNull
public VisualPosition adjustVisualPosition(@NotNull LogicalPosition logical, @NotNull VisualPosition defaultVisual) {
if (myUpdateInProgress || !prepareToMapping()) {
if (myBulkUpdateInProgress || myUpdateInProgress || !prepareToMapping()) {
return defaultVisual;
}
@@ -566,6 +573,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
@Override
public void beforeDocumentChange(DocumentEvent event) {
if (myBulkUpdateInProgress) {
return;
}
myUpdateInProgress = true;
if (!isSoftWrappingEnabled()) {
myDirty = true;
@@ -578,6 +588,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
@Override
public void documentChanged(DocumentEvent event) {
if (myBulkUpdateInProgress) {
return;
}
myUpdateInProgress = false;
if (!isSoftWrappingEnabled()) {
return;
@@ -587,6 +600,20 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
}
}
@Override
public void updateStarted(@NotNull Document doc) {
myBulkUpdateInProgress = true;
}
@Override
public void updateFinished(@NotNull Document doc) {
myBulkUpdateInProgress = false;
if (!isSoftWrappingEnabled()) {
return;
}
recalculate();
}
@Override
public void onFoldRegionStateChange(@NotNull FoldRegion region) {
myUpdateInProgress = true;
@@ -619,6 +646,11 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
return myDataMapper;
}
@Override
public void dispose() {
release();
}
@Override
public void release() {
myDataMapper.release();
@@ -632,6 +664,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
myApplianceManager.reset();
myDeferredFoldRegions.clear();
myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
myApplianceManager.recalculateIfNecessary();
}
public SoftWrapApplianceManager getApplianceManager() {