Make testable navigation from line markers for super declarations

This commit is contained in:
Nikolay Krasko
2014-07-24 16:46:03 +04:00
parent 7c0acd9da5
commit 6a714436f2
@@ -28,6 +28,7 @@ import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
@@ -45,6 +46,7 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.asJava.LightClassUtil;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -254,53 +256,21 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
// NOTE: Don't store descriptors in line markers because line markers are not deleted while editing other files and this can prevent
// clearing the whole BindingTrace.
return new LineMarkerInfo<PsiElement>(
element,
return new LineMarkerInfo<JetElement>(
(JetElement) element,
element.getTextOffset(),
allOverriddenAbstract ? IMPLEMENTING_MARK : OVERRIDING_MARK,
Pass.UPDATE_ALL,
new Function<PsiElement, String>() {
new Function<JetElement, String>() {
@Override
public String fun(PsiElement element) {
public String fun(JetElement element) {
return calculateTooltipString(element);
}
},
new GutterIconNavigationHandler<PsiElement>() {
@Override
public void navigate(MouseEvent event, PsiElement elt) {
iconNavigatorHandler(event, elt);
}
}
new KotlinSuperNavigationHandler()
);
}
private static void iconNavigatorHandler(MouseEvent event, PsiElement elt) {
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement((JetElement) elt);
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, elt);
if (!(descriptor instanceof CallableMemberDescriptor)) return;
Set<CallableMemberDescriptor> overriddenMembers =
OverrideResolver.getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
if (overriddenMembers.isEmpty()) return;
List<NavigatablePsiElement> list = Lists.newArrayList();
for (CallableMemberDescriptor overriddenMember : overriddenMembers) {
Collection<PsiElement> declarations = DescriptorToDeclarationUtil.INSTANCE$.resolveToPsiElements(elt.getProject(), overriddenMember);
for (PsiElement declaration : declarations) {
if (declaration instanceof NavigatablePsiElement) {
list.add((NavigatablePsiElement) declaration);
}
}
}
PsiElementListNavigator.openTargets(
event,
ArrayUtil.toObjectArray(list, NavigatablePsiElement.class),
JetBundle.message("navigation.title.super.declaration", descriptor.getName()),
JetBundle.message("navigation.findUsages.title.super.declaration", descriptor.getName()),
new JetFunctionPsiElementCellRenderer(bindingContext));
}
private static String calculateTooltipString(PsiElement element) {
JetFile file = (JetFile)element.getContainingFile();
if (file == null) return "";
@@ -512,4 +482,50 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
return overridden;
}
public static class KotlinSuperNavigationHandler implements GutterIconNavigationHandler<JetElement> {
private List<NavigatablePsiElement> testNavigableElements;
@TestOnly
@NotNull
public Collection<NavigatablePsiElement> getNavigationElements() {
Collection<NavigatablePsiElement> navigationResult = testNavigableElements;
testNavigableElements = null;
return navigationResult;
}
@Override
public void navigate(MouseEvent e, JetElement element) {
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(element);
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
if (!(descriptor instanceof CallableMemberDescriptor)) return;
Set<CallableMemberDescriptor> overriddenMembers =
OverrideResolver.getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
if (overriddenMembers.isEmpty()) return;
List<NavigatablePsiElement> superDeclarations = Lists.newArrayList();
for (CallableMemberDescriptor overriddenMember : overriddenMembers) {
Collection<PsiElement> declarations =
DescriptorToDeclarationUtil.INSTANCE$.resolveToPsiElements(element.getProject(), overriddenMember);
for (PsiElement declaration : declarations) {
if (declaration instanceof NavigatablePsiElement) {
superDeclarations.add((NavigatablePsiElement) declaration);
}
}
}
if (!ApplicationManager.getApplication().isUnitTestMode()) {
PsiElementListNavigator.openTargets(
e,
ArrayUtil.toObjectArray(superDeclarations, NavigatablePsiElement.class),
JetBundle.message("navigation.title.super.declaration", descriptor.getName()),
JetBundle.message("navigation.findUsages.title.super.declaration", descriptor.getName()),
new JetFunctionPsiElementCellRenderer(bindingContext));
}
else {
testNavigableElements = superDeclarations;
}
}
}
}