Skip to content

Add support for Kotlin 2.x #5575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9551214
upgrade Kotlin to 2.1.20
barbulescu Apr 26, 2025
1f9ef66
remove generics from IrConst usage
barbulescu Apr 26, 2025
d6b3304
fix type.toRegularClassSymbol(firSession)
barbulescu Apr 26, 2025
19dc8ca
Merge remote-tracking branch 'origin/main'
barbulescu May 3, 2025
0dcb845
Merge remote-tracking branch 'origin/main'
barbulescu May 6, 2025
5f76403
Merge remote-tracking branch 'origin/main'
barbulescu May 7, 2025
410df13
Merge remote-tracking branch 'origin/main'
barbulescu May 7, 2025
0f2cdde
Merge remote-tracking branch 'origin/main'
barbulescu May 8, 2025
ddd2490
Merge remote-tracking branch 'origin/main'
barbulescu May 9, 2025
a9fef48
Merge remote-tracking branch 'origin/main'
barbulescu May 10, 2025
378374d
Replaced outdated Kotlin FIR API calls and updated type references to…
barbulescu May 10, 2025
5fdab96
Merge remote-tracking branch 'origin/main'
barbulescu May 12, 2025
b2895a0
Merge remote-tracking branch 'origin/main'
barbulescu May 13, 2025
f007f53
Merge remote-tracking branch 'origin/main'
barbulescu May 25, 2025
6e1c66b
Merge remote-tracking branch 'origin/main'
barbulescu May 31, 2025
e83131d
Merge remote-tracking branch 'origin/main'
barbulescu Jun 1, 2025
b0226fe
Updated KotlinParser to utilize the latest Kotlin FIR APIs, added sup…
barbulescu Jun 1, 2025
c01788d
Merge branch 'openrewrite:main' into main
barbulescu Jun 6, 2025
4ca96f0
Merge branch 'openrewrite:main' into main
barbulescu Jun 7, 2025
21048af
Refactor: Simplify module building in KotlinParser and enhance type s…
barbulescu Jun 7, 2025
655feb0
Merge remote-tracking branch 'origin/main'
barbulescu Jun 7, 2025
d7fa49a
Merge branch 'openrewrite:main' into main
barbulescu Jun 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions rewrite-kotlin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
id("org.openrewrite.build.language-library")
kotlin("jvm") version "1.9.25"
kotlin("jvm") version "2.1.20"
}

val kotlinVersion = "1.9.25"
val kotlinVersion = "2.1.21"

dependencies {
compileOnly(project(":rewrite-core"))
Expand Down
302 changes: 184 additions & 118 deletions rewrite-kotlin/src/main/java/org/openrewrite/kotlin/KotlinParser.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import lombok.AllArgsConstructor;
import lombok.Data;
import org.jetbrains.kotlin.KtFakeSourceElement;
import org.jetbrains.kotlin.KtFakePsiSourceElement;
import org.jetbrains.kotlin.KtRealPsiSourceElement;
import org.jetbrains.kotlin.KtSourceElement;
import org.jetbrains.kotlin.com.intellij.openapi.util.TextRange;
Expand All @@ -29,7 +29,6 @@
import org.jetbrains.kotlin.fir.declarations.FirProperty;
import org.jetbrains.kotlin.fir.expressions.*;
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference;
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag;
import org.jetbrains.kotlin.fir.types.*;
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor;
import org.jetbrains.kotlin.ir.IrElement;
Expand Down Expand Up @@ -486,7 +485,7 @@ public static String printFirElement(FirElement firElement) {

if (source instanceof KtRealPsiSourceElement) {
sb.append("Real ");
} else if (source instanceof KtFakeSourceElement) {
} else if (source instanceof KtFakePsiSourceElement) {
sb.append("Fake ");
} else {
sb.append(source.getClass().getSimpleName());
Expand Down Expand Up @@ -545,7 +544,7 @@ private static String printConeKotlinType(ConeTypeProjection coneKotlinType) {
return ((FirProperty) firElement).getName().toString();
} else if (firElement instanceof FirResolvedTypeRef) {
FirResolvedTypeRef resolvedTypeRef = (FirResolvedTypeRef) firElement;
ConeKotlinType coneKotlinType = resolvedTypeRef.getType();
ConeKotlinType coneKotlinType = resolvedTypeRef.getConeType();
return printConeKotlinType(coneKotlinType);
} else if (firElement instanceof FirResolvedNamedReference) {
return ((FirResolvedNamedReference) firElement).getName().toString();
Expand Down Expand Up @@ -575,8 +574,8 @@ private static String printConeKotlinType(ConeTypeProjection coneKotlinType) {
}
return sb.toString();
}
} else if (firElement instanceof FirConstExpression) {
Object value = ((FirConstExpression<?>) firElement).getValue();
} else if (firElement instanceof FirLiteralExpression) {
Object value = ((FirLiteralExpression) firElement).getValue();
return value != null ? value.toString() : null;
// return ((FirConstExpression<?>) firElement).getKind().toString();
} else if (firElement instanceof FirWhenBranch) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class KotlinIrTypeMapping(private val typeCache: JavaTypeCache) : JavaTypeMappin
return type(baseType.type)
}

is IrConst<*> -> {
is IrConst -> {
return primitive(baseType)
}

Expand Down Expand Up @@ -536,7 +536,7 @@ class KotlinIrTypeMapping(private val typeCache: JavaTypeCache) : JavaTypeMappin

fun primitive(type: Any?): JavaType.Primitive {
return when (type) {
is IrConst<*> -> {
is IrConst -> {
when (type.kind) {
IrConstKind.Int -> JavaType.Primitive.Int
IrConstKind.Boolean -> JavaType.Primitive.Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class KotlinTypeIrSignatureBuilder : JavaTypeSignatureBuilder {
return signature(baseType.type)
}

is IrConst<*> -> {
is IrConst -> {
return primitiveSignature(baseType)
}

Expand Down Expand Up @@ -265,7 +265,7 @@ class KotlinTypeIrSignatureBuilder : JavaTypeSignatureBuilder {

override fun primitiveSignature(type: Any): String {
return when (type) {
is IrConst<*> -> type.type.classFqName!!.asString()
is IrConst -> type.type.classFqName!!.asString()
else -> {
throw UnsupportedOperationException("Unsupported primitive type" + type.javaClass)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
import org.jetbrains.kotlin.fir.resolve.providers.toSymbol
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.resolve.toRegularClassSymbol
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.*
Expand Down Expand Up @@ -75,7 +74,7 @@ class KotlinTypeMapping(
private val signatureBuilder: KotlinTypeSignatureBuilder = KotlinTypeSignatureBuilder(firSession, firFile)

override fun type(type: Any?): JavaType {
if (type == null || type is FirErrorTypeRef || type is FirExpression && type.typeRef is FirErrorTypeRef || type is FirResolvedQualifier && type.classId == null) {
if (type == null || type is FirErrorTypeRef || type is FirExpression && type.resolvedType is FirErrorTypeRef || type is FirResolvedQualifier && type.classId == null) {
return Unknown.getInstance()
}

Expand All @@ -89,7 +88,7 @@ class KotlinTypeMapping(
}

fun type(type: Any?, parent: Any?): JavaType? {
if (type == null || type is FirErrorTypeRef || type is FirExpression && type.typeRef is FirErrorTypeRef || type is FirResolvedQualifier && type.classId == null) {
if (type == null || type is FirErrorTypeRef || type is FirExpression && type.resolvedType is FirErrorTypeRef || type is FirResolvedQualifier && type.classId == null) {
return Unknown.getInstance()
}
val signature = signatureBuilder.signature(type, parent)
Expand Down Expand Up @@ -201,11 +200,11 @@ class KotlinTypeMapping(
}

is FirVariableAssignment -> {
type(type.lValue.typeRef, parent, signature)
type(type.lValue.resolvedType, parent, signature)
}

is FirExpression -> {
type(type.typeRef, parent, signature)
type(type.resolvedType, parent, signature)
}

is JavaElement -> {
Expand Down Expand Up @@ -312,7 +311,7 @@ class KotlinTypeMapping(
val firClass = when (type) {
is FirClass -> type
is FirResolvedQualifier -> {
val ref = type.typeRef.toRegularClassSymbol(firSession)
val ref = type.resolvedType.toRegularClassSymbol(firSession)
if (type.typeArguments.isNotEmpty()) {
params = type.typeArguments
}
Expand All @@ -326,7 +325,7 @@ class KotlinTypeMapping(
is ConeClassLikeType -> {
if (type.toSymbol(firSession) is FirTypeAliasSymbol) {
return classType(
(type.toSymbol(firSession) as FirTypeAliasSymbol).resolvedExpandedTypeRef.type,
(type.toSymbol(firSession) as FirTypeAliasSymbol).resolvedExpandedTypeRef.coneType,
parent,
signature
)
Expand Down Expand Up @@ -499,7 +498,7 @@ class KotlinTypeMapping(

@OptIn(SymbolInternals::class)
fun methodDeclarationType(enumEntry: FirEnumEntry): Method? {
val type = when (val fir = enumEntry.symbol.getContainingClassSymbol(firSession)?.fir) {
val type = when (val fir = enumEntry.symbol.getContainingClassSymbol()?.fir) {
is FirClass -> {
when (val primary = fir.declarations.firstOrNull { it is FirPrimaryConstructor }) {
is FirPrimaryConstructor -> type(primary as FirFunction)
Expand Down Expand Up @@ -549,8 +548,8 @@ class KotlinTypeMapping(
var parentType = when {
function.symbol is FirConstructorSymbol -> type(function.returnTypeRef)
function.dispatchReceiverType != null -> type(function.dispatchReceiverType!!)
function.symbol.getOwnerLookupTag()?.toFirRegularClass(firSession) != null -> {
type(function.symbol.getOwnerLookupTag()!!.toFirRegularClass(firSession)!!)
function.symbol.getOwnerLookupTag()?.toRegularClassSymbol(firSession) != null -> {
type(function.symbol.getOwnerLookupTag()!!.toRegularClassSymbol(firSession)!!)
}

parent is FirRegularClass || parent != null -> type(parent)
Expand Down Expand Up @@ -672,7 +671,8 @@ class KotlinTypeMapping(
}

fun methodInvocationType(fir: FirFunctionCall): Method? {
if (fir.typeRef is FirErrorTypeRef) {
//TODO is this correct?
if (!fir.isResolved) {
return null
}
val signature = signatureBuilder.methodCallSignature(fir)
Expand Down Expand Up @@ -742,11 +742,11 @@ class KotlinTypeMapping(
if (resolvedSymbol.dispatchReceiverType is ConeClassLikeType) {
declaringType = TypeUtils.asFullyQualified(type(resolvedSymbol.dispatchReceiverType))
} else if (resolvedSymbol.containingClassLookupTag() != null &&
resolvedSymbol.containingClassLookupTag()!!.toFirRegularClass(firSession) != null
resolvedSymbol.containingClassLookupTag()!!.toRegularClassSymbol(firSession) != null
) {
declaringType = TypeUtils.asFullyQualified(
type(
resolvedSymbol.containingClassLookupTag()!!.toFirRegularClass(firSession)
resolvedSymbol.containingClassLookupTag()!!.toRegularClassSymbol(firSession)
)
)
} else if (resolvedSymbol.origin == FirDeclarationOrigin.Library) {
Expand All @@ -766,19 +766,19 @@ class KotlinTypeMapping(
declaringType = createShallowClass("kotlin.Library")
}
} else if (resolvedSymbol.origin == FirDeclarationOrigin.SamConstructor) {
declaringType = when(val type = type(function.typeRef)) {
declaringType = when(val type = type(function.resolvedType)) {
is Class -> type
is Parameterized -> type.type
else -> Unknown.getInstance()
}
}
} else {
declaringType = TypeUtils.asFullyQualified(type(function.typeRef))
declaringType = TypeUtils.asFullyQualified(type(function.resolvedType))
}
if (declaringType == null) {
declaringType = TypeUtils.asFullyQualified(type(firFile))
}
val returnType = type(function.typeRef)
val returnType = type(function.resolvedType)

if (function.toResolvedCallableSymbol()?.receiverParameter != null) {
paramTypes!!.add(type(function.toResolvedCallableSymbol()?.receiverParameter!!.typeRef))
Expand All @@ -805,12 +805,12 @@ class KotlinTypeMapping(
if (t is GenericTypeVariable) {
if (mapNames && args != null) {
if (args.containsKey(p.name.asString())) {
paramTypes.add(type(args[p.name.asString()]!!.typeRef, function)!!)
paramTypes.add(type(args[p.name.asString()]!!.resolvedType, function)!!)
} else {
paramTypes.add(t)
}
} else if (index < valueParams.size) {
paramTypes.add(type(function.arguments[index].typeRef, function)!!)
paramTypes.add(type(function.arguments[index].resolvedType, function)!!)
}
} else {
paramTypes.add(t)
Expand Down Expand Up @@ -896,9 +896,9 @@ class KotlinTypeMapping(
declaringType = type(variable.symbol.dispatchReceiverType)
}

variable.symbol.getContainingClassSymbol(firSession) != null -> {
if (variable.symbol.getContainingClassSymbol(firSession) !is FirAnonymousObjectSymbol) {
declaringType = type(variable.symbol.getContainingClassSymbol(firSession)!!.fir)
variable.symbol.getContainingClassSymbol() != null -> {
if (variable.symbol.getContainingClassSymbol() !is FirAnonymousObjectSymbol) {
declaringType = type(variable.symbol.getContainingClassSymbol()!!.fir)
}
}

Expand Down Expand Up @@ -1233,7 +1233,7 @@ class KotlinTypeMapping(
private fun listAnnotations(firAnnotations: List<FirAnnotation>): MutableList<FullyQualified>? {
var annotations: MutableList<FullyQualified>? = null
for (firAnnotation in firAnnotations) {
val fir = firAnnotation.typeRef.toRegularClassSymbol(firSession)?.fir
val fir = firAnnotation.resolvedType.toRegularClassSymbol(firSession)?.fir
if (fir != null && isNotSourceRetention(fir.annotations)) {
if (annotations == null) {
annotations = ArrayList()
Expand Down Expand Up @@ -1267,9 +1267,10 @@ class KotlinTypeMapping(

private fun isNotSourceRetention(annotations: List<FirAnnotation>): Boolean {
for (ann in annotations) {
if ("kotlin.annotation.Retention" == convertClassIdToFqn(ann.typeRef.coneType.classId)) {
if ("kotlin.annotation.Retention" == convertClassIdToFqn(ann.resolvedType.classId)) {
for (v in ann.argumentMapping.mapping.values) {
if (v.calleeReference is FirResolvedNamedReference && (v.calleeReference as FirResolvedNamedReference).name.asString() == "SOURCE") {
val reference = v.toReference(firSession)
if (reference is FirResolvedNamedReference && reference.name.asString() == "SOURCE") {
return false
}
}
Expand Down Expand Up @@ -1345,7 +1346,7 @@ class KotlinTypeMapping(

fun primitive(type: FirElement): Primitive {
return when (type) {
is FirConstExpression<*> -> {
is FirLiteralExpression -> {
when (type.kind) {
ConstantValueKind.Boolean -> Primitive.Boolean
ConstantValueKind.Byte, ConstantValueKind.UnsignedByte -> Primitive.Byte
Expand Down
Loading
Loading