diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt index b4c70238745..05cc6121b6c 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt @@ -891,4 +891,34 @@ class KotlinGradleIT : BaseGradleIT() { assertNotContains(MULTIPLE_KOTLIN_PLUGINS_SPECIFIC_PROJECTS_WARNING) } } + + @Test + fun testNewModelInOldJvmPlugin() = with(Project("new-model-in-old-plugin", GradleVersionRequired.AtLeast("4.10.2"))) { + setupWorkingDir() + gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl) + + build("publish", "check", "runBenchmark") { + assertSuccessful() + assertTasksExecuted(":compileKotlin", ":compileTestKotlin", ":compileBenchmarkKotlin", ":test", ":runBenchmark") + + // Find the benchmark output: + assertContains("f ran at the speed of light") + + val moduleDir = "build/repo/com/example/new-model/1.0/" + + val publishedJar = fileInWorkingDir(moduleDir + "new-model-1.0.jar") + ZipFile(publishedJar).use { zip -> + val entries = zip.entries().asSequence().map { it.name } + assertTrue { "com/example/A.class" in entries } + } + + val publishedPom = fileInWorkingDir(moduleDir + "new-model-1.0.pom") + val kotlinVersion = defaultBuildOptions().kotlinVersion + val pomText = publishedPom.readText().replace(Regex("\\s+"), "") + assertTrue { "kotlin-gradle-plugin-api$kotlinVersioncompile" in pomText } + assertTrue { "kotlin-stdlib-jdk8$kotlinVersionruntime" in pomText } + + assertFileExists(moduleDir + "new-model-1.0-sources.jar") + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/build.gradle.kts new file mode 100644 index 00000000000..a37f237ef82 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/build.gradle.kts @@ -0,0 +1,60 @@ +plugins { + kotlin("jvm").version("") + `maven-publish` +} + +group = "com.example" +version = "1.0" + +repositories { + mavenLocal() + jcenter() +} + +kotlin.target.compilations { + all { + kotlinOptions { + allWarningsAsErrors = true + jvmTarget = "1.8" + } + } + + val main by getting { + defaultSourceSet.dependencies { + api(kotlin("gradle-plugin-api")) + implementation(kotlin("stdlib-jdk8")) + } + } + + val test by getting { + defaultSourceSet.dependencies { + implementation(kotlin("test-junit")) + } + } + + val benchmark by creating { + defaultSourceSet.dependencies { + implementation(main.compileDependencyFiles + main.output.allOutputs) + runtimeOnly(main.runtimeDependencyFiles) + + implementation(kotlin("reflect")) + } + } +} + +val runBenchmark by tasks.registering(JavaExec::class) { + classpath = kotlin.target.compilations["benchmark"].run { runtimeDependencyFiles + output.allOutputs } + main = "com.example.ABenchmarkKt" +} + +publishing { + publications { + create("default", MavenPublication::class) { + from(kotlin.target.components.single()) + artifact(tasks.getByName("kotlinSourcesJar")) + } + } + repositories { + maven("${buildDir}/repo") + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/settings.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/settings.gradle.kts new file mode 100644 index 00000000000..21a19d3645c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/settings.gradle.kts @@ -0,0 +1,8 @@ +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + } +} + +rootProject.name = "new-model" \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/benchmark/kotlin/ABenchmark.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/benchmark/kotlin/ABenchmark.kt new file mode 100644 index 00000000000..2ab90dbb1e8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/benchmark/kotlin/ABenchmark.kt @@ -0,0 +1,8 @@ +package com.example + +fun main() { + val a = A() + val f = a::f + f() + println("${a::f.name} ran at the speed of light") +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/main/kotlin/A.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/main/kotlin/A.kt new file mode 100644 index 00000000000..b2ee3d1f08a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/main/kotlin/A.kt @@ -0,0 +1,5 @@ +package com.example + +class A { + fun f(): String = "hello".also(::println) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/test/kotlin/ATest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/test/kotlin/ATest.kt new file mode 100644 index 00000000000..8d74fec6fb5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-model-in-old-plugin/src/test/kotlin/ATest.kt @@ -0,0 +1,11 @@ +package com.example + +import kotlin.test.* + +class ATest { + @Test + fun testF() { + val f = A().f() + assertEquals("hello", f) + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt index c5ebe89d6b0..e15ea20e597 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt @@ -20,6 +20,8 @@ import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import org.gradle.api.internal.plugins.DslObject import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.KotlinTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget import kotlin.reflect.KClass @@ -52,12 +54,33 @@ open class KotlinProjectExtension { } } -open class KotlinSingleJavaTargetExtension : KotlinProjectExtension() { - // TODO define subtypes with proper type arguments for each of the option types once the new model is available in old projects - internal lateinit var target: KotlinWithJavaTarget<*> +abstract class KotlinSingleTargetExtension : KotlinProjectExtension() { + abstract val target: KotlinTarget } -open class KotlinJvmProjectExtension : KotlinSingleJavaTargetExtension() +abstract class KotlinSingleJavaTargetExtension : KotlinSingleTargetExtension() { + override abstract val target: KotlinWithJavaTarget<*> +} + +open class KotlinJvmProjectExtension : KotlinSingleJavaTargetExtension() { + override lateinit var target: KotlinWithJavaTarget + internal set +} + +open class Kotlin2JsProjectExtension : KotlinSingleJavaTargetExtension() { + override lateinit var target: KotlinWithJavaTarget + internal set +} + +open class KotlinCommonProjectExtension : KotlinSingleJavaTargetExtension() { + override lateinit var target: KotlinWithJavaTarget + internal set +} + +open class KotlinAndroidProjectExtension : KotlinSingleTargetExtension() { + override lateinit var target: KotlinAndroidTarget + internal set +} open class ExperimentalExtension { var coroutines: Coroutines? = null diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 66e066d2682..20b24b42f2f 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -562,10 +562,10 @@ internal open class KotlinPlugin( Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion) override fun apply(project: Project) { - val target = KotlinWithJavaTarget(project, KotlinPlatformType.jvm, targetName).apply { + val target = KotlinWithJavaTarget(project, KotlinPlatformType.jvm, targetName).apply { disambiguationClassifier = null // don't add anything to the task names } - (project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target + (project.kotlinExtension as KotlinJvmProjectExtension).target = target project.pluginManager.apply(ScriptingGradleSubplugin::class.java) @@ -590,8 +590,8 @@ internal open class KotlinCommonPlugin( KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion) override fun apply(project: Project) { - val target = KotlinWithJavaTarget(project, KotlinPlatformType.common, targetName) - (project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target + val target = KotlinWithJavaTarget(project, KotlinPlatformType.common, targetName) + (project.kotlinExtension as KotlinCommonProjectExtension).target = target super.apply(project) } @@ -616,9 +616,9 @@ internal open class Kotlin2JsPlugin( ) override fun apply(project: Project) { - val target = KotlinWithJavaTarget(project, KotlinPlatformType.js, targetName) + val target = KotlinWithJavaTarget(project, KotlinPlatformType.js, targetName) - (project.kotlinExtension as KotlinSingleJavaTargetExtension).target = target + (project.kotlinExtension as Kotlin2JsProjectExtension).target = target super.apply(project) } } @@ -632,6 +632,8 @@ internal open class KotlinAndroidPlugin( checkGradleCompatibility() val androidTarget = KotlinAndroidTarget("", project) + (project.kotlinExtension as KotlinAndroidProjectExtension).target = androidTarget + applyToTarget(kotlinPluginVersion, androidTarget) registry.register(KotlinModelBuilder(kotlinPluginVersion, androidTarget)) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index a6e07f95839..3c624aa8a1a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -113,8 +113,8 @@ open class KotlinCommonPluginWrapper @Inject constructor( override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin = KotlinCommonPlugin(kotlinPluginVersion, registry) - override val projectExtensionClass: KClass - get() = KotlinSingleJavaTargetExtension::class + override val projectExtensionClass: KClass + get() = KotlinCommonProjectExtension::class } open class KotlinAndroidPluginWrapper @Inject constructor( @@ -123,6 +123,9 @@ open class KotlinAndroidPluginWrapper @Inject constructor( ) : KotlinBasePluginWrapper(fileResolver) { override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin = KotlinAndroidPlugin(kotlinPluginVersion, registry) + + override val projectExtensionClass: KClass + get() = KotlinAndroidProjectExtension::class } open class Kotlin2JsPluginWrapper @Inject constructor( @@ -132,8 +135,8 @@ open class Kotlin2JsPluginWrapper @Inject constructor( override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin = Kotlin2JsPlugin(kotlinPluginVersion, registry) - override val projectExtensionClass: KClass - get() = KotlinSingleJavaTargetExtension::class + override val projectExtensionClass: KClass + get() = Kotlin2JsProjectExtension::class } open class KotlinMultiplatformPluginWrapper @Inject constructor(