[Analysis API] KTIJ-24107 Fix resolution of qualified invoke calls on objects

^KTIJ-24107 Fixed
^KTIJ-24344 Fixed
This commit is contained in:
Roman Golyshev
2023-01-24 19:29:54 +01:00
committed by teamcity
parent aab853ad12
commit 71a368e06e
55 changed files with 852 additions and 40 deletions
@@ -960,6 +960,76 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated extends A
} }
} }
@Nested
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects")
@TestDataPath("$PROJECT_ROOT")
public class InvokeOnObjects {
@Test
public void testAllFilesPresentInInvokeOnObjects() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("companionObject1.kt")
public void testCompanionObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObject1.kt");
}
@Test
@TestMetadata("companionObject2.kt")
public void testCompanionObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObject2.kt");
}
@Test
@TestMetadata("companionObjectWithName1.kt")
public void testCompanionObjectWithName1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObjectWithName1.kt");
}
@Test
@TestMetadata("companionObjectWithName2.kt")
public void testCompanionObjectWithName2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObjectWithName2.kt");
}
@Test
@TestMetadata("nestedObject1.kt")
public void testNestedObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject1.kt");
}
@Test
@TestMetadata("nestedObject2.kt")
public void testNestedObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject2.kt");
}
@Test
@TestMetadata("nestedObject3.kt")
public void testNestedObject3() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject3.kt");
}
@Test
@TestMetadata("nestedObject4.kt")
public void testNestedObject4() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject4.kt");
}
@Test
@TestMetadata("simpleObject1.kt")
public void testSimpleObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/simpleObject1.kt");
}
@Test
@TestMetadata("simpleObject2.kt")
public void testSimpleObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/simpleObject2.kt");
}
}
@Nested @Nested
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls") @TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -1075,6 +1075,76 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt"); runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt");
} }
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/onObjects")
@TestDataPath("$PROJECT_ROOT")
public class OnObjects {
@Test
public void testAllFilesPresentInOnObjects() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/invoke/onObjects"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("companionObject1.kt")
public void testCompanionObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject1.kt");
}
@Test
@TestMetadata("companionObject2.kt")
public void testCompanionObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject2.kt");
}
@Test
@TestMetadata("companionObjectWithName1.kt")
public void testCompanionObjectWithName1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName1.kt");
}
@Test
@TestMetadata("companionObjectWithName2.kt")
public void testCompanionObjectWithName2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName2.kt");
}
@Test
@TestMetadata("nestedObject1.kt")
public void testNestedObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject1.kt");
}
@Test
@TestMetadata("nestedObject2.kt")
public void testNestedObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject2.kt");
}
@Test
@TestMetadata("nestedObject3.kt")
public void testNestedObject3() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject3.kt");
}
@Test
@TestMetadata("nestedObject4.kt")
public void testNestedObject4() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject4.kt");
}
@Test
@TestMetadata("simpleObject1.kt")
public void testSimpleObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject1.kt");
}
@Test
@TestMetadata("simpleObject2.kt")
public void testSimpleObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject2.kt");
}
}
@Nested @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/withErrors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/withErrors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -161,20 +161,32 @@ internal class KtFirCallResolver(
} }
} }
if (resolveCalleeExpressionOfFunctionCall && this is FirImplicitInvokeCall) { if (this is FirImplicitInvokeCall) {
// For implicit invoke, we resolve the calleeExpression of the CallExpression to the call that creates the receiver of this
// implicit invoke call. For example, // If we have a PSI expression like `Foo.Bar.Baz()` and try to resolve `Bar` part,
// ``` // and the only FIR that we have for that PSI is an implicit invoke call, that means that
// fun test(f: () -> Unit) { // `Foo.Bar` is definitely not a property access - otherwise it would have had its own FIR.
// f() // calleeExpression `f` resolves to the local variable access, while `f()` resolves to the implicit `invoke` call. // So, it does not make sense to try to resolve such parts of qualifiers as KtCall
// // This way `f` is also the explicit receiver of this implicit `invoke` call if ((psi as? KtExpression)?.getPossiblyQualifiedCallExpression() == null) {
// } return null
// ``` }
return explicitReceiver?.toKtCallInfo(
psi, if (resolveCalleeExpressionOfFunctionCall) {
resolveCalleeExpressionOfFunctionCall = false, // For implicit invoke, we resolve the calleeExpression of the CallExpression to the call that creates the receiver of this
resolveFragmentOfCall = resolveFragmentOfCall // implicit invoke call. For example,
) // ```
// fun test(f: () -> Unit) {
// f() // calleeExpression `f` resolves to the local variable access, while `f()` resolves to the implicit `invoke` call.
// // This way `f` is also the explicit receiver of this implicit `invoke` call
// }
// ```
val psiToResolve = (psi as? KtCallExpression)?.calleeExpression ?: psi
return explicitReceiver?.toKtCallInfo(
psiToResolve,
resolveCalleeExpressionOfFunctionCall = false,
resolveFragmentOfCall = resolveFragmentOfCall
)
}
} }
fun <T> transformErrorReference(call: FirResolvable, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder { fun <T> transformErrorReference(call: FirResolvable, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder {
@@ -45,9 +45,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
import org.jetbrains.kotlin.psi.psiUtil.unwrapNullability
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
@@ -393,14 +391,18 @@ internal object FirReferenceResolveHelper {
if (expression is KtLabelReferenceExpression && fir is FirPropertyAccessExpression && fir.calleeReference is FirSuperReference) { if (expression is KtLabelReferenceExpression && fir is FirPropertyAccessExpression && fir.calleeReference is FirSuperReference) {
return listOfNotNull((fir.dispatchReceiver.typeRef as? FirResolvedTypeRef)?.toTargetSymbol(session, symbolBuilder)) return listOfNotNull((fir.dispatchReceiver.typeRef as? FirResolvedTypeRef)?.toTargetSymbol(session, symbolBuilder))
} }
val implicitInvokeReceiver = if (fir is FirImplicitInvokeCall) { val receiverOrImplicitInvoke = if (fir is FirImplicitInvokeCall) {
fir.explicitReceiver?.unwrapSmartcastExpression() as? FirQualifiedAccessExpression fir.explicitReceiver?.unwrapSmartcastExpression()
} else { } else {
null null
} }
val calleeReference = implicitInvokeReceiver?.calleeReference ?: fir.calleeReference
return calleeReference.toTargetSymbol(session, symbolBuilder, isInLabelReference = expression is KtLabelReferenceExpression) return if (receiverOrImplicitInvoke is FirResolvedQualifier) {
getSymbolsForResolvedQualifier(receiverOrImplicitInvoke, expression, session, symbolBuilder)
} else {
val calleeReference = (receiverOrImplicitInvoke as? FirQualifiedAccessExpression)?.calleeReference ?: fir.calleeReference
calleeReference.toTargetSymbol(session, symbolBuilder, isInLabelReference = expression is KtLabelReferenceExpression)
}
} }
@@ -494,8 +496,12 @@ internal object FirReferenceResolveHelper {
} }
val referencedClass = referencedSymbol.fir val referencedClass = referencedSymbol.fir
val referencedSymbolsByFir = listOfNotNull(symbolBuilder.buildSymbol(referencedSymbol)) val referencedSymbolsByFir = listOfNotNull(symbolBuilder.buildSymbol(referencedSymbol))
val firSourcePsi = fir.source.psi val fullQualifiedAccess = when (val psi = fir.source.psi) {
if (firSourcePsi !is KtDotQualifiedExpression) return referencedSymbolsByFir // for cases like `Foo.Bar()`, where `Foo.Bar` is an object, and `Foo.Bar()` is a call to `invoke` operator
is KtSimpleNameExpression -> psi.getQualifiedElement()
else -> psi
}
if (fullQualifiedAccess !is KtDotQualifiedExpression) return referencedSymbolsByFir
// When the source of an `FirResolvedQualifier` is a KtDotQualifiedExpression, we need to manually break up the qualified access and // When the source of an `FirResolvedQualifier` is a KtDotQualifiedExpression, we need to manually break up the qualified access and
// resolve individual parts of it because in FIR, the entire qualified access is one element. // resolve individual parts of it because in FIR, the entire qualified access is one element.
@@ -503,14 +509,21 @@ internal object FirReferenceResolveHelper {
// TODO: handle local classes after KT-47135 is fixed // TODO: handle local classes after KT-47135 is fixed
return referencedSymbolsByFir return referencedSymbolsByFir
} else { } else {
var qualifiedAccess: KtDotQualifiedExpression = firSourcePsi var qualifiedAccess: KtDotQualifiedExpression = fullQualifiedAccess
val referencedClassId = val referencedClassId =
if ((referencedClass as? FirRegularClass)?.isCompanion == true && if ((referencedClass as? FirRegularClass)?.isCompanion == true) {
(qualifiedAccess.selectorExpression as? KtNameReferenceExpression)?.getReferencedName() != referencedClass.classId.shortClassName.asString() val deepestQualifier = qualifiedAccess.selectorExpression?.referenceExpression() as? KtNameReferenceExpression
) {
// Remove the last companion name part if the qualified access does not contain it. // If we're looking for the deepest qualifier, then just resolve to the companion
// This is needed because the companion name part is optional. if (expression === deepestQualifier) return referencedSymbolsByFir
referencedClass.classId.outerClassId ?: return referencedSymbolsByFir
if (deepestQualifier?.getReferencedName() != referencedClass.classId.shortClassName.asString()) {
// Remove the last companion name part if the qualified access does not contain it.
// This is needed because the companion name part is optional.
referencedClass.classId.outerClassId ?: return referencedSymbolsByFir
} else {
referencedClass.classId
}
} else { } else {
referencedClass.classId referencedClass.classId
} }
@@ -548,7 +561,7 @@ internal object FirReferenceResolveHelper {
// Handle nested classes. // Handle nested classes.
while (classId != null) { while (classId != null) {
if (expression === qualifiedAccess.selectorExpression) { if (expression === qualifiedAccess.selectorExpression?.referenceExpression()) {
return listOfNotNull(classId.toTargetPsi(session, symbolBuilder)) return listOfNotNull(classId.toTargetPsi(session, symbolBuilder))
} }
val outerClassId = classId.outerClassId val outerClassId = classId.outerClassId
@@ -609,7 +622,13 @@ internal object FirReferenceResolveHelper {
.toList() .toList()
.asReversed() .asReversed()
val qualifyingReferences = qualifiers.map { it as? KtNameReferenceExpression ?: return null } val qualifyingReferences = qualifiers.mapIndexed { index, qualifier ->
// We want to handle qualified calls like `foo.Bar.Baz()`, but not like `foo.Bar().Baz()`
if (qualifier is KtCallExpression && index != qualifiers.lastIndex) return null
qualifier.referenceExpression() as? KtNameReferenceExpression ?: return null
}
return qualifyingReferences.map { it.getReferencedName() } return qualifyingReferences.map { it.getReferencedName() }
} }
@@ -960,6 +960,76 @@ public class FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated extends Ab
} }
} }
@Nested
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects")
@TestDataPath("$PROJECT_ROOT")
public class InvokeOnObjects {
@Test
public void testAllFilesPresentInInvokeOnObjects() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("companionObject1.kt")
public void testCompanionObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObject1.kt");
}
@Test
@TestMetadata("companionObject2.kt")
public void testCompanionObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObject2.kt");
}
@Test
@TestMetadata("companionObjectWithName1.kt")
public void testCompanionObjectWithName1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObjectWithName1.kt");
}
@Test
@TestMetadata("companionObjectWithName2.kt")
public void testCompanionObjectWithName2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObjectWithName2.kt");
}
@Test
@TestMetadata("nestedObject1.kt")
public void testNestedObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject1.kt");
}
@Test
@TestMetadata("nestedObject2.kt")
public void testNestedObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject2.kt");
}
@Test
@TestMetadata("nestedObject3.kt")
public void testNestedObject3() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject3.kt");
}
@Test
@TestMetadata("nestedObject4.kt")
public void testNestedObject4() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject4.kt");
}
@Test
@TestMetadata("simpleObject1.kt")
public void testSimpleObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/simpleObject1.kt");
}
@Test
@TestMetadata("simpleObject2.kt")
public void testSimpleObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/simpleObject2.kt");
}
}
@Nested @Nested
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls") @TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -1075,6 +1075,76 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt"); runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt");
} }
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/onObjects")
@TestDataPath("$PROJECT_ROOT")
public class OnObjects {
@Test
public void testAllFilesPresentInOnObjects() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/invoke/onObjects"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("companionObject1.kt")
public void testCompanionObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject1.kt");
}
@Test
@TestMetadata("companionObject2.kt")
public void testCompanionObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject2.kt");
}
@Test
@TestMetadata("companionObjectWithName1.kt")
public void testCompanionObjectWithName1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName1.kt");
}
@Test
@TestMetadata("companionObjectWithName2.kt")
public void testCompanionObjectWithName2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName2.kt");
}
@Test
@TestMetadata("nestedObject1.kt")
public void testNestedObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject1.kt");
}
@Test
@TestMetadata("nestedObject2.kt")
public void testNestedObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject2.kt");
}
@Test
@TestMetadata("nestedObject3.kt")
public void testNestedObject3() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject3.kt");
}
@Test
@TestMetadata("nestedObject4.kt")
public void testNestedObject4() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject4.kt");
}
@Test
@TestMetadata("simpleObject1.kt")
public void testSimpleObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject1.kt");
}
@Test
@TestMetadata("simpleObject2.kt")
public void testSimpleObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject2.kt");
}
}
@Nested @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/withErrors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/withErrors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -998,6 +998,76 @@ public class FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerate
public void testOneParamRPar() throws Exception { public void testOneParamRPar() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt"); runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt");
} }
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/onObjects")
@TestDataPath("$PROJECT_ROOT")
public class OnObjects {
@Test
public void testAllFilesPresentInOnObjects() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/invoke/onObjects"), Pattern.compile("^([^.]+)\\.kt$"), null, true, "withErrors");
}
@Test
@TestMetadata("companionObject1.kt")
public void testCompanionObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject1.kt");
}
@Test
@TestMetadata("companionObject2.kt")
public void testCompanionObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject2.kt");
}
@Test
@TestMetadata("companionObjectWithName1.kt")
public void testCompanionObjectWithName1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName1.kt");
}
@Test
@TestMetadata("companionObjectWithName2.kt")
public void testCompanionObjectWithName2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName2.kt");
}
@Test
@TestMetadata("nestedObject1.kt")
public void testNestedObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject1.kt");
}
@Test
@TestMetadata("nestedObject2.kt")
public void testNestedObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject2.kt");
}
@Test
@TestMetadata("nestedObject3.kt")
public void testNestedObject3() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject3.kt");
}
@Test
@TestMetadata("nestedObject4.kt")
public void testNestedObject4() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject4.kt");
}
@Test
@TestMetadata("simpleObject1.kt")
public void testSimpleObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject1.kt");
}
@Test
@TestMetadata("simpleObject2.kt")
public void testSimpleObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject2.kt");
}
}
} }
@Nested @Nested
@@ -1075,6 +1075,76 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt"); runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt");
} }
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/onObjects")
@TestDataPath("$PROJECT_ROOT")
public class OnObjects {
@Test
public void testAllFilesPresentInOnObjects() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/invoke/onObjects"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("companionObject1.kt")
public void testCompanionObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject1.kt");
}
@Test
@TestMetadata("companionObject2.kt")
public void testCompanionObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject2.kt");
}
@Test
@TestMetadata("companionObjectWithName1.kt")
public void testCompanionObjectWithName1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName1.kt");
}
@Test
@TestMetadata("companionObjectWithName2.kt")
public void testCompanionObjectWithName2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName2.kt");
}
@Test
@TestMetadata("nestedObject1.kt")
public void testNestedObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject1.kt");
}
@Test
@TestMetadata("nestedObject2.kt")
public void testNestedObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject2.kt");
}
@Test
@TestMetadata("nestedObject3.kt")
public void testNestedObject3() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject3.kt");
}
@Test
@TestMetadata("nestedObject4.kt")
public void testNestedObject4() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject4.kt");
}
@Test
@TestMetadata("simpleObject1.kt")
public void testSimpleObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject1.kt");
}
@Test
@TestMetadata("simpleObject2.kt")
public void testSimpleObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject2.kt");
}
}
@Nested @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/withErrors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/withErrors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -960,6 +960,76 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated ext
} }
} }
@Nested
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects")
@TestDataPath("$PROJECT_ROOT")
public class InvokeOnObjects {
@Test
public void testAllFilesPresentInInvokeOnObjects() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects"), Pattern.compile("^(.+)\\.kt$"), null, true, "withTestCompilerPluginEnabled");
}
@Test
@TestMetadata("companionObject1.kt")
public void testCompanionObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObject1.kt");
}
@Test
@TestMetadata("companionObject2.kt")
public void testCompanionObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObject2.kt");
}
@Test
@TestMetadata("companionObjectWithName1.kt")
public void testCompanionObjectWithName1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObjectWithName1.kt");
}
@Test
@TestMetadata("companionObjectWithName2.kt")
public void testCompanionObjectWithName2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/companionObjectWithName2.kt");
}
@Test
@TestMetadata("nestedObject1.kt")
public void testNestedObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject1.kt");
}
@Test
@TestMetadata("nestedObject2.kt")
public void testNestedObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject2.kt");
}
@Test
@TestMetadata("nestedObject3.kt")
public void testNestedObject3() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject3.kt");
}
@Test
@TestMetadata("nestedObject4.kt")
public void testNestedObject4() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/nestedObject4.kt");
}
@Test
@TestMetadata("simpleObject1.kt")
public void testSimpleObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/simpleObject1.kt");
}
@Test
@TestMetadata("simpleObject2.kt")
public void testSimpleObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invokeOnObjects/simpleObject2.kt");
}
}
@Nested @Nested
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls") @TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCall/nonCalls")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -1075,6 +1075,76 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt"); runTest("analysis/analysis-api/testData/referenceResolve/invoke/oneParamRPar.kt");
} }
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/onObjects")
@TestDataPath("$PROJECT_ROOT")
public class OnObjects {
@Test
public void testAllFilesPresentInOnObjects() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/invoke/onObjects"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("companionObject1.kt")
public void testCompanionObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject1.kt");
}
@Test
@TestMetadata("companionObject2.kt")
public void testCompanionObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObject2.kt");
}
@Test
@TestMetadata("companionObjectWithName1.kt")
public void testCompanionObjectWithName1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName1.kt");
}
@Test
@TestMetadata("companionObjectWithName2.kt")
public void testCompanionObjectWithName2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/companionObjectWithName2.kt");
}
@Test
@TestMetadata("nestedObject1.kt")
public void testNestedObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject1.kt");
}
@Test
@TestMetadata("nestedObject2.kt")
public void testNestedObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject2.kt");
}
@Test
@TestMetadata("nestedObject3.kt")
public void testNestedObject3() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject3.kt");
}
@Test
@TestMetadata("nestedObject4.kt")
public void testNestedObject4() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/nestedObject4.kt");
}
@Test
@TestMetadata("simpleObject1.kt")
public void testSimpleObject1() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject1.kt");
}
@Test
@TestMetadata("simpleObject2.kt")
public void testSimpleObject2() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/invoke/onObjects/simpleObject2.kt");
}
}
@Nested @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/withErrors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/invoke/withErrors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -0,0 +1,9 @@
class Foo private constructor() {
companion object {
operator fun invoke() {}
}
}
fun test() {
<expr>Foo</expr>()
}
@@ -0,0 +1,11 @@
package foo
class Foo private constructor() {
companion object {
operator fun invoke() {}
}
}
fun test() {
foo.<expr>Foo</expr>()
}
@@ -0,0 +1,9 @@
class Foo private constructor() {
companion object Helper {
operator fun invoke() {}
}
}
fun test() {
Foo.<expr>Helper</expr>()
}
@@ -0,0 +1,9 @@
class Foo private constructor() {
companion object Helper {
operator fun invoke() {}
}
}
fun test() {
<expr>Foo</expr>()
}
@@ -0,0 +1,9 @@
object Foo {
object Helper {
operator fun invoke() {}
}
}
fun test() {
<expr>Foo</expr>.Helper()
}
@@ -0,0 +1,9 @@
object Foo {
object Helper {
operator fun invoke() {}
}
}
fun test() {
Foo.<expr>Helper</expr>()
}
@@ -0,0 +1,11 @@
package foo.bar.baz
object Foo {
object Helper {
operator fun invoke() {}
}
}
fun test() {
foo.bar.baz.<expr>Foo</expr>.Helper()
}
@@ -0,0 +1,11 @@
package foo.bar.baz
object Foo {
object Helper {
operator fun invoke() {}
}
}
fun test() {
foo.bar.baz.Foo.<expr>Helper</expr>()
}
@@ -0,0 +1,7 @@
object Foo {
operator fun invoke() {}
}
fun test() {
<expr>Foo</expr>()
}
@@ -0,0 +1,9 @@
package foo
object Foo {
operator fun invoke() {}
}
fun test() {
foo.<expr>Foo</expr>()
}
@@ -1,2 +0,0 @@
Resolved to:
0: (in test) object Conflict
@@ -1,2 +1,2 @@
Resolved to: Resolved to:
0: (in test.Conflict) operator fun invoke() 0: (in test) object Conflict
@@ -1,2 +0,0 @@
Resolved to:
0: (in test) object Conflict
@@ -1,2 +1,2 @@
Resolved to: Resolved to:
0: (in test) operator fun test.Conflict.invoke() 0: (in test) object Conflict
@@ -0,0 +1,9 @@
class Foo private constructor() {
companion object {
operator fun invoke() {}
}
}
fun test() {
Fo<caret>o()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in Foo) companion object
@@ -0,0 +1,11 @@
package foo
class Foo(i: Int) {
companion object {
operator fun invoke() {}
}
}
fun test() {
foo.Fo<caret>o()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in foo.Foo) companion object
@@ -0,0 +1,9 @@
class Foo private constructor() {
companion object Helper {
operator fun invoke() {}
}
}
fun test() {
Foo.He<caret>lper()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in Foo) companion object Helper
@@ -0,0 +1,9 @@
class Foo private constructor() {
companion object Helper {
operator fun invoke() {}
}
}
fun test() {
Fo<caret>o()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in Foo) companion object Helper
@@ -0,0 +1,9 @@
object Foo {
object Helper {
operator fun invoke() {}
}
}
fun test() {
Fo<caret>o.Helper()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in ROOT) object Foo
@@ -0,0 +1,9 @@
object Foo {
object Helper {
operator fun invoke() {}
}
}
fun test() {
Foo.He<caret>lper()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in Foo) object Helper
@@ -0,0 +1,11 @@
package foo.bar.baz
object Foo {
object Helper {
operator fun invoke() {}
}
}
fun test() {
foo.bar.baz.Fo<caret>o.Helper()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in foo.bar.baz) object Foo
@@ -0,0 +1,11 @@
package foo.bar.baz
object Foo {
object Helper {
operator fun invoke() {}
}
}
fun test() {
foo.bar.baz.Foo.He<caret>lper()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in foo.bar.baz.Foo) object Helper
@@ -0,0 +1,7 @@
object Foo {
operator fun invoke() {}
}
fun test() {
Fo<caret>o()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in ROOT) object Foo
@@ -0,0 +1,9 @@
package foo
object Foo {
operator fun invoke() {}
}
fun test() {
foo.Fo<caret>o()
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in foo) object Foo
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.calls.tower package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fakeElement import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
@@ -286,7 +287,10 @@ private fun BodyResolveComponents.createExplicitReceiverForInvoke(
is FirCallableSymbol<*> -> createExplicitReceiverForInvokeByCallable( is FirCallableSymbol<*> -> createExplicitReceiverForInvokeByCallable(
candidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression, symbol candidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression, symbol
) )
is FirRegularClassSymbol -> buildResolvedQualifierForClass(symbol, sourceElement = null) is FirRegularClassSymbol -> buildResolvedQualifierForClass(
symbol,
sourceElement = info.fakeSourceForImplicitInvokeCallReceiver
)
is FirTypeAliasSymbol -> { is FirTypeAliasSymbol -> {
val type = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session) val type = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
val expansionRegularClassSymbol = type.lookupTag.toSymbolOrError(session) val expansionRegularClassSymbol = type.lookupTag.toSymbolOrError(session)
@@ -321,12 +325,15 @@ private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
if (candidate.currentApplicability == CandidateApplicability.K2_PROPERTY_AS_OPERATOR) { if (candidate.currentApplicability == CandidateApplicability.K2_PROPERTY_AS_OPERATOR) {
nonFatalDiagnostics.add(ConePropertyAsOperator(candidate.symbol as FirPropertySymbol)) nonFatalDiagnostics.add(ConePropertyAsOperator(candidate.symbol as FirPropertySymbol))
} }
source = (info.callSite as? FirFunctionCall)?.calleeReference?.source?.fakeElement(KtFakeSourceElementKind.ImplicitInvokeCall) source = info.fakeSourceForImplicitInvokeCallReceiver
}.build().let { }.build().let {
transformQualifiedAccessUsingSmartcastInfo(it) transformQualifiedAccessUsingSmartcastInfo(it)
} }
} }
private val CallInfo.fakeSourceForImplicitInvokeCallReceiver: KtSourceElement?
get() = (callSite as? FirFunctionCall)?.calleeReference?.source?.fakeElement(KtFakeSourceElementKind.ImplicitInvokeCall)
private class InvokeReceiverResolveTask( private class InvokeReceiverResolveTask(
components: BodyResolveComponents, components: BodyResolveComponents,
manager: TowerResolveManager, manager: TowerResolveManager,