diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 227bda213c4..2de48a435ab 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -509,6 +509,7 @@
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodsWithGenericsSearcher.kt b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodsWithGenericsSearcher.kt
new file mode 100644
index 00000000000..c5c87c01c92
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodsWithGenericsSearcher.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010-2015 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.kotlin.idea.search.ideaExtensions
+
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.search.searches.ClassInheritorsSearch
+import com.intellij.psi.search.searches.OverridingMethodsSearch
+import com.intellij.util.Processor
+import com.intellij.util.QueryExecutor
+import org.jetbrains.kotlin.asJava.KotlinLightClass
+import org.jetbrains.kotlin.asJava.KotlinLightMethod
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
+import org.jetbrains.kotlin.idea.util.application.runReadAction
+import org.jetbrains.kotlin.psi.JetCallableDeclaration
+import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
+import org.jetbrains.kotlin.resolve.OverrideResolver
+
+public class KotlinOverridingMethodsWithGenericsSearcher : QueryExecutor {
+ override fun execute(p: OverridingMethodsSearch.SearchParameters, consumer: Processor): Boolean {
+ val method = p.method
+ if (method !is KotlinLightMethod) return true
+
+ val declaration = method.getOrigin() as? JetCallableDeclaration
+ if (declaration == null) return true
+
+ val callDescriptor = declaration.resolveToDescriptor()
+ if (callDescriptor !is CallableDescriptor) return true
+
+ // Java overriding method search can't find overloads with primitives types, so
+ // we do additional search for such methods.
+ if (!callDescriptor.valueParameters.any { it.type.constructor.declarationDescriptor is TypeParameterDescriptor }) return true
+
+ val parentClass = runReadAction { method.containingClass }!!
+
+ return ClassInheritorsSearch.search(parentClass, p.scope, true).forEach(Processor { inheritor: PsiClass ->
+ val found = runReadAction {
+ findOverridingMethod(inheritor, declaration)
+ }
+
+ found == null || (consumer.process(found) && p.isCheckDeep)
+ })
+ }
+
+ private fun findOverridingMethod(inheritor: PsiClass, callableDeclaration: JetCallableDeclaration): PsiMethod? {
+ // Leave Java classes search to JavaOverridingMethodsSearcher
+ if (inheritor !is KotlinLightClass) return null
+
+ val name = callableDeclaration.name
+ val methodsByName = inheritor.findMethodsByName(name, false)
+
+ for (lightMethodCandidate in methodsByName) {
+ val candidateDescriptor = (lightMethodCandidate as? KotlinLightMethod)?.getOrigin()?.resolveToDescriptor() ?: continue
+ if (candidateDescriptor !is CallableMemberDescriptor) continue
+
+ val overriddenDescriptors = OverrideResolver.getDirectlyOverriddenDeclarations(candidateDescriptor)
+ for (candidateSuper in overriddenDescriptors) {
+ val candidateDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(candidateSuper)
+ if (candidateDeclaration == callableDeclaration) {
+ return lightMethodCandidate
+ }
+ }
+ }
+
+ return null
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/navigation/gotoSuper/SuperWithNativeToGenericMapping.test b/idea/testData/navigation/gotoSuper/SuperWithNativeToGenericMapping.test
new file mode 100644
index 00000000000..571d875cd7a
--- /dev/null
+++ b/idea/testData/navigation/gotoSuper/SuperWithNativeToGenericMapping.test
@@ -0,0 +1,18 @@
+// FILE: b.kt
+open class Foo {
+ open fun bar(t: T) {}
+}
+
+class Bar() : Foo() {
+ override fun bar(ts: Int) {
+ }
+}
+// FILE: a.kt
+open class Foo {
+ open fun bar(t: T) {}
+}
+
+class Bar() : Foo() {
+ override fun bar(ts: Int) {
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/navigation/implementations/ImplementGenericWithPrimitives.kt b/idea/testData/navigation/implementations/ImplementGenericWithPrimitives.kt
new file mode 100644
index 00000000000..75439f2c22b
--- /dev/null
+++ b/idea/testData/navigation/implementations/ImplementGenericWithPrimitives.kt
@@ -0,0 +1,53 @@
+open class Foo {
+ open fun bar(t: T, u: U): Z {
+ return null
+ }
+}
+
+class AllTypes() : Foo() {
+ override fun bar(i: Int, d: Double): Int = 42
+}
+
+class SomeParameters() : Foo() {
+ override fun bar(d: Double, a: Any): Int = 42
+}
+
+class ReturnType() : Foo() {
+ override fun bar(a: Any, s: String): Byte = 12.toByte()
+}
+
+class ParameterStillGeneric() : Foo() {
+ override fun bar(i: Int, z: Z): String = ""
+}
+
+class ReturnStillGeneric() : Foo() {
+ override fun bar(i: Int, i2: Int): A = null
+}
+
+open class ThroughProxyAllGenerics: Foo()
+class ThroughProxyAllGenericsImpl: ThroughProxyAllGenerics() {
+ override fun bar(t: Double, i: Int): Boolean = true
+}
+
+open class ThroughProxySomeGenerics: Foo()
+class ThroughProxySomeGenericsImpl: ThroughProxySomeGenerics() {
+ override fun bar(t: Double, i: Int): Boolean = true
+}
+
+class NoPrimitives: Foo() {
+ override fun bar(t: String, u: Any): String = ""
+}
+
+class NoOverride: Foo() {
+ // Error: Not override
+ override fun bar(t: Any, u: String): String = ""
+}
+
+// REF: "(in AllTypes).bar(Int,Double)"
+// REF: "(in NoPrimitives).bar(String,Any)"
+// REF: "(in ParameterStillGeneric).bar(Int,Z)"
+// REF: "(in ReturnStillGeneric).bar(Int,Int)"
+// REF: "(in ReturnType).bar(Any,String)"
+// REF: "(in SomeParameters).bar(Double,Any)"
+// REF: "(in ThroughProxyAllGenericsImpl).bar(Double,Int)"
+// REF: "(in ThroughProxySomeGenericsImpl).bar(Double,Int)"
diff --git a/idea/tests/org/jetbrains/kotlin/idea/navigation/GotoSuperTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/navigation/GotoSuperTestGenerated.java
index 8a7ec6497a9..f0f5a8b1cbf 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/navigation/GotoSuperTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/navigation/GotoSuperTestGenerated.java
@@ -89,6 +89,12 @@ public class GotoSuperTestGenerated extends AbstractGotoSuperTest {
doTest(fileName);
}
+ @TestMetadata("SuperWithNativeToGenericMapping.test")
+ public void testSuperWithNativeToGenericMapping() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("idea/testData/navigation/gotoSuper/SuperWithNativeToGenericMapping.test");
+ doTest(fileName);
+ }
+
@TestMetadata("TraitSimple.test")
public void testTraitSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/navigation/gotoSuper/TraitSimple.test");
diff --git a/idea/tests/org/jetbrains/kotlin/idea/navigation/KotlinGotoImplementationTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/navigation/KotlinGotoImplementationTestGenerated.java
index dba1b8d349b..c299685f406 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/navigation/KotlinGotoImplementationTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/navigation/KotlinGotoImplementationTestGenerated.java
@@ -71,6 +71,12 @@ public class KotlinGotoImplementationTestGenerated extends AbstractKotlinGotoImp
doTest(fileName);
}
+ @TestMetadata("ImplementGenericWithPrimitives.kt")
+ public void testImplementGenericWithPrimitives() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("idea/testData/navigation/implementations/ImplementGenericWithPrimitives.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("OverridesInEnumEntries.kt")
public void testOverridesInEnumEntries() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/navigation/implementations/OverridesInEnumEntries.kt");