diff --git a/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/api/compilerPlugin/ir/DataClassSparkifyGenerator.kt b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/api/compilerPlugin/ir/DataClassSparkifyGenerator.kt index 7d3992dc..c27050d0 100644 --- a/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/api/compilerPlugin/ir/DataClassSparkifyGenerator.kt +++ b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/api/compilerPlugin/ir/DataClassSparkifyGenerator.kt @@ -207,18 +207,20 @@ class DataClassSparkifyGenerator( if (!declaration.isData) return super.visitClass(declaration) - // add superclass + // add superclasses val scalaProductClass = productFqNames.firstNotNullOfOrNull { val classId = ClassId.topLevel(FqName(it)) -// ClassId( -// packageFqName = FqName("scala"), -// topLevelName = Name.identifier("Product"), -// ) pluginContext.referenceClass(classId) }!! declaration.superTypes += scalaProductClass.defaultType + val serializableClass = pluginContext.referenceClass( + ClassId.topLevel(FqName("java.io.Serializable")) + )!! + + declaration.superTypes += serializableClass.defaultType + // finding the constructor params val constructorParams = declaration.primaryConstructor?.valueParameters ?: return super.visitClass(declaration) @@ -349,7 +351,7 @@ class DataClassSparkifyGenerator( } val ioobClass = pluginContext.referenceClass( - FqName("java.lang.IndexOutOfBoundsException").toClassId() + ClassId(FqName("java.lang"), Name.identifier("IndexOutOfBoundsException")) )!! val ioobConstructor = ioobClass.constructors.first { it.owner.valueParameters.isEmpty() } val throwCall = irThrow( diff --git a/compiler-plugin/src/test/resources/testData/box/dataClassInFunctionTest.fir.ir.txt b/compiler-plugin/src/test/resources/testData/box/dataClassInFunctionTest.fir.ir.txt index c8c2aa17..edde60a0 100644 --- a/compiler-plugin/src/test/resources/testData/box/dataClassInFunctionTest.fir.ir.txt +++ b/compiler-plugin/src/test/resources/testData/box/dataClassInFunctionTest.fir.ir.txt @@ -94,7 +94,7 @@ FILE fqName:foo.bar fileName:/dataClassInFunctionTest.kt VALUE_PARAMETER name:n index:0 type:kotlin.Int FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String BLOCK_BODY - CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product] + CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable] annotations: Sparkify $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.bar.box.User @@ -168,7 +168,7 @@ FILE fqName:foo.bar fileName:/dataClassInFunctionTest.kt CONST Double type=kotlin.Double value=2.0 BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product]' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:foo.bar.box.User) returnType:kotlin.String [operator] $this: VALUE_PARAMETER name: type:foo.bar.box.User BLOCK_BODY @@ -402,7 +402,7 @@ FILE fqName:foo.bar fileName:/dataClassInFunctionTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.box.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="name" p0: GET_VAR 'val user: foo.bar.box.User declared in foo.bar.box' type=foo.bar.box.User origin=null VAR name:age type:@[FlexibleNullability] kotlin.Any? [val] @@ -410,7 +410,7 @@ FILE fqName:foo.bar fileName:/dataClassInFunctionTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.box.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="age" p0: GET_VAR 'val user: foo.bar.box.User declared in foo.bar.box' type=foo.bar.box.User origin=null VAR name:a type:@[FlexibleNullability] kotlin.Any? [val] @@ -418,7 +418,7 @@ FILE fqName:foo.bar fileName:/dataClassInFunctionTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.box.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="a" p0: GET_VAR 'val user: foo.bar.box.User declared in foo.bar.box' type=foo.bar.box.User origin=null VAR name:b type:@[FlexibleNullability] kotlin.Any? [val] @@ -426,7 +426,7 @@ FILE fqName:foo.bar fileName:/dataClassInFunctionTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.box.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:local [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="b" p0: GET_VAR 'val user: foo.bar.box.User declared in foo.bar.box' type=foo.bar.box.User origin=null WHEN type=kotlin.Unit origin=IF diff --git a/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.fir.ir.txt b/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.fir.ir.txt index 7db10a08..d204965a 100644 --- a/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.fir.ir.txt +++ b/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.fir.ir.txt @@ -49,7 +49,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt overridden: public open fun toString (): kotlin.String declared in kotlin.Annotation $this: VALUE_PARAMETER name: type:kotlin.Any - CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product] + CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable] annotations: Sparkify $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.bar.User @@ -123,7 +123,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt CONST Double type=kotlin.Double value=2.0 BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.String [operator] $this: VALUE_PARAMETER name: type:foo.bar.User BLOCK_BODY @@ -402,7 +402,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="name" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null VAR name:age type:@[FlexibleNullability] kotlin.Any? [val] @@ -410,7 +410,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="age" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null VAR name:a type:@[FlexibleNullability] kotlin.Any? [val] @@ -418,7 +418,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="a" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null VAR name:b type:@[FlexibleNullability] kotlin.Any? [val] @@ -426,7 +426,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="b" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null WHEN type=kotlin.Unit origin=IF @@ -471,12 +471,18 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null then: RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in foo.bar' CONST String type=kotlin.String value="User is not a Product" + WHEN type=kotlin.Unit origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=java.io.Serializable + GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null + then: RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in foo.bar' + CONST String type=kotlin.String value="User is not Serializable" VAR name:canEqual type:@[FlexibleNullability] kotlin.Any? [val] CALL 'public open fun invoke (p0: @[FlexibleNullability] kotlin.Any?, vararg p1: @[FlexibleNullability] kotlin.Any?): @[FlexibleNullability] kotlin.Any? declared in java.lang.reflect.Method' type=@[FlexibleNullability] kotlin.Any? origin=null $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="canEqual" p1: VARARG type=@[FlexibleNullability] @[FlexibleArrayElementVariance] kotlin.Array?>? varargElementType=@[FlexibleNullability] java.lang.Class<*>? CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY @@ -499,7 +505,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="productArity" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null WHEN type=kotlin.Unit origin=IF @@ -518,7 +524,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="productElement" p1: VARARG type=@[FlexibleNullability] @[FlexibleArrayElementVariance] kotlin.Array?>? varargElementType=@[FlexibleNullability] java.lang.Class<*>? CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY @@ -545,7 +551,7 @@ FILE fqName:foo.bar fileName:/dataClassIsProductTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="productElement" p1: VARARG type=@[FlexibleNullability] @[FlexibleArrayElementVariance] kotlin.Array?>? varargElementType=@[FlexibleNullability] java.lang.Class<*>? CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY diff --git a/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.fir.txt b/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.fir.txt index d3df3864..d038809c 100644 --- a/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.fir.txt +++ b/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.fir.txt @@ -44,6 +44,12 @@ FILE: dataClassIsProductTest.kt } } + @R|kotlin/Suppress|(names = vararg(String(USELESS_IS_CHECK))) when () { + (R|/user| !is R|java/io/Serializable|) -> { + ^box String(User is not Serializable) + } + } + lval canEqual: R|kotlin/Any!| = (Q|foo/bar/User|).R|kotlin/jvm/java|.R|SubstitutionOverride|(String(canEqual), vararg((Q|kotlin/Any|).R|kotlin/jvm/java|)).R|java/lang/reflect/Method.invoke|(R|/user|, vararg(R|/user|)) when () { !=(R|/canEqual|, Boolean(true)) -> { diff --git a/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.kt b/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.kt index f62410e3..629af08f 100644 --- a/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.kt +++ b/compiler-plugin/src/test/resources/testData/box/dataClassIsProductTest.kt @@ -28,6 +28,10 @@ fun box(): String { if (user !is foo.bar.Product) return "User is not a Product" + @Suppress("USELESS_IS_CHECK") + if (user !is java.io.Serializable) + return "User is not Serializable" + val canEqual = User::class.java.getMethod("canEqual", Any::class.java).invoke(user, user) if (canEqual != true) { return "Could invoke function canEqual() from Java but was false" diff --git a/compiler-plugin/src/test/resources/testData/box/dataClassTest.fir.ir.txt b/compiler-plugin/src/test/resources/testData/box/dataClassTest.fir.ir.txt index 842274d2..b669ac1b 100644 --- a/compiler-plugin/src/test/resources/testData/box/dataClassTest.fir.ir.txt +++ b/compiler-plugin/src/test/resources/testData/box/dataClassTest.fir.ir.txt @@ -189,7 +189,7 @@ FILE fqName:foo.bar fileName:/dataClassTest.kt GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null receiver: GET_VAR ': foo.bar.NormalUser declared in foo.bar.NormalUser.toString' type=foo.bar.NormalUser origin=null CONST String type=kotlin.String value=")" - CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product] + CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable] annotations: Sparkify $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.bar.User @@ -263,7 +263,7 @@ FILE fqName:foo.bar fileName:/dataClassTest.kt CONST Double type=kotlin.Double value=2.0 BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.String [operator] $this: VALUE_PARAMETER name: type:foo.bar.User BLOCK_BODY @@ -542,7 +542,7 @@ FILE fqName:foo.bar fileName:/dataClassTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="name" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null VAR name:age type:@[FlexibleNullability] kotlin.Any? [val] @@ -550,7 +550,7 @@ FILE fqName:foo.bar fileName:/dataClassTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="age" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null VAR name:a type:@[FlexibleNullability] kotlin.Any? [val] @@ -558,7 +558,7 @@ FILE fqName:foo.bar fileName:/dataClassTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="a" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null VAR name:b type:@[FlexibleNullability] kotlin.Any? [val] @@ -566,7 +566,7 @@ FILE fqName:foo.bar fileName:/dataClassTest.kt $this: CALL 'public open fun getMethod (p0: @[FlexibleNullability] kotlin.String?, vararg p1: @[FlexibleNullability] java.lang.Class<*>?): @[FlexibleNullability] java.lang.reflect.Method? declared in java.lang.Class' type=@[FlexibleNullability] java.lang.reflect.Method? origin=null $this: CALL 'public final fun (): java.lang.Class> declared in kotlin.jvm' type=java.lang.Class origin=GET_PROPERTY : foo.bar.User - $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product]' type=kotlin.reflect.KClass + $receiver: CLASS_REFERENCE 'CLASS CLASS name:User modality:FINAL visibility:public [data] superTypes:[kotlin.Any; foo.bar.Product; java.io.Serializable]' type=kotlin.reflect.KClass p0: CONST String type=kotlin.String value="b" p0: GET_VAR 'val user: foo.bar.User declared in foo.bar.box' type=foo.bar.User origin=null WHEN type=kotlin.Unit origin=IF diff --git a/gradle/bootstraps/compiler-plugin.jar b/gradle/bootstraps/compiler-plugin.jar index 84d321b1..2ea26a00 100644 Binary files a/gradle/bootstraps/compiler-plugin.jar and b/gradle/bootstraps/compiler-plugin.jar differ diff --git a/kotlin-spark-api/src/main/kotlin/org/jetbrains/kotlinx/spark/api/Encoding.kt b/kotlin-spark-api/src/main/kotlin/org/jetbrains/kotlinx/spark/api/Encoding.kt index ec174c96..09db5076 100644 --- a/kotlin-spark-api/src/main/kotlin/org/jetbrains/kotlinx/spark/api/Encoding.kt +++ b/kotlin-spark-api/src/main/kotlin/org/jetbrains/kotlinx/spark/api/Encoding.kt @@ -230,13 +230,14 @@ object KotlinTypeInference : Serializable { // can't be checked if injected by Sparkify val isProduct = this.isSubclassOf(scala.Product::class) + val isSerializable = this.isSubclassOf(Serializable::class) when { // happy path isAnnotated && mismatchedNames.isEmpty() -> return // not annotated but still happy as spark will like it - !isAnnotated && mismatchedNames.isEmpty() && isProduct -> return + !isAnnotated && mismatchedNames.isEmpty() && isProduct && isSerializable -> return } val warningMessage = buildString { @@ -264,6 +265,9 @@ object KotlinTypeInference : Serializable { if (!isProduct) { appendLine(" - It is not a scala.Product, which is fine for most cases, but can break compatibility with UDFs. You can let your data class implement scala.Product to fix this or let @Sparkify handle it for you.") } + if (!isSerializable) { + appendLine(" - It is not Serializable, which is fine for most cases, but can break compatibility. You can let your data class implement java.io.Serializable to fix this or let @Sparkify handle it for you.") + } } println(warningMessage) diff --git a/kotlin-spark-api/src/test/kotlin/org/jetbrains/kotlinx/spark/api/CompilerPluginTest.kt b/kotlin-spark-api/src/test/kotlin/org/jetbrains/kotlinx/spark/api/CompilerPluginTest.kt new file mode 100644 index 00000000..c9f684a7 --- /dev/null +++ b/kotlin-spark-api/src/test/kotlin/org/jetbrains/kotlinx/spark/api/CompilerPluginTest.kt @@ -0,0 +1,47 @@ +package org.jetbrains.kotlinx.spark.api + +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.kotest.assertions.throwables.shouldThrowAny +import io.kotest.core.spec.style.ShouldSpec +import io.kotest.matchers.should +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.beInstanceOf +import org.jetbrains.kotlinx.spark.api.plugin.annotations.ColumnName +import org.jetbrains.kotlinx.spark.api.plugin.annotations.Sparkify + +class CompilerPluginTest : ShouldSpec({ + + @Sparkify + data class User( + val name: String = "John Doe", + val age: Int = 25, + @ColumnName("test") + val isEmpty: Boolean = false, + ) + + context("Compiler Plugin") { + should("be enabled") { + val user = User() + shouldNotThrowAny { + User::class.java.getMethod("name").invoke(user) shouldBe user.name + User::class.java.getMethod("age").invoke(user) shouldBe user.age + User::class.java.getMethod("test").invoke(user) shouldBe user.isEmpty + } + + user should beInstanceOf() + user should beInstanceOf() + user should beInstanceOf() + + shouldNotThrowAny { + User::class.java.getMethod("canEqual", Any::class.java).invoke(user, user) shouldBe true + User::class.java.getMethod("productArity").invoke(user) shouldBe 3 + User::class.java.getMethod("productElement", Int::class.java).invoke(user, 0) shouldBe user.name + User::class.java.getMethod("productElement", Int::class.java).invoke(user, 1) shouldBe user.age + User::class.java.getMethod("productElement", Int::class.java).invoke(user, 2) shouldBe user.isEmpty + } + shouldThrowAny { + User::class.java.getMethod("productElement", Int::class.java).invoke(user, 10) + } + } + } +}) \ No newline at end of file