correctly find usages of overridden Java method through synthetic accessors
#KT-12869 Fixed
This commit is contained in:
+19
-6
@@ -25,6 +25,7 @@ import com.intellij.psi.search.searches.MethodReferencesSearch
|
|||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
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.references.readWriteAccess
|
||||||
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
||||||
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
|
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
|
||||||
@@ -67,17 +68,29 @@ class KotlinOverridingMethodReferenceSearcher : MethodUsagesSearcher() {
|
|||||||
strictSignatureSearch: Boolean): MethodTextOccurrenceProcessor {
|
strictSignatureSearch: Boolean): MethodTextOccurrenceProcessor {
|
||||||
return object: MethodTextOccurrenceProcessor(aClass, strictSignatureSearch, *methods) {
|
return object: MethodTextOccurrenceProcessor(aClass, strictSignatureSearch, *methods) {
|
||||||
override fun processInexactReference(ref: PsiReference, refElement: PsiElement?, method: PsiMethod, consumer: Processor<PsiReference>): Boolean {
|
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()
|
var lightMethods = refElement.toLightMethods()
|
||||||
.filterNot { it.hasModifierProperty(PsiModifier.FINAL) }
|
.filterNot { it.hasModifierProperty(PsiModifier.FINAL) }
|
||||||
.ifEmpty { return true }
|
.ifEmpty { return true }
|
||||||
if (refElement is KtProperty || refElement is KtParameter) {
|
if (refElement is KtProperty || refElement is KtParameter) {
|
||||||
val isGetter = JvmAbi.isGetterName(method.name)
|
if (isWrongAccessorReference()) return true
|
||||||
if (ref is KtSimpleNameReference) {
|
|
||||||
val readWriteAccess = ref.expression.readWriteAccess(true)
|
|
||||||
if (readWriteAccess.isRead != isGetter && readWriteAccess.isWrite == isGetter) return true
|
|
||||||
}
|
|
||||||
lightMethods = lightMethods.filter { JvmAbi.isGetterName(it.name) == isGetter }
|
lightMethods = lightMethods.filter { JvmAbi.isGetterName(it.name) == isGetter }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+10
@@ -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 "";}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fun AI.A.bar() {
|
||||||
|
getFoo() // Found
|
||||||
|
foo // Not found
|
||||||
|
}
|
||||||
Vendored
+2
@@ -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);
|
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")
|
@TestMetadata("SyntheticProperties.0.java")
|
||||||
public void testSyntheticProperties() throws Exception {
|
public void testSyntheticProperties() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/SyntheticProperties.0.java");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/SyntheticProperties.0.java");
|
||||||
|
|||||||
Reference in New Issue
Block a user