[AA] Fix processing of member invoke functions from objects in reference shortening and import optimization

Correctly handle `KtDotQualifedExpression`s with function calls as
selectors (like `foo.Bar()`). Without such handling, processing of
member invoke calls on objects was broken both
for reference shortener (causing KTIJ-26695)
and import optimizer (causing KTIJ-23407)

Also, to fix KTIJ-23407, do not ignore qualifiers with
`ImplicitInvokeCall` fake source

^KTIJ-26695 Fixed
^KTIJ-23407 Fixed
This commit is contained in:
Roman Golyshev
2023-08-17 21:26:52 +02:00
committed by teamcity
parent 4958196c51
commit 52d6ac5ed0
13 changed files with 108 additions and 4 deletions
@@ -118,6 +118,12 @@ public class Fe10IdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGene
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedInvokeOperatorImport.kt");
}
@Test
@TestMetadata("unusedObject_invokeOperator.kt")
public void testUnusedObject_invokeOperator() throws Exception {
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedObject_invokeOperator.kt");
}
@Test
@TestMetadata("unusedStaticFunctionImportFromJavaChildClass.kt")
public void testUnusedStaticFunctionImportFromJavaChildClass() throws Exception {
@@ -214,6 +220,12 @@ public class Fe10IdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGene
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedInvokeOperatorImport.kt");
}
@Test
@TestMetadata("usedObject_invokeOperator.kt")
public void testUsedObject_invokeOperator() throws Exception {
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedObject_invokeOperator.kt");
}
@Test
@TestMetadata("usedStaticFunctionImportFromJavaChildClass.kt")
public void testUsedStaticFunctionImportFromJavaChildClass() throws Exception {
@@ -500,7 +500,12 @@ private sealed interface TypeQualifier {
companion object {
val FirResolvedQualifier.isPresentInSource: Boolean
get() = source?.kind is KtRealSourceElementKind
get() = when (source?.kind) {
is KtRealSourceElementKind -> true
is KtFakeSourceElementKind.ImplicitInvokeCall -> true
else -> false
}
fun createFor(qualifier: FirResolvedQualifier): TypeQualifier? {
if (!qualifier.isPresentInSource) return null
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesResolver
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.declarations.*
@@ -1308,8 +1307,8 @@ private fun KtUserType.hasFakeRootPrefix(): Boolean =
private fun KtDotQualifiedExpression.hasFakeRootPrefix(): Boolean =
(receiverExpression as? KtNameReferenceExpression)?.getReferencedName() == ROOT_PREFIX_FOR_IDE_RESOLUTION_MODE
internal fun KtElement.getDotQualifiedExpressionForSelector(): KtDotQualifiedExpression? =
getQualifiedExpressionForSelector() as? KtDotQualifiedExpression
internal fun KtSimpleNameExpression.getDotQualifiedExpressionForSelector(): KtDotQualifiedExpression? =
getQualifiedElement() as? KtDotQualifiedExpression
private fun KtElement.getQualifier(): KtElement? = when (this) {
is KtUserType -> qualifier
@@ -118,6 +118,12 @@ public class FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGener
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedInvokeOperatorImport.kt");
}
@Test
@TestMetadata("unusedObject_invokeOperator.kt")
public void testUnusedObject_invokeOperator() throws Exception {
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedObject_invokeOperator.kt");
}
@Test
@TestMetadata("unusedStaticFunctionImportFromJavaChildClass.kt")
public void testUnusedStaticFunctionImportFromJavaChildClass() throws Exception {
@@ -214,6 +220,12 @@ public class FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGener
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedInvokeOperatorImport.kt");
}
@Test
@TestMetadata("usedObject_invokeOperator.kt")
public void testUsedObject_invokeOperator() throws Exception {
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedObject_invokeOperator.kt");
}
@Test
@TestMetadata("usedStaticFunctionImportFromJavaChildClass.kt")
public void testUsedStaticFunctionImportFromJavaChildClass() throws Exception {
@@ -316,6 +316,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClass3.kt");
}
@Test
@TestMetadata("objectWithInvokeOperator.kt")
public void testObjectWithInvokeOperator() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/objectWithInvokeOperator.kt");
}
@Test
@TestMetadata("parameterTypeTopLevelTypeLoses.kt")
public void testParameterTypeTopLevelTypeLoses() throws Exception {
@@ -118,6 +118,12 @@ public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTe
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedInvokeOperatorImport.kt");
}
@Test
@TestMetadata("unusedObject_invokeOperator.kt")
public void testUnusedObject_invokeOperator() throws Exception {
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/unusedObject_invokeOperator.kt");
}
@Test
@TestMetadata("unusedStaticFunctionImportFromJavaChildClass.kt")
public void testUnusedStaticFunctionImportFromJavaChildClass() throws Exception {
@@ -214,6 +220,12 @@ public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTe
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedInvokeOperatorImport.kt");
}
@Test
@TestMetadata("usedObject_invokeOperator.kt")
public void testUsedObject_invokeOperator() throws Exception {
runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/usedObject_invokeOperator.kt");
}
@Test
@TestMetadata("usedStaticFunctionImportFromJavaChildClass.kt")
public void testUsedStaticFunctionImportFromJavaChildClass() throws Exception {
@@ -316,6 +316,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClass3.kt");
}
@Test
@TestMetadata("objectWithInvokeOperator.kt")
public void testObjectWithInvokeOperator() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/objectWithInvokeOperator.kt");
}
@Test
@TestMetadata("parameterTypeTopLevelTypeLoses.kt")
public void testParameterTypeTopLevelTypeLoses() throws Exception {
@@ -0,0 +1,15 @@
// FILE: main.kt
package test
import dependency.MyObject
fun usage() {
dependency.MyObject()
}
// FILE: dependency.kt
package dependency
object MyObject {
operator fun invoke() {}
}
@@ -0,0 +1,15 @@
// FILE: main.kt
package test
import dependency.MyObject
fun usage() {
MyObject()
}
// FILE: dependency.kt
package dependency
object MyObject {
operator fun invoke() {}
}
@@ -0,0 +1,14 @@
// FILE: main.kt
package test
fun test() {
<expr>dependency.Foo()</expr>
}
// FILE: dependency.kt
package dependency
object Foo {
operator fun invoke() {}
}
@@ -0,0 +1,7 @@
Before shortening: dependency.Foo()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
[qualifier] dependency.Foo()
with SHORTEN_AND_STAR_IMPORT:
[qualifier] dependency.Foo()