Rewrite to Kotlin: super navigation markers methods

This commit is contained in:
Nikolay Krasko
2014-08-25 03:00:00 +04:00
committed by Nikolay Krasko
parent f7edd5abe7
commit 7bf622dd26
4 changed files with 150 additions and 119 deletions
@@ -159,36 +159,43 @@ public class DescriptorRendererBuilder {
return this;
}
@NotNull
public DescriptorRendererBuilder setIncludePropertyConstant(boolean includePropertyConstant) {
this.includePropertyConstant = includePropertyConstant;
return this;
}
@NotNull
public DescriptorRendererBuilder setIncludeSynthesizedParameterNames(boolean includeSynthesizedParameterNames) {
this.includeSynthesizedParameterNames = includeSynthesizedParameterNames;
return this;
}
@NotNull
public DescriptorRendererBuilder setWithoutTypeParameters(boolean withoutTypeParameters) {
this.withoutTypeParameters = withoutTypeParameters;
return this;
}
@NotNull
public DescriptorRendererBuilder setWithoutFunctionParameterNames(boolean withoutFunctionParameterNames) {
this.withoutFunctionParameterNames = withoutFunctionParameterNames;
return this;
}
@NotNull
public DescriptorRendererBuilder setReceiverAfterName(boolean receiverAfterName) {
this.receiverAfterName = receiverAfterName;
return this;
}
@NotNull
public DescriptorRendererBuilder setRenderClassObjectName(boolean renderClassObjectName) {
this.renderClassObjectName = renderClassObjectName;
return this;
}
@NotNull
public DescriptorRendererBuilder setWithoutSuperTypes(boolean withoutSuperTypes) {
this.withoutSuperTypes = withoutSuperTypes;
return this;
@@ -19,7 +19,6 @@ package org.jetbrains.jet.plugin.highlighter;
import com.google.common.collect.*;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.DaemonBundle;
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.codeInsight.daemon.impl.GutterIconTooltipHelper;
@@ -32,14 +31,12 @@ import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.ide.util.MethodCellRenderer;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiElementProcessor;
@@ -55,29 +52,24 @@ import kotlin.KotlinPackage;
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.KotlinLightMethodFromTrait;
import org.jetbrains.jet.asJava.LightClassUtil;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.Modality;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetBundle;
import org.jetbrains.jet.plugin.ProjectRootsUtil;
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil;
import org.jetbrains.jet.plugin.codeInsight.JetFunctionPsiElementCellRenderer;
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
import org.jetbrains.jet.plugin.highlighter.markers.MarkersPackage;
import org.jetbrains.jet.plugin.highlighter.markers.ResolveWithParentsResult;
import org.jetbrains.jet.plugin.highlighter.markers.SuperDeclarationMarkerNavigationHandler;
import org.jetbrains.jet.plugin.highlighter.markers.SuperDeclarationMarkerTooltip;
import org.jetbrains.jet.plugin.search.ideaExtensions.KotlinDefinitionsSearcher;
import org.jetbrains.jet.renderer.DescriptorRenderer;
import org.jetbrains.jet.renderer.DescriptorRendererBuilder;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.OverrideResolver.getDirectlyOverriddenDeclarations;
public class JetLineMarkerProvider implements LineMarkerProvider {
public static final Icon OVERRIDING_MARK = AllIcons.Gutter.OverridingMethod;
public static final Icon IMPLEMENTING_MARK = AllIcons.Gutter.ImplementingMethod;
@@ -245,46 +237,6 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
return null;
}
private static String calculateTooltipString(JetElement element) {
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(element);
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
if (!(descriptor instanceof CallableMemberDescriptor)) return "";
CallableMemberDescriptor callableDescriptor = (CallableMemberDescriptor) descriptor;
Set<CallableMemberDescriptor> overriddenMembers = getDirectlyOverriddenDeclarations(callableDescriptor);
if (overriddenMembers.isEmpty()) return "";
final boolean isAbstract = callableDescriptor.getModality() == Modality.ABSTRACT;
final DescriptorRenderer renderer = new DescriptorRendererBuilder()
.setTextFormat(DescriptorRenderer.TextFormat.HTML)
.setWithDefinedIn(false)
.setStartFromName(true)
.setWithoutSuperTypes(true)
.build();
List<String> containingStrings = ContainerUtil.map(overriddenMembers, new Function<CallableMemberDescriptor, String>() {
@Override
public String fun(CallableMemberDescriptor overriddenDescriptor) {
DeclarationDescriptor declaration = overriddenDescriptor.getContainingDeclaration();
String memberKind =
overriddenDescriptor instanceof PropertyAccessorDescriptor || overriddenDescriptor instanceof PropertyDescriptor ?
"property" : "function";
boolean isBaseAbstract = overriddenDescriptor.getModality() == Modality.ABSTRACT;
return String.format("%s %s in '%s'",
!isAbstract && isBaseAbstract ? "Implements" : "Overrides",
memberKind, renderer.render(declaration));
}
});
Collections.sort(containingStrings);
return StringUtil.join(containingStrings, "<br/>");
}
private static boolean isImplementsAndNotOverrides(
CallableMemberDescriptor descriptor,
Collection<? extends CallableMemberDescriptor> overriddenMembers
@@ -340,28 +292,20 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
if (!declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) return;
DeclarationDescriptor descriptor =
ResolvePackage.getLazyResolveSession(declaration).resolveToDescriptor(declaration);
if (!(descriptor instanceof CallableMemberDescriptor)) return;
Set<? extends CallableMemberDescriptor> overriddenMembers = getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
if (overriddenMembers.isEmpty()) return;
ResolveWithParentsResult resolveWithParents = MarkersPackage.resolveDeclarationWithParents(declaration);
if (resolveWithParents.getOverriddenDescriptors().isEmpty()) return;
// 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.
LineMarkerInfo<JetElement> marker = new LineMarkerInfo<JetElement>(
declaration,
declaration.getTextOffset(),
isImplementsAndNotOverrides((CallableMemberDescriptor) descriptor, overriddenMembers) ? IMPLEMENTING_MARK : OVERRIDING_MARK,
isImplementsAndNotOverrides(resolveWithParents.getDescriptor(), resolveWithParents.getOverriddenDescriptors()) ?
IMPLEMENTING_MARK :
OVERRIDING_MARK,
Pass.UPDATE_OVERRIDEN_MARKERS,
new Function<JetElement, String>() {
@Override
public String fun(JetElement element) {
return calculateTooltipString(element);
}
},
new KotlinSuperNavigationHandler()
SuperDeclarationMarkerTooltip.INSTANCE$,
new SuperDeclarationMarkerNavigationHandler()
);
result.add(marker);
@@ -608,50 +552,4 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
});
}
}
public static class KotlinSuperNavigationHandler implements GutterIconNavigationHandler<JetElement> {
private List<NavigatablePsiElement> testNavigableElements;
@TestOnly
@NotNull
public List<NavigatablePsiElement> getNavigationElements() {
List<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 =
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;
}
}
}
}
@@ -0,0 +1,126 @@
/*
* Copyright 2010-2014 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 org.jetbrains.jet.plugin.highlighter.markers
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor
import org.jetbrains.jet.lang.resolve.OverrideResolver
import org.jetbrains.jet.lang.descriptors.Modality
import org.jetbrains.jet.renderer.DescriptorRenderer
import org.jetbrains.jet.renderer.DescriptorRendererBuilder
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
import com.intellij.psi.NavigatablePsiElement
import java.awt.event.MouseEvent
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator
import org.jetbrains.jet.plugin.JetBundle
import org.jetbrains.jet.plugin.codeInsight.JetFunctionPsiElementCellRenderer
import org.jetbrains.annotations.TestOnly
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler
import java.util.ArrayList
import com.intellij.util.Function
object SuperDeclarationMarkerTooltip: Function<JetElement, String> {
override fun `fun`(param: JetElement?): String? {
val element = param!!
[suppress("UNUSED_VARIABLE")]
val (elementDescriptor, _, overriddenDescriptors) = resolveDeclarationWithParents(element)
if (overriddenDescriptors.isEmpty()) return ""
val isAbstract = elementDescriptor!!.getModality() == Modality.ABSTRACT
val renderer = DescriptorRendererBuilder()
.setTextFormat(DescriptorRenderer.TextFormat.HTML)
.setWithDefinedIn(false)
.setStartFromName(true)
.setWithoutSuperTypes(true)
.build()
val containingStrings = overriddenDescriptors.map {
val declaration = it.getContainingDeclaration()
val memberKind = if (it is PropertyAccessorDescriptor || it is PropertyDescriptor) "property" else "function"
val isBaseAbstract = it.getModality() == Modality.ABSTRACT
"${if (!isAbstract && isBaseAbstract) "Implements" else "Overrides"} $memberKind in '${renderer.render(declaration)}'"
}
return containingStrings.sort().join(separator = "<br/>")
}
}
public class SuperDeclarationMarkerNavigationHandler : GutterIconNavigationHandler<JetElement> {
private var testNavigableElements: List<NavigatablePsiElement>? = null
TestOnly
public fun getNavigationElements(): List<NavigatablePsiElement> {
val navigationResult = testNavigableElements!!
testNavigableElements = null
return navigationResult
}
override fun navigate(e: MouseEvent?, element: JetElement?) {
if (element == null) return
val (elementDescriptor, bindingContext, overriddenDescriptors) = resolveDeclarationWithParents(element)
if (overriddenDescriptors.isEmpty()) return
val superDeclarations = ArrayList<NavigatablePsiElement>()
for (overriddenMember in overriddenDescriptors) {
val declarations = DescriptorToDeclarationUtil.resolveToPsiElements(element.getProject(), overriddenMember)
for (declaration in declarations) {
if (declaration is NavigatablePsiElement) {
superDeclarations.add(declaration as NavigatablePsiElement)
}
}
}
if (!ApplicationManager.getApplication()!!.isUnitTestMode()) {
val elementName = elementDescriptor!!.getName()
PsiElementListNavigator.openTargets(
e,
superDeclarations.copyToArray(),
JetBundle.message("navigation.title.super.declaration", elementName),
JetBundle.message("navigation.findUsages.title.super.declaration", elementName),
JetFunctionPsiElementCellRenderer(bindingContext))
}
else {
// Only store elements for retrieve in test
testNavigableElements = superDeclarations
}
}
}
public data class ResolveWithParentsResult(
val descriptor: CallableMemberDescriptor?,
val bindingContext: BindingContext,
val overriddenDescriptors: Collection<CallableMemberDescriptor>)
public fun resolveDeclarationWithParents(element: JetElement): ResolveWithParentsResult {
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element)
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element)
if (descriptor !is CallableMemberDescriptor) return ResolveWithParentsResult(null, bindingContext, listOf())
val overriddenMembers = OverrideResolver.getDirectlyOverriddenDeclarations(descriptor)
return ResolveWithParentsResult(descriptor, bindingContext, overriddenMembers)
}
@@ -33,7 +33,7 @@ import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import org.jetbrains.jet.plugin.highlighter.JetLineMarkerProvider;
import org.jetbrains.jet.plugin.highlighter.markers.SuperDeclarationMarkerNavigationHandler;
import org.jetbrains.jet.plugin.navigation.NavigationTestUtils;
import org.jetbrains.jet.testing.HighlightTestDataUtil;
import org.jetbrains.jet.testing.ReferenceUtils;
@@ -113,13 +113,13 @@ public abstract class AbstractLineMarkersTest extends JetLightCodeInsightFixture
navigateMarker);
GutterIconNavigationHandler handler = navigateMarker.getNavigationHandler();
if (handler instanceof JetLineMarkerProvider.KotlinSuperNavigationHandler) {
if (handler instanceof SuperDeclarationMarkerNavigationHandler) {
PsiElement element = navigateMarker.getElement();
//noinspection unchecked
handler.navigate(null, element);
List<NavigatablePsiElement> navigateElements =
((JetLineMarkerProvider.KotlinSuperNavigationHandler) handler).getNavigationElements();
((SuperDeclarationMarkerNavigationHandler) handler).getNavigationElements();
Collections.sort(navigateElements, new Comparator<NavigatablePsiElement>() {
@Override
@@ -137,7 +137,7 @@ public abstract class AbstractLineMarkersTest extends JetLightCodeInsightFixture
assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData);
}
else {
Assert.fail("Only JetLineMarkerProvider.KotlinSuperNavigationHandler are supported in navigate check");
Assert.fail("Only SuperDeclarationMarkerNavigationHandler are supported in navigate check");
}
}
}