ReferencesSearch finds references of data class component functions in Java code
#KT-8808 Fixed
This commit is contained in:
@@ -131,4 +131,8 @@ public class KotlinLightParameter extends LightParameter implements KotlinLightE
|
|||||||
JetParameter origin = getOrigin();
|
JetParameter origin = getOrigin();
|
||||||
return origin != null ? origin.getUseScope() : GlobalSearchScope.EMPTY_SCOPE;
|
return origin != null ? origin.getUseScope() : GlobalSearchScope.EMPTY_SCOPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KotlinLightMethod getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -25,12 +25,14 @@ import com.intellij.psi.search.searches.ReferencesSearch
|
|||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import org.jetbrains.kotlin.asJava.KotlinLightMethod
|
import org.jetbrains.kotlin.asJava.KotlinLightMethod
|
||||||
|
import org.jetbrains.kotlin.asJava.KotlinLightParameter
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||||
import org.jetbrains.kotlin.idea.JetFileType
|
import org.jetbrains.kotlin.idea.JetFileType
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
import org.jetbrains.kotlin.idea.search.KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT
|
import org.jetbrains.kotlin.idea.search.KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchLocation
|
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchLocation
|
||||||
|
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.getSpecialNamesToSearch
|
import org.jetbrains.kotlin.idea.search.usagesSearch.getSpecialNamesToSearch
|
||||||
import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope
|
import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
@@ -159,6 +161,18 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
|
|||||||
searchNamedElement(queryParameters, PsiTreeUtil.getParentOfType<JetProperty>(declaration, javaClass<JetProperty>()))
|
searchNamedElement(queryParameters, PsiTreeUtil.getParentOfType<JetProperty>(declaration, javaClass<JetProperty>()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is KotlinLightParameter -> {
|
||||||
|
val componentFunctionDescriptor = element.getOrigin()?.dataClassComponentFunction()
|
||||||
|
if (componentFunctionDescriptor != null) {
|
||||||
|
val containingClass = element.method.containingClass
|
||||||
|
val componentFunction = containingClass?.methods?.find {
|
||||||
|
it.name == componentFunctionDescriptor.name.asString() && it.parameterList.parametersCount == 0
|
||||||
|
}
|
||||||
|
if (componentFunction != null) {
|
||||||
|
searchNamedElement(queryParameters, componentFunction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-7
@@ -25,6 +25,7 @@ import com.intellij.util.Processor
|
|||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil.PropertyAccessorsPsiMethods
|
import org.jetbrains.kotlin.asJava.LightClassUtil.PropertyAccessorsPsiMethods
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
@@ -45,8 +46,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassReceiver
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
import java.util.Collections
|
|
||||||
|
|
||||||
val isTargetUsage = (PsiReference::matchesTarget).searchFilter
|
val isTargetUsage = (PsiReference::matchesTarget).searchFilter
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ public fun PsiNamedElement.getSpecialNamesToSearch(): List<String> {
|
|||||||
return when {
|
return when {
|
||||||
name == null || !Name.isValidIdentifier(name) -> Collections.emptyList<String>()
|
name == null || !Name.isValidIdentifier(name) -> Collections.emptyList<String>()
|
||||||
this is JetParameter -> {
|
this is JetParameter -> {
|
||||||
val componentFunctionName = this.dataClassComponentFunctionName()
|
val componentFunctionName = this.dataClassComponentFunction()?.name
|
||||||
if (componentFunctionName == null) return Collections.emptyList<String>()
|
if (componentFunctionName == null) return Collections.emptyList<String>()
|
||||||
|
|
||||||
return listOf(componentFunctionName.asString(), JetTokens.LPAR.getValue())
|
return listOf(componentFunctionName.asString(), JetTokens.LPAR.getValue())
|
||||||
@@ -97,7 +97,7 @@ public fun PsiNamedElement.getSpecialNamesToSearch(): List<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JetParameter.dataClassComponentFunctionName(): Name? {
|
fun JetParameter.dataClassComponentFunction(): FunctionDescriptor? {
|
||||||
if (!hasValOrVar()) return null
|
if (!hasValOrVar()) return null
|
||||||
|
|
||||||
// Forcing full resolve of owner class: otherwise DATA_CLASS_COMPONENT_FUNCTION won't be calculated.
|
// Forcing full resolve of owner class: otherwise DATA_CLASS_COMPONENT_FUNCTION won't be calculated.
|
||||||
@@ -107,9 +107,7 @@ fun JetParameter.dataClassComponentFunctionName(): Name? {
|
|||||||
|
|
||||||
val context = this.analyze()
|
val context = this.analyze()
|
||||||
val paramDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? ValueParameterDescriptor
|
val paramDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? ValueParameterDescriptor
|
||||||
return context[BindingContext.DATA_CLASS_COMPONENT_FUNCTION, paramDescriptor]?.let {
|
return context[BindingContext.DATA_CLASS_COMPONENT_FUNCTION, paramDescriptor]
|
||||||
it.getName()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class UsagesSearchHelper<T : PsiNamedElement> {
|
public abstract class UsagesSearchHelper<T : PsiNamedElement> {
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
|||||||
if (declaration is JetProperty && declaration.isSerializationImplicitlyUsedField()) return
|
if (declaration is JetProperty && declaration.isSerializationImplicitlyUsedField()) return
|
||||||
if (isCompanionObject && (declaration as JetObjectDeclaration).hasSerializationImplicitlyUsedField()) return
|
if (isCompanionObject && (declaration as JetObjectDeclaration).hasSerializationImplicitlyUsedField()) return
|
||||||
// properties can be referred by component1/component2, which is too expensive to search, don't mark them as unused
|
// properties can be referred by component1/component2, which is too expensive to search, don't mark them as unused
|
||||||
if (declaration is JetParameter && declaration.dataClassComponentFunctionName() != null) return
|
if (declaration is JetParameter && declaration.dataClassComponentFunction() != null) return
|
||||||
|
|
||||||
// Main checks: finding reference usages && text usages
|
// Main checks: finding reference usages && text usages
|
||||||
if (hasNonTrivialUsages(declaration)) return
|
if (hasNonTrivialUsages(declaration)) return
|
||||||
|
|||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public class A {
|
||||||
|
public void usage(RemData p) {
|
||||||
|
System.out.println(p.component1());
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
data public class RemData(val remo<caret>vable: Int)
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
parameter removable has 1 usage that is not safe to delete.
|
||||||
@@ -1081,6 +1081,12 @@ public class JetSafeDeleteTestGenerated extends AbstractJetSafeDeleteTest {
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("dataClassComponent.kt")
|
||||||
|
public void testDataClassComponent() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt");
|
||||||
|
doValueParameterTestWithJava(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hierarchyWithSafeUsages1.kt")
|
@TestMetadata("hierarchyWithSafeUsages1.kt")
|
||||||
public void testHierarchyWithSafeUsages1() throws Exception {
|
public void testHierarchyWithSafeUsages1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/hierarchyWithSafeUsages1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/hierarchyWithSafeUsages1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user