mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-68357 IDEA unresponsive with large MXML files
Suppress injected text repaint requests triggered by injected-unaware lexer-based highlighter
This commit is contained in:
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.ex;
|
||||
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.impl.EditorRepaintStrategy;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This strategy handles the situation when typing is performed inside parsed injected text. Usually editor's highlighter
|
||||
* doesn't know anything about injected context internals and sees it just as a single big token (e.g. MXML files may contain
|
||||
* Flash code inside CDATA comment and the highlighter (based on XML lexer) considers the whole Flash code block to be just
|
||||
* a CDATA token).
|
||||
* <p/>
|
||||
* So, every time user types at injected context, highlighter receives document change event and asks editor to repaint
|
||||
* affected token. That is rather heavy operation if performed frequently for the large text range. That's why current
|
||||
* strategy handles such requests to the whole injected context repaint and skips them.
|
||||
* <p/>
|
||||
* It's assumed that corresponding repainting is performed during editor's markup model updates triggered by injected
|
||||
* context processing.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 6/17/11 11:16 AM
|
||||
*/
|
||||
public class InjectedAwareEditorRepaintStrategy implements EditorRepaintStrategy {
|
||||
|
||||
@Override
|
||||
public TextRange adjustHighlighterRegion(@NotNull EditorEx editor, int startOffset, int endOffset) {
|
||||
return isInjectedContext(editor, startOffset, endOffset) ? null : new TextRange(startOffset, endOffset);
|
||||
}
|
||||
|
||||
private static boolean isInjectedContext(@NotNull EditorEx editor, int startOffset, int endOffset) {
|
||||
final Project project = editor.getProject();
|
||||
if (project == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
|
||||
final PsiFile psiFile = documentManager.getCachedPsiFile(editor.getDocument());
|
||||
if (psiFile == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final List<DocumentWindow> injectedDocuments = InjectedLanguageUtil.getCachedInjectedDocuments(psiFile);
|
||||
for (DocumentWindow injectedDocument : injectedDocuments) {
|
||||
for (RangeMarker rangeMarker : injectedDocument.getHostRanges()) {
|
||||
if (Math.max(rangeMarker.getStartOffset(), startOffset) <= Math.min(rangeMarker.getEndOffset(), endOffset)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
|
||||
import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType;
|
||||
import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper;
|
||||
import com.intellij.openapi.editor.markup.*;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
@@ -1312,22 +1313,33 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
return line * getLineHeight();
|
||||
}
|
||||
|
||||
public void repaint(int startOffset, int endOffset) {
|
||||
public void repaint(final int startOffset, final int endOffset) {
|
||||
if (!isShowing() || myScrollPane == null || myDocument.isInBulkUpdate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int startOffsetToUse = startOffset;
|
||||
int endOffsetToUse = endOffset;
|
||||
assertIsDispatchThread();
|
||||
|
||||
if (endOffset > myDocument.getTextLength()) {
|
||||
endOffset = myDocument.getTextLength();
|
||||
if (endOffsetToUse > myDocument.getTextLength()) {
|
||||
endOffsetToUse = myDocument.getTextLength();
|
||||
}
|
||||
|
||||
for (EditorRepaintStrategy repaintStrategy : Extensions.getExtensions(EditorRepaintStrategy.EP_NAME)) {
|
||||
final TextRange range = repaintStrategy.adjustHighlighterRegion(this, startOffsetToUse, endOffsetToUse);
|
||||
if (range == null) {
|
||||
return;
|
||||
}
|
||||
startOffsetToUse = range.getStartOffset();
|
||||
endOffsetToUse = range.getEndOffset();
|
||||
}
|
||||
|
||||
// We do repaint in case of equal offsets because there is a possible case that there is a soft wrap at the same offset and
|
||||
// it does occupy particular amount of visual space that may be necessary to repaint.
|
||||
if (startOffset <= endOffset) {
|
||||
int startLine = myDocument.getLineNumber(startOffset);
|
||||
int endLine = myDocument.getLineNumber(endOffset);
|
||||
if (startOffsetToUse <= endOffsetToUse) {
|
||||
int startLine = myDocument.getLineNumber(startOffsetToUse);
|
||||
int endLine = myDocument.getLineNumber(endOffsetToUse);
|
||||
repaintLines(startLine, endLine);
|
||||
}
|
||||
}
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Defines contract for the strategy that may adjust/control editor's repainting.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 6/17/11 11:04 AM
|
||||
*/
|
||||
public interface EditorRepaintStrategy {
|
||||
|
||||
ExtensionPointName<EditorRepaintStrategy> EP_NAME = ExtensionPointName.create("com.intellij.editorRepaintStrategy");
|
||||
|
||||
/**
|
||||
* Asks current strategy to adjust (if necessary) target document region repaint request received from the given editor's highlighter.
|
||||
*
|
||||
* @param editor target editor
|
||||
* @param startOffset start offset of the document text range requested to be repainted (inclusive)
|
||||
* @param endOffset end offset of the document text range requested to be repainted (exclusive)
|
||||
* @return actual text range to repaint (if any); <code>null</code> as an indication that no further processing
|
||||
* for the current repaint request should be performed
|
||||
*/
|
||||
@Nullable
|
||||
TextRange adjustHighlighterRegion(@NotNull EditorEx editor, int startOffset, int endOffset);
|
||||
}
|
||||
@@ -456,6 +456,7 @@
|
||||
<codeFoldingOptionsProvider instance="com.intellij.application.options.editor.BaseCodeFoldingOptionsProvider" order="first"/>
|
||||
<editorOptionsProvider instance="com.intellij.application.options.editor.EditorSmartKeysConfigurable"/>
|
||||
<editorOptionsProvider instance="com.intellij.application.options.editor.EditorAppearanceConfigurable"/>
|
||||
<editorRepaintStrategy implementation="com.intellij.openapi.editor.ex.InjectedAwareEditorRepaintStrategy"/>
|
||||
<editorCustomization implementation="com.intellij.ui.SoftWrapsEditorCustomization"/>
|
||||
<editorCustomization implementation="com.intellij.ui.HorizontalScrollBarEditorCustomization"/>
|
||||
<editorCustomization implementation="com.intellij.ui.AdditionalPageAtBottomEditorCustomization"/>
|
||||
|
||||
@@ -112,6 +112,8 @@
|
||||
|
||||
<extensionPoint name="editorCustomization" area="IDEA_PROJECT" interface="com.intellij.ui.EditorCustomization"/>
|
||||
<extensionPoint name="editorNavigation" interface="com.intellij.openapi.editor.EditorNavigationDelegate"/>
|
||||
<extensionPoint name="editorRepaintStrategy" interface="com.intellij.openapi.editor.impl.EditorRepaintStrategy"/>
|
||||
|
||||
<extensionPoint name="statistics.usagesCollector" interface="com.intellij.internal.statistic.UsagesCollector"/>
|
||||
|
||||
<extensionPoint name="xmlRpcHandler" beanClass="com.intellij.ide.XmlRpcHandlerBean"/>
|
||||
|
||||
Reference in New Issue
Block a user