From 26f30df96de550c6a512d0404410811a4b4b75a1 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Tue, 8 Nov 2016 10:13:52 +0100 Subject: [PATCH] show first result and start background thread to check the rest when search for implementations --- .../codeInsight/daemon/impl/MarkerType.java | 32 ++++++++++++++----- .../daemon/impl/PsiElementListNavigator.java | 23 +++++++++---- .../navigation/BackgroundUpdaterTask.java | 12 ++++++- .../navigation/GotoImplementationHandler.java | 13 ++++++-- .../navigation/GotoTargetHandler.java | 26 ++++++++++----- .../navigation/ImplementationSearcher.java | 2 +- 6 files changed, 81 insertions(+), 27 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java index 5233e6748ab7..1cf674f31c09 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java @@ -28,6 +28,7 @@ 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.application.ReadAction; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -267,12 +268,7 @@ public class MarkerType { if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> { OverridingMethodsSearch.search(method).forEach(new PsiElementProcessorAdapter<>(collectProcessor)); if (isAbstract && collectProcessor.getCollection().size() < 2) { - final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public PsiClass compute() { - return method.getContainingClass(); - } - }); + final PsiClass aClass = ReadAction.compute(() -> method.getContainingClass()); if (aClass != null) { FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(collectExprProcessor)); } @@ -353,11 +349,11 @@ public class MarkerType { final PsiElementProcessor.CollectElementsWithLimit collectProcessor = new PsiElementProcessor.CollectElementsWithLimit<>(2, new THashSet<>()); final PsiElementProcessor.CollectElementsWithLimit collectExprProcessor = - new PsiElementProcessor.CollectElementsWithLimit<>(2, + new PsiElementProcessor.CollectElementsWithLimit<>(1, new THashSet<>()); if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> { ClassInheritorsSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(collectProcessor)); - if (collectProcessor.getCollection().size() < 2) { + if (collectProcessor.getCollection().size() < 1) { FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(collectExprProcessor)); } }, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent)e.getComponent())) { @@ -392,6 +388,16 @@ public class MarkerType { : DaemonBundle.message("navigation.title.subclass", myClass.getName(), size, suffix); } + @Override + public void onFinished() { + super.onFinished(); + PsiElement oneElement = getTheOnlyOneElement(); + if (oneElement instanceof NavigatablePsiElement) { + ((NavigatablePsiElement)oneElement).navigate(true); + myPopup.cancel(); + } + } + @Override public void run(@NotNull final ProgressIndicator indicator) { super.run(indicator); @@ -441,6 +447,16 @@ public class MarkerType { DaemonBundle.message("navigation.title.overrider.method", myMethod.getName(), size); } + @Override + public void onFinished() { + super.onFinished(); + PsiElement oneElement = getTheOnlyOneElement(); + if (oneElement instanceof NavigatablePsiElement) { + ((NavigatablePsiElement)oneElement).navigate(true); + myPopup.cancel(); + } + } + @Override public void run(@NotNull final ProgressIndicator indicator) { super.run(indicator); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java index 37de5fee46b6..643c0ae35aaa 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -26,7 +26,6 @@ import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.PopupChooserBuilder; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; import com.intellij.psi.NavigatablePsiElement; import com.intellij.psi.PsiElement; @@ -36,8 +35,8 @@ import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.popup.AbstractPopup; import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.usages.UsageView; +import com.intellij.util.Alarm; import com.intellij.util.Consumer; -import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -63,7 +62,16 @@ public class PsiElementListNavigator { ListCellRenderer listRenderer, @Nullable ListBackgroundUpdaterTask listUpdaterTask) { JBPopup popup = navigateOrCreatePopup(targets, title, findUsagesTitle, listRenderer, listUpdaterTask); - if (popup != null) popup.show(new RelativePoint(e)); + if (popup != null) { + if (listUpdaterTask != null) { + Alarm alarm = new Alarm(popup); + alarm.addRequest(() -> popup.show(new RelativePoint(e)), 300); + ProgressManager.getInstance().run(listUpdaterTask); + } + else { + popup.show(new RelativePoint(e)); + } + } } public static void openTargets(Editor e, NavigatablePsiElement[] targets, String title, final String findUsagesTitle, ListCellRenderer listRenderer) { @@ -86,6 +94,9 @@ public class PsiElementListNavigator { }); } + /** + * listUpdaterTask should be started after alarm is initialized so one-item popup won't blink + */ @Nullable public static JBPopup navigateOrCreatePopup(@NotNull final NavigatablePsiElement[] targets, final String title, @@ -94,7 +105,7 @@ public class PsiElementListNavigator { @Nullable final ListBackgroundUpdaterTask listUpdaterTask, @NotNull final Consumer consumer) { if (targets.length == 0) return null; - if (targets.length == 1) { + if (targets.length == 1 && (listUpdaterTask == null || listUpdaterTask.isFinished())) { consumer.consume(targets); return null; } @@ -166,8 +177,6 @@ public class PsiElementListNavigator { if (listUpdaterTask != null) { listUpdaterTask.init((AbstractPopup)popup, list, usageView); - - ProgressManager.getInstance().run(listUpdaterTask); } return popup; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java index 27f2d36c76c2..455bb68d6b4c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -147,6 +147,16 @@ public abstract class BackgroundUpdaterTask extends Task.Backgroundable { myFinished = true; } + @Nullable + protected PsiElement getTheOnlyOneElement() { + synchronized (lock) { + if (myData.size() == 1) { + return myData.get(0); + } + } + return null; + } + public boolean isFinished() { return myFinished; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoImplementationHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoImplementationHandler.java index 14dfa7e01e08..95cf6e3abab9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoImplementationHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoImplementationHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -63,7 +63,16 @@ public class GotoImplementationHandler extends GotoTargetHandler { }.searchImplementations(editor, source, offset); if (targets == null) return null; GotoData gotoData = new GotoData(source, targets, Collections.emptyList()); - gotoData.listUpdaterTask = new ImplementationsUpdaterTask(gotoData, editor, offset, reference); + gotoData.listUpdaterTask = new ImplementationsUpdaterTask(gotoData, editor, offset, reference) { + @Override + public void onFinished() { + super.onFinished(); + PsiElement oneElement = getTheOnlyOneElement(); + if (oneElement != null && navigateToElement(oneElement)) { + myPopup.cancel(); + } + } + }; return gotoData; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java index 79d45d04f06a..423b8fe31c98 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -46,6 +46,7 @@ import com.intellij.ui.JBListWithHintProvider; import com.intellij.ui.popup.AbstractPopup; import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.usages.UsageView; +import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NonNls; @@ -100,11 +101,9 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler { return; } - if (targets.length == 1 && additionalActions.isEmpty()) { - Navigatable descriptor = targets[0] instanceof Navigatable ? (Navigatable)targets[0] : EditSourceUtil.getDescriptor(targets[0]); - if (descriptor != null && descriptor.canNavigate()) { - navigateToElement(descriptor); - } + boolean finished = gotoData.listUpdaterTask == null || gotoData.listUpdaterTask.isFinished(); + if (targets.length == 1 && additionalActions.isEmpty() && finished) { + navigateToElement(targets[0]); return; } @@ -113,7 +112,6 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler { } final String name = ((PsiNamedElement)gotoData.source).getName(); - boolean finished = gotoData.listUpdaterTask == null || gotoData.listUpdaterTask.isFinished(); final String title = getChooserTitle(gotoData.source, name, targets.length, finished); if (shouldSortTargets()) { @@ -200,10 +198,14 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler { builder.getScrollPane().setViewportBorder(null); if (gotoData.listUpdaterTask != null) { + Alarm alarm = new Alarm(popup); + alarm.addRequest(() -> popup.showInBestPositionFor(editor), 300); gotoData.listUpdaterTask.init((AbstractPopup)popup, list, usageView); ProgressManager.getInstance().run(gotoData.listUpdaterTask); } - popup.showInBestPositionFor(editor); + else { + popup.showInBestPositionFor(editor); + } } @NotNull @@ -250,6 +252,14 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler { return renderer; } + protected boolean navigateToElement(PsiElement target) { + Navigatable descriptor = target instanceof Navigatable ? (Navigatable)target : EditSourceUtil.getDescriptor(target); + if (descriptor != null && descriptor.canNavigate()) { + navigateToElement(descriptor); + return true; + } + return false; + } protected void navigateToElement(@NotNull Navigatable descriptor) { descriptor.navigate(true); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/ImplementationSearcher.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/ImplementationSearcher.java index 16335251822e..ca0516e2eb41 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/ImplementationSearcher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/ImplementationSearcher.java @@ -128,7 +128,7 @@ public class ImplementationSearcher { } PsiElementProcessor.CollectElementsWithLimit collectProcessor = - new PsiElementProcessor.CollectElementsWithLimit<>(2, new THashSet<>()); + new PsiElementProcessor.CollectElementsWithLimit<>(1, new THashSet<>()); PsiElement[][] result = new PsiElement[1][]; if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override