a quick&dirty way of making async editor highlighter update more interruptible on large files (IDEA-225827)

GitOrigin-RevId: 2111ace1b268f8acee2d0739bca97137eb0c8091
This commit is contained in:
peter
2019-10-30 21:21:16 +01:00
committed by intellij-monorepo-bot
parent 04fece2ecb
commit 25053f075f
2 changed files with 23 additions and 0 deletions

View File

@@ -22,6 +22,7 @@ import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
@@ -30,6 +31,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.text.ImmutableCharSequence;
import com.intellij.util.text.SingleCharSequence;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -48,6 +50,7 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc
private EditorColorsScheme myScheme;
private final int myInitialState;
protected CharSequence myText;
private boolean myCancelable;
public LexerEditorHighlighter(@NotNull SyntaxHighlighter highlighter, @NotNull EditorColorsScheme scheme) {
myScheme = scheme;
@@ -58,6 +61,15 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc
mySegments = createSegments();
}
/**
* @param cancelable whether {@link #setText} may be interrupted by a {@link ProcessCanceledException} safely and this lexer
* won't be used after that exception and thus its internal incomplete data structures won't break anyone
*/
@ApiStatus.Internal
public void setCancelable(boolean cancelable) {
myCancelable = cancelable;
}
@NotNull
protected SegmentArrayWithData createSegments() {
return new SegmentArrayWithData(createStorage());
@@ -429,6 +441,7 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc
final int textLength = text.length();
myLexer.start(text, 0, textLength, myLexer instanceof RestartableLexer ? ((RestartableLexer)myLexer).getStartState() : myInitialState);
mySegments.removeAll();
boolean cancelable = myCancelable;
int i = 0;
while (true) {
final IElementType tokenType = myLexer.getTokenType();
@@ -438,6 +451,9 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc
int data = mySegments.packData(tokenType, state, canRestart(state));
processor.addToken(i, myLexer.getTokenStart(), myLexer.getTokenEnd(), data, tokenType);
i++;
if (cancelable && i % 1024 == 0) {
ProgressManager.checkCanceled();
}
myLexer.advance();
}
processor.finish();

View File

@@ -10,6 +10,7 @@ import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.util.EmptyEditorHighlighter;
import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.extensions.ExtensionPointListener;
@@ -103,7 +104,13 @@ public class EditorHighlighterUpdater {
EditorHighlighter highlighter = myFile != null
? EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, myFile)
: new EmptyEditorHighlighter(EditorColorsManager.getInstance().getGlobalScheme().getAttributes(HighlighterColors.TEXT));
if (highlighter instanceof LexerEditorHighlighter) {
((LexerEditorHighlighter)highlighter).setCancelable(true);
}
highlighter.setText(myEditor.getDocument().getImmutableCharSequence());
if (highlighter instanceof LexerEditorHighlighter) {
((LexerEditorHighlighter)highlighter).setCancelable(false);
}
return highlighter;
}