Fix navigate to super declaration line marker tooltip
Don't show overridden function signature each time, show only where it's declared
This commit is contained in:
@@ -42,27 +42,26 @@ import com.intellij.psi.search.searches.AllOverridingMethodsSearch;
|
|||||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||||
import com.intellij.util.*;
|
import com.intellij.util.*;
|
||||||
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import gnu.trove.THashSet;
|
import gnu.trove.THashSet;
|
||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.TestOnly;
|
import org.jetbrains.annotations.TestOnly;
|
||||||
import org.jetbrains.jet.asJava.LightClassUtil;
|
import org.jetbrains.jet.asJava.LightClassUtil;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.Modality;
|
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.OverrideResolver;
|
import org.jetbrains.jet.lang.resolve.OverrideResolver;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.jetbrains.jet.plugin.JetBundle;
|
import org.jetbrains.jet.plugin.JetBundle;
|
||||||
import org.jetbrains.jet.plugin.ProjectRootsUtil;
|
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.DescriptorToDeclarationUtil;
|
||||||
import org.jetbrains.jet.plugin.codeInsight.JetFunctionPsiElementCellRenderer;
|
import org.jetbrains.jet.plugin.codeInsight.JetFunctionPsiElementCellRenderer;
|
||||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
|
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
|
||||||
import org.jetbrains.jet.plugin.search.ideaExtensions.KotlinDefinitionsSearcher;
|
import org.jetbrains.jet.plugin.search.ideaExtensions.KotlinDefinitionsSearcher;
|
||||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||||
|
import org.jetbrains.jet.renderer.DescriptorRendererBuilder;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
@@ -239,27 +238,18 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
|
|||||||
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement((JetElement) element);
|
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement((JetElement) element);
|
||||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||||
|
|
||||||
if (!(descriptor instanceof CallableMemberDescriptor)) {
|
if (!(descriptor instanceof CallableMemberDescriptor)) return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<? extends CallableMemberDescriptor> overriddenMembers = OverrideResolver.getDirectlyOverriddenDeclarations(
|
Set<? extends CallableMemberDescriptor> overriddenMembers = OverrideResolver.getDirectlyOverriddenDeclarations(
|
||||||
(CallableMemberDescriptor) descriptor);
|
(CallableMemberDescriptor) descriptor);
|
||||||
if (overriddenMembers.size() == 0) {
|
if (overriddenMembers.isEmpty()) return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean allOverriddenAbstract = true;
|
|
||||||
for (CallableMemberDescriptor function : overriddenMembers) {
|
|
||||||
allOverriddenAbstract &= function.getModality() == Modality.ABSTRACT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Don't store descriptors in line markers because line markers are not deleted while editing other files and this can prevent
|
// 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.
|
// clearing the whole BindingTrace.
|
||||||
return new LineMarkerInfo<JetElement>(
|
return new LineMarkerInfo<JetElement>(
|
||||||
(JetElement) element,
|
(JetElement) element,
|
||||||
element.getTextOffset(),
|
element.getTextOffset(),
|
||||||
allOverriddenAbstract ? IMPLEMENTING_MARK : OVERRIDING_MARK,
|
isImplementsAndNotOverrides((CallableMemberDescriptor) descriptor, overriddenMembers) ? IMPLEMENTING_MARK : OVERRIDING_MARK,
|
||||||
Pass.UPDATE_ALL,
|
Pass.UPDATE_ALL,
|
||||||
new Function<JetElement, String>() {
|
new Function<JetElement, String>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -271,45 +261,57 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String calculateTooltipString(PsiElement element) {
|
private static String calculateTooltipString(JetElement element) {
|
||||||
JetFile file = (JetFile)element.getContainingFile();
|
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(element);
|
||||||
if (file == null) return "";
|
|
||||||
|
|
||||||
BindingContext bindingContext = ResolvePackage.getBindingContext(file);
|
|
||||||
|
|
||||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||||
if (!(descriptor instanceof CallableMemberDescriptor)) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<CallableMemberDescriptor> overriddenMembers = OverrideResolver
|
if (!(descriptor instanceof CallableMemberDescriptor)) return "";
|
||||||
.getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
|
CallableMemberDescriptor callableDescriptor = (CallableMemberDescriptor) descriptor;
|
||||||
if (overriddenMembers.size() == 0) {
|
|
||||||
return "";
|
Set<CallableMemberDescriptor> overriddenMembers = OverrideResolver.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
|
||||||
|
) {
|
||||||
|
if (descriptor.getModality() == Modality.ABSTRACT) return false;
|
||||||
|
|
||||||
boolean allOverriddenAbstract = true;
|
|
||||||
for (CallableMemberDescriptor function : overriddenMembers) {
|
for (CallableMemberDescriptor function : overriddenMembers) {
|
||||||
allOverriddenAbstract &= function.getModality() == Modality.ABSTRACT;
|
if (function.getModality() != Modality.ABSTRACT) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String implementsOrOverrides = allOverriddenAbstract ? "implements" : "overrides";
|
return true;
|
||||||
String memberKind = element instanceof JetNamedFunction ? "function" : "property";
|
|
||||||
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append(DescriptorRenderer.HTML.render(descriptor));
|
|
||||||
int overrideCount = overriddenMembers.size();
|
|
||||||
if (overrideCount >= 1) {
|
|
||||||
builder.append("<br/>").append(implementsOrOverrides).append("<br/>");
|
|
||||||
builder.append(DescriptorRenderer.HTML.render(overriddenMembers.iterator().next()));
|
|
||||||
}
|
|
||||||
if (overrideCount > 1) {
|
|
||||||
int otherCount = overrideCount - 1;
|
|
||||||
builder.append("<br/>and ").append(otherCount).append(" other ").append(StringUtil.pluralize(memberKind, otherCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ trait <lineMarker></lineMarker>TestTrait {
|
|||||||
class A {
|
class A {
|
||||||
class B {
|
class B {
|
||||||
class object : TestTrait { // TODO: No line marker
|
class object : TestTrait { // TODO: No line marker
|
||||||
override fun <lineMarker descr="<b>internal</b> <b>open</b> <b>fun</b> test(): kotlin.Unit <i>defined in</i> A.B.<class-object-for-B><br/>implements<br/><b>internal</b> <b>abstract</b> <b>fun</b> test(): kotlin.Unit <i>defined in</i> TestTrait"></lineMarker>test() {
|
override fun <lineMarker descr="Implements function in 'TestTrait'"></lineMarker>test() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ open class <lineMarker></lineMarker>C(b : B) : B by b, A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class D(b : B) : C(b) {
|
class D(b : B) : C(b) {
|
||||||
override fun <lineMarker descr="<b>internal</b> <b>open</b> <b>fun</b> f(): kotlin.Unit <i>defined in</i> D<br/>overrides<br/><b>internal</b> <b>open</b> <b>fun</b> f(): kotlin.Unit <i>defined in</i> A"></lineMarker>f() {}
|
override fun <lineMarker descr="Overrides function in 'A'"></lineMarker>f() {}
|
||||||
}
|
}
|
||||||
@@ -9,5 +9,5 @@ open class <lineMarker></lineMarker>C(b : B) : B by b, A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class D(b : B) : C(b) {
|
class D(b : B) : C(b) {
|
||||||
override val <lineMarker descr="<b>internal</b> <b>open</b> <b>val</b> f: kotlin.Int <i>defined in</i> D<br/>overrides<br/><b>internal</b> <b>open</b> <b>val</b> f: kotlin.Int <i>defined in</i> A"></lineMarker>f: Int = 2
|
override val <lineMarker descr="Overrides property in 'A'"></lineMarker>f: Int = 2
|
||||||
}
|
}
|
||||||
@@ -7,5 +7,5 @@ trait <lineMarker></lineMarker>B : A
|
|||||||
trait <lineMarker></lineMarker>C : B, A
|
trait <lineMarker></lineMarker>C : B, A
|
||||||
|
|
||||||
class SomeClass() : C {
|
class SomeClass() : C {
|
||||||
override fun <lineMarker descr="<b>internal</b> <b>open</b> <b>fun</b> f(): kotlin.Unit <i>defined in</i> SomeClass<br/>overrides<br/><b>internal</b> <b>open</b> <b>fun</b> f(): kotlin.Unit <i>defined in</i> A"></lineMarker>f() {}
|
override fun <lineMarker descr="Overrides function in 'A'"></lineMarker>f() {}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -9,5 +9,5 @@ trait <lineMarker></lineMarker>B : A {
|
|||||||
trait <lineMarker></lineMarker>C : B, A
|
trait <lineMarker></lineMarker>C : B, A
|
||||||
|
|
||||||
class SomeClass() : C {
|
class SomeClass() : C {
|
||||||
override fun <lineMarker descr="<b>internal</b> <b>open</b> <b>fun</b> f(): kotlin.Unit <i>defined in</i> SomeClass<br/>overrides<br/><b>internal</b> <b>open</b> <b>fun</b> f(): kotlin.Unit <i>defined in</i> B"></lineMarker>f() {}
|
override fun <lineMarker descr="Overrides function in 'B'"></lineMarker>f() {}
|
||||||
}
|
}
|
||||||
@@ -8,5 +8,5 @@ trait <lineMarker></lineMarker>B : A
|
|||||||
trait <lineMarker></lineMarker>C : B, A
|
trait <lineMarker></lineMarker>C : B, A
|
||||||
|
|
||||||
class SomeClass() : C {
|
class SomeClass() : C {
|
||||||
override val <lineMarker descr="<b>internal</b> <b>open</b> <b>val</b> f: kotlin.Int <i>defined in</i> SomeClass<br/>overrides<br/><b>internal</b> <b>open</b> <b>val</b> f: kotlin.Int <i>defined in</i> A"></lineMarker>f: Int = 4
|
override val <lineMarker descr="Overrides property in 'A'"></lineMarker>f: Int = 4
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user