diff --git a/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeMapping.kt b/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeMapping.kt index 54cb3739d..d4f025c56 100644 --- a/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeMapping.kt +++ b/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeMapping.kt @@ -789,7 +789,9 @@ class KotlinTypeMapping(typeCache: JavaTypeCache, firSession: FirSession) : Java if ((functionCall.calleeReference as FirResolvedNamedReference).resolvedSymbol is FirNamedFunctionSymbol) { val resolvedSymbol = (functionCall.calleeReference as FirResolvedNamedReference).resolvedSymbol as FirNamedFunctionSymbol - if (resolvedSymbol.containingClassLookupTag() != null) { + if (resolvedSymbol.dispatchReceiverType is ConeClassLikeType) { + resolvedDeclaringType = TypeUtils.asFullyQualified(type(resolvedSymbol.dispatchReceiverType)) + } else if (resolvedSymbol.containingClassLookupTag() != null) { val lookupTag: ConeClassLikeLookupTag = resolvedSymbol.containingClassLookupTag()!! val classSymbol: FirRegularClassSymbol? = lookupTag.toFirRegularClassSymbol(firSession) if (classSymbol != null) { diff --git a/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeSignatureBuilder.kt b/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeSignatureBuilder.kt index dca07a095..54cb71634 100644 --- a/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeSignatureBuilder.kt +++ b/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeSignatureBuilder.kt @@ -604,6 +604,8 @@ class KotlinTypeSignatureBuilder(private val firSession: FirSession) : JavaTypeS var owner = "{undefined}" if (functionCall.explicitReceiver != null) { owner = signature(functionCall.explicitReceiver!!.typeRef) + } else if ((functionCall.calleeReference as FirResolvedNamedReference).resolvedSymbol is FirConstructorSymbol) { + return signature((functionCall.calleeReference as FirResolvedNamedReference).resolvedSymbol as FirConstructorSymbol) } else if (functionCall.calleeReference is FirResolvedNamedReference) { if ((functionCall.calleeReference as FirResolvedNamedReference).resolvedSymbol is FirNamedFunctionSymbol) { val resolvedSymbol = diff --git a/src/main/kotlin/org/openrewrite/kotlin/internal/KotlinParserVisitor.kt b/src/main/kotlin/org/openrewrite/kotlin/internal/KotlinParserVisitor.kt index c36b274c7..3906bbc99 100644 --- a/src/main/kotlin/org/openrewrite/kotlin/internal/KotlinParserVisitor.kt +++ b/src/main/kotlin/org/openrewrite/kotlin/internal/KotlinParserVisitor.kt @@ -577,6 +577,7 @@ class KotlinParserVisitor( val args: JContainer saveCursor = cursor val before = whitespace() + var constructorType: JavaType.Method? = null args = if (source[cursor] == '(') { if (anonymousObject.declarations.isNotEmpty() && anonymousObject.declarations[0] is FirPrimaryConstructor && @@ -586,6 +587,10 @@ class KotlinParserVisitor( cursor(saveCursor) val delegatedConstructor = (anonymousObject.declarations[0] as FirPrimaryConstructor).delegatedConstructor!! + val type = typeMapping.type((delegatedConstructor.calleeReference as FirResolvedNamedReference).resolvedSymbol) + if (type is JavaType.Method) { + constructorType = type + } mapFunctionalCallArguments(delegatedConstructor) } else { skip("(") @@ -641,7 +646,7 @@ class KotlinParserVisitor( clazz, args, body, - null + constructorType ) } @@ -1385,7 +1390,7 @@ class KotlinParserVisitor( Markers.EMPTY, emptyList(), initializer.name.asString(), - null, + typeMapping.type((propertiesPairs[0].second as FirProperty).returnTypeRef), null ), emptyList(), @@ -3776,7 +3781,7 @@ class KotlinParserVisitor( Markers.EMPTY, emptyList(), componentCall.calleeReference.name.asString(), - null, + type, null ) } else { diff --git a/src/test/java/org/openrewrite/kotlin/KotlinTypeMappingTest.java b/src/test/java/org/openrewrite/kotlin/KotlinTypeMappingTest.java index 3a5e77289..0f5405527 100644 --- a/src/test/java/org/openrewrite/kotlin/KotlinTypeMappingTest.java +++ b/src/test/java/org/openrewrite/kotlin/KotlinTypeMappingTest.java @@ -364,5 +364,67 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Atomi ) ); } + + @Test + void destructs() { + rewriteRun( + kotlin( + """ + fun foo() { + val ( a , b , c ) = Triple ( 1 , 2 , 3 ) + } + """, spec -> spec.afterRecipe(cu -> { + AtomicBoolean found = new AtomicBoolean(false); + new KotlinIsoVisitor() { + @Override + public K.DestructuringDeclaration visitDestructuringDeclaration(K.DestructuringDeclaration destructuringDeclaration, AtomicBoolean atomicBoolean) { + atomicBoolean.set(true); + return super.visitDestructuringDeclaration(destructuringDeclaration, atomicBoolean); + } + + @Override + public J.NewClass visitNewClass(J.NewClass newClass, AtomicBoolean atomicBoolean) { + if ("Triple".equals(((J.Identifier) newClass.getClazz()).getSimpleName())) { + assertThat(newClass.getClazz().getType().toString()).isEqualTo("kotlin.Triple"); + assertThat(newClass.getConstructorType().toString()).isEqualTo("kotlin.Triple{name=,return=kotlin.Triple,parameters=[Generic{A},Generic{B},Generic{C}]}"); + } + return super.visitNewClass(newClass, atomicBoolean); + } + + @Override + public J.VariableDeclarations.NamedVariable visitVariable(J.VariableDeclarations.NamedVariable variable, AtomicBoolean atomicBoolean) { + switch (variable.getSimpleName()) { + case "" -> assertThat(variable.getName().getType().toString()) + .isEqualTo("kotlin.Triple"); + case "a" -> { + assertThat(variable.getVariableType().toString()) + .isEqualTo("openRewriteFile0Kt{name=a,type=kotlin.Int}"); + assertThat(variable.getInitializer()).isInstanceOf(J.MethodInvocation.class); + assertThat(((J.MethodInvocation) variable.getInitializer()).getMethodType().toString()) + .isEqualTo("kotlin.Triple{name=component1,return=kotlin.Int,parameters=[]}"); + } + case "b" -> { + assertThat(variable.getVariableType().toString()) + .isEqualTo("openRewriteFile0Kt{name=b,type=kotlin.Int}"); + assertThat(variable.getInitializer()).isInstanceOf(J.MethodInvocation.class); + assertThat(((J.MethodInvocation) variable.getInitializer()).getMethodType().toString()) + .isEqualTo("kotlin.Triple{name=component2,return=kotlin.Int,parameters=[]}"); + } + case "c" -> { + assertThat(variable.getVariableType().toString()) + .isEqualTo("openRewriteFile0Kt{name=c,type=kotlin.Int}"); + assertThat(variable.getInitializer()).isInstanceOf(J.MethodInvocation.class); + assertThat(((J.MethodInvocation) variable.getInitializer()).getMethodType().toString()) + .isEqualTo("kotlin.Triple{name=component3,return=kotlin.Int,parameters=[]}"); + } + } + return super.visitVariable(variable, atomicBoolean); + } + }.visit(cu, found); + assertThat(found.get()).isTrue(); + }) + ) + ); + } } }