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();
|
||||
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.util.Processor
|
||||
import org.jetbrains.kotlin.asJava.KotlinLightMethod
|
||||
import org.jetbrains.kotlin.asJava.KotlinLightParameter
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.idea.JetFileType
|
||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||
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.dataClassComponentFunction
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.getSpecialNamesToSearch
|
||||
import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope
|
||||
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>()))
|
||||
}
|
||||
}
|
||||
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 org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil.PropertyAccessorsPsiMethods
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
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.scopes.receivers.ClassReceiver
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import java.util.*
|
||||
|
||||
val isTargetUsage = (PsiReference::matchesTarget).searchFilter
|
||||
|
||||
@@ -88,7 +88,7 @@ public fun PsiNamedElement.getSpecialNamesToSearch(): List<String> {
|
||||
return when {
|
||||
name == null || !Name.isValidIdentifier(name) -> Collections.emptyList<String>()
|
||||
this is JetParameter -> {
|
||||
val componentFunctionName = this.dataClassComponentFunctionName()
|
||||
val componentFunctionName = this.dataClassComponentFunction()?.name
|
||||
if (componentFunctionName == null) return Collections.emptyList<String>()
|
||||
|
||||
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
|
||||
|
||||
// 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 paramDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? ValueParameterDescriptor
|
||||
return context[BindingContext.DATA_CLASS_COMPONENT_FUNCTION, paramDescriptor]?.let {
|
||||
it.getName()
|
||||
}
|
||||
return context[BindingContext.DATA_CLASS_COMPONENT_FUNCTION, paramDescriptor]
|
||||
}
|
||||
|
||||
public abstract class UsagesSearchHelper<T : PsiNamedElement> {
|
||||
|
||||
@@ -159,7 +159,7 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
if (declaration is JetProperty && declaration.isSerializationImplicitlyUsedField()) 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
|
||||
if (declaration is JetParameter && declaration.dataClassComponentFunctionName() != null) return
|
||||
if (declaration is JetParameter && declaration.dataClassComponentFunction() != null) return
|
||||
|
||||
// Main checks: finding reference usages && text usages
|
||||
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);
|
||||
}
|
||||
|
||||
@TestMetadata("dataClassComponent.kt")
|
||||
public void testDataClassComponent() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt");
|
||||
doValueParameterTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("hierarchyWithSafeUsages1.kt")
|
||||
public void testHierarchyWithSafeUsages1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/hierarchyWithSafeUsages1.kt");
|
||||
|
||||
Reference in New Issue
Block a user