From 27bbca7fe414cc5f2b88b6ae293b92584243e878 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 10 Jan 2013 13:52:18 +0400 Subject: [PATCH] Navigate to source when functions differ only in upper bounds of type parameters. --- .../libraries/JetSourceNavigationHelper.java | 58 ++++++++++++++++++- .../libraries/decompiled/namespace.kt | 4 ++ idea/testData/libraries/library/main.kt | 9 ++- .../usercode/OverloadedFunWithTypeParam.kt | 12 ++++ .../NavigateToLibrarySourceTest.java | 4 ++ 5 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 idea/testData/libraries/usercode/OverloadedFunWithTypeParam.kt diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java index bff3bd75fb0..27e7b2d0224 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java @@ -17,8 +17,7 @@ package org.jetbrains.jet.plugin.libraries; import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; +import com.google.common.collect.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.OrderRootType; @@ -31,6 +30,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScopes; import com.intellij.psi.stubs.StringStubIndexExtension; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,12 +42,14 @@ import org.jetbrains.jet.lang.resolve.lazy.FileBasedDeclarationProviderFactory; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex; import org.jetbrains.jet.plugin.stubindex.JetTopLevelFunctionsFqnNameIndex; import org.jetbrains.jet.plugin.stubindex.JetTopLevelPropertiesFqnNameIndex; import org.jetbrains.jet.renderer.DescriptorRenderer; +import org.jetbrains.jet.util.CommonSuppliers; import java.util.Collection; import java.util.Collections; @@ -257,7 +259,8 @@ public class JetSourceNavigationHelper { //noinspection unchecked Descr candidateDescriptor = (Descr) resolveSession.resolveToDescriptor(candidate); if (receiversMatch(receiverType, candidateDescriptor.getReceiverParameter()) - && navigationStrategy.declarationAndDescriptorMatchByParameterTypes(decompiledDeclaration, candidateDescriptor)) { + && navigationStrategy.declarationAndDescriptorMatchByParameterTypes(decompiledDeclaration, candidateDescriptor) + && typeParametersMatch((JetTypeParameterListOwner) decompiledDeclaration, candidateDescriptor.getTypeParameters())) { return candidate; } } @@ -369,6 +372,55 @@ public class JetSourceNavigationHelper { return false; } + private static boolean typeParametersMatch( + @NotNull JetTypeParameterListOwner typeParameterListOwner, + @NotNull List typeParameterDescriptors + ) { + List decompiledParameters = typeParameterListOwner.getTypeParameters(); + if (decompiledParameters.size() != typeParameterDescriptors.size()) { + return false; + } + + Multimap decompiledParameterToBounds = Multimaps.newSetMultimap( + Maps.>newHashMap(), CommonSuppliers.getHashSetSupplier()); + for (JetTypeParameter parameter : decompiledParameters) { + JetTypeReference extendsBound = parameter.getExtendsBound(); + if (extendsBound != null) { + decompiledParameterToBounds.put(parameter.getNameAsName(), extendsBound.getText()); + } + } + + for (JetTypeConstraint typeConstraint : typeParameterListOwner.getTypeConstraints()) { + Name name = typeConstraint.getSubjectTypeParameterName().getReferencedNameAsName(); + decompiledParameterToBounds.put(name, typeConstraint.getBoundTypeReference().getText()); + } + + for (int i = 0; i < decompiledParameters.size(); i++) { + JetTypeParameter decompiledParameter = decompiledParameters.get(i); + TypeParameterDescriptor descriptor = typeParameterDescriptors.get(i); + + if (!decompiledParameter.getNameAsName().equals(descriptor.getName())) { + return false; + } + + Set descriptorUpperBounds = Sets.newHashSet(ContainerUtil.map( + descriptor.getUpperBounds(), new Function() { + @Override + public String fun(JetType type) { + return DescriptorRenderer.TEXT.renderType(type); + } + })); + + Set decompiledUpperBounds = decompiledParameterToBounds.get(descriptor.getName()).isEmpty() + ? Sets.newHashSet(DescriptorRenderer.TEXT.renderType(KotlinBuiltIns.getInstance().getDefaultBound())) + : Sets.newHashSet(decompiledParameterToBounds.get(descriptor.getName())); + if (!descriptorUpperBounds.equals(decompiledUpperBounds)) { + return false; + } + } + return true; + } + @Nullable public static JetNamedDeclaration getSourceProperty(final @NotNull JetProperty decompiledProperty) { return getSourcePropertyOrFunction(decompiledProperty, new PropertyNavigationStrategy()); diff --git a/idea/testData/libraries/decompiled/namespace.kt b/idea/testData/libraries/decompiled/namespace.kt index 54440adba9c..34e6e9e1294 100644 --- a/idea/testData/libraries/decompiled/namespace.kt +++ b/idea/testData/libraries/decompiled/namespace.kt @@ -13,6 +13,10 @@ package testData.libraries [public val testData.libraries.Pair.exProp : jet.String] /* compiled code */ +[public fun funWithTypeParam(t : T) : Unit { /* compiled code */ }] + +[public fun funWithTypeParam(t : T) : Unit { /* compiled code */ }] + [public fun func() : Unit { /* compiled code */ }] [public fun func(cs : jet.CharSequence) : Unit { /* compiled code */ }] diff --git a/idea/testData/libraries/library/main.kt b/idea/testData/libraries/library/main.kt index 614f33d99c8..acf04bef0c3 100644 --- a/idea/testData/libraries/library/main.kt +++ b/idea/testData/libraries/library/main.kt @@ -109,4 +109,11 @@ public class Double public fun processDouble(d: Double) {} -public fun processDouble(d: jet.Double) {} \ No newline at end of file +public fun processDouble(d: jet.Double) {} + + +public fun funWithTypeParam(t: T) { +} + +public fun funWithTypeParam(t: T) { +} diff --git a/idea/testData/libraries/usercode/OverloadedFunWithTypeParam.kt b/idea/testData/libraries/usercode/OverloadedFunWithTypeParam.kt new file mode 100644 index 00000000000..5de2c17fbf5 --- /dev/null +++ b/idea/testData/libraries/usercode/OverloadedFunWithTypeParam.kt @@ -0,0 +1,12 @@ +import testData.libraries.* + +fun main(args: Array) { + funWithTypeParam(1) + funWithTypeParam("") +} + +// main.kt +//public fun <2>funWithTypeParam(t: T) { +//} +// +//public fun <1>funWithTypeParam(t: T) { diff --git a/idea/tests/org/jetbrains/jet/plugin/libraries/NavigateToLibrarySourceTest.java b/idea/tests/org/jetbrains/jet/plugin/libraries/NavigateToLibrarySourceTest.java index 4a967a0f980..890f7347472 100644 --- a/idea/tests/org/jetbrains/jet/plugin/libraries/NavigateToLibrarySourceTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/libraries/NavigateToLibrarySourceTest.java @@ -84,6 +84,10 @@ public class NavigateToLibrarySourceTest extends AbstractNavigateToLibraryTest { doTest(); } + public void testOverloadedFunWithTypeParam() { + doTest(); + } + private void doTest() { userFile = LocalFileSystem.getInstance().findFileByPath(TEST_DATA_PATH + "/usercode/" + getTestName(false) + ".kt"); assertNotNull(userFile);