Optimize isReferenceTo() when searching for PsiMethod usages
Avoid resolving references when we know from context that a reference at given location can't resolve to a PsiMethod.
This commit is contained in:
+13
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.references
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -47,6 +48,18 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
|
||||
return result
|
||||
}
|
||||
|
||||
override fun isReferenceTo(element: PsiElement?): Boolean {
|
||||
if (element !is PsiMethod || !isAccessorName(element.name)) return false
|
||||
return super.isReferenceTo(element)
|
||||
}
|
||||
|
||||
private fun isAccessorName(name: String): Boolean {
|
||||
if (getter) {
|
||||
return name.startsWith("get") || name.startsWith("is")
|
||||
}
|
||||
return name.startsWith("set")
|
||||
}
|
||||
|
||||
override fun getRangeInElement() = TextRange(0, expression.textLength)
|
||||
|
||||
override fun canRename() = true
|
||||
|
||||
@@ -80,6 +80,9 @@ fun PsiReference.matchesTarget(candidateTarget: PsiElement): Boolean {
|
||||
is KtDestructuringDeclarationReference -> {
|
||||
if (candidateTarget !is KtNamedFunction && candidateTarget !is KtParameter && candidateTarget !is PsiMethod) return false
|
||||
}
|
||||
is KtSimpleNameReference -> {
|
||||
if (unwrappedCandidate is PsiMethod && !canBePsiMethodReference()) return false
|
||||
}
|
||||
}
|
||||
|
||||
val targets = unwrappedTargets
|
||||
@@ -124,6 +127,24 @@ fun PsiReference.matchesTarget(candidateTarget: PsiElement): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
fun KtSimpleNameReference.canBePsiMethodReference(): Boolean {
|
||||
// NOTE: Accessor references are handled separately, see SyntheticPropertyAccessorReference
|
||||
if (element == (element.parent as? KtCallExpression)?.calleeExpression) return true
|
||||
|
||||
val callableReference = element.getParentOfTypeAndBranch<KtCallableReferenceExpression> { callableReference }
|
||||
if (callableReference != null) return true
|
||||
|
||||
val binaryOperator = element.getParentOfTypeAndBranch<KtBinaryExpression> { operationReference }
|
||||
if (binaryOperator != null) return true
|
||||
|
||||
val unaryOperator = element.getParentOfTypeAndBranch<KtUnaryExpression> { operationReference }
|
||||
if (unaryOperator != null) return true
|
||||
|
||||
if (element.getNonStrictParentOfType<KtImportDirective>() != null) return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun PsiElement.isConstructorOf(unwrappedCandidate: PsiElement) =
|
||||
// call to Java constructor
|
||||
(this is PsiMethod && isConstructor && containingClass == unwrappedCandidate) ||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// PSI_ELEMENT: com.intellij.psi.PsiMethod
|
||||
// OPTIONS: usages
|
||||
public class UnaryNot {
|
||||
public UnaryNot <caret>not() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fun unaryClient() {
|
||||
val u1 = UnaryNot()
|
||||
val u2 = !u1
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
Checked type of u1
|
||||
Checked type of u2
|
||||
Resolved !u1
|
||||
Searched references to UnaryNot
|
||||
Searched references to UnaryNot.not() in non-Java files
|
||||
Searched references to u1 in non-Java files
|
||||
Searched references to u2 in non-Java files
|
||||
@@ -0,0 +1 @@
|
||||
Function call 3 val u2 = !u1
|
||||
@@ -1656,6 +1656,12 @@ public class FindUsagesTestGenerated extends AbstractFindUsagesTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/SyntheticProperties.0.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UnaryNot.0.java")
|
||||
public void testUnaryNot() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/UnaryNot.0.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/java/findJavaPropertyUsages")
|
||||
|
||||
Reference in New Issue
Block a user