Find Usages: Support primary constructors
#KT-7881 Fixed
This commit is contained in:
@@ -79,7 +79,7 @@ public fun PsiReference.matchesTarget(candidateTarget: PsiElement): Boolean {
|
||||
}
|
||||
}
|
||||
// TODO: Workaround for Kotlin constructor search in Java code. To be removed after refactoring of the search API
|
||||
else if (this is PsiJavaCodeReferenceElement && unwrappedCandidate is JetSecondaryConstructor) {
|
||||
else if (this is PsiJavaCodeReferenceElement && unwrappedCandidate is JetConstructor<*>) {
|
||||
var parent = getElement().getParent()
|
||||
if (parent is PsiAnonymousClass) {
|
||||
parent = parent.getParent()
|
||||
@@ -104,7 +104,7 @@ private fun PsiElement.isConstructorOf(unwrappedCandidate: PsiElement) =
|
||||
// call to Java constructor
|
||||
(this is PsiMethod && isConstructor() && getContainingClass() == unwrappedCandidate) ||
|
||||
// call to Kotlin constructor
|
||||
(this is JetSecondaryConstructor && getStrictParentOfType<JetClass>() == unwrappedCandidate)
|
||||
(this is JetConstructor<*> && getClassOrObject() == unwrappedCandidate)
|
||||
|
||||
fun AbstractJetReference<out JetExpression>.renameImplicitConventionalCall(newName: String?): JetExpression {
|
||||
if (newName == null) return expression
|
||||
|
||||
@@ -86,7 +86,8 @@ fun PsiReference.isConstructorUsage(jetClassOrObject: JetClassOrObject): Boolean
|
||||
val descriptor = getConstructorCallDescriptor()
|
||||
if (descriptor !is ConstructorDescriptor) return false
|
||||
|
||||
return DescriptorToSourceUtils.descriptorToDeclaration(descriptor.getContainingDeclaration()) == jetClassOrObject
|
||||
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor.getContainingDeclaration())
|
||||
return declaration == jetClassOrObject || (declaration is JetConstructor<*> && declaration.getClassOrObject() == jetClassOrObject)
|
||||
}
|
||||
|
||||
checkJavaUsage() || checkKotlinUsage()
|
||||
@@ -118,7 +119,7 @@ public fun PsiElement.processDelegationCallConstructorUsages(scope: SearchScope,
|
||||
private fun PsiElement.processDelegationCallKotlinConstructorUsages(scope: SearchScope, process: (JetConstructorDelegationCall) -> Unit) {
|
||||
val element = unwrapped
|
||||
val klass = when (element) {
|
||||
is JetSecondaryConstructor -> element.getClassOrObject()
|
||||
is JetConstructor<*> -> element.getClassOrObject()
|
||||
is JetClass -> element
|
||||
else -> return
|
||||
}
|
||||
|
||||
@@ -46,14 +46,14 @@ public class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandle
|
||||
element is JetProperty ||
|
||||
element is JetParameter ||
|
||||
element is JetTypeParameter ||
|
||||
element is JetSecondaryConstructor
|
||||
element is JetConstructor<*>
|
||||
|
||||
public override fun createFindUsagesHandler(element: PsiElement, forHighlightUsages: Boolean): FindUsagesHandler? {
|
||||
val handler = when (element) {
|
||||
is JetClassOrObject ->
|
||||
KotlinFindClassUsagesHandler(element, this)
|
||||
|
||||
is JetNamedFunction, is JetProperty, is JetParameter, is JetSecondaryConstructor -> {
|
||||
is JetNamedFunction, is JetProperty, is JetParameter, is JetConstructor<*> -> {
|
||||
val declaration = element as JetNamedDeclaration
|
||||
|
||||
if (forHighlightUsages) return KotlinFindMemberUsagesHandler.getInstance(declaration, this)
|
||||
|
||||
+2
-2
@@ -123,7 +123,7 @@ public abstract class KotlinFindMemberUsagesHandler<T extends JetNamedDeclaratio
|
||||
protected abstract UsagesSearchHelper<T> getSearchHelper(KotlinCallableFindUsagesOptions options);
|
||||
|
||||
private static Iterable<PsiMethod> getLightMethods(JetNamedDeclaration element) {
|
||||
if (element instanceof JetNamedFunction || element instanceof JetSecondaryConstructor) {
|
||||
if (element instanceof JetFunction) {
|
||||
PsiMethod method = LightClassUtil.getLightClassMethod((JetFunction) element);
|
||||
return method != null ? Collections.singletonList(method) : Collections.<PsiMethod>emptyList();
|
||||
}
|
||||
@@ -163,7 +163,7 @@ public abstract class KotlinFindMemberUsagesHandler<T extends JetNamedDeclaratio
|
||||
PsiMethod psiMethod =
|
||||
element instanceof PsiMethod
|
||||
? (PsiMethod) element
|
||||
: element instanceof JetSecondaryConstructor
|
||||
: element instanceof JetConstructor
|
||||
? LightClassUtil.getLightClassMethod((JetFunction) element)
|
||||
: null;
|
||||
if (psiMethod != null) {
|
||||
|
||||
+11
-1
@@ -17,12 +17,22 @@
|
||||
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
||||
|
||||
import com.intellij.codeInsight.TargetElementEvaluator
|
||||
import com.intellij.codeInsight.TargetElementEvaluatorEx
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAbstract
|
||||
import com.intellij.psi.PsiReference
|
||||
import org.jetbrains.kotlin.psi.JetClass
|
||||
import org.jetbrains.kotlin.psi.JetPrimaryConstructor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
|
||||
public class JetTargetElementEvaluator : TargetElementEvaluator {
|
||||
public class JetTargetElementEvaluator : TargetElementEvaluatorEx {
|
||||
override fun includeSelfInGotoImplementation(element: PsiElement): Boolean = !(element is JetClass && element.isAbstract())
|
||||
|
||||
override fun getElementByReference(ref: PsiReference, flags: Int): PsiElement? = null
|
||||
|
||||
override fun isIdentifierPart(file: PsiFile, text: CharSequence?, offset: Int): Boolean {
|
||||
// '(' is considered identifier part if it belongs to primary constructor without 'constructor' keyword
|
||||
return file.findElementAt(offset)?.getNonStrictParentOfType<JetPrimaryConstructor>()?.getTextOffset() == offset
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// PSI_ELEMENT: com.intellij.psi.PsiMethod
|
||||
// OPTIONS: usages
|
||||
// FIND_BY_REF
|
||||
// WITH_FILE_NAME
|
||||
class J extends A {
|
||||
constructor(n: Int) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
static void test() {
|
||||
new A();
|
||||
new <caret>A(1);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
open class A (n: Int) {
|
||||
constructor(): this(1)
|
||||
}
|
||||
|
||||
class B: A {
|
||||
constructor(n: Int): super(n)
|
||||
}
|
||||
|
||||
class C(): A(1)
|
||||
|
||||
fun test() {
|
||||
A()
|
||||
A(1)
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
[primaryConstructorByJavaRef.0.java] New instance creation (12: 13) new A(1);
|
||||
[primaryConstructorByJavaRef.0.java] Unclassified usage (7: 9) super(n);
|
||||
[primaryConstructorByJavaRef.1.kt] New instance creation (13: 5) A(1)
|
||||
[primaryConstructorByJavaRef.1.kt] Supertype (9: 12) class C(): A(1)
|
||||
[primaryConstructorByJavaRef.1.kt] Unclassified usage (2: 20) constructor(): this(1)
|
||||
[primaryConstructorByJavaRef.1.kt] Unclassified usage (6: 26) constructor(n: Int): super(n)
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
// PSI_ELEMENT: com.intellij.psi.PsiMethod
|
||||
// OPTIONS: usages
|
||||
// FIND_BY_REF
|
||||
// WITH_FILE_NAME
|
||||
class J extends A {
|
||||
constructor(n: Int) {
|
||||
<caret>super(n);
|
||||
}
|
||||
|
||||
static void test() {
|
||||
new A();
|
||||
new A(1);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
open class A (n: Int) {
|
||||
constructor(): this(1)
|
||||
}
|
||||
|
||||
class B: A {
|
||||
constructor(n: Int): super(n)
|
||||
}
|
||||
|
||||
class C(): A(1)
|
||||
|
||||
fun test() {
|
||||
A()
|
||||
A(1)
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
[primaryConstructorByJavaSuperRef.0.java] New instance creation (12: 13) new A(1);
|
||||
[primaryConstructorByJavaSuperRef.0.java] Unclassified usage (7: 9) super(n);
|
||||
[primaryConstructorByJavaSuperRef.1.kt] New instance creation (13: 5) A(1)
|
||||
[primaryConstructorByJavaSuperRef.1.kt] Supertype (9: 12) class C(): A(1)
|
||||
[primaryConstructorByJavaSuperRef.1.kt] Unclassified usage (2: 20) constructor(): this(1)
|
||||
[primaryConstructorByJavaSuperRef.1.kt] Unclassified usage (6: 26) constructor(n: Int): super(n)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.JetPrimaryConstructor
|
||||
// OPTIONS: usages
|
||||
// FIND_BY_REF
|
||||
open class A (n: Int) {
|
||||
constructor(): this(1)
|
||||
}
|
||||
|
||||
class B: A {
|
||||
constructor(n: Int): super(n)
|
||||
}
|
||||
|
||||
class C(): A(1)
|
||||
|
||||
fun test() {
|
||||
A()
|
||||
<caret>A(1)
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
New instance creation (16: 5) A(1)
|
||||
Supertype (12: 12) class C(): A(1)
|
||||
Unclassified usage (5: 20) constructor(): this(1)
|
||||
Unclassified usage (9: 26) constructor(n: Int): super(n)
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.JetPrimaryConstructor
|
||||
// OPTIONS: usages
|
||||
open class A <caret>(n: Int) {
|
||||
constructor(): this(1)
|
||||
}
|
||||
|
||||
class B: A {
|
||||
constructor(n: Int): super(n)
|
||||
}
|
||||
|
||||
class C(): A(1)
|
||||
|
||||
fun test() {
|
||||
A()
|
||||
A(1)
|
||||
}
|
||||
idea/testData/findUsages/kotlin/findPrimaryConstructorUsages/primaryConstructorNoKeyword.results.txt
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
New instance creation (15: 5) A(1)
|
||||
Supertype (11: 12) class C(): A(1)
|
||||
Unclassified usage (4: 20) constructor(): this(1)
|
||||
Unclassified usage (8: 26) constructor(n: Int): super(n)
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.JetPrimaryConstructor
|
||||
// OPTIONS: usages
|
||||
open class A <caret>constructor(n: Int) {
|
||||
constructor(): this(1)
|
||||
}
|
||||
|
||||
class B: A {
|
||||
constructor(n: Int): super(n)
|
||||
}
|
||||
|
||||
class C(): A(1)
|
||||
|
||||
fun test() {
|
||||
A()
|
||||
A(1)
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
New instance creation (15: 5) A(1)
|
||||
Supertype (11: 12) class C(): A(1)
|
||||
Unclassified usage (4: 20) constructor(): this(1)
|
||||
Unclassified usage (8: 26) constructor(n: Int): super(n)
|
||||
@@ -736,6 +736,33 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/kotlin/findPrimaryConstructorUsages")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class FindPrimaryConstructorUsages extends AbstractJetFindUsagesTest {
|
||||
public void testAllFilesPresentInFindPrimaryConstructorUsages() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/findUsages/kotlin/findPrimaryConstructorUsages"), Pattern.compile("^(.+)\\.0\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorByRef.0.kt")
|
||||
public void testPrimaryConstructorByRef() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/findPrimaryConstructorUsages/primaryConstructorByRef.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorNoKeyword.0.kt")
|
||||
public void testPrimaryConstructorNoKeyword() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/findPrimaryConstructorUsages/primaryConstructorNoKeyword.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorWithKeyword.0.kt")
|
||||
public void testPrimaryConstructorWithKeyword() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/findPrimaryConstructorUsages/primaryConstructorWithKeyword.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/kotlin/findPropertyUsages")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -1056,6 +1083,18 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorByJavaRef.0.java")
|
||||
public void testPrimaryConstructorByJavaRef() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/java/findConstructorUsages/primaryConstructorByJavaRef.0.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorByJavaSuperRef.0.java")
|
||||
public void testPrimaryConstructorByJavaSuperRef() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/java/findConstructorUsages/primaryConstructorByJavaSuperRef.0.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("secondaryConstructorByJavaNewExpression.0.java")
|
||||
public void testSecondaryConstructorByJavaNewExpression() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/java/findConstructorUsages/secondaryConstructorByJavaNewExpression.0.java");
|
||||
|
||||
Reference in New Issue
Block a user