From 4d6b4242805c2b4712fa12d71f7db367c1a0991d Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Tue, 14 Jun 2022 16:02:26 +0400 Subject: [PATCH] [FIR IDE] Properly handle generic types qualifiers In code like `foo.Bar`, `Bar` is considered to be `KtCallExpression` from the PSI point ^KT-52779 Fixed --- .../api/fir/components/KtFirImportOptimizer.kt | 14 +++++++++----- ...AnalysisApiImportOptimizerTestGenerated.java | 12 ++++++++++++ ...AnalysisApiImportOptimizerTestGenerated.java | 12 ++++++++++++ .../unusedGenericTypeQualifier.imports | 1 + .../unusedGenericTypeQualifier.kt | 17 +++++++++++++++++ .../usedGenericTypeQualifier.imports | 0 .../analyseImports/usedGenericTypeQualifier.kt | 17 +++++++++++++++++ 7 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.imports create mode 100644 analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.kt create mode 100644 analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.imports create mode 100644 analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt index f33fa9b47c9..7129fc8faa8 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression import org.jetbrains.kotlin.psi.psiUtil.unwrapNullability import org.jetbrains.kotlin.resolve.ImportPath +import org.jetbrains.kotlin.resolve.calls.util.getCalleeExpressionIfAny import org.jetbrains.kotlin.util.OperatorNameConventions internal class KtFirImportOptimizer( @@ -323,11 +324,14 @@ private sealed interface TypeQualifier { private val dotQualifier: KtDotQualifiedExpression? = qualifier as? KtDotQualifiedExpression - private val typeNameReference: KtNameReferenceExpression = when (qualifier) { - is KtDotQualifiedExpression -> qualifier.selectorExpression as? KtNameReferenceExpression - is KtNameReferenceExpression -> qualifier - else -> null - } ?: error("Cannot get referenced name from '${qualifier.text}'") + private val typeNameReference: KtNameReferenceExpression = run { + require(qualifier is KtNameReferenceExpression || qualifier is KtDotQualifiedExpression || qualifier is KtCallExpression) { + "Unexpected qualifier '${qualifier.text}' of type '${qualifier::class}'" + } + + qualifier.getCalleeExpressionIfAny() as? KtNameReferenceExpression + ?: error("Cannot get referenced name from '${qualifier.text}'") + } override val referencedByName: Name get() = typeNameReference.getReferencedNameAsName() diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/importOptimizer/FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/importOptimizer/FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java index b37e56d01bb..146e4b5d9f1 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/importOptimizer/FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/importOptimizer/FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java @@ -58,6 +58,12 @@ public class FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGener runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedFunctionImports.kt"); } + @Test + @TestMetadata("unusedGenericTypeQualifier.kt") + public void testUnusedGenericTypeQualifier() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.kt"); + } + @Test @TestMetadata("unusedInvokeOperatorImport.kt") public void testUnusedInvokeOperatorImport() throws Exception { @@ -82,6 +88,12 @@ public class FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGener runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedFunctionImport.kt"); } + @Test + @TestMetadata("usedGenericTypeQualifier.kt") + public void testUsedGenericTypeQualifier() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.kt"); + } + @Test @TestMetadata("usedInvokeOperatorAliasedImport.kt") public void testUsedInvokeOperatorAliasedImport() throws Exception { diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/importOptimizer/FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/importOptimizer/FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java index 4d38dc73b73..ddbdfc45310 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/importOptimizer/FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/importOptimizer/FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java @@ -58,6 +58,12 @@ public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTe runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedFunctionImports.kt"); } + @Test + @TestMetadata("unusedGenericTypeQualifier.kt") + public void testUnusedGenericTypeQualifier() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.kt"); + } + @Test @TestMetadata("unusedInvokeOperatorImport.kt") public void testUnusedInvokeOperatorImport() throws Exception { @@ -82,6 +88,12 @@ public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTe runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedFunctionImport.kt"); } + @Test + @TestMetadata("usedGenericTypeQualifier.kt") + public void testUsedGenericTypeQualifier() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.kt"); + } + @Test @TestMetadata("usedInvokeOperatorAliasedImport.kt") public void testUsedInvokeOperatorAliasedImport() throws Exception { diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.imports new file mode 100644 index 00000000000..78782534898 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.imports @@ -0,0 +1 @@ +dependency.Bar \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.kt new file mode 100644 index 00000000000..704b81c01fb --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedGenericTypeQualifier.kt @@ -0,0 +1,17 @@ +// FILE: main.kt +package test + +import dependency.Bar + +class MyClass + +fun usage() { + val a = dependency.Bar::foo +} + +// FILE: dependency.kt +package dependency + +class Bar { + fun foo() {} +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.imports new file mode 100644 index 00000000000..e69de29bb2d diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.kt new file mode 100644 index 00000000000..9e1c1080a5e --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedGenericTypeQualifier.kt @@ -0,0 +1,17 @@ +// FILE: main.kt +package test + +import dependency.Bar + +class MyClass + +fun usage() { + val a = Bar::foo +} + +// FILE: dependency.kt +package dependency + +class Bar { + fun foo() {} +} \ No newline at end of file