Implement kotlin-tooling-metadata.json artifact
- Introduce new :kotlin-tooling-metadata project - Create new buildKotlinToolingMetadata task by default - Add `kotlin-tooling-metadata.json` to root mpp publications - Add kotlin.mpp.enableKotlinToolingMetadataArtifact flag to disable kotlin-tooling-metadata.json artifact ^KT-44584 Verification Pending
This commit is contained in:
committed by
TeamCityServer
parent
88058ca2c8
commit
ac8b4c1b79
@@ -41,6 +41,7 @@ val kotlinGradlePluginAndItsRequired = arrayOf(
|
|||||||
":kotlin-gradle-plugin-api",
|
":kotlin-gradle-plugin-api",
|
||||||
":kotlin-gradle-plugin",
|
":kotlin-gradle-plugin",
|
||||||
":kotlin-gradle-plugin-model",
|
":kotlin-gradle-plugin-model",
|
||||||
|
":kotlin-tooling-metadata",
|
||||||
":kotlin-reflect",
|
":kotlin-reflect",
|
||||||
":kotlin-annotation-processing-gradle",
|
":kotlin-annotation-processing-gradle",
|
||||||
":kotlin-test",
|
":kotlin-test",
|
||||||
@@ -59,7 +60,8 @@ val kotlinGradlePluginAndItsRequired = arrayOf(
|
|||||||
":kotlin-serialization",
|
":kotlin-serialization",
|
||||||
":kotlin-test-js-runner",
|
":kotlin-test-js-runner",
|
||||||
":native:kotlin-klib-commonizer-embeddable",
|
":native:kotlin-klib-commonizer-embeddable",
|
||||||
":native:kotlin-klib-commonizer-api"
|
":native:kotlin-klib-commonizer-api",
|
||||||
|
":native:kotlin-native-utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
fun Task.dependsOnKotlinGradlePluginInstall() {
|
fun Task.dependsOnKotlinGradlePluginInstall() {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<trust group="org.jetbrains.kotlin" name="kotlin-gradle-plugin-model"/>
|
<trust group="org.jetbrains.kotlin" name="kotlin-gradle-plugin-model"/>
|
||||||
<trust group="org.jetbrains.kotlin" name="kotlin-klib-commonizer-api"/>
|
<trust group="org.jetbrains.kotlin" name="kotlin-klib-commonizer-api"/>
|
||||||
<trust group="org.jetbrains.kotlin" name="kotlin-klib-commonizer-embeddable"/>
|
<trust group="org.jetbrains.kotlin" name="kotlin-klib-commonizer-embeddable"/>
|
||||||
|
<trust group="org.jetbrains.kotlin" name="kotlin-tooling-metadata"/>
|
||||||
<trust group="org.jetbrains.kotlin" name="kotlin-native-utils"/>
|
<trust group="org.jetbrains.kotlin" name="kotlin-native-utils"/>
|
||||||
<trust group="org.jetbrains.kotlin" name="kotlin-reflect"/>
|
<trust group="org.jetbrains.kotlin" name="kotlin-reflect"/>
|
||||||
<trust group="org.jetbrains.kotlin" name="kotlin-sam-with-receiver"/>
|
<trust group="org.jetbrains.kotlin" name="kotlin-sam-with-receiver"/>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ val kotlinGradlePluginTest = project(":kotlin-gradle-plugin").sourceSets.named("
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation(project(":kotlin-gradle-plugin"))
|
testImplementation(project(":kotlin-gradle-plugin"))
|
||||||
|
testImplementation(project(":kotlin-tooling-metadata"))
|
||||||
testImplementation(kotlinGradlePluginTest)
|
testImplementation(kotlinGradlePluginTest)
|
||||||
testImplementation(project(":kotlin-gradle-subplugin-example"))
|
testImplementation(project(":kotlin-gradle-subplugin-example"))
|
||||||
testImplementation(project(":kotlin-allopen"))
|
testImplementation(project(":kotlin-allopen"))
|
||||||
|
|||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.tooling.BuildKotlinToolingMetadataTask
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import org.jetbrains.kotlin.tooling.KotlinToolingMetadata
|
||||||
|
import org.jetbrains.kotlin.tooling.parseJsonOrThrow
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class KotlinToolingMetadataIT : BaseGradleIT() {
|
||||||
|
override val defaultGradleVersion: GradleVersionRequired = GradleVersionRequired.FOR_MPP_SUPPORT
|
||||||
|
|
||||||
|
private val defaultKotlinToolingMetadataJsonPath = "build/kotlinToolingMetadata/kotlin-tooling-metadata.json"
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `new-mpp-published`() = with(transformProjectWithPluginsDsl("new-mpp-published")) {
|
||||||
|
build("publish") {
|
||||||
|
assertSuccessful()
|
||||||
|
assertTasksExecuted(
|
||||||
|
":${BuildKotlinToolingMetadataTask.defaultTaskName}"
|
||||||
|
)
|
||||||
|
/* Check metadata file in build dir */
|
||||||
|
assertFileExists(defaultKotlinToolingMetadataJsonPath)
|
||||||
|
val metadataJson = projectDir.resolve(defaultKotlinToolingMetadataJsonPath).readText()
|
||||||
|
val metadata = KotlinToolingMetadata.parseJsonOrThrow(metadataJson)
|
||||||
|
assertEquals(
|
||||||
|
listOf(
|
||||||
|
KotlinPlatformType.common.name, KotlinPlatformType.jvm.name,
|
||||||
|
KotlinPlatformType.js.name, KotlinPlatformType.native.name
|
||||||
|
).sorted(),
|
||||||
|
metadata.projectTargets.map { it.platformType }.sorted()
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Check metadata file in published repository */
|
||||||
|
val publishedMetadataJson = projectDir.parentFile.resolve(
|
||||||
|
"repo/com/example/bar/my-lib-bar/1.0/my-lib-bar-1.0-kotlin-tooling-metadata.json"
|
||||||
|
).readText()
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
metadataJson, publishedMetadataJson,
|
||||||
|
"Expected published kotlin-tooling-metadata.json to contain same content as in buildDir"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checking UP-TO-DATE behaviour */
|
||||||
|
build("publish") {
|
||||||
|
assertSuccessful()
|
||||||
|
// Nothing changed. Should be up-to-date
|
||||||
|
assertTasksUpToDate(":${BuildKotlinToolingMetadataTask.defaultTaskName}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding macos target
|
||||||
|
val buildFile = projectDir.resolve("build.gradle.kts")
|
||||||
|
buildFile.writeText(
|
||||||
|
buildFile.readText().replace(
|
||||||
|
"linuxX64()", "linuxX64()\nmacosX64()"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
build("publish") {
|
||||||
|
assertSuccessful()
|
||||||
|
assertTasksExecuted(":${BuildKotlinToolingMetadataTask.defaultTaskName}")
|
||||||
|
val metadata = KotlinToolingMetadata.parseJsonOrThrow(projectDir.resolve(defaultKotlinToolingMetadataJsonPath).readText())
|
||||||
|
assertEquals(
|
||||||
|
listOf(KonanTarget.LINUX_X64.name, KonanTarget.MACOS_X64.name).sorted(),
|
||||||
|
metadata.projectTargets.mapNotNull { it.extras["konanTarget"] }.sorted()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `new-mpp-published with KotlinToolingMetadataArtifact disabled`() = with(transformProjectWithPluginsDsl("new-mpp-published")) {
|
||||||
|
projectDir.resolve("gradle.properties").appendText("\nkotlin.mpp.enableKotlinToolingMetadataArtifact=false")
|
||||||
|
build("publish") {
|
||||||
|
assertSuccessful()
|
||||||
|
assertNoSuchFile(defaultKotlinToolingMetadataJsonPath)
|
||||||
|
assertTasksNotRealized(
|
||||||
|
":${BuildKotlinToolingMetadataTask.defaultTaskName}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `kotlin-js-browser-project`() = with(transformProjectWithPluginsDsl("kotlin-js-browser-project")) {
|
||||||
|
build(BuildKotlinToolingMetadataTask.defaultTaskName) {
|
||||||
|
assertSuccessful()
|
||||||
|
assertTasksExecuted(":app:${BuildKotlinToolingMetadataTask.defaultTaskName}")
|
||||||
|
assertTasksExecuted(":base:${BuildKotlinToolingMetadataTask.defaultTaskName}")
|
||||||
|
assertTasksExecuted(":lib:${BuildKotlinToolingMetadataTask.defaultTaskName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform").version("<pluginMarkerVersion>")
|
||||||
|
`maven-publish`
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
maven("../repo")
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.example.bar"
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvm()
|
||||||
|
js()
|
||||||
|
linuxX64()
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
val commonMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlin("stdlib-common"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val commonTest by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlin("test-common"))
|
||||||
|
implementation(kotlin("test-annotations-common"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val jvmAndJsMain by creating {
|
||||||
|
dependsOn(commonMain)
|
||||||
|
}
|
||||||
|
|
||||||
|
val jvmAndJsTest by creating {
|
||||||
|
dependsOn(commonTest)
|
||||||
|
}
|
||||||
|
|
||||||
|
val linuxAndJsMain by creating {
|
||||||
|
dependsOn(commonMain)
|
||||||
|
}
|
||||||
|
|
||||||
|
val linuxAndJsTest by creating {
|
||||||
|
dependsOn(commonTest)
|
||||||
|
}
|
||||||
|
|
||||||
|
jvm().compilations["main"].defaultSourceSet {
|
||||||
|
dependsOn(jvmAndJsMain)
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlin("stdlib"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jvm().compilations["test"].defaultSourceSet {
|
||||||
|
dependsOn(jvmAndJsTest)
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlin("test-junit"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
js().compilations["main"].defaultSourceSet {
|
||||||
|
dependsOn(jvmAndJsMain)
|
||||||
|
dependsOn(linuxAndJsMain)
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlin("stdlib-js"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
js().compilations["test"].defaultSourceSet {
|
||||||
|
dependsOn(jvmAndJsTest)
|
||||||
|
dependsOn(linuxAndJsTest)
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlin("test-js"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
linuxX64().compilations["main"].defaultSourceSet {
|
||||||
|
dependsOn(linuxAndJsMain)
|
||||||
|
}
|
||||||
|
|
||||||
|
linuxX64().compilations["test"].defaultSourceSet {
|
||||||
|
dependsOn(linuxAndJsTest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
repositories {
|
||||||
|
maven("../repo")
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
||||||
|
kotlin.mpp.enableCompatibilityMetadataVariant=true
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = "my-lib-bar"
|
||||||
|
|
||||||
|
enableFeaturePreview("GRADLE_METADATA")
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example.bar
|
||||||
|
|
||||||
|
fun stub() = ""
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package com.example.bar
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
class BarTest {
|
||||||
|
@Test
|
||||||
|
fun testBar() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example.bar
|
||||||
|
|
||||||
|
fun jvmAndJsStub() = ""
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package com.example.bar
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
class BarJvmAndJsTest {
|
||||||
|
@Test
|
||||||
|
fun testBarJvmAndJs() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testThirdParty() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example.bar
|
||||||
|
|
||||||
|
fun linuxAndJsStub() = ""
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package com.example.bar
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
class BarLinuxAndJsTest {
|
||||||
|
@Test
|
||||||
|
fun testBarLinuxAndJs() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example.bar
|
||||||
|
|
||||||
|
fun linuxStub() =""
|
||||||
@@ -43,6 +43,8 @@ dependencies {
|
|||||||
implementation(kotlinStdlib())
|
implementation(kotlinStdlib())
|
||||||
implementation(project(":kotlin-util-klib"))
|
implementation(project(":kotlin-util-klib"))
|
||||||
implementation(project(":native:kotlin-klib-commonizer-api"))
|
implementation(project(":native:kotlin-klib-commonizer-api"))
|
||||||
|
implementation(project(":kotlin-tooling-metadata"))
|
||||||
|
compileOnly(project(":native:kotlin-native-utils"))
|
||||||
compileOnly(project(":kotlin-reflect-api"))
|
compileOnly(project(":kotlin-reflect-api"))
|
||||||
compileOnly(project(":kotlin-android-extensions"))
|
compileOnly(project(":kotlin-android-extensions"))
|
||||||
compileOnly(project(":kotlin-build-common"))
|
compileOnly(project(":kotlin-build-common"))
|
||||||
|
|||||||
+154
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("FunctionName")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import com.android.build.gradle.BaseExtension
|
||||||
|
import org.gradle.api.JavaVersion
|
||||||
|
import org.gradle.api.internal.project.ProjectInternal
|
||||||
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJsProjectExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.tooling.BuildKotlinToolingMetadataTask
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import org.jetbrains.kotlin.tooling.KotlinToolingMetadata
|
||||||
|
import org.jetbrains.kotlin.tooling.toJsonString
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class BuildKotlinToolingMetadataTest {
|
||||||
|
|
||||||
|
private val project = ProjectBuilder.builder().build() as ProjectInternal
|
||||||
|
private val multiplatform get() = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
|
||||||
|
private val js get() = project.extensions.getByType(KotlinJsProjectExtension::class.java)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `multiplatform empty setup`() {
|
||||||
|
project.plugins.apply("kotlin-multiplatform")
|
||||||
|
|
||||||
|
val metadata = getKotlinToolingMetadata()
|
||||||
|
|
||||||
|
assertEquals("Gradle", metadata.buildSystem)
|
||||||
|
assertEquals(project.gradle.gradleVersion, metadata.buildSystemVersion)
|
||||||
|
assertEquals(KotlinMultiplatformPluginWrapper::class.java.canonicalName, metadata.buildPlugin)
|
||||||
|
assertEquals(project.getKotlinPluginVersion().toString(), metadata.buildPluginVersion)
|
||||||
|
assertEquals(1, metadata.projectTargets.size, "Expected one target (metadata)")
|
||||||
|
assertTrue(
|
||||||
|
KotlinMetadataTarget::class.java.isAssignableFrom(Class.forName(metadata.projectTargets.single().target)),
|
||||||
|
"Expect target to be implement ${KotlinMetadataTarget::class.simpleName}"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
KotlinPlatformType.common.name, metadata.projectTargets.single().platformType
|
||||||
|
)
|
||||||
|
assertTrue(metadata.toJsonString().isNotBlank(), "Expected non blank json representation")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `multiplatform JS JVM Android setup`() {
|
||||||
|
project.plugins.apply("com.android.application")
|
||||||
|
project.plugins.apply("kotlin-multiplatform")
|
||||||
|
|
||||||
|
val android = project.extensions.getByType(BaseExtension::class.java)
|
||||||
|
val kotlin = multiplatform
|
||||||
|
|
||||||
|
android.compileSdkVersion(28)
|
||||||
|
kotlin.android()
|
||||||
|
kotlin.jvm()
|
||||||
|
kotlin.js {
|
||||||
|
nodejs()
|
||||||
|
browser()
|
||||||
|
}
|
||||||
|
|
||||||
|
project.evaluate()
|
||||||
|
|
||||||
|
val metadata = getKotlinToolingMetadata()
|
||||||
|
assertEquals(KotlinMultiplatformPluginWrapper::class.java.canonicalName, metadata.buildPlugin)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
listOf(KotlinPlatformType.common, KotlinPlatformType.androidJvm, KotlinPlatformType.jvm, KotlinPlatformType.js)
|
||||||
|
.map { it.name }.sorted(),
|
||||||
|
metadata.projectTargets.map { it.platformType }.sorted()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `multiplatform Android target with different source and target compatibility`() {
|
||||||
|
project.plugins.apply("kotlin-multiplatform")
|
||||||
|
project.plugins.apply("com.android.application")
|
||||||
|
val android = project.extensions.getByType(BaseExtension::class.java)
|
||||||
|
val kotlin = multiplatform
|
||||||
|
android.compileSdkVersion(28)
|
||||||
|
kotlin.android()
|
||||||
|
android.compileOptions.setSourceCompatibility(JavaVersion.VERSION_1_6)
|
||||||
|
android.compileOptions.setTargetCompatibility(JavaVersion.VERSION_1_8)
|
||||||
|
project.evaluate()
|
||||||
|
|
||||||
|
val androidTargetMetadata = getKotlinToolingMetadata()
|
||||||
|
.projectTargets.single { it.platformType == KotlinPlatformType.androidJvm.name }
|
||||||
|
|
||||||
|
assertEquals("1.6", androidTargetMetadata.extras["sourceCompatibility"])
|
||||||
|
assertEquals("1.8", androidTargetMetadata.extras["targetCompatibility"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `multiplatform JVM with different targets`() {
|
||||||
|
project.plugins.apply("kotlin-multiplatform")
|
||||||
|
val kotlin = multiplatform
|
||||||
|
val jvm = kotlin.jvm()
|
||||||
|
jvm.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).kotlinOptions.jvmTarget = "12"
|
||||||
|
jvm.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME).kotlinOptions.jvmTarget = "10"
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"12", getKotlinToolingMetadata().projectTargets
|
||||||
|
.single { it.platformType == KotlinPlatformType.jvm.name }.extras["jvmTarget"],
|
||||||
|
"Expected jvmTarget of main compilation"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `multiplatform with native target`() {
|
||||||
|
project.plugins.apply("kotlin-multiplatform")
|
||||||
|
val kotlin = multiplatform
|
||||||
|
kotlin.linuxX64()
|
||||||
|
|
||||||
|
val metadata = getKotlinToolingMetadata()
|
||||||
|
val linuxTarget = metadata.projectTargets.single { it.platformType == KotlinPlatformType.native.name }
|
||||||
|
assertEquals(KonanTarget.LINUX_X64.name, linuxTarget.extras["konanTarget"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun js() {
|
||||||
|
project.plugins.apply("org.jetbrains.kotlin.js")
|
||||||
|
val kotlin = js
|
||||||
|
kotlin.js { nodejs() }
|
||||||
|
|
||||||
|
val metadata = getKotlinToolingMetadata()
|
||||||
|
assertEquals(org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper::class.java.canonicalName, metadata.buildPlugin)
|
||||||
|
|
||||||
|
val jsTarget = metadata.projectTargets.single { it.platformType == KotlinPlatformType.js.name }
|
||||||
|
assertEquals("true", jsTarget.extras["isNodejsConfigured"])
|
||||||
|
assertEquals("false", jsTarget.extras["isBrowserConfigured"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun jvm() {
|
||||||
|
project.plugins.apply("org.jetbrains.kotlin.jvm")
|
||||||
|
val metadata = getKotlinToolingMetadata()
|
||||||
|
assertEquals(org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper::class.java.canonicalName, metadata.buildPlugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getKotlinToolingMetadata(): KotlinToolingMetadata {
|
||||||
|
val task = project.tasks.named(BuildKotlinToolingMetadataTask.defaultTaskName, BuildKotlinToolingMetadataTask::class.java).get()
|
||||||
|
return task.getKotlinToolingMetadata()
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -24,7 +24,6 @@ import org.gradle.api.plugins.MavenPluginConvention
|
|||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.publish.PublishingExtension
|
import org.gradle.api.publish.PublishingExtension
|
||||||
import org.gradle.api.publish.maven.MavenPom
|
import org.gradle.api.publish.maven.MavenPom
|
||||||
import org.gradle.api.artifacts.maven.MavenPom as OldMavenPom
|
|
||||||
import org.gradle.api.publish.maven.MavenPublication
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.api.tasks.compile.AbstractCompile
|
import org.gradle.api.tasks.compile.AbstractCompile
|
||||||
@@ -49,6 +48,7 @@ import java.io.File
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
import java.util.jar.Manifest
|
import java.util.jar.Manifest
|
||||||
|
import org.gradle.api.artifacts.maven.MavenPom as OldMavenPom
|
||||||
|
|
||||||
const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath"
|
const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath"
|
||||||
const val NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinNativeCompilerPluginClasspath"
|
const val NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinNativeCompilerPluginClasspath"
|
||||||
|
|||||||
+3
-5
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.gradle.tasks.KOTLIN_COMPILER_EMBEDDABLE
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_KLIB_COMMONIZER_EMBEDDABLE
|
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_KLIB_COMMONIZER_EMBEDDABLE
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP
|
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP
|
||||||
import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry
|
import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry
|
||||||
|
import org.jetbrains.kotlin.gradle.tooling.BuildKotlinToolingMetadataTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility
|
import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility
|
||||||
import org.jetbrains.kotlin.gradle.utils.loadPropertyFromResources
|
import org.jetbrains.kotlin.gradle.utils.loadPropertyFromResources
|
||||||
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
||||||
@@ -90,6 +91,7 @@ abstract class KotlinBasePluginWrapper : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
project.extensions.add(KotlinTestsRegistry.PROJECT_EXTENSION_NAME, createTestRegistry(project))
|
project.extensions.add(KotlinTestsRegistry.PROJECT_EXTENSION_NAME, createTestRegistry(project))
|
||||||
|
project.tasks.register(BuildKotlinToolingMetadataTask.defaultTaskName, BuildKotlinToolingMetadataTask::class.java)
|
||||||
|
|
||||||
val plugin = getPlugin(project, kotlinGradleBuildServices)
|
val plugin = getPlugin(project, kotlinGradleBuildServices)
|
||||||
|
|
||||||
@@ -210,13 +212,9 @@ open class KotlinJsPluginWrapper @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
open class KotlinMultiplatformPluginWrapper @Inject constructor(
|
open class KotlinMultiplatformPluginWrapper @Inject constructor(
|
||||||
private val featurePreviews: FeaturePreviews
|
|
||||||
) : KotlinBasePluginWrapper() {
|
) : KotlinBasePluginWrapper() {
|
||||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||||
KotlinMultiplatformPlugin(
|
KotlinMultiplatformPlugin(kotlinPluginVersion)
|
||||||
kotlinPluginVersion,
|
|
||||||
featurePreviews
|
|
||||||
)
|
|
||||||
|
|
||||||
override val projectExtensionClass: KClass<out KotlinMultiplatformExtension>
|
override val projectExtensionClass: KClass<out KotlinMultiplatformExtension>
|
||||||
get() = KotlinMultiplatformExtension::class
|
get() = KotlinMultiplatformExtension::class
|
||||||
|
|||||||
+3
@@ -126,6 +126,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
|||||||
val enableCompatibilityMetadataVariant: Boolean
|
val enableCompatibilityMetadataVariant: Boolean
|
||||||
get() = booleanProperty("kotlin.mpp.enableCompatibilityMetadataVariant") ?: true
|
get() = booleanProperty("kotlin.mpp.enableCompatibilityMetadataVariant") ?: true
|
||||||
|
|
||||||
|
val enableKotlinToolingMetadataArtifact: Boolean
|
||||||
|
get() = booleanProperty("kotlin.mpp.enableKotlinToolingMetadataArtifact") ?: true
|
||||||
|
|
||||||
val mppStabilityNoWarn: Boolean?
|
val mppStabilityNoWarn: Boolean?
|
||||||
get() = booleanProperty(KotlinMultiplatformPlugin.STABILITY_NOWARN_FLAG)
|
get() = booleanProperty(KotlinMultiplatformPlugin.STABILITY_NOWARN_FLAG)
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -44,8 +44,7 @@ import org.jetbrains.kotlin.konan.target.presetName
|
|||||||
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
||||||
|
|
||||||
class KotlinMultiplatformPlugin(
|
class KotlinMultiplatformPlugin(
|
||||||
private val kotlinPluginVersion: String,
|
private val kotlinPluginVersion: String
|
||||||
private val featurePreviews: FeaturePreviews // TODO get rid of this internal API usage once we don't need it
|
|
||||||
) : Plugin<Project> {
|
) : Plugin<Project> {
|
||||||
|
|
||||||
private class TargetFromPresetExtension(val targetsContainer: KotlinTargetsContainerWithPresets) {
|
private class TargetFromPresetExtension(val targetsContainer: KotlinTargetsContainerWithPresets) {
|
||||||
|
|||||||
+15
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
||||||
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||||
|
import org.jetbrains.kotlin.gradle.tooling.BuildKotlinToolingMetadataTask
|
||||||
|
|
||||||
internal fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") {
|
internal fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") {
|
||||||
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
||||||
@@ -43,6 +44,20 @@ private fun createRootPublication(project: Project, publishing: PublishingExtens
|
|||||||
kotlinSoftwareComponent.sourcesArtifacts.forEach { sourceArtifact ->
|
kotlinSoftwareComponent.sourcesArtifacts.forEach { sourceArtifact ->
|
||||||
artifact(sourceArtifact)
|
artifact(sourceArtifact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addKotlinToolingMetadataArtifactIfNeeded(project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MavenPublication.addKotlinToolingMetadataArtifactIfNeeded(project: Project) {
|
||||||
|
if (!PropertiesProvider(project).enableKotlinToolingMetadataArtifact) return
|
||||||
|
val buildKotlinToolingMetadataTask = project.tasks.withType(BuildKotlinToolingMetadataTask::class.java)
|
||||||
|
.named(BuildKotlinToolingMetadataTask.defaultTaskName) ?: return
|
||||||
|
|
||||||
|
|
||||||
|
artifact(buildKotlinToolingMetadataTask.flatMap { it.outputFile }) { artifact ->
|
||||||
|
artifact.classifier = "kotlin-tooling-metadata"
|
||||||
|
artifact.builtBy(buildKotlinToolingMetadataTask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+126
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.tooling
|
||||||
|
|
||||||
|
import com.android.build.gradle.BaseExtension
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.gradle.api.tasks.OutputFile
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetContainerDsl
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVariantEnabled
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||||
|
import org.jetbrains.kotlin.tooling.KotlinToolingMetadata
|
||||||
|
import org.jetbrains.kotlin.tooling.toJsonString
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
open class BuildKotlinToolingMetadataTask : DefaultTask() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val defaultTaskName: String = "buildKotlinToolingMetadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
group = "build"
|
||||||
|
description = "Build metadata json file containing information about the used Kotlin tooling"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
val outputFile: Property<File> = project.objects.property(File::class.java)
|
||||||
|
.convention(project.buildDir.resolve("kotlinToolingMetadata").resolve("kotlin-tooling-metadata.json"))
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
fun getKotlinToolingMetadata(): KotlinToolingMetadata {
|
||||||
|
return project.kotlinExtension.getKotlinToolingMetadata()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input
|
||||||
|
internal fun getKotlinToolingMetadataJson(): String = getKotlinToolingMetadata().toJsonString()
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
internal fun createToolingMetadataFile() {
|
||||||
|
val outputFile = outputFile.orNull ?: return
|
||||||
|
outputFile.parentFile.mkdirs()
|
||||||
|
outputFile.writeText(getKotlinToolingMetadataJson())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KotlinProjectExtension.getKotlinToolingMetadata(): KotlinToolingMetadata {
|
||||||
|
return KotlinToolingMetadata(
|
||||||
|
buildSystem = "Gradle",
|
||||||
|
buildSystemVersion = project.gradle.gradleVersion,
|
||||||
|
buildPlugin = project.plugins.withType(KotlinBasePluginWrapper::class.java).joinToString(";") { it.javaClass.canonicalName },
|
||||||
|
buildPluginVersion = project.getKotlinPluginVersion() ?: throw IllegalStateException(
|
||||||
|
"Failed to infer Kotlin Plugin version"
|
||||||
|
),
|
||||||
|
projectSettings = buildProjectSettings(),
|
||||||
|
projectTargets = buildProjectTargets()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KotlinProjectExtension.buildProjectSettings(): KotlinToolingMetadata.ProjectSettings {
|
||||||
|
return KotlinToolingMetadata.ProjectSettings(
|
||||||
|
isHmppEnabled = project.isKotlinGranularMetadataEnabled,
|
||||||
|
isCompatibilityMetadataVariantEnabled = project.isCompatibilityMetadataVariantEnabled
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KotlinProjectExtension.buildProjectTargets(): List<KotlinToolingMetadata.ProjectTargetMetadata> {
|
||||||
|
val targets = when (this) {
|
||||||
|
is KotlinMultiplatformExtension -> this.targets.toSet()
|
||||||
|
is KotlinSingleTargetExtension -> setOf(this.target)
|
||||||
|
else -> emptySet()
|
||||||
|
}
|
||||||
|
|
||||||
|
return targets.map { target -> buildTargetMetadata(target) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildTargetMetadata(target: KotlinTarget): KotlinToolingMetadata.ProjectTargetMetadata {
|
||||||
|
return KotlinToolingMetadata.ProjectTargetMetadata(
|
||||||
|
target = target.javaClass.canonicalName,
|
||||||
|
platformType = target.platformType.name,
|
||||||
|
extras = buildTargetMetadataExtras(target)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildTargetMetadataExtras(target: KotlinTarget): Map<String, String> {
|
||||||
|
val extras = mutableMapOf<String, String>()
|
||||||
|
when (target) {
|
||||||
|
is KotlinJvmTarget -> {
|
||||||
|
extras["withJavaEnabled"] = target.withJavaEnabled.toString()
|
||||||
|
target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME)?.let { mainCompilation ->
|
||||||
|
extras["jvmTarget"] = mainCompilation.kotlinOptions.jvmTarget
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is KotlinAndroidTarget -> {
|
||||||
|
val androidExtension = target.project.extensions.findByType(BaseExtension::class.java)
|
||||||
|
extras["sourceCompatibility"] = androidExtension?.compileOptions?.sourceCompatibility.toString()
|
||||||
|
extras["targetCompatibility"] = androidExtension?.compileOptions?.targetCompatibility.toString()
|
||||||
|
}
|
||||||
|
is KotlinJsSubTargetContainerDsl -> {
|
||||||
|
extras["isBrowserConfigured"] = target.isBrowserConfigured.toString()
|
||||||
|
extras["isNodejsConfigured"] = target.isNodejsConfigured.toString()
|
||||||
|
}
|
||||||
|
is KotlinNativeTarget -> {
|
||||||
|
extras["konanTarget"] = target.konanTarget.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extras.toMap()
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
plugins {
|
||||||
|
java
|
||||||
|
kotlin("jvm")
|
||||||
|
id("jps-compatible")
|
||||||
|
}
|
||||||
|
|
||||||
|
publish()
|
||||||
|
sourcesJar()
|
||||||
|
javadocJar()
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlinStdlib())
|
||||||
|
implementation("com.google.code.gson:gson:${rootProject.extra["versions.jar.gson"]}")
|
||||||
|
testImplementation(project(":kotlin-test:kotlin-test-junit"))
|
||||||
|
}
|
||||||
+124
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.tooling
|
||||||
|
|
||||||
|
import com.google.gson.*
|
||||||
|
import org.jetbrains.kotlin.tooling.KotlinToolingMetadataParsingResult.Failure
|
||||||
|
import org.jetbrains.kotlin.tooling.KotlinToolingMetadataParsingResult.Success
|
||||||
|
|
||||||
|
fun KotlinToolingMetadata.toJsonString(): String {
|
||||||
|
val gson = GsonBuilder().setPrettyPrinting().create()
|
||||||
|
return gson.toJson(toJsonObject())
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinToolingMetadata.toJsonObject(): JsonObject {
|
||||||
|
return JsonObject().apply {
|
||||||
|
addProperty("buildSystem", buildSystem)
|
||||||
|
addProperty("buildSystemVersion", buildSystemVersion)
|
||||||
|
addProperty("buildPlugin", buildPlugin)
|
||||||
|
addProperty("buildPluginVersion", buildPluginVersion)
|
||||||
|
add("projectSettings", projectSettings.toJsonObject())
|
||||||
|
add("projectTargets", projectTargets.toJsonArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinToolingMetadata.ProjectSettings.toJsonObject(): JsonObject {
|
||||||
|
return JsonObject().apply {
|
||||||
|
addProperty("isHmppEnabled", isHmppEnabled)
|
||||||
|
addProperty("isCompatibilityMetadataVariantEnabled", isCompatibilityMetadataVariantEnabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun List<KotlinToolingMetadata.ProjectTargetMetadata>.toJsonArray(): JsonArray {
|
||||||
|
return JsonArray().apply {
|
||||||
|
this@toJsonArray.forEach { targetMetadata ->
|
||||||
|
add(targetMetadata.toJsonObject())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinToolingMetadata.ProjectTargetMetadata.toJsonObject(): JsonObject {
|
||||||
|
return JsonObject().apply {
|
||||||
|
addProperty("target", target)
|
||||||
|
addProperty("platformType", platformType)
|
||||||
|
if (extras.isNotEmpty()) {
|
||||||
|
add("extras", JsonObject().apply {
|
||||||
|
for (extra in extras) {
|
||||||
|
addProperty(extra.key, extra.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class KotlinToolingMetadataParsingResult {
|
||||||
|
data class Success(val value: KotlinToolingMetadata) : KotlinToolingMetadataParsingResult()
|
||||||
|
data class Failure(val reason: String) : KotlinToolingMetadataParsingResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KotlinToolingMetadata.Companion.parseJson(json: String): KotlinToolingMetadataParsingResult {
|
||||||
|
val jsonElement = try {
|
||||||
|
JsonParser.parseString(json)
|
||||||
|
} catch (e: JsonParseException) {
|
||||||
|
return Failure("Invalid json: ${e.message}")
|
||||||
|
}
|
||||||
|
if (jsonElement !is JsonObject) {
|
||||||
|
return Failure("Expected JsonObject. Found ${json::class.java.canonicalName}")
|
||||||
|
}
|
||||||
|
return runCatching { jsonElement.toKotlinToolingMetadataOrThrow() }
|
||||||
|
.fold(
|
||||||
|
onSuccess = { Success(it) },
|
||||||
|
onFailure = { Failure("Failed parsing JsonObject: ${it.message}") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KotlinToolingMetadata.Companion.parseJsonOrThrow(value: String): KotlinToolingMetadata {
|
||||||
|
return when (val result = parseJson(value)) {
|
||||||
|
is Success -> result.value
|
||||||
|
is Failure -> throw IllegalArgumentException(result.reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JsonObject.toKotlinToolingMetadataOrThrow(): KotlinToolingMetadata {
|
||||||
|
return KotlinToolingMetadata(
|
||||||
|
buildSystem = getOrThrow("buildSystem").asString,
|
||||||
|
buildSystemVersion = getOrThrow("buildSystemVersion").asString,
|
||||||
|
buildPlugin = getOrThrow("buildPlugin").asString,
|
||||||
|
buildPluginVersion = getOrThrow("buildPluginVersion").asString,
|
||||||
|
projectSettings = getOrThrow("projectSettings").asJsonObject.toProjectSettingsOrThrow(),
|
||||||
|
projectTargets = getOrThrow("projectTargets").asJsonArray.map { it.asJsonObject.toTargetMetadataOrThrow() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JsonObject.toProjectSettingsOrThrow(): KotlinToolingMetadata.ProjectSettings {
|
||||||
|
return KotlinToolingMetadata.ProjectSettings(
|
||||||
|
isHmppEnabled = getOrThrow("isHmppEnabled").asBoolean,
|
||||||
|
isCompatibilityMetadataVariantEnabled = getOrThrow("isCompatibilityMetadataVariantEnabled").asBoolean
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JsonObject.toTargetMetadataOrThrow(): KotlinToolingMetadata.ProjectTargetMetadata {
|
||||||
|
return KotlinToolingMetadata.ProjectTargetMetadata(
|
||||||
|
target = getOrThrow("target").asString,
|
||||||
|
platformType = getOrThrow("platformType").asString,
|
||||||
|
extras = (get("extras") as? JsonObject)?.toTargetMetadataExtrasOrThrow() ?: emptyMap()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JsonObject.toTargetMetadataExtrasOrThrow(): Map<String, String> {
|
||||||
|
val map = mutableMapOf<String, String>()
|
||||||
|
this.keySet().forEach { key ->
|
||||||
|
val primitive = this[key] as? JsonPrimitive
|
||||||
|
if (primitive != null) {
|
||||||
|
map[key] = primitive.asString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JsonObject.getOrThrow(key: String): JsonElement {
|
||||||
|
return get(key) ?: throw IllegalArgumentException("Missing key: $key")
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.tooling
|
||||||
|
|
||||||
|
|
||||||
|
data class KotlinToolingMetadata(
|
||||||
|
/**
|
||||||
|
* Build System used (e.g. Gradle, Maven, ...)
|
||||||
|
*/
|
||||||
|
val buildSystem: String,
|
||||||
|
val buildSystemVersion: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin used to build (e.g.
|
||||||
|
* - org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
|
||||||
|
* - org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlugin
|
||||||
|
* - ...
|
||||||
|
*/
|
||||||
|
val buildPlugin: String,
|
||||||
|
val buildPluginVersion: String,
|
||||||
|
|
||||||
|
val projectSettings: ProjectSettings,
|
||||||
|
val projectTargets: List<ProjectTargetMetadata>,
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class ProjectSettings(
|
||||||
|
val isHmppEnabled: Boolean,
|
||||||
|
val isCompatibilityMetadataVariantEnabled: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ProjectTargetMetadata(
|
||||||
|
val target: String,
|
||||||
|
val platformType: String,
|
||||||
|
val extras: Map<String, String>
|
||||||
|
)
|
||||||
|
|
||||||
|
companion object
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.tooling
|
||||||
|
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
|
||||||
|
class DeserializationFailureTest {
|
||||||
|
@Test
|
||||||
|
fun sample1() {
|
||||||
|
val result = KotlinToolingMetadata.parseJson("")
|
||||||
|
assertTrue(
|
||||||
|
result is KotlinToolingMetadataParsingResult.Failure,
|
||||||
|
"Expected empty String to produce Failure. Actual: $result"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertFailsWith<IllegalArgumentException> { KotlinToolingMetadata.parseJsonOrThrow("") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `sample2 missing build pluginVersion`() {
|
||||||
|
@Language("JSON") val json =
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"buildSystem": "Gradle",
|
||||||
|
"buildSystemVersion": "6.7",
|
||||||
|
"buildPlugin": "org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper",
|
||||||
|
"projectSettings": {
|
||||||
|
"isHmppEnabled": false,
|
||||||
|
"isCompatibilityMetadataVariantEnabled": true
|
||||||
|
},
|
||||||
|
"projectTargets": []
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val result = KotlinToolingMetadata.parseJson(json)
|
||||||
|
assertTrue(
|
||||||
|
result is KotlinToolingMetadataParsingResult.Failure,
|
||||||
|
"Expected parsing failure, because of missing pluginVersion. Actual: $result"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertFailsWith<IllegalArgumentException> { KotlinToolingMetadata.parseJsonOrThrow(json) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.tooling
|
||||||
|
|
||||||
|
import junit.framework.Assert.assertFalse
|
||||||
|
import junit.framework.Assert.assertTrue
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DeserializeStringTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sample1() {
|
||||||
|
@Language("JSON") val json =
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"buildSystem": "Gradle",
|
||||||
|
"buildSystemVersion": "6.7",
|
||||||
|
"buildPlugin": "org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper",
|
||||||
|
"buildPluginVersion": "1.5.255-SNAPSHOT",
|
||||||
|
"projectSettings": {
|
||||||
|
"isHmppEnabled": false,
|
||||||
|
"isCompatibilityMetadataVariantEnabled": true
|
||||||
|
},
|
||||||
|
"projectTargets": [
|
||||||
|
{
|
||||||
|
"target": "org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget",
|
||||||
|
"platformType": "androidJvm",
|
||||||
|
"extras": {
|
||||||
|
"sourceCompatibility": "1.7",
|
||||||
|
"targetCompatibility": "1.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget_Decorated",
|
||||||
|
"platformType": "js",
|
||||||
|
"extras": {
|
||||||
|
"isBrowserConfigured": "true",
|
||||||
|
"isNodejsConfigured": "true"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget_Decorated",
|
||||||
|
"platformType": "jvm",
|
||||||
|
"extras": {
|
||||||
|
"withJavaEnabled": "false",
|
||||||
|
"jvmTarget": "1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget_Decorated",
|
||||||
|
"platformType": "common"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val metadata = KotlinToolingMetadata.parseJsonOrThrow(json)
|
||||||
|
assertEquals("Gradle", metadata.buildSystem)
|
||||||
|
assertEquals("6.7", metadata.buildSystemVersion)
|
||||||
|
assertEquals("org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper", metadata.buildPlugin)
|
||||||
|
assertEquals("1.5.255-SNAPSHOT", metadata.buildPluginVersion)
|
||||||
|
assertFalse(metadata.projectSettings.isHmppEnabled)
|
||||||
|
assertTrue(metadata.projectSettings.isCompatibilityMetadataVariantEnabled)
|
||||||
|
assertEquals(4, metadata.projectTargets.size, "Expected exactly 4 targets")
|
||||||
|
|
||||||
|
val androidJvmTarget = metadata.projectTargets.single { it.platformType == "androidJvm" }
|
||||||
|
assertEquals("org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget", androidJvmTarget.target)
|
||||||
|
assertEquals(2, androidJvmTarget.extras.size, "Expected exactly two extras")
|
||||||
|
assertEquals("1.7", androidJvmTarget.extras["sourceCompatibility"])
|
||||||
|
assertEquals("1.7", androidJvmTarget.extras["targetCompatibility"])
|
||||||
|
|
||||||
|
val jsTarget = metadata.projectTargets.single { it.platformType == "js" }
|
||||||
|
assertEquals("org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget_Decorated", jsTarget.target)
|
||||||
|
assertEquals(2, jsTarget.extras.size, "Expected exactly two extras")
|
||||||
|
assertEquals("true", jsTarget.extras["isBrowserConfigured"])
|
||||||
|
assertEquals("true", jsTarget.extras["isNodejsConfigured"])
|
||||||
|
|
||||||
|
val jvmTarget = metadata.projectTargets.single { it.platformType == "jvm" }
|
||||||
|
assertEquals("org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget_Decorated", jvmTarget.target)
|
||||||
|
assertEquals(2, jvmTarget.extras.size, "Expected exactly two extras")
|
||||||
|
assertEquals("false", jvmTarget.extras["withJavaEnabled"])
|
||||||
|
assertEquals("1.8", jvmTarget.extras["jvmTarget"])
|
||||||
|
|
||||||
|
val commonTarget = metadata.projectTargets.single { it.platformType == "common" }
|
||||||
|
assertEquals("org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget_Decorated", commonTarget.target)
|
||||||
|
assertEquals(0, commonTarget.extras.size, "Expected zero extras")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.tooling
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.tooling.KotlinToolingMetadata.ProjectTargetMetadata
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SerializeAndDeserializeTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sample1() = assertDeserializedMatchesOrigin(
|
||||||
|
defaultKotlinToolingMetadata()
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sample2() = assertDeserializedMatchesOrigin(
|
||||||
|
defaultKotlinToolingMetadata().copy(
|
||||||
|
projectTargets = listOf(
|
||||||
|
ProjectTargetMetadata(
|
||||||
|
target = "generic target",
|
||||||
|
platformType = "generic platform type",
|
||||||
|
extras = mapOf(
|
||||||
|
"extra0" to "extra value0",
|
||||||
|
"extra1" to "extra value1"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun sample3() = assertDeserializedMatchesOrigin(
|
||||||
|
defaultKotlinToolingMetadata().copy(
|
||||||
|
projectTargets = listOf(
|
||||||
|
ProjectTargetMetadata(
|
||||||
|
target = "generic target",
|
||||||
|
platformType = "generic platform type",
|
||||||
|
extras = mapOf(
|
||||||
|
"extra0" to "{ some extra value %\" with, chars to escape",
|
||||||
|
"extra1" to "extra value1"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
ProjectTargetMetadata(
|
||||||
|
target = "generic target 2 (with no extras)",
|
||||||
|
platformType = "generic platform type 2",
|
||||||
|
extras = emptyMap()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun assertDeserializedMatchesOrigin(origin: KotlinToolingMetadata) {
|
||||||
|
val json = origin.toJsonString()
|
||||||
|
val deserialized = KotlinToolingMetadata.parseJsonOrThrow(json)
|
||||||
|
assertEquals(origin, deserialized)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun defaultKotlinToolingMetadata(): KotlinToolingMetadata {
|
||||||
|
return KotlinToolingMetadata(
|
||||||
|
buildSystem = "generic build system",
|
||||||
|
buildSystemVersion = "v1.0 (build system)",
|
||||||
|
buildPlugin = "generic build plugin",
|
||||||
|
buildPluginVersion = "v1.0 (build plugin)",
|
||||||
|
projectSettings = KotlinToolingMetadata.ProjectSettings(
|
||||||
|
isHmppEnabled = false,
|
||||||
|
isCompatibilityMetadataVariantEnabled = true
|
||||||
|
),
|
||||||
|
projectTargets = emptyList()
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -253,6 +253,7 @@ include ":benchmarks",
|
|||||||
":kotlin-gradle-plugin-model",
|
":kotlin-gradle-plugin-model",
|
||||||
":kotlin-gradle-plugin-test-utils-embeddable",
|
":kotlin-gradle-plugin-test-utils-embeddable",
|
||||||
":kotlin-gradle-plugin-integration-tests",
|
":kotlin-gradle-plugin-integration-tests",
|
||||||
|
":kotlin-tooling-metadata",
|
||||||
":kotlin-allopen",
|
":kotlin-allopen",
|
||||||
":kotlin-noarg",
|
":kotlin-noarg",
|
||||||
":kotlin-sam-with-receiver",
|
":kotlin-sam-with-receiver",
|
||||||
@@ -520,6 +521,7 @@ project(':kotlin-gradle-plugin').projectDir = "$rootDir/libraries/tools/kotlin-g
|
|||||||
project(':kotlin-gradle-plugin-model').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-model" as File
|
project(':kotlin-gradle-plugin-model').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-model" as File
|
||||||
project(':kotlin-gradle-plugin-test-utils-embeddable').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-test-utils-embeddable" as File
|
project(':kotlin-gradle-plugin-test-utils-embeddable').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-test-utils-embeddable" as File
|
||||||
project(':kotlin-gradle-plugin-integration-tests').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-integration-tests" as File
|
project(':kotlin-gradle-plugin-integration-tests').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-integration-tests" as File
|
||||||
|
project(':kotlin-tooling-metadata').projectDir = "$rootDir/libraries/tools/kotlin-tooling-metadata" as File
|
||||||
project(':kotlin-allopen').projectDir = "$rootDir/libraries/tools/kotlin-allopen" as File
|
project(':kotlin-allopen').projectDir = "$rootDir/libraries/tools/kotlin-allopen" as File
|
||||||
project(':kotlin-noarg').projectDir = "$rootDir/libraries/tools/kotlin-noarg" as File
|
project(':kotlin-noarg').projectDir = "$rootDir/libraries/tools/kotlin-noarg" as File
|
||||||
project(':kotlin-sam-with-receiver').projectDir = "$rootDir/libraries/tools/kotlin-sam-with-receiver" as File
|
project(':kotlin-sam-with-receiver').projectDir = "$rootDir/libraries/tools/kotlin-sam-with-receiver" as File
|
||||||
|
|||||||
Reference in New Issue
Block a user