diff --git a/build.gradle.kts b/build.gradle.kts index 2d3e76bc..9b8a6d91 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,10 @@ @file:Suppress("UnstableApiUsage") +import Projects.compilerPlugin +import Projects.gradlePlugin +import com.github.gmazzo.buildconfig.BuildConfigExtension + + buildscript { repositories { mavenCentral() @@ -15,6 +20,7 @@ plugins { dokka version Versions.dokka idea kotlin version Versions.kotlin apply false + buildconfig version Versions.buildconfig apply false } group = Versions.groupID @@ -113,4 +119,36 @@ allprojects { } } } +} + +subprojects { + afterEvaluate { + extensions.findByType()?.apply { + val projectVersion = Versions.project + val groupId = Versions.groupID + + val compilerPluginId = "$groupId.compilerPlugin" + + val compilerPluginArtifactId = compilerPlugin.name + val gradlePluginArtifactId = gradlePlugin.name + + val defaultSparkifyFqName = "$groupId.plugin.annotations.Sparkify" + val defaultColumnNameFqName = "$groupId.plugin.annotations.ColumnName" + + val projectRoot = project.rootDir.absolutePath + + packageName(groupId) + className("Artifacts") + + buildConfigField("compilerPluginId", compilerPluginId) + buildConfigField("groupId", groupId) + buildConfigField("gradlePluginArtifactId", gradlePluginArtifactId) + buildConfigField("projectVersion", projectVersion) + buildConfigField("compilerPluginArtifactId", compilerPluginArtifactId) + + buildConfigField("defaultSparkifyFqName", defaultSparkifyFqName) + buildConfigField("defaultColumnNameFqName", defaultColumnNameFqName) + buildConfigField("projectRoot", projectRoot) + } + } } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 225dff11..95168433 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -9,7 +9,16 @@ object Dependencies { inline val hadoopClient get() = "org.apache.hadoop:hadoop-client:${Versions.hadoop}" inline val sparkRepl get() = "org.apache.spark:spark-repl_${Versions.scalaCompat}:${Versions.spark}" inline val jupyter get() = "org.jetbrains.kotlinx:kotlin-jupyter-api:${Versions.jupyter}" - inline val junit get() = "org.junit.jupiter:junit-jupiter-engine:5.8.1" + inline val junitJupiterEngine get() = "org.junit.jupiter:junit-jupiter-engine:${Versions.junitJupiterEngine}" + // must be platform() + inline val junitBom get() = "org.junit:junit-bom:${Versions.junitJupiterEngine}" + inline val junitJupiter get() = "org.junit.jupiter:junit-jupiter" + inline val junitPlatformCommons get() = "org.junit.platform:junit-platform-commons" + inline val junitPlatformLauncher get() = "org.junit.platform:junit-platform-launcher" + inline val junitPlatformRunner get() = "org.junit.platform:junit-platform-runner" + inline val junitPlatformSuiteApi get() = "org.junit.platform:junit-platform-suite-api" + + inline val junit get() = "junit:junit:${Versions.junit}" inline val sparkStreamingKafka get() = "org.apache.spark:spark-streaming-kafka-0-10_${Versions.scalaCompat}:${Versions.spark}" inline val kotest get() = "io.kotest:kotest-runner-junit5:${Versions.kotest}" inline val kotestTestcontainers get() = "io.kotest.extensions:kotest-extensions-testcontainers:${Versions.kotestTestContainers}" @@ -22,6 +31,10 @@ object Dependencies { inline val kotlinScriptingJvm get() = "org.jetbrains.kotlin:kotlin-scripting-jvm" inline val jacksonDatabind get() = "com.fasterxml.jackson.core:jackson-databind:${Versions.jacksonDatabind}" inline val kotlinDateTime get() = "org.jetbrains.kotlinx:kotlinx-datetime:${Versions.kotlinxDateTime}" + inline val kotlinCompiler get() = "org.jetbrains.kotlin:kotlin-compiler:${Versions.kotlin}" + inline val kotlinScriptRuntime get() = "org.jetbrains.kotlin:kotlin-script-runtime:${Versions.kotlin}" + inline val kotlinAnnotationsJvm get() = "org.jetbrains.kotlin:kotlin-annotations-jvm:${Versions.kotlin}" + inline val kotlinCompilerInternalTestFramework get() = "org.jetbrains.kotlin:kotlin-compiler-internal-test-framework:${Versions.kotlin}" } diff --git a/buildSrc/src/main/kotlin/Helpers.kt b/buildSrc/src/main/kotlin/Helpers.kt index e62a8dae..0f0f3c40 100644 --- a/buildSrc/src/main/kotlin/Helpers.kt +++ b/buildSrc/src/main/kotlin/Helpers.kt @@ -18,6 +18,11 @@ fun DependencyHandler.testImplementation(vararg dependencyNotations: Any): List< add("testImplementation", it) } +fun DependencyHandler.testRuntimeOnly(vararg dependencyNotations: Any): List = + dependencyNotations.map { + add("testRuntimeOnly", it) + } + fun DependencyHandler.implementation(vararg dependencyNotations: Any): List = dependencyNotations.map { add("implementation", it) diff --git a/buildSrc/src/main/kotlin/Plugins.kt b/buildSrc/src/main/kotlin/Plugins.kt index 354727db..3b5f66af 100644 --- a/buildSrc/src/main/kotlin/Plugins.kt +++ b/buildSrc/src/main/kotlin/Plugins.kt @@ -33,3 +33,6 @@ inline val Project.mavenPublishBase inline val PluginDependenciesSpec.jupyter get() = kotlin("jupyter.api") version Versions.jupyter +inline val PluginDependenciesSpec.buildconfig + get() = id("com.github.gmazzo.buildconfig") + diff --git a/buildSrc/src/main/kotlin/Projects.kt b/buildSrc/src/main/kotlin/Projects.kt index a84f4d80..16c03483 100644 --- a/buildSrc/src/main/kotlin/Projects.kt +++ b/buildSrc/src/main/kotlin/Projects.kt @@ -26,4 +26,10 @@ object Projects { inline val Project.scalaTuplesInKotlin get() = searchProject("scala-tuples-in-kotlin") + + inline val Project.compilerPlugin + get() = searchProject("compiler-plugin") + + inline val Project.gradlePlugin + get() = searchProject("gradle-plugin") } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index efb7563a..c8b09d24 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -1,21 +1,24 @@ object Versions { const val project = "1.2.5-SNAPSHOT" const val groupID = "org.jetbrains.kotlinx.spark" - const val kotlin = "1.9.22" + const val kotlin = "2.0.0-Beta5" const val jvmTarget = "8" const val jupyterJvmTarget = "8" inline val spark get() = System.getProperty("spark") as String - inline val scala get() = System.getProperty("scala") as String inline val sparkMinor get() = spark.substringBeforeLast('.') - inline val scalaCompat get() = scala.substringBeforeLast('.') + inline val scalaCompat get() = scala.substringBeforeLast('.') // TODO inline val sparkConnect get() = System.getProperty("sparkConnect", "false").toBoolean() - const val jupyter = "0.12.0-32-1" const val kotest = "5.5.4" + + const val buildconfig = "5.3.5" + + const val junitJupiterEngine = "5.8.1" + const val junit = "4.13.2" const val kotestTestContainers = "1.3.3" const val dokka = "1.8.20" const val jcp = "7.0.5" diff --git a/compiler-plugin/build.gradle.kts b/compiler-plugin/build.gradle.kts new file mode 100644 index 00000000..2644c065 --- /dev/null +++ b/compiler-plugin/build.gradle.kts @@ -0,0 +1,92 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + java + kotlin + mavenPublishBase + buildconfig +} + +group = Versions.groupID +version = Versions.project + +repositories { + mavenCentral() + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") +} + +sourceSets { + test { + val srcDirs = listOf("src/test-gen/kotlin") + kotlin.srcDirs(srcDirs) + java.srcDirs(srcDirs) + } +} + +dependencies { + with(Dependencies) { + compileOnly(kotlinCompiler) + + testRuntimeOnly( + kotlinTest, + kotlinScriptRuntime, + kotlinAnnotationsJvm, + ) + + testImplementation( + kotlinCompiler, + reflect, + kotlinCompilerInternalTestFramework, + junit, + + platform(junitBom), + junitJupiter, + junitPlatformCommons, + junitPlatformLauncher, + junitPlatformRunner, + junitPlatformSuiteApi, + ) + } +} + +tasks.test { + useJUnitPlatform() + doFirst { + setLibraryProperty("org.jetbrains.kotlin.test.kotlin-stdlib", "kotlin-stdlib") + setLibraryProperty("org.jetbrains.kotlin.test.kotlin-stdlib-jdk8", "kotlin-stdlib-jdk8") + setLibraryProperty("org.jetbrains.kotlin.test.kotlin-reflect", "kotlin-reflect") + setLibraryProperty("org.jetbrains.kotlin.test.kotlin-test", "kotlin-test") + setLibraryProperty("org.jetbrains.kotlin.test.kotlin-script-runtime", "kotlin-script-runtime") + setLibraryProperty("org.jetbrains.kotlin.test.kotlin-annotations-jvm", "kotlin-annotations-jvm") + } +} + +tasks.withType().configureEach { + kotlinOptions { + languageVersion = "2.0" + freeCompilerArgs = freeCompilerArgs + + "-opt-in=org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi" + + "-Xcontext-receivers" + } +} + +val generateTests by tasks.creating(JavaExec::class) { + classpath = sourceSets.test.get().runtimeClasspath + mainClass.set("org.jetbrains.kotlinx.spark.compilerPlugin.GenerateTestsKt") +} + +val compileTestKotlin by tasks.getting { + doLast { + generateTests.exec() + } +} + +fun Test.setLibraryProperty(propName: String, jarName: String) { + val path = project.configurations + .testRuntimeClasspath.get() + .files + .find { """$jarName-\d.*jar""".toRegex().matches(it.name) } + ?.absolutePath + ?: return + systemProperty(propName, path) +} \ No newline at end of file diff --git a/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SimplePluginRegistrar.kt b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SimplePluginRegistrar.kt new file mode 100644 index 00000000..2acc6cdc --- /dev/null +++ b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SimplePluginRegistrar.kt @@ -0,0 +1,8 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin + +import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar + +// Potential future K2 FIR hook +class SimplePluginRegistrar(private val sparkifyAnnotationFqNames: List) : FirExtensionRegistrar() { + override fun ExtensionRegistrarContext.configurePlugin() {} +} diff --git a/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SparkifyCommandLineProcessor.kt b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SparkifyCommandLineProcessor.kt new file mode 100644 index 00000000..c5081347 --- /dev/null +++ b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SparkifyCommandLineProcessor.kt @@ -0,0 +1,72 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin + +import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption +import org.jetbrains.kotlin.compiler.plugin.CliOption +import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.CompilerConfigurationKey +import org.jetbrains.kotlinx.spark.Artifacts + +open class SparkifyCommandLineProcessor : CommandLineProcessor { + + init { + println("SparkifyCommandLineProcessor loaded") + } + + override val pluginId: String = Artifacts.compilerPluginId + + override val pluginOptions: Collection = listOf( + OPTION_ENABLED, + OPTION_SPARKIFY_ANNOTATION_FQ_NAMES, + OPTION_COLUMN_NAME_ANNOTATION_FQ_NAMES, + ) + + override fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) { + when (val optionName = option.optionName) { + OPTION_ENABLED.optionName -> + configuration.put(KEY_ENABLED, value.toBoolean()) + + OPTION_SPARKIFY_ANNOTATION_FQ_NAMES.optionName -> + configuration.put(KEY_SPARKIFY_ANNOTATION_FQ_NAMES, value.split(",").map { it.trim() }) + + OPTION_COLUMN_NAME_ANNOTATION_FQ_NAMES.optionName -> + configuration.put(KEY_COLUMN_NAME_ANNOTATION_FQ_NAMES, value.split(",").map { it.trim() }) + + else -> error("Unexpected option: $optionName") + } + } +} + +internal val KEY_ENABLED = CompilerConfigurationKey("Whether to enable Sparkify") + +internal val OPTION_ENABLED = CliOption( + optionName = "enabled", + valueDescription = "", + description = "Whether to enable Sparkify", + required = false, + allowMultipleOccurrences = false, +) + +internal val KEY_SPARKIFY_ANNOTATION_FQ_NAMES = CompilerConfigurationKey>( + "Fully qualified names of annotations for Sparkify" +) + +internal val OPTION_SPARKIFY_ANNOTATION_FQ_NAMES = CliOption( + optionName = "sparkifyAnnotationFqNames", + valueDescription = "", + description = "Fully qualified names of annotations to sparkify", + required = false, + allowMultipleOccurrences = false, +) + +internal val KEY_COLUMN_NAME_ANNOTATION_FQ_NAMES = CompilerConfigurationKey>( + "Fully qualified names of annotations for ColumnName" +) + +internal val OPTION_COLUMN_NAME_ANNOTATION_FQ_NAMES = CliOption( + optionName = "columnNameAnnotationFqNames", + valueDescription = "", + description = "Fully qualified names of annotations for ColumnName", + required = false, + allowMultipleOccurrences = false, +) \ No newline at end of file diff --git a/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SparkifyCompilerPluginRegistrar.kt b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SparkifyCompilerPluginRegistrar.kt new file mode 100644 index 00000000..264b5a3b --- /dev/null +++ b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/SparkifyCompilerPluginRegistrar.kt @@ -0,0 +1,33 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin + +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlinx.spark.Artifacts +import org.jetbrains.kotlinx.spark.compilerPlugin.ir.SparkifyIrGenerationExtension + +open class SparkifyCompilerPluginRegistrar: CompilerPluginRegistrar() { + init { + println("SparkifyCompilerPluginRegistrar loaded") + } + + override val supportsK2: Boolean + get() = true + + override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) { + if (configuration.get(KEY_ENABLED) != true) return + + val sparkifyAnnotationFqNames = configuration.get(KEY_SPARKIFY_ANNOTATION_FQ_NAMES) + ?: listOf(Artifacts.defaultSparkifyFqName) + + val columnNameAnnotationFqNames = configuration.get(KEY_COLUMN_NAME_ANNOTATION_FQ_NAMES) + ?: listOf(Artifacts.defaultColumnNameFqName) + + IrGenerationExtension.registerExtension( + SparkifyIrGenerationExtension( + sparkifyAnnotationFqNames = sparkifyAnnotationFqNames, + columnNameAnnotationFqNames = columnNameAnnotationFqNames, + ) + ) + } +} diff --git a/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/ir/DataClassPropertyAnnotationGenerator.kt b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/ir/DataClassPropertyAnnotationGenerator.kt new file mode 100644 index 00000000..7e39ab38 --- /dev/null +++ b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/ir/DataClassPropertyAnnotationGenerator.kt @@ -0,0 +1,116 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin.ir + +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.backend.js.utils.valueArguments +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.expressions.IrConst +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl +import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.ir.util.isAnnotationWithEqualFqName +import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.primaryConstructor +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName + +class DataClassPropertyAnnotationGenerator( + private val pluginContext: IrPluginContext, + private val sparkifyAnnotationFqNames: List, + private val columnNameAnnotationFqNames: List, +) : IrElementVisitorVoid { + + init { + require(sparkifyAnnotationFqNames.isNotEmpty()) { + "At least one sparkify annotation must be provided" + } + require(columnNameAnnotationFqNames.isNotEmpty()) { + "At least one column name annotation must be provided" + } + } + + override fun visitElement(element: IrElement) { + when (element) { + is IrDeclaration, + is IrFile, + is IrModuleFragment -> element.acceptChildrenVoid(this) + } + } + + override fun visitProperty(declaration: IrProperty) { + val origin = declaration.parent as? IrClass ?: return super.visitProperty(declaration) + if (sparkifyAnnotationFqNames.none { origin.hasAnnotation(FqName(it)) }) + return super.visitProperty(declaration) + + // must be in primary constructor + val constructorParams = declaration.parentAsClass.primaryConstructor?.valueParameters + ?: return super.visitProperty(declaration) + + if (declaration.name !in constructorParams.map { it.name }) + return super.visitProperty(declaration) + + val getter = declaration.getter ?: return super.visitProperty(declaration) + + // Let's find if there's a ColumnName annotation + val columnNameAnnotationFqNames = columnNameAnnotationFqNames.map { FqName(it) } + + val allAnnotations = declaration.annotations + + getter.annotations + + constructorParams.first { it.name == declaration.name }.annotations + val columnNameAnnotation = allAnnotations + .firstOrNull { annotation -> + columnNameAnnotationFqNames.any { + annotation.isAnnotationWithEqualFqName(it) && + annotation.valueArguments.count { + it?.type == pluginContext.irBuiltIns.stringType + } >= 1 + } + } + + // if there is, get the ColumnName value, else use the property name as newName + val columnName = columnNameAnnotation + ?.valueArguments + ?.firstOrNull { it?.type == pluginContext.irBuiltIns.stringType } + ?.let { it as? IrConst<*> } + ?.value as? String + val newName = columnName ?: declaration.name.identifier + + val jvmNameFqName = FqName(JvmName::class.qualifiedName!!) + + // remove previous JvmNames + getter.annotations = getter.annotations + .filterNot { it.isAnnotationWithEqualFqName(jvmNameFqName) } + + // create a new JvmName annotation with newName + val jvmNameClassId = ClassId(jvmNameFqName.parent(), jvmNameFqName.shortName()) + val jvmName = pluginContext.referenceClass(jvmNameClassId)!! + val jvmNameConstructor = jvmName + .constructors + .firstOrNull()!! + + val jvmNameAnnotationCall = IrConstructorCallImpl.fromSymbolOwner( + type = jvmName.defaultType, + constructorSymbol = jvmNameConstructor, + ) + jvmNameAnnotationCall.putValueArgument( + index = 0, + valueArgument = IrConstImpl.string( + startOffset = UNDEFINED_OFFSET, + endOffset = UNDEFINED_OFFSET, + type = pluginContext.irBuiltIns.stringType, + value = newName, + ) + ) + getter.annotations += jvmNameAnnotationCall + println("Added @get:JvmName(\"$newName\") annotation to property ${origin.name}.${declaration.name}") + } +} \ No newline at end of file diff --git a/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/ir/SparkifyIrGenerationExtension.kt b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/ir/SparkifyIrGenerationExtension.kt new file mode 100644 index 00000000..ca2e9bbd --- /dev/null +++ b/compiler-plugin/src/main/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/ir/SparkifyIrGenerationExtension.kt @@ -0,0 +1,24 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin.ir + +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid + +class SparkifyIrGenerationExtension( + private val sparkifyAnnotationFqNames: List, + private val columnNameAnnotationFqNames: List, +) : IrGenerationExtension { + override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { + val visitors = listOf( + DataClassPropertyAnnotationGenerator( + pluginContext = pluginContext, + sparkifyAnnotationFqNames = sparkifyAnnotationFqNames, + columnNameAnnotationFqNames = columnNameAnnotationFqNames, + ), + ) + for (visitor in visitors) { + moduleFragment.acceptChildrenVoid(visitor) + } + } +} diff --git a/compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor b/compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor new file mode 100644 index 00000000..4d95540d --- /dev/null +++ b/compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor @@ -0,0 +1 @@ +org.jetbrains.kotlinx.spark.compilerPlugin.SparkifyCommandLineProcessor diff --git a/compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar b/compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar new file mode 100644 index 00000000..f1d5a663 --- /dev/null +++ b/compiler-plugin/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar @@ -0,0 +1 @@ +org.jetbrains.kotlinx.spark.compilerPlugin.SparkifyCompilerPluginRegistrar diff --git a/compiler-plugin/src/test-gen/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/BoxTestGenerated.java b/compiler-plugin/src/test-gen/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/BoxTestGenerated.java new file mode 100644 index 00000000..70904cb8 --- /dev/null +++ b/compiler-plugin/src/test-gen/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/BoxTestGenerated.java @@ -0,0 +1,29 @@ + + +package org.jetbrains.kotlinx.spark.compilerPlugin.runners; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlinx.spark.compilerPlugin.GenerateTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("/mnt/data/Projects/kotlin-spark-api/compiler-plugin/src/test/resources/testData/box") +@TestDataPath("$PROJECT_ROOT") +public class BoxTestGenerated extends AbstractBoxTest { + @Test + public void testAllFilesPresentInBox() { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("/mnt/data/Projects/kotlin-spark-api/compiler-plugin/src/test/resources/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("dataClassTest.kt") + public void testDataClassTest() { + runTest("/mnt/data/Projects/kotlin-spark-api/compiler-plugin/src/test/resources/testData/box/dataClassTest.kt"); + } +} diff --git a/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/GenerateTests.kt b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/GenerateTests.kt new file mode 100644 index 00000000..8b74142c --- /dev/null +++ b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/GenerateTests.kt @@ -0,0 +1,22 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin + +import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5 +import org.jetbrains.kotlinx.spark.Artifacts +import org.jetbrains.kotlinx.spark.compilerPlugin.runners.AbstractBoxTest + +fun main() { + generateTestGroupSuiteWithJUnit5 { + testGroup( + testDataRoot = "${Artifacts.projectRoot}/${Artifacts.compilerPluginArtifactId}/src/test/resources/testData", + testsRoot = "${Artifacts.projectRoot}/${Artifacts.compilerPluginArtifactId}/src/test-gen/kotlin", + ) { +// testClass { +// model("diagnostics") +// } + + testClass { + model("box") + } + } + } +} diff --git a/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/AbstractBoxTest.kt b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/AbstractBoxTest.kt new file mode 100644 index 00000000..ed2608b1 --- /dev/null +++ b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/AbstractBoxTest.kt @@ -0,0 +1,61 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin.runners + +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms +import org.jetbrains.kotlin.test.FirParser +import org.jetbrains.kotlin.test.TargetBackend +import org.jetbrains.kotlin.test.backend.BlackBoxCodegenSuppressor +import org.jetbrains.kotlin.test.backend.handlers.IrTextDumpHandler +import org.jetbrains.kotlin.test.backend.handlers.IrTreeVerifierHandler +import org.jetbrains.kotlin.test.backend.handlers.JvmBoxRunner +import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.builders.fir2IrStep +import org.jetbrains.kotlin.test.builders.irHandlersStep +import org.jetbrains.kotlin.test.builders.jvmArtifactsHandlersStep +import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.DUMP_IR +import org.jetbrains.kotlin.test.directives.configureFirParser +import org.jetbrains.kotlin.test.model.DependencyKind +import org.jetbrains.kotlin.test.runners.RunnerWithTargetBackendForTestGeneratorMarker + +/* + * Containers of different directives, which can be used in tests: + * - ModuleStructureDirectives + * - LanguageSettingsDirectives + * - DiagnosticsDirectives + * - CodegenTestDirectives + * + * All of them are located in `org.jetbrains.kotlin.test.directives` package + */ +open class AbstractBoxTest : BaseTestRunner(), RunnerWithTargetBackendForTestGeneratorMarker { + override val targetBackend: TargetBackend + get() = TargetBackend.JVM_IR + + override fun TestConfigurationBuilder.configuration() { + globalDefaults { + targetBackend = TargetBackend.JVM_IR + targetPlatform = JvmPlatforms.defaultJvmPlatform + dependencyKind = DependencyKind.Binary + } + + configureFirParser(FirParser.Psi) + + defaultDirectives { + +DUMP_IR + } + + commonFirWithPluginFrontendConfiguration() + fir2IrStep() + irHandlersStep { + useHandlers( + ::IrTextDumpHandler, + ::IrTreeVerifierHandler, + ) + } + facadeStep(::JvmIrBackendFacade) + jvmArtifactsHandlersStep { + useHandlers(::JvmBoxRunner) + } + + useAfterAnalysisCheckers(::BlackBoxCodegenSuppressor) + } +} diff --git a/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/AbstractDiagnosticTest.kt b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/AbstractDiagnosticTest.kt new file mode 100644 index 00000000..626186aa --- /dev/null +++ b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/AbstractDiagnosticTest.kt @@ -0,0 +1,21 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin.runners + +import org.jetbrains.kotlin.test.FirParser +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.directives.ConfigurationDirectives.WITH_STDLIB +import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.FIR_DUMP +import org.jetbrains.kotlin.test.directives.configureFirParser +import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration +import org.jetbrains.kotlin.test.services.EnvironmentBasedStandardLibrariesPathProvider +import org.jetbrains.kotlin.test.services.KotlinStandardLibrariesPathProvider + +abstract class AbstractDiagnosticTest : BaseTestRunner() { + override fun TestConfigurationBuilder.configuration() { + commonFirWithPluginFrontendConfiguration() + configureFirParser(FirParser.Psi) + } + + override fun createKotlinStandardLibrariesPathProvider(): KotlinStandardLibrariesPathProvider { + return EnvironmentBasedStandardLibrariesPathProvider + } +} diff --git a/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/BaseTestRunner.kt b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/BaseTestRunner.kt new file mode 100644 index 00000000..f43cd4ce --- /dev/null +++ b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/runners/BaseTestRunner.kt @@ -0,0 +1,40 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin.runners + +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives +import org.jetbrains.kotlin.test.initIdeaConfiguration +import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest +import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration +import org.jetbrains.kotlin.test.services.EnvironmentBasedStandardLibrariesPathProvider +import org.jetbrains.kotlin.test.services.KotlinStandardLibrariesPathProvider +import org.jetbrains.kotlinx.spark.compilerPlugin.services.ExtensionRegistrarConfigurator +import org.junit.jupiter.api.BeforeAll + +abstract class BaseTestRunner : AbstractKotlinCompilerTest() { + companion object { + @BeforeAll + @JvmStatic + fun setUp() { + initIdeaConfiguration() + } + } + + override fun createKotlinStandardLibrariesPathProvider(): KotlinStandardLibrariesPathProvider { + return EnvironmentBasedStandardLibrariesPathProvider + } +} + +fun TestConfigurationBuilder.commonFirWithPluginFrontendConfiguration() { + baseFirDiagnosticTestConfiguration() + + defaultDirectives { + +FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES + +FirDiagnosticsDirectives.FIR_DUMP + +JvmEnvironmentConfigurationDirectives.FULL_JDK + } + + useConfigurators( + ::ExtensionRegistrarConfigurator + ) +} diff --git a/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/services/ExtensionRegistrarConfigurator.kt b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/services/ExtensionRegistrarConfigurator.kt new file mode 100644 index 00000000..563af572 --- /dev/null +++ b/compiler-plugin/src/test/kotlin/org/jetbrains/kotlinx/spark/compilerPlugin/services/ExtensionRegistrarConfigurator.kt @@ -0,0 +1,25 @@ +package org.jetbrains.kotlinx.spark.compilerPlugin.services + +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.EnvironmentConfigurator +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlinx.spark.compilerPlugin.ir.SparkifyIrGenerationExtension + +class ExtensionRegistrarConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) { + override fun CompilerPluginRegistrar.ExtensionStorage.registerCompilerExtensions( + module: TestModule, + configuration: CompilerConfiguration, + ) { + val sparkifyAnnotationFqNames = listOf("foo.bar.Sparkify") + val columnNameAnnotationFqNames = listOf("foo.bar.ColumnName") + IrGenerationExtension.registerExtension( + SparkifyIrGenerationExtension( + sparkifyAnnotationFqNames = sparkifyAnnotationFqNames, + columnNameAnnotationFqNames = columnNameAnnotationFqNames, + ) + ) + } +} 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 new file mode 100644 index 00000000..68834cea --- /dev/null +++ b/compiler-plugin/src/test/resources/testData/box/dataClassTest.fir.ir.txt @@ -0,0 +1,539 @@ +FILE fqName:foo.bar fileName:/dataClassTest.kt + CLASS ANNOTATION_CLASS name:ColumnName modality:OPEN visibility:public superTypes:[kotlin.Annotation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.bar.ColumnName + PROPERTY name:name visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final] + EXPRESSION_BODY + GET_VAR 'name: kotlin.String declared in foo.bar.ColumnName.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:foo.bar.ColumnName) returnType:kotlin.String + correspondingProperty: PROPERTY name:name visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:foo.bar.ColumnName + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in foo.bar.ColumnName' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.ColumnName declared in foo.bar.ColumnName.' type=foo.bar.ColumnName origin=null + CONSTRUCTOR visibility:public <> (name:kotlin.String) returnType:foo.bar.ColumnName [primary] + VALUE_PARAMETER name:name index:0 type:kotlin.String + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ANNOTATION_CLASS name:ColumnName modality:OPEN visibility:public superTypes:[kotlin.Annotation]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS ANNOTATION_CLASS name:Sparkify modality:OPEN visibility:public superTypes:[kotlin.Annotation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.bar.Sparkify + CONSTRUCTOR visibility:public <> () returnType:foo.bar.Sparkify [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ANNOTATION_CLASS name:Sparkify modality:OPEN visibility:public superTypes:[kotlin.Annotation]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:NormalUser modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.bar.NormalUser + PROPERTY name:name visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final] + EXPRESSION_BODY + GET_VAR 'name: kotlin.String declared in foo.bar.NormalUser.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:foo.bar.NormalUser) returnType:kotlin.String + correspondingProperty: PROPERTY name:name visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:foo.bar.NormalUser + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in foo.bar.NormalUser' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.NormalUser declared in foo.bar.NormalUser.' type=foo.bar.NormalUser origin=null + PROPERTY name:age visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'age: kotlin.Int declared in foo.bar.NormalUser.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:foo.bar.NormalUser) returnType:kotlin.Int + correspondingProperty: PROPERTY name:age visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:foo.bar.NormalUser + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in foo.bar.NormalUser' + 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.' type=foo.bar.NormalUser origin=null + CONSTRUCTOR visibility:public <> (name:kotlin.String, age:kotlin.Int) returnType:foo.bar.NormalUser [primary] + VALUE_PARAMETER name:name index:0 type:kotlin.String + EXPRESSION_BODY + CONST String type=kotlin.String value="John Doe" + VALUE_PARAMETER name:age index:1 type:kotlin.Int + EXPRESSION_BODY + CONST Int type=kotlin.Int value=25 + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:NormalUser modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:foo.bar.NormalUser) returnType:kotlin.String [operator] + $this: VALUE_PARAMETER name: type:foo.bar.NormalUser + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String declared in foo.bar.NormalUser' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.NormalUser declared in foo.bar.NormalUser.component1' type=foo.bar.NormalUser origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component2 visibility:public modality:FINAL <> ($this:foo.bar.NormalUser) returnType:kotlin.Int [operator] + $this: VALUE_PARAMETER name: type:foo.bar.NormalUser + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component2 (): kotlin.Int declared in foo.bar.NormalUser' + 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.component2' type=foo.bar.NormalUser origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:foo.bar.NormalUser, name:kotlin.String, age:kotlin.Int) returnType:foo.bar.NormalUser + $this: VALUE_PARAMETER name: type:foo.bar.NormalUser + VALUE_PARAMETER name:name index:0 type:kotlin.String + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.NormalUser declared in foo.bar.NormalUser.copy' type=foo.bar.NormalUser origin=null + VALUE_PARAMETER name:age index:1 type:kotlin.Int + EXPRESSION_BODY + 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.copy' type=foo.bar.NormalUser origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (name: kotlin.String, age: kotlin.Int): foo.bar.NormalUser declared in foo.bar.NormalUser' + CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, age: kotlin.Int) declared in foo.bar.NormalUser' type=foo.bar.NormalUser origin=null + name: GET_VAR 'name: kotlin.String declared in foo.bar.NormalUser.copy' type=kotlin.String origin=null + age: GET_VAR 'age: kotlin.Int declared in foo.bar.NormalUser.copy' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:foo.bar.NormalUser, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any + $this: VALUE_PARAMETER name: type:foo.bar.NormalUser + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': foo.bar.NormalUser declared in foo.bar.NormalUser.equals' type=foo.bar.NormalUser origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in foo.bar.NormalUser.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.NormalUser' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=foo.bar.NormalUser + GET_VAR 'other: kotlin.Any? declared in foo.bar.NormalUser.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.NormalUser' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:foo.bar.NormalUser [val] + TYPE_OP type=foo.bar.NormalUser origin=CAST typeOperand=foo.bar.NormalUser + GET_VAR 'other: kotlin.Any? declared in foo.bar.NormalUser.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.NormalUser declared in foo.bar.NormalUser.equals' type=foo.bar.NormalUser origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR 'val tmp_0: foo.bar.NormalUser declared in foo.bar.NormalUser.equals' type=foo.bar.NormalUser origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.NormalUser' + CONST Boolean type=kotlin.Boolean value=false + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: 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.equals' type=foo.bar.NormalUser origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR 'val tmp_0: foo.bar.NormalUser declared in foo.bar.NormalUser.equals' type=foo.bar.NormalUser origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.NormalUser' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.NormalUser' + CONST Boolean type=kotlin.Boolean value=true + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:foo.bar.NormalUser) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:foo.bar.NormalUser + BLOCK_BODY + VAR name:result type:kotlin.Int [var] + CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.NormalUser declared in foo.bar.NormalUser.hashCode' type=foo.bar.NormalUser origin=null + SET_VAR 'var result: kotlin.Int declared in foo.bar.NormalUser.hashCode' type=kotlin.Unit origin=EQ + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_VAR 'var result: kotlin.Int declared in foo.bar.NormalUser.hashCode' type=kotlin.Int origin=null + other: CONST Int type=kotlin.Int value=31 + other: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: 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.hashCode' type=foo.bar.NormalUser origin=null + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in foo.bar.NormalUser' + GET_VAR 'var result: kotlin.Int declared in foo.bar.NormalUser.hashCode' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:foo.bar.NormalUser) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:foo.bar.NormalUser + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in foo.bar.NormalUser' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="NormalUser(" + CONST String type=kotlin.String value="name=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String 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=", " + CONST String type=kotlin.String value="age=" + 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] + annotations: + Sparkify + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.bar.User + PROPERTY name:name visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final] + EXPRESSION_BODY + GET_VAR 'name: kotlin.String declared in foo.bar.User.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.String + annotations: + JvmName(name = "name") + correspondingProperty: PROPERTY name:name visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in foo.bar.User' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.' type=foo.bar.User origin=null + PROPERTY name:age visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'age: kotlin.Int declared in foo.bar.User.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.Int + annotations: + JvmName(name = "age") + correspondingProperty: PROPERTY name:age visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in foo.bar.User' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.' type=foo.bar.User origin=null + PROPERTY name:test visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Double visibility:private [final] + EXPRESSION_BODY + GET_VAR 'test: kotlin.Double declared in foo.bar.User.' type=kotlin.Double origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.Double + annotations: + JvmName(name = "a") + correspondingProperty: PROPERTY name:test visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Double declared in foo.bar.User' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.' type=foo.bar.User origin=null + PROPERTY name:test2 visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Double visibility:private [final] + EXPRESSION_BODY + GET_VAR 'test2: kotlin.Double declared in foo.bar.User.' type=kotlin.Double origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.Double + annotations: + ColumnName(name = "b") + JvmName(name = "b") + correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Double declared in foo.bar.User' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.' type=foo.bar.User origin=null + CONSTRUCTOR visibility:public <> (name:kotlin.String, age:kotlin.Int, test:kotlin.Double, test2:kotlin.Double) returnType:foo.bar.User [primary] + VALUE_PARAMETER name:name index:0 type:kotlin.String + EXPRESSION_BODY + CONST String type=kotlin.String value="John Doe" + VALUE_PARAMETER name:age index:1 type:kotlin.Int + EXPRESSION_BODY + CONST Int type=kotlin.Int value=25 + VALUE_PARAMETER name:test index:2 type:kotlin.Double + annotations: + ColumnName(name = "a") + EXPRESSION_BODY + CONST Double type=kotlin.Double value=1.0 + VALUE_PARAMETER name:test2 index:3 type:kotlin.Double + EXPRESSION_BODY + 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]' + 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 + RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String declared in foo.bar.User' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.component1' type=foo.bar.User origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component2 visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.Int [operator] + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component2 (): kotlin.Int declared in foo.bar.User' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.component2' type=foo.bar.User origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component3 visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.Double [operator] + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component3 (): kotlin.Double declared in foo.bar.User' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.component3' type=foo.bar.User origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component4 visibility:public modality:FINAL <> ($this:foo.bar.User) returnType:kotlin.Double [operator] + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component4 (): kotlin.Double declared in foo.bar.User' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.component4' type=foo.bar.User origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:foo.bar.User, name:kotlin.String, age:kotlin.Int, test:kotlin.Double, test2:kotlin.Double) returnType:foo.bar.User + $this: VALUE_PARAMETER name: type:foo.bar.User + VALUE_PARAMETER name:name index:0 type:kotlin.String + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.copy' type=foo.bar.User origin=null + VALUE_PARAMETER name:age index:1 type:kotlin.Int + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.copy' type=foo.bar.User origin=null + VALUE_PARAMETER name:test index:2 type:kotlin.Double + annotations: + ColumnName(name = "a") + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.copy' type=foo.bar.User origin=null + VALUE_PARAMETER name:test2 index:3 type:kotlin.Double + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.copy' type=foo.bar.User origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (name: kotlin.String, age: kotlin.Int, test: kotlin.Double, test2: kotlin.Double): foo.bar.User declared in foo.bar.User' + CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, age: kotlin.Int, test: kotlin.Double, test2: kotlin.Double) declared in foo.bar.User' type=foo.bar.User origin=null + name: GET_VAR 'name: kotlin.String declared in foo.bar.User.copy' type=kotlin.String origin=null + age: GET_VAR 'age: kotlin.Int declared in foo.bar.User.copy' type=kotlin.Int origin=null + test: GET_VAR 'test: kotlin.Double declared in foo.bar.User.copy' type=kotlin.Double origin=null + test2: GET_VAR 'test2: kotlin.Double declared in foo.bar.User.copy' type=kotlin.Double origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:foo.bar.User, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any + $this: VALUE_PARAMETER name: type:foo.bar.User + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in foo.bar.User.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.User' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=foo.bar.User + GET_VAR 'other: kotlin.Any? declared in foo.bar.User.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.User' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:foo.bar.User [val] + TYPE_OP type=foo.bar.User origin=CAST typeOperand=foo.bar.User + GET_VAR 'other: kotlin.Any? declared in foo.bar.User.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR 'val tmp_1: foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.User' + CONST Boolean type=kotlin.Boolean value=false + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR 'val tmp_1: foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.User' + CONST Boolean type=kotlin.Boolean value=false + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR 'val tmp_1: foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.User' + CONST Boolean type=kotlin.Boolean value=false + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR 'val tmp_1: foo.bar.User declared in foo.bar.User.equals' type=foo.bar.User origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.User' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in foo.bar.User' + CONST Boolean type=kotlin.Boolean value=true + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:foo.bar.User) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + VAR name:result type:kotlin.Int [var] + CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.hashCode' type=foo.bar.User origin=null + SET_VAR 'var result: kotlin.Int declared in foo.bar.User.hashCode' type=kotlin.Unit origin=EQ + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_VAR 'var result: kotlin.Int declared in foo.bar.User.hashCode' type=kotlin.Int origin=null + other: CONST Int type=kotlin.Int value=31 + other: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.hashCode' type=foo.bar.User origin=null + SET_VAR 'var result: kotlin.Int declared in foo.bar.User.hashCode' type=kotlin.Unit origin=EQ + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_VAR 'var result: kotlin.Int declared in foo.bar.User.hashCode' type=kotlin.Int origin=null + other: CONST Int type=kotlin.Int value=31 + other: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Double' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.hashCode' type=foo.bar.User origin=null + SET_VAR 'var result: kotlin.Int declared in foo.bar.User.hashCode' type=kotlin.Unit origin=EQ + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null + $this: GET_VAR 'var result: kotlin.Int declared in foo.bar.User.hashCode' type=kotlin.Int origin=null + other: CONST Int type=kotlin.Int value=31 + other: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Double' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.hashCode' type=foo.bar.User origin=null + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in foo.bar.User' + GET_VAR 'var result: kotlin.Int declared in foo.bar.User.hashCode' type=kotlin.Int origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:foo.bar.User) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:foo.bar.User + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in foo.bar.User' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="User(" + CONST String type=kotlin.String value="name=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.toString' type=foo.bar.User origin=null + CONST String type=kotlin.String value=", " + CONST String type=kotlin.String value="age=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:age type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.toString' type=foo.bar.User origin=null + CONST String type=kotlin.String value=", " + CONST String type=kotlin.String value="test=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.toString' type=foo.bar.User origin=null + CONST String type=kotlin.String value=", " + CONST String type=kotlin.String value="test2=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Double visibility:private [final]' type=kotlin.Double origin=null + receiver: GET_VAR ': foo.bar.User declared in foo.bar.User.toString' type=foo.bar.User origin=null + CONST String type=kotlin.String value=")" + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + VAR name:user type:foo.bar.User [val] + CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, age: kotlin.Int, test: kotlin.Double, test2: kotlin.Double) declared in foo.bar.User' type=foo.bar.User origin=null + VAR name:name 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]' 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] + 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]' 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] + 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]' 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] + 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]' 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 + BRANCH + if: WHEN type=kotlin.Boolean origin=OROR + BRANCH + if: WHEN type=kotlin.Boolean origin=OROR + BRANCH + if: WHEN type=kotlin.Boolean origin=OROR + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR 'val name: @[FlexibleNullability] kotlin.Any? declared in foo.bar.box' type=@[FlexibleNullability] kotlin.Any? origin=null + arg1: CONST String type=kotlin.String value="John Doe" + then: CONST Boolean type=kotlin.Boolean value=true + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR 'val age: @[FlexibleNullability] kotlin.Any? declared in foo.bar.box' type=@[FlexibleNullability] kotlin.Any? origin=null + arg1: CONST Int type=kotlin.Int value=25 + then: CONST Boolean type=kotlin.Boolean value=true + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR 'val a: @[FlexibleNullability] kotlin.Any? declared in foo.bar.box' type=@[FlexibleNullability] kotlin.Any? origin=null + arg1: CONST Double type=kotlin.Double value=1.0 + then: CONST Boolean type=kotlin.Boolean value=true + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR 'val b: @[FlexibleNullability] kotlin.Any? declared in foo.bar.box' type=@[FlexibleNullability] kotlin.Any? origin=null + arg1: CONST Double type=kotlin.Double value=2.0 + then: BLOCK type=kotlin.Unit origin=null + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in foo.bar' + CONST String type=kotlin.String value="Could not invoke functions name(), age(), a(), or b() from Java" + TRY type=kotlin.Unit + try: BLOCK type=kotlin.Unit origin=null + VAR name:normalUser type:foo.bar.NormalUser [val] + CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, age: kotlin.Int) declared in foo.bar.NormalUser' type=foo.bar.NormalUser origin=null + VAR name:name 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.NormalUser + $receiver: CLASS_REFERENCE 'CLASS CLASS name:NormalUser modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' 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] + 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.NormalUser + $receiver: CLASS_REFERENCE 'CLASS CLASS name:NormalUser modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' 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 + CATCH parameter=val e: java.lang.Exception declared in foo.bar.box + VAR CATCH_PARAMETER name:e type:java.lang.Exception [val] + BLOCK type=kotlin.Nothing origin=null + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in foo.bar' + CONST String type=kotlin.String value="OK" + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in foo.bar' + CONST String type=kotlin.String value="Fail" diff --git a/compiler-plugin/src/test/resources/testData/box/dataClassTest.fir.txt b/compiler-plugin/src/test/resources/testData/box/dataClassTest.fir.txt new file mode 100644 index 00000000..abd7219f --- /dev/null +++ b/compiler-plugin/src/test/resources/testData/box/dataClassTest.fir.txt @@ -0,0 +1,87 @@ +FILE: dataClassTest.kt + package foo.bar + + public final annotation class Sparkify : R|kotlin/Annotation| { + public constructor(): R|foo/bar/Sparkify| { + super() + } + + } + public final annotation class ColumnName : R|kotlin/Annotation| { + public constructor(name: R|kotlin/String|): R|foo/bar/ColumnName| { + super() + } + + public final val name: R|kotlin/String| = R|/name| + public get(): R|kotlin/String| + + } + public final fun box(): R|kotlin/String| { + lval user: R|foo/bar/User| = R|foo/bar/User.User|() + lval name: R|kotlin/Any!| = (Q|foo/bar/User|).R|kotlin/jvm/java|.R|SubstitutionOverride|(String(name)).R|java/lang/reflect/Method.invoke|(R|/user|) + lval age: R|kotlin/Any!| = (Q|foo/bar/User|).R|kotlin/jvm/java|.R|SubstitutionOverride|(String(age)).R|java/lang/reflect/Method.invoke|(R|/user|) + lval a: R|kotlin/Any!| = (Q|foo/bar/User|).R|kotlin/jvm/java|.R|SubstitutionOverride|(String(a)).R|java/lang/reflect/Method.invoke|(R|/user|) + lval b: R|kotlin/Any!| = (Q|foo/bar/User|).R|kotlin/jvm/java|.R|SubstitutionOverride|(String(b)).R|java/lang/reflect/Method.invoke|(R|/user|) + when () { + !=(R|/name|, String(John Doe)) || !=(R|/age|, Int(25)) || !=(R|/a|, Double(1.0)) || !=(R|/b|, Double(2.0)) -> { + ^box String(Could not invoke functions name(), age(), a(), or b() from Java) + } + } + + try { + lval normalUser: R|foo/bar/NormalUser| = R|foo/bar/NormalUser.NormalUser|() + lval name: R|kotlin/Any!| = (Q|foo/bar/NormalUser|).R|kotlin/jvm/java|.R|SubstitutionOverride|(String(name)).R|java/lang/reflect/Method.invoke|(R|/user|) + lval age: R|kotlin/Any!| = (Q|foo/bar/NormalUser|).R|kotlin/jvm/java|.R|SubstitutionOverride|(String(age)).R|java/lang/reflect/Method.invoke|(R|/user|) + } + catch (e: R|kotlin/Exception|) { + ^box String(OK) + } + + ^box String(Fail) + } + @R|foo/bar/Sparkify|() public final data class User : R|kotlin/Any| { + public constructor(name: R|kotlin/String| = String(John Doe), age: R|kotlin/Int| = Int(25), @R|foo/bar/ColumnName|(name = String(a)) test: R|kotlin/Double| = Double(1.0), test2: R|kotlin/Double| = Double(2.0)): R|foo/bar/User| { + super() + } + + public final val name: R|kotlin/String| = R|/name| + public get(): R|kotlin/String| + + public final val age: R|kotlin/Int| = R|/age| + public get(): R|kotlin/Int| + + public final val test: R|kotlin/Double| = R|/test| + public get(): R|kotlin/Double| + + public final val test2: R|kotlin/Double| = R|/test2| + @PROPERTY_GETTER:R|foo/bar/ColumnName|(name = String(b)) public get(): R|kotlin/Double| + + public final operator fun component1(): R|kotlin/String| + + public final operator fun component2(): R|kotlin/Int| + + public final operator fun component3(): R|kotlin/Double| + + public final operator fun component4(): R|kotlin/Double| + + public final fun copy(name: R|kotlin/String| = this@R|foo/bar/User|.R|foo/bar/User.name|, age: R|kotlin/Int| = this@R|foo/bar/User|.R|foo/bar/User.age|, @R|foo/bar/ColumnName|(name = String(a)) test: R|kotlin/Double| = this@R|foo/bar/User|.R|foo/bar/User.test|, test2: R|kotlin/Double| = this@R|foo/bar/User|.R|foo/bar/User.test2|): R|foo/bar/User| + + } + public final data class NormalUser : R|kotlin/Any| { + public constructor(name: R|kotlin/String| = String(John Doe), age: R|kotlin/Int| = Int(25)): R|foo/bar/NormalUser| { + super() + } + + public final val name: R|kotlin/String| = R|/name| + public get(): R|kotlin/String| + + public final val age: R|kotlin/Int| = R|/age| + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/String| + + public final operator fun component2(): R|kotlin/Int| + + public final fun copy(name: R|kotlin/String| = this@R|foo/bar/NormalUser|.R|foo/bar/NormalUser.name|, age: R|kotlin/Int| = this@R|foo/bar/NormalUser|.R|foo/bar/NormalUser.age|): R|foo/bar/NormalUser| + + } diff --git a/compiler-plugin/src/test/resources/testData/box/dataClassTest.kt b/compiler-plugin/src/test/resources/testData/box/dataClassTest.kt new file mode 100644 index 00000000..25cd0988 --- /dev/null +++ b/compiler-plugin/src/test/resources/testData/box/dataClassTest.kt @@ -0,0 +1,39 @@ +package foo.bar + +annotation class Sparkify +annotation class ColumnName(val name: String) + +fun box(): String { + val user = User() + val name = User::class.java.getMethod("name").invoke(user) + val age = User::class.java.getMethod("age").invoke(user) + val a = User::class.java.getMethod("a").invoke(user) + val b = User::class.java.getMethod("b").invoke(user) + + if (name != "John Doe" || age != 25 || a != 1.0 || b != 2.0) { + return "Could not invoke functions name(), age(), a(), or b() from Java" + } + + try { + val normalUser = NormalUser() + val name = NormalUser::class.java.getMethod("name").invoke(user) + val age = NormalUser::class.java.getMethod("age").invoke(user) + } catch (e: Exception) { + return "OK" + } + + return "Fail" +} + +@Sparkify +data class User( + val name: String = "John Doe", + val age: Int = 25, + @ColumnName("a") val test: Double = 1.0, + @get:ColumnName("b") val test2: Double = 2.0, +) + +data class NormalUser( + val name: String = "John Doe", + val age: Int = 25, +) \ No newline at end of file diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 90f45fe4..409d2122 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -37,8 +37,6 @@ dependencies { kotlin { jvmToolchain { - languageVersion.set( - JavaLanguageVersion.of(Versions.jvmTarget) - ) + languageVersion = JavaLanguageVersion.of(Versions.jvmTarget) } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 070cb702..a5952066 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/jupyter/build.gradle.kts b/jupyter/build.gradle.kts index bac43fb3..9d02f5a3 100644 --- a/jupyter/build.gradle.kts +++ b/jupyter/build.gradle.kts @@ -74,10 +74,10 @@ dependencies { val kotlinMainSources = kotlin.sourceSets.main.get().kotlin.sourceDirectories val preprocessMain by tasks.creating(JcpTask::class) { - sources.set(kotlinMainSources) - clearTarget.set(true) - fileExtensions.set(listOf("kt")) - vars.set(Versions.versionMap) + sources = kotlinMainSources + clearTarget = true + fileExtensions = listOf("kt") + vars = Versions.versionMap outputs.upToDateWhen { target.get().exists() } } @@ -110,10 +110,10 @@ tasks.compileKotlin { val kotlinTestSources = kotlin.sourceSets.test.get().kotlin.sourceDirectories val preprocessTest by tasks.creating(JcpTask::class) { - sources.set(kotlinTestSources) - clearTarget.set(true) - fileExtensions.set(listOf("java", "kt")) - vars.set(Versions.versionMap) + sources = kotlinTestSources + clearTarget = true + fileExtensions = listOf("java", "kt") + vars = Versions.versionMap outputs.upToDateWhen { target.get().exists() } } @@ -143,9 +143,7 @@ tasks.compileTestKotlin { kotlin { jvmToolchain { - languageVersion.set( - JavaLanguageVersion.of(Versions.jupyterJvmTarget) - ) + languageVersion = JavaLanguageVersion.of(Versions.jupyterJvmTarget) } } diff --git a/kotlin-spark-api/build.gradle.kts b/kotlin-spark-api/build.gradle.kts index 39c09ba0..34f121c9 100644 --- a/kotlin-spark-api/build.gradle.kts +++ b/kotlin-spark-api/build.gradle.kts @@ -69,10 +69,10 @@ dependencies { val kotlinMainSources = kotlin.sourceSets.main.get().kotlin.sourceDirectories val preprocessMain by tasks.creating(JcpTask::class) { - sources.set(kotlinMainSources) - clearTarget.set(true) - fileExtensions.set(listOf("kt")) - vars.set(Versions.versionMap) + sources = kotlinMainSources + clearTarget = true + fileExtensions = listOf("kt") + vars = Versions.versionMap outputs.upToDateWhen { target.get().exists() } } @@ -108,10 +108,10 @@ tasks.compileKotlin { val kotlinTestSources = kotlin.sourceSets.test.get().kotlin.sourceDirectories val preprocessTest by tasks.creating(JcpTask::class) { - sources.set(kotlinTestSources) - clearTarget.set(true) - fileExtensions.set(listOf("kt")) - vars.set(Versions.versionMap) + sources = kotlinTestSources + clearTarget = true + fileExtensions = listOf("kt") + vars = Versions.versionMap outputs.upToDateWhen { target.get().exists() } } @@ -144,9 +144,8 @@ tasks.compileTestKotlin { kotlin { jvmToolchain { - languageVersion.set( - JavaLanguageVersion.of(Versions.jvmTarget) - ) + languageVersion = JavaLanguageVersion.of(Versions.jvmTarget) + } } 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 cec0e020..c2b9f972 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 @@ -119,6 +119,9 @@ inline fun schemaFor(): DataType = schemaFor(typeOf()) fun schemaFor(kType: KType): DataType = kotlinEncoderFor(kType).schema().unwrap() +@Deprecated("Use schemaFor instead", ReplaceWith("schemaFor(kType)")) +fun schema(kType: KType) = schemaFor(kType) + object KotlinTypeInference { /** diff --git a/scala-helpers/build.gradle.kts b/scala-helpers/build.gradle.kts index 73e62f7d..f4ba628b 100644 --- a/scala-helpers/build.gradle.kts +++ b/scala-helpers/build.gradle.kts @@ -38,13 +38,10 @@ dependencies { java { toolchain { if (Versions.scalaCompat.toDouble() > 2.12) { // scala 2.12 will always target java 8 - languageVersion.set( - JavaLanguageVersion.of(Versions.jvmTarget) - ) + languageVersion = JavaLanguageVersion.of(Versions.jvmTarget) + } else if (Versions.jvmTarget == "1.8" || Versions.jvmTarget == "8") { - languageVersion.set( - JavaLanguageVersion.of(8) - ) + languageVersion = JavaLanguageVersion.of(8) } } } @@ -60,10 +57,10 @@ tasks.withType { val scalaMainSources = sourceSets.main.get().scala.sourceDirectories val preprocessMain by tasks.creating(JcpTask::class) { - sources.set(scalaMainSources) - clearTarget.set(true) - fileExtensions.set(listOf("scala")) - vars.set(Versions.versionMap) + sources = scalaMainSources + clearTarget = true + fileExtensions = listOf("scala") + vars = Versions.versionMap outputs.upToDateWhen { target.get().exists() } } diff --git a/scala-helpers/src/main/scala/org/jetbrains/kotlinx/spark/extensions/KSparkExtensions.scala b/scala-helpers/src/main/scala/org/jetbrains/kotlinx/spark/extensions/KSparkExtensions.scala index 359b1324..5fc912b7 100644 --- a/scala-helpers/src/main/scala/org/jetbrains/kotlinx/spark/extensions/KSparkExtensions.scala +++ b/scala-helpers/src/main/scala/org/jetbrains/kotlinx/spark/extensions/KSparkExtensions.scala @@ -19,26 +19,23 @@ */ package org.jetbrains.kotlinx.spark.extensions -import org.apache.spark.sql._ - -import java.util import scala.reflect.ClassTag object KSparkExtensions { - def col(d: Dataset[_], name: String): Column = d.col(name) - - def col(name: String): Column = functions.col(name) - - def lit(literal: Any): Column = functions.lit(literal) - - def collectAsList[T](ds: Dataset[T]): util.List[T] = { - //#if scalaCompat >= 2.13 - scala.jdk.javaapi.CollectionConverters.asJava(ds.collect()) - //#else - //$scala.collection.JavaConverters.seqAsJavaList(ds.collect()) - //#endif - } +// def col(d: Dataset[_], name: String): Column = d.col(name) +// +// def col(name: String): Column = functions.col(name) +// +// def lit(literal: Any): Column = functions.lit(literal) +// +// def collectAsList[T](ds: Dataset[T]): util.List[T] = { +// //#if scalaCompat >= 2.13 +// scala.jdk.javaapi.CollectionConverters.asJava(ds.collect()) +// //#else +// //$scala.collection.JavaConverters.seqAsJavaList(ds.collect()) +// //#endif +// } /** * Produces a ClassTag[T], which is actually just a casted ClassTag[AnyRef]. diff --git a/scala-tuples-in-kotlin/build.gradle.kts b/scala-tuples-in-kotlin/build.gradle.kts index c088efea..866dc166 100644 --- a/scala-tuples-in-kotlin/build.gradle.kts +++ b/scala-tuples-in-kotlin/build.gradle.kts @@ -43,9 +43,7 @@ dependencies { kotlin { jvmToolchain { - languageVersion.set( - JavaLanguageVersion.of(Versions.jvmTarget) - ) + languageVersion = JavaLanguageVersion.of(Versions.jvmTarget) } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 4193f335..df71f5ba 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,11 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") + } +} + plugins { id("com.gradle.enterprise") version "3.10.3" } @@ -16,7 +24,6 @@ System.setProperty("spark", spark) System.setProperty("scala", scala) System.setProperty("skipScalaOnlyDependent", skipScalaOnlyDependent) - val scalaCompat get() = scala.substringBeforeLast('.') @@ -29,6 +36,8 @@ include("scala-tuples-in-kotlin") include("kotlin-spark-api") include("jupyter") include("examples") +include("compiler-plugin") +include("gradle-plugin") // just scala dependent project(":scala-helpers").name = "scala-helpers_$scalaCompat"