From 24d67e360b84462c5f2808db7d8a32c9c23f6c43 Mon Sep 17 00:00:00 2001 From: Dmitry Kozhevnikov Date: Tue, 23 Jan 2018 15:56:49 +0300 Subject: [PATCH] Don't reparse in the UI thread for the "Highlight Usages" pass Just moving the handler creation to background is not enough, since java's HighlightSuppressedWarningsHandler requires editor visible range, which has to be calculated on EDT, so pre-calculate it first, and pass to the handler factory then. This fixes CPP-9373. --- .../HighlightSuppressedWarningsFactory.java | 17 +++++++++++-- .../HighlightSuppressedWarningsHandler.java | 10 ++++++-- .../impl/IdentifierHighlighterPass.java | 22 +++++++++-------- .../highlighting/HighlightUsagesHandler.java | 16 ++++++++++++- .../HighlightUsagesHandlerFactory.java | 13 ++++++++++ .../HighlightUsagesHandlerFactoryBase.java | 24 +++++++++++++++++-- 6 files changed, 85 insertions(+), 17 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsFactory.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsFactory.java index 4182f003e1bd..5344c6280573 100644 --- a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsFactory.java +++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsFactory.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.highlighting; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.ProperTextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiElement; @@ -24,18 +25,30 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiLiteralExpression; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author yole */ public class HighlightSuppressedWarningsFactory extends HighlightUsagesHandlerFactoryBase { + + @Nullable @Override - public HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, @NotNull PsiElement target) { + public HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, + @NotNull PsiFile file, + @NotNull PsiElement target) { + throw new UnsupportedOperationException("Use createHighlightUsagesHandler(editor, file, target, visibleRange)"); + } + + @Override + public HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, @NotNull PsiElement target, + @NotNull ProperTextRange visibleRange) { final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(target, PsiAnnotation.class); if (annotation != null && Comparing.strEqual(SuppressWarnings.class.getName(), annotation.getQualifiedName())) { final VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile != null && !virtualFile.getFileType().isBinary()) { - return new HighlightSuppressedWarningsHandler(editor, file, annotation, PsiTreeUtil.getParentOfType(target, PsiLiteralExpression.class)); + return new HighlightSuppressedWarningsHandler(editor, file, annotation, + PsiTreeUtil.getParentOfType(target, PsiLiteralExpression.class), visibleRange); } } return null; diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java index 0cad016e992e..132f1e7e9223 100644 --- a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java @@ -45,13 +45,19 @@ class HighlightSuppressedWarningsHandler extends HighlightUsagesHandlerBase myReadAccessRanges = Collections.synchronizedList(new ArrayList<>()); private final Collection myWriteAccessRanges = Collections.synchronizedList(new ArrayList<>()); private final int myCaretOffset; - private final HighlightUsagesHandlerBase myHighlightUsagesHandler; + private final ProperTextRange myVisibleRange; IdentifierHighlighterPass(@NotNull Project project, @NotNull PsiFile file, @NotNull Editor editor) { super(project, editor.getDocument(), false); myFile = file; myEditor = editor; myCaretOffset = myEditor.getCaretModel().getOffset(); - myHighlightUsagesHandler = HighlightUsagesHandler.createCustomHandler(myEditor, myFile); + myVisibleRange = VisibleHighlightingPassFactory.calculateVisibleRange(myEditor); } @Override public void doCollectInformation(@NotNull final ProgressIndicator progress) { - if (myHighlightUsagesHandler != null) { - List targets = myHighlightUsagesHandler.getTargets(); - myHighlightUsagesHandler.computeUsages(targets); - final List readUsages = myHighlightUsagesHandler.getReadUsages(); + final HighlightUsagesHandlerBase highlightUsagesHandler = HighlightUsagesHandler.createCustomHandler(myEditor, myFile, myVisibleRange); + if (highlightUsagesHandler != null) { + List targets = highlightUsagesHandler.getTargets(); + highlightUsagesHandler.computeUsages(targets); + final List readUsages = highlightUsagesHandler.getReadUsages(); for (TextRange readUsage : readUsages) { - LOG.assertTrue(readUsage != null, "null text range from " + myHighlightUsagesHandler); + LOG.assertTrue(readUsage != null, "null text range from " + highlightUsagesHandler); } myReadAccessRanges.addAll(readUsages); - final List writeUsages = myHighlightUsagesHandler.getWriteUsages(); + final List writeUsages = highlightUsagesHandler.getWriteUsages(); for (TextRange writeUsage : writeUsages) { - LOG.assertTrue(writeUsage != null, "null text range from " + myHighlightUsagesHandler); + LOG.assertTrue(writeUsage != null, "null text range from " + highlightUsagesHandler); } myWriteAccessRanges.addAll(writeUsages); - if (!myHighlightUsagesHandler.highlightReferences()) return; + if (!highlightUsagesHandler.highlightReferences()) return; } int flags = TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java index 7082b3acd5f6..13518302867d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java @@ -19,6 +19,7 @@ package com.intellij.codeInsight.highlighting; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.TargetElementUtil; import com.intellij.codeInsight.daemon.impl.IdentifierUtil; +import com.intellij.codeInsight.daemon.impl.VisibleHighlightingPassFactory; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.find.EditorSearchSession; import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter; @@ -28,6 +29,7 @@ import com.intellij.navigation.NavigationItem; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.actionSystem.Shortcut; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; @@ -41,6 +43,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ProperTextRange; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.WindowManager; @@ -152,8 +155,19 @@ public class HighlightUsagesHandler extends HighlightHandlerBase { @Nullable public static HighlightUsagesHandlerBase createCustomHandler(@NotNull Editor editor, @NotNull PsiFile file) { + ApplicationManager.getApplication().assertIsDispatchThread(); + ProperTextRange visibleRange = VisibleHighlightingPassFactory.calculateVisibleRange(editor); + return createCustomHandler(editor, file, visibleRange); + } + + /** + * @see HighlightUsagesHandlerFactory#createHighlightUsagesHandler(Editor, PsiFile, ProperTextRange) + */ + @Nullable + public static HighlightUsagesHandlerBase createCustomHandler(@NotNull Editor editor, @NotNull PsiFile file, + @NotNull ProperTextRange visibleRange) { for (HighlightUsagesHandlerFactory factory : Extensions.getExtensions(HighlightUsagesHandlerFactory.EP_NAME)) { - final HighlightUsagesHandlerBase handler = factory.createHighlightUsagesHandler(editor, file); + final HighlightUsagesHandlerBase handler = factory.createHighlightUsagesHandler(editor, file, visibleRange); if (handler != null) { //noinspection unchecked return handler; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java index e6d3d9dda34b..e205c9d70cbb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.highlighting; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.util.ProperTextRange; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,4 +33,16 @@ public interface HighlightUsagesHandlerFactory { @Nullable HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file); + + + /** + * @param visibleRange To avoid parsing in EDT, these factory methods should be called in a background thread + * (as implementation use the PSI element under cursor to choose the specific handler). + * However, some handlers require the editor visible range, which must be calculated in EDT, + * so it's passed externally + */ + @Nullable + default HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, @NotNull ProperTextRange visibleRange) { + return createHighlightUsagesHandler(editor, file); + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactoryBase.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactoryBase.java index 140e474e1110..7ad387ece129 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactoryBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactoryBase.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.highlighting; import com.intellij.codeInsight.TargetElementUtil; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.ProperTextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; @@ -29,12 +30,31 @@ public abstract class HighlightUsagesHandlerFactoryBase implements HighlightUsag @Nullable @Override public final HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file) { - int offset = TargetElementUtil.adjustOffset(file, editor.getDocument(), editor.getCaretModel().getOffset()); - PsiElement target = file.findElementAt(offset); + PsiElement target = findTarget(editor, file); if (target == null) return null; return createHighlightUsagesHandler(editor, file, target); } + @Nullable + @Override + public final HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, + @NotNull ProperTextRange visibleRange) { + PsiElement target = findTarget(editor, file); + if (target == null) return null; + return createHighlightUsagesHandler(editor, file, target, visibleRange); + } + @Nullable public abstract HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, @NotNull PsiElement target); + + @Nullable + public HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, @NotNull PsiElement target, + @NotNull ProperTextRange visibleRange) { + return createHighlightUsagesHandler(editor, file, target); + } + + private static PsiElement findTarget(@NotNull Editor editor, @NotNull PsiFile file) { + int offset = TargetElementUtil.adjustOffset(file, editor.getDocument(), editor.getCaretModel().getOffset()); + return file.findElementAt(offset); + } }