correctly find usages of overridden Java method through synthetic accessors

#KT-12869 Fixed
This commit is contained in:
Dmitry Jemerov
2016-07-14 13:40:28 +02:00
parent e2b836db09
commit 14037f099c
5 changed files with 41 additions and 6 deletions
@@ -25,6 +25,7 @@ import com.intellij.psi.search.searches.MethodReferencesSearch
import com.intellij.util.Processor
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference
import org.jetbrains.kotlin.idea.references.readWriteAccess
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
@@ -67,17 +68,29 @@ class KotlinOverridingMethodReferenceSearcher : MethodUsagesSearcher() {
strictSignatureSearch: Boolean): MethodTextOccurrenceProcessor {
return object: MethodTextOccurrenceProcessor(aClass, strictSignatureSearch, *methods) {
override fun processInexactReference(ref: PsiReference, refElement: PsiElement?, method: PsiMethod, consumer: Processor<PsiReference>): Boolean {
if (refElement !is KtCallableDeclaration) return true
val isGetter = JvmAbi.isGetterName(method.name)
fun isWrongAccessorReference(): Boolean {
if (ref is KtSimpleNameReference) {
val readWriteAccess = ref.expression.readWriteAccess(true)
return readWriteAccess.isRead != isGetter && readWriteAccess.isWrite == isGetter
}
if (ref is SyntheticPropertyAccessorReference) {
return (ref is SyntheticPropertyAccessorReference.Getter) != isGetter
}
return false
}
if (refElement !is KtCallableDeclaration) {
if (isWrongAccessorReference()) return true
return super.processInexactReference(ref, refElement, method, consumer)
}
var lightMethods = refElement.toLightMethods()
.filterNot { it.hasModifierProperty(PsiModifier.FINAL) }
.ifEmpty { return true }
if (refElement is KtProperty || refElement is KtParameter) {
val isGetter = JvmAbi.isGetterName(method.name)
if (ref is KtSimpleNameReference) {
val readWriteAccess = ref.expression.readWriteAccess(true)
if (readWriteAccess.isRead != isGetter && readWriteAccess.isWrite == isGetter) return true
}
if (isWrongAccessorReference()) return true
lightMethods = lightMethods.filter { JvmAbi.isGetterName(it.name) == isGetter }
}
@@ -0,0 +1,10 @@
// PSI_ELEMENT: com.intellij.psi.PsiMethod
// OPTIONS: usages
public interface AI {
String <caret>getFoo();
public class A implements AI {
@Override
public String getFoo() {return "";}
}
}
@@ -0,0 +1,4 @@
fun AI.A.bar() {
getFoo() // Found
foo // Not found
}
@@ -0,0 +1,2 @@
Function call 2 getFoo() // Found
Value read 3 foo // Not found
@@ -1452,6 +1452,12 @@ public class FindUsagesTestGenerated extends AbstractFindUsagesTest {
doTest(fileName);
}
@TestMetadata("OverriddenMethodSyntheticAccessor.0.java")
public void testOverriddenMethodSyntheticAccessor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/OverriddenMethodSyntheticAccessor.0.java");
doTest(fileName);
}
@TestMetadata("SyntheticProperties.0.java")
public void testSyntheticProperties() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/SyntheticProperties.0.java");