Supported default objects in class usages.
This commit is contained in:
@@ -16,34 +16,23 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.references
|
||||
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.kotlin.psi.JetPropertyAccessor
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.idea.intentions.OperatorToFunctionIntention
|
||||
import org.jetbrains.kotlin.psi.JetQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.JetCallExpression
|
||||
import org.jetbrains.kotlin.psi.JetObjectDeclaration
|
||||
import org.jetbrains.kotlin.psi.JetClass
|
||||
import com.intellij.psi.PsiPolyVariantReference
|
||||
import org.jetbrains.kotlin.utils.emptyOrSingletonList
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.utils.emptyOrSingletonList
|
||||
import java.util.HashSet
|
||||
|
||||
// Navigation element of the resolved reference
|
||||
// For property accessor return enclosing property
|
||||
// For default object return enclosing class
|
||||
public val PsiReference.unwrappedTargets: Set<PsiElement>
|
||||
get() {
|
||||
fun PsiElement.adjust(): PsiElement? {
|
||||
val target = unwrapped?.getOriginalElement()
|
||||
return when {
|
||||
target is JetPropertyAccessor -> target.getNonStrictParentOfType<JetProperty>()
|
||||
target is JetObjectDeclaration && target.isDefault() -> target.getNonStrictParentOfType<JetClass>()
|
||||
else -> target
|
||||
}
|
||||
}
|
||||
@@ -62,6 +51,18 @@ public fun PsiReference.matchesTarget(candidateTarget: PsiElement): Boolean {
|
||||
if (this is JetReference) {
|
||||
return targets.any {
|
||||
it is PsiMethod && it.isConstructor() && it.getContainingClass() == unwrappedCandidate
|
||||
|| it is JetObjectDeclaration && it.isDefault() && it.getNonStrictParentOfType<JetClass>() == unwrappedCandidate
|
||||
}
|
||||
}
|
||||
if (this is PsiReferenceExpression && candidateTarget is JetObjectDeclaration && unwrappedTargets.size() == 1) {
|
||||
val referredClass = unwrappedTargets.first()
|
||||
if (referredClass is JetClass && candidateTarget in referredClass.getDefaultObjects()) {
|
||||
val parentReference = getParent().getReference()
|
||||
if (parentReference != null) {
|
||||
return parentReference.unwrappedTargets.any {
|
||||
(it is JetProperty || it is JetNamedFunction) && it.getParent()?.getParent() == candidateTarget
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
+11
-8
@@ -17,18 +17,12 @@
|
||||
package org.jetbrains.kotlin.idea.search.usagesSearch
|
||||
|
||||
import com.intellij.psi.PsiReference
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.*
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchFilter.*
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
import org.jetbrains.kotlin.psi.JetNamedFunction
|
||||
import java.util.Collections
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.psi.JetParameter
|
||||
import org.jetbrains.kotlin.psi.JetPsiUtil
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil.PropertyAccessorsPsiMethods
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -37,9 +31,10 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.idea.references.*
|
||||
import org.jetbrains.kotlin.psi.JetDeclaration
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
|
||||
val isTargetUsage = (PsiReference::matchesTarget).searchFilter
|
||||
|
||||
@@ -68,6 +63,14 @@ fun PsiNamedElement.getAccessorNames(readable: Boolean = true, writable: Boolean
|
||||
return Collections.emptyList()
|
||||
}
|
||||
|
||||
public fun PsiNamedElement.getClassNameForDefaultObject(): String? {
|
||||
return if (this is JetObjectDeclaration) {
|
||||
getNonStrictParentOfType<JetClass>()?.getName()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
public fun PsiNamedElement.getSpecialNamesToSearch(): List<String> {
|
||||
val name = getName()
|
||||
return when {
|
||||
@@ -102,7 +105,7 @@ public abstract class UsagesSearchHelper<T : PsiNamedElement> {
|
||||
|
||||
protected open fun makeWordList(target: UsagesSearchTarget<T>): List<String> {
|
||||
return with(target.element) {
|
||||
ContainerUtil.createMaybeSingletonList(getName()) + getAccessorNames() + getSpecialNamesToSearch()
|
||||
getName().singletonOrEmptyList() + getAccessorNames() + getClassNameForDefaultObject().singletonOrEmptyList() + getSpecialNamesToSearch()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.JetObjectDeclaration
|
||||
// OPTIONS: usages
|
||||
|
||||
import kotlin.platform.platformStatic
|
||||
|
||||
class Foo {
|
||||
default <caret>object {
|
||||
fun f() {
|
||||
}
|
||||
|
||||
platformStatic fun s() {
|
||||
}
|
||||
|
||||
val CONST = 42
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class JavaUsage {
|
||||
public static void main(String[] args) {
|
||||
System.out.println(Foo.CONST);
|
||||
Foo.s();
|
||||
Foo.Default.f();
|
||||
Foo foo = new Foo(); // not usage of default object
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Class static member access (3: 28) System.out.println(Foo.CONST);
|
||||
Class static member access (4: 9) Foo.s();
|
||||
Unclassified usage (5: 13) Foo.Default.f();
|
||||
@@ -0,0 +1,8 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.JetObjectDeclaration
|
||||
// OPTIONS: usages
|
||||
class Foo {
|
||||
default object <caret>Bar {
|
||||
fun f() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fun main(args: Array<String>) {
|
||||
val p: Foo = Foo() // simple class usage
|
||||
|
||||
// default object usages
|
||||
Foo.f()
|
||||
val x = Foo
|
||||
|
||||
Foo.Bar.f()
|
||||
val xx = Foo.Bar
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Nested class/object (5: 5) Foo.f()
|
||||
Nested class/object (8: 9) Foo.Bar.f()
|
||||
Unclassified usage (6: 13) val x = Foo
|
||||
Unclassified usage (9: 18) val xx = Foo.Bar
|
||||
@@ -0,0 +1,8 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.JetObjectDeclaration
|
||||
// OPTIONS: usages
|
||||
class Foo {
|
||||
default <caret>object {
|
||||
fun f() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fun main(args: Array<String>) {
|
||||
val p: Foo = Foo() // simple class usage
|
||||
|
||||
// default object usages
|
||||
Foo.f()
|
||||
val x = Foo
|
||||
|
||||
Foo.Default.f()
|
||||
val xx = Foo.Default
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Nested class/object (5: 5) Foo.f()
|
||||
Nested class/object (8: 9) Foo.Default.f()
|
||||
Unclassified usage (6: 13) val x = Foo
|
||||
Unclassified usage (9: 18) val xx = Foo.Default
|
||||
@@ -38,6 +38,7 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({
|
||||
Kotlin.Conventions.class,
|
||||
Kotlin.DefaultObject.class,
|
||||
Kotlin.FindClassUsages.class,
|
||||
Kotlin.FindFunctionUsages.class,
|
||||
Kotlin.FindObjectUsages.class,
|
||||
@@ -167,6 +168,33 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/kotlin/defaultObject")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DefaultObject extends AbstractJetFindUsagesTest {
|
||||
public void testAllFilesPresentInDefaultObject() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/findUsages/kotlin/defaultObject"), Pattern.compile("^(.+)\\.0\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("javaUsage.0.kt")
|
||||
public void testJavaUsage() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/defaultObject/javaUsage.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("named.0.kt")
|
||||
public void testNamed() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/defaultObject/named.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.0.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/defaultObject/simple.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/kotlin/findClassUsages")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user