From 24f45a382efe5ada4ff9d3ec4be1e716322594c9 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 21 Aug 2015 15:46:59 +0200 Subject: [PATCH] ReferencesSearch finds references of data class component functions in Java code #KT-8808 Fixed --- .../kotlin/asJava/KotlinLightParameter.java | 4 ++++ .../ideaExtensions/KotlinReferencesSearcher.kt | 14 ++++++++++++++ .../idea/search/usagesSearch/searchHelpers.kt | 12 +++++------- .../idea/inspections/UnusedSymbolInspection.kt | 2 +- .../dataClassComponent.java | 7 +++++++ .../dataClassComponent.kt | 3 +++ .../dataClassComponent.kt.messages | 1 + .../safeDelete/JetSafeDeleteTestGenerated.java | 6 ++++++ 8 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.java create mode 100644 idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt create mode 100644 idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt.messages diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightParameter.java b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightParameter.java index ca17a72b177..5783b0f7467 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightParameter.java +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightParameter.java @@ -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; + } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt index 3505a6eebf6..44dd0bb5cfc 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt @@ -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(declaration, javaClass())) } } + 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) + } + } + } } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt index a6f4c135267..4f8dc41dfab 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt @@ -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 { return when { name == null || !Name.isValidIdentifier(name) -> Collections.emptyList() this is JetParameter -> { - val componentFunctionName = this.dataClassComponentFunctionName() + val componentFunctionName = this.dataClassComponentFunction()?.name if (componentFunctionName == null) return Collections.emptyList() return listOf(componentFunctionName.asString(), JetTokens.LPAR.getValue()) @@ -97,7 +97,7 @@ public fun PsiNamedElement.getSpecialNamesToSearch(): List { } } -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 { diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt index 0b9627d4f29..43caeae447d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt @@ -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 diff --git a/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.java b/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.java new file mode 100644 index 00000000000..873d2cb3d18 --- /dev/null +++ b/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.java @@ -0,0 +1,7 @@ +package test; + +public class A { + public void usage(RemData p) { + System.out.println(p.component1()); + } +} \ No newline at end of file diff --git a/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt b/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt new file mode 100644 index 00000000000..2e393af517e --- /dev/null +++ b/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt @@ -0,0 +1,3 @@ +package test + +data public class RemData(val removable: Int) diff --git a/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt.messages b/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt.messages new file mode 100644 index 00000000000..804ff49895c --- /dev/null +++ b/idea/testData/safeDelete/deleteValueParameter/kotlinValueParameterWithJava/dataClassComponent.kt.messages @@ -0,0 +1 @@ +parameter removable has 1 usage that is not safe to delete. \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/safeDelete/JetSafeDeleteTestGenerated.java b/idea/tests/org/jetbrains/kotlin/safeDelete/JetSafeDeleteTestGenerated.java index 34cc2a8d370..91e61795501 100644 --- a/idea/tests/org/jetbrains/kotlin/safeDelete/JetSafeDeleteTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/safeDelete/JetSafeDeleteTestGenerated.java @@ -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");