From 12732f0b59c11d15decf1758fb64fafde11d578b Mon Sep 17 00:00:00 2001 From: traceyyoshima Date: Fri, 6 Oct 2023 11:33:31 -0600 Subject: [PATCH] Fixed type mapping for getters on properties. --- .../org/openrewrite/kotlin/KotlinTypeGoat.kt | 6 ++++- .../openrewrite/kotlin/KotlinTypeMapping.kt | 2 +- .../kotlin/KotlinTypeSignatureBuilder.kt | 11 +++++--- .../KotlinTypeSignatureBuilderTest.java | 25 +++++++++++++++++-- src/test/resources/KotlinTypeGoat.kt | 6 ++++- 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/openrewrite/kotlin/KotlinTypeGoat.kt b/src/main/java/org/openrewrite/kotlin/KotlinTypeGoat.kt index d6e8bf2e3..c14953365 100644 --- a/src/main/java/org/openrewrite/kotlin/KotlinTypeGoat.kt +++ b/src/main/java/org/openrewrite/kotlin/KotlinTypeGoat.kt @@ -15,11 +15,12 @@ */ @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "unused") -// Whenever this class is changed, make a corresponding change in JavaTypeGoat in the main resources folder. +// Whenever this class is changed, make a corresponding change in KotlinTypeGoat in the main resources folder. package org.openrewrite.kotlin import java.lang.Object +// TODO: FIX ME. Files needs to declare fields and methods to assert type mapping. @AnnotationWithRuntimeRetention @AnnotationWithSourceRetention abstract class KotlinTypeGoat { @@ -28,6 +29,9 @@ abstract class KotlinTypeGoat { val field: Int = 10 + val gettableField: Int + get() = 10 + // abstract class InheritedKotlinTypeGoat : KotlinTypeGoat() where U : PT, U : C enum class EnumTypeA { diff --git a/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeMapping.kt b/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeMapping.kt index bd4811017..dcd693504 100644 --- a/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeMapping.kt +++ b/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeMapping.kt @@ -500,7 +500,7 @@ class KotlinTypeMapping(typeCache: JavaTypeCache, firSession: FirSession) : Java ): JavaType.Method? { val methodSymbol = function?.symbol if (methodSymbol != null) { - val signature = signatureBuilder.methodDeclarationSignature(function.symbol) + val signature = signatureBuilder.methodDeclarationSignature(function.symbol, ownerFallBack) val existing = typeCache.get(signature) if (existing != null) { return existing diff --git a/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeSignatureBuilder.kt b/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeSignatureBuilder.kt index 24ae4844d..1203c9169 100644 --- a/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeSignatureBuilder.kt +++ b/src/main/kotlin/org/openrewrite/kotlin/KotlinTypeSignatureBuilder.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaField import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod import org.jetbrains.kotlin.fir.java.declarations.FirJavaValueParameter import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag @@ -68,7 +69,7 @@ class KotlinTypeSignatureBuilder(private val firSession: FirSession) : JavaTypeS } is FirFunction -> { - return methodDeclarationSignature(type.symbol) + return methodDeclarationSignature(type.symbol, ownerSymbol) } is FirVariable -> { @@ -640,7 +641,8 @@ class KotlinTypeSignatureBuilder(private val firSession: FirSession) : JavaTypeS * Generate the method declaration signature. */ @OptIn(SymbolInternals::class) - fun methodDeclarationSignature(symbol: FirFunctionSymbol): String { + fun methodDeclarationSignature(symbol: FirFunctionSymbol, + ownerSymbol: @Nullable FirBasedSymbol<*>?): String { var s: String = when { symbol is FirConstructorSymbol -> { @@ -650,7 +652,10 @@ class KotlinTypeSignatureBuilder(private val firSession: FirSession) : JavaTypeS classSignature(symbol.dispatchReceiverType!!) } symbol.getOwnerLookupTag() != null && symbol.getOwnerLookupTag()!!.toFirRegularClassSymbol(firSession) != null -> { - classSignature(symbol.getOwnerLookupTag()!!.toFirRegularClassSymbol(firSession)!!) + classSignature(symbol.getOwnerLookupTag()!!.toFirRegularClass(firSession)!!) + } + ownerSymbol != null -> { + signature(ownerSymbol.fir) } else -> { "{undefined}" diff --git a/src/test/java/org/openrewrite/kotlin/KotlinTypeSignatureBuilderTest.java b/src/test/java/org/openrewrite/kotlin/KotlinTypeSignatureBuilderTest.java index 57c591873..c3091b4aa 100644 --- a/src/test/java/org/openrewrite/kotlin/KotlinTypeSignatureBuilderTest.java +++ b/src/test/java/org/openrewrite/kotlin/KotlinTypeSignatureBuilderTest.java @@ -68,7 +68,7 @@ public String constructorSignature() { .map(FirFunction.class::cast) .findFirst() .orElseThrow() - .getSymbol()); + .getSymbol(), null); } public Object innerClassSignature(String innerClassSimpleName) { @@ -95,6 +95,21 @@ public String fieldSignature(String field) { .getSymbol(), null); } + public String fieldPropertyGetterSignature(String field) { + FirProperty getter = getCompiledSource().getDeclarations().stream() + .map(FirRegularClass.class::cast) + .flatMap(it -> it.getDeclarations().stream()) + .filter(FirProperty.class::isInstance) + .map(FirProperty.class::cast) + .filter(it -> field.equals(it.getName().asString())) + .findFirst() + .orElseThrow(); + if (getter.getGetter() == null) { + throw new UnsupportedOperationException("No getter for " + field); + } + return signatureBuilder().methodDeclarationSignature(getter.getGetter().getSymbol(), getCompiledSource().getSymbol()); + } + public Object firstMethodParameterSignature(String methodName) { return signatureBuilder().signature(getCompiledSource().getDeclarations().stream() .map(FirRegularClass.class::cast) @@ -127,7 +142,7 @@ public String methodSignature(String methodName) { .filter(it -> methodName.equals(it.getName().asString())) .findFirst() .orElseThrow() - .getSymbol()); + .getSymbol(), null); } @Test @@ -148,6 +163,12 @@ void fieldType() { .isEqualTo("org.openrewrite.kotlin.KotlinTypeGoat{name=field,type=kotlin.Int}"); } + @Test + void gettableField() { + assertThat(fieldPropertyGetterSignature("gettableField")) + .isEqualTo("org.openrewrite.kotlin.KotlinTypeGoat{name=accessor,return=kotlin.Int,parameters=[]}"); + } + @Test void classSignature() { assertThat(firstMethodParameterSignature("clazz")) diff --git a/src/test/resources/KotlinTypeGoat.kt b/src/test/resources/KotlinTypeGoat.kt index 231033c4e..6ff52ce55 100644 --- a/src/test/resources/KotlinTypeGoat.kt +++ b/src/test/resources/KotlinTypeGoat.kt @@ -15,11 +15,12 @@ */ @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "unused") -// Whenever this class is changed, make a corresponding change in JavaTypeGoat in the main java source set. +// Whenever this class is changed, make a corresponding change in KotlinTypeGoat in the main java source set. package org.openrewrite.kotlin import java.lang.Object +// TODO: FIX ME. Files needs to declare fields and methods to assert type mapping. @AnnotationWithRuntimeRetention @AnnotationWithSourceRetention abstract class KotlinTypeGoat { @@ -28,6 +29,9 @@ abstract class KotlinTypeGoat { val field: Int = 10 + val gettableField: Int + get() = 10 + // abstract class InheritedKotlinTypeGoat : KotlinTypeGoat() where U : PT, U : C enum class EnumTypeA {