Finding implicit usages of companion object in containing class.
This commit is contained in:
+2
-1
@@ -84,7 +84,8 @@ public class KotlinReferencesSearcher extends QueryExecutorBase<PsiReference, Re
|
||||
UsagesSearchRequestItem requestItem = new UsagesSearchRequestItem(
|
||||
searchTarget,
|
||||
UsagesSearchPackage.getSpecialNamesToSearch(unwrappedElement),
|
||||
UsagesSearchPackage.getIsTargetUsage()
|
||||
UsagesSearchPackage.getIsTargetUsage(),
|
||||
null
|
||||
);
|
||||
searchHelper.processFilesWithText(requestItem, consumer);
|
||||
}
|
||||
|
||||
+33
-1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchFilter.*
|
||||
import java.util.Collections
|
||||
import java.util.ArrayList
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil.PropertyAccessorsPsiMethods
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
@@ -33,7 +34,10 @@ import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.idea.references.*
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassReceiver
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
|
||||
val isTargetUsage = (PsiReference::matchesTarget).searchFilter
|
||||
@@ -113,8 +117,10 @@ public abstract class UsagesSearchHelper<T : PsiNamedElement> {
|
||||
protected open fun makeItemList(target: UsagesSearchTarget<T>): List<UsagesSearchRequestItem> =
|
||||
Collections.singletonList(newItem(target))
|
||||
|
||||
protected open fun makeAdditionalSearchDelegate(target: T): ((Processor<PsiReference>) -> Boolean)? = null
|
||||
|
||||
fun newItem(target: UsagesSearchTarget<T>): UsagesSearchRequestItem {
|
||||
return UsagesSearchRequestItem(target, makeWordList(target), makeFilter(target))
|
||||
return UsagesSearchRequestItem(target, makeWordList(target), makeFilter(target), makeAdditionalSearchDelegate(target.element))
|
||||
}
|
||||
|
||||
fun newRequest(target: UsagesSearchTarget<T>): UsagesSearchRequest {
|
||||
@@ -151,6 +157,32 @@ class ClassUsagesSearchHelper(
|
||||
!constructorUsages && !nonConstructorUsages -> False
|
||||
else -> True
|
||||
}
|
||||
|
||||
override fun makeAdditionalSearchDelegate(target: JetClassOrObject): ((Processor<PsiReference>) -> Boolean)? {
|
||||
if (target is JetObjectDeclaration && target.isCompanion()) {
|
||||
val companionObjectDescriptor = target.descriptor
|
||||
val klass = target.getStrictParentOfType<JetClass>() ?: return null
|
||||
return { processor ->
|
||||
klass.acceptChildren(object : JetVisitorVoid() {
|
||||
override fun visitJetElement(element: JetElement) {
|
||||
if (element == target) return // skip companion object itself
|
||||
element.acceptChildren(this)
|
||||
|
||||
val bindingContext = element.analyze()
|
||||
val call = bindingContext[BindingContext.CALL, element] ?: return
|
||||
val resolvedCall = bindingContext[BindingContext.RESOLVED_CALL, call] ?: return
|
||||
if ((resolvedCall.getDispatchReceiver() as? ClassReceiver)?.getDeclarationDescriptor() == companionObjectDescriptor
|
||||
|| (resolvedCall.getExtensionReceiver() as? ClassReceiver)?.getDeclarationDescriptor() == companionObjectDescriptor) {
|
||||
element.getReference()?.let { processor.process(it) }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
class ClassDeclarationsUsagesSearchHelper(
|
||||
|
||||
+4
-2
@@ -103,7 +103,8 @@ public trait UsagesSearchFilter {
|
||||
public data class UsagesSearchRequestItem(
|
||||
val target: UsagesSearchTarget<PsiElement>,
|
||||
val words: List<String>,
|
||||
val filter: UsagesSearchFilter
|
||||
val filter: UsagesSearchFilter,
|
||||
val additionalSearchDelegate: ((Processor<PsiReference>) -> Boolean)?
|
||||
)
|
||||
|
||||
public data class UsagesSearchRequest(val project: Project, val items: List<UsagesSearchRequestItem>) {
|
||||
@@ -164,7 +165,8 @@ public object UsagesSearch: QueryFactory<PsiReference, UsagesSearchRequest>() {
|
||||
val executorImpl = object : QueryExecutorBase<PsiReference, UsagesSearchRequest>() {
|
||||
override fun processQuery(request: UsagesSearchRequest, consumer: Processor<PsiReference>) {
|
||||
val searchHelper = KotlinPsiSearchHelper(request.project)
|
||||
request.items.filter { it.filter != False }.all { searchHelper.processFilesWithText(it, consumer) }
|
||||
request.items.filter { it.filter != False }.all {
|
||||
searchHelper.processFilesWithText(it, consumer) && (it.additionalSearchDelegate?.invoke(consumer) ?: true) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.JetObjectDeclaration
|
||||
// OPTIONS: usages
|
||||
class A {
|
||||
init {
|
||||
foo()
|
||||
v
|
||||
|
||||
1[2] // using companion object function by convention
|
||||
|
||||
ext() // companion object is extension receiver
|
||||
}
|
||||
|
||||
companion <caret>object: Foo {
|
||||
fun foo() {
|
||||
}
|
||||
|
||||
val v = 42
|
||||
|
||||
fun Int.get(a: Int) = this + a
|
||||
}
|
||||
}
|
||||
|
||||
trait Foo
|
||||
|
||||
fun Foo.ext() {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Function call (10: 9) ext() // companion object is extension receiver
|
||||
Function call (5: 9) foo()
|
||||
Implicit 'get' (8: 9) 1[2] // using companion object function by convention
|
||||
Value read (6: 9) v
|
||||
@@ -176,6 +176,12 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/findUsages/kotlin/defaultObject"), Pattern.compile("^(.+)\\.0\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("inContainingClass.0.kt")
|
||||
public void testInContainingClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/defaultObject/inContainingClass.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("javaUsage.0.kt")
|
||||
public void testJavaUsage() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/defaultObject/javaUsage.0.kt");
|
||||
|
||||
Reference in New Issue
Block a user