Overridden methods with generic type shows no implementations found (KT-8723)
#KT-8723 Fixed
This commit is contained in:
@@ -509,6 +509,7 @@
|
||||
|
||||
<referencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearcher"/>
|
||||
<directClassInheritorsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDirectInheritorsSearcher"/>
|
||||
<overridingMethodsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinOverridingMethodsWithGenericsSearcher"/>
|
||||
<definitionsScopedSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher"/>
|
||||
<annotatedElementsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinAnnotatedElementsSearcher"/>
|
||||
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinPropertyAccessorsReferenceSearcher"/>
|
||||
|
||||
+84
@@ -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<PsiMethod, OverridingMethodsSearch.SearchParameters> {
|
||||
override fun execute(p: OverridingMethodsSearch.SearchParameters, consumer: Processor<PsiMethod>): 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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// FILE: b.kt
|
||||
open class Foo<T> {
|
||||
open fun bar(t: T) {}
|
||||
}
|
||||
|
||||
class Bar() : Foo<Int>() {
|
||||
override fun <caret>bar(ts: Int) {
|
||||
}
|
||||
}
|
||||
// FILE: a.kt
|
||||
open class Foo<T> {
|
||||
open fun <caret>bar(t: T) {}
|
||||
}
|
||||
|
||||
class Bar() : Foo<Int>() {
|
||||
override fun bar(ts: Int) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
open class Foo<T, U, Z> {
|
||||
open fun <caret>bar(t: T, u: U): Z {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
class AllTypes() : Foo<Int, Double, Int>() {
|
||||
override fun bar(i: Int, d: Double): Int = 42
|
||||
}
|
||||
|
||||
class SomeParameters() : Foo<Double, Any, Int>() {
|
||||
override fun bar(d: Double, a: Any): Int = 42
|
||||
}
|
||||
|
||||
class ReturnType() : Foo<Any, String, Byte>() {
|
||||
override fun bar(a: Any, s: String): Byte = 12.toByte()
|
||||
}
|
||||
|
||||
class ParameterStillGeneric<Z>() : Foo<Int, Z, String>() {
|
||||
override fun bar(i: Int, z: Z): String = ""
|
||||
}
|
||||
|
||||
class ReturnStillGeneric<A>() : Foo<Int, Int, A>() {
|
||||
override fun bar(i: Int, i2: Int): A = null
|
||||
}
|
||||
|
||||
open class ThroughProxyAllGenerics<A, B, C>: Foo<A, B, C>()
|
||||
class ThroughProxyAllGenericsImpl: ThroughProxyAllGenerics<Double, Int, Boolean>() {
|
||||
override fun bar(t: Double, i: Int): Boolean = true
|
||||
}
|
||||
|
||||
open class ThroughProxySomeGenerics<A, C>: Foo<A, Int, C>()
|
||||
class ThroughProxySomeGenericsImpl: ThroughProxySomeGenerics<Double, Boolean>() {
|
||||
override fun bar(t: Double, i: Int): Boolean = true
|
||||
}
|
||||
|
||||
class NoPrimitives: Foo<String, Any, String>() {
|
||||
override fun bar(t: String, u: Any): String = ""
|
||||
}
|
||||
|
||||
class NoOverride: Foo<String, Any, String>() {
|
||||
// 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)"
|
||||
@@ -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");
|
||||
|
||||
+6
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user