Add '-opt-in' option into Gradle compiler options DSL

^KT-53924 Fixed
This commit is contained in:
Yahor Berdnikau
2023-02-26 22:18:40 +01:00
committed by Space Team
parent 2b4abb0c7b
commit 174f39aa46
15 changed files with 230 additions and 11 deletions
@@ -107,6 +107,10 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
field = value
}
@GradleOption(
value = DefaultValue.EMPTY_STRING_ARRAY_DEFAULT,
gradleInputType = GradleInputTypes.INPUT
)
@Argument(
value = "-opt-in",
deprecatedName = "-Xopt-in",
@@ -35,6 +35,7 @@ enum class DefaultValue {
BOOLEAN_TRUE_DEFAULT,
STRING_NULL_DEFAULT,
EMPTY_STRING_LIST_DEFAULT,
EMPTY_STRING_ARRAY_DEFAULT,
LANGUAGE_VERSIONS,
API_VERSIONS,
JVM_TARGET_VERSIONS,
@@ -39,6 +39,13 @@ open class DefaultValues(
object EmptyStringListDefault : DefaultValues("emptyList<String>()", typeOf<List<String>>(), typeOf<List<String>>())
object EmptyStringArrayDefault : DefaultValues(
"emptyList<String>()",
typeOf<List<String>>(),
typeOf<List<String>>(),
toArgumentConverter = ".toTypedArray()"
)
object LanguageVersions : DefaultValues(
"null",
typeOf<KotlinVersionDsl?>(),
@@ -794,6 +794,7 @@ private val KProperty1<*, *>.gradleValues: DefaultValues
DefaultValue.BOOLEAN_TRUE_DEFAULT -> DefaultValues.BooleanTrueDefault
DefaultValue.STRING_NULL_DEFAULT -> DefaultValues.StringNullDefault
DefaultValue.EMPTY_STRING_LIST_DEFAULT -> DefaultValues.EmptyStringListDefault
DefaultValue.EMPTY_STRING_ARRAY_DEFAULT -> DefaultValues.EmptyStringArrayDefault
DefaultValue.JVM_TARGET_VERSIONS -> DefaultValues.JvmTargetVersions
DefaultValue.LANGUAGE_VERSIONS -> DefaultValues.LanguageVersions
DefaultValue.API_VERSIONS -> DefaultValues.ApiVersions
@@ -165,6 +165,7 @@ public abstract interface class org/jetbrains/kotlin/gradle/dsl/KotlinArtifactsE
public abstract interface class org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerOptions : org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerToolOptions {
public abstract fun getApiVersion ()Lorg/gradle/api/provider/Property;
public abstract fun getLanguageVersion ()Lorg/gradle/api/provider/Property;
public abstract fun getOptIn ()Lorg/gradle/api/provider/ListProperty;
public abstract fun getUseK2 ()Lorg/gradle/api/provider/Property;
}
@@ -25,6 +25,13 @@ interface KotlinCommonCompilerOptions : org.jetbrains.kotlin.gradle.dsl.KotlinCo
@get:org.gradle.api.tasks.Input
val languageVersion: org.gradle.api.provider.Property<org.jetbrains.kotlin.gradle.dsl.KotlinVersion>
/**
* Enable usages of API that requires opt-in with an opt-in requirement marker with the given fully qualified name
* Default value: emptyList<String>()
*/
@get:org.gradle.api.tasks.Input
val optIn: org.gradle.api.provider.ListProperty<kotlin.String>
/**
* Compile using experimental K2. K2 is a new compiler pipeline, no compatibility guarantees are yet provided
* Default value: false
@@ -138,4 +138,165 @@ internal class CompilerOptionsIT : KGPBaseTest() {
}
}
}
@DisplayName("Should pass -opt-in from compiler options DSL")
@JvmGradlePluginTests
@GradleTest
fun passesOptInAnnotation(gradleVersion: GradleVersion) {
project(
projectName = "simpleProject",
gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) {
buildGradle.appendText(
"""
|
|tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class).configureEach {
| compilerOptions.optIn.addAll("kotlin.RequiresOptIn", "my.CustomOptIn")
|}
""".trimMargin()
)
build("compileKotlin") {
val compilerArgs = output
.lineSequence()
.first {
it.contains("Kotlin compiler args:")
}
.substringAfter("Kotlin compiler args:")
val expectedOptIn = "-opt-in kotlin.RequiresOptIn,my.CustomOptIn"
assert(compilerArgs.contains(expectedOptIn)) {
printBuildOutput()
"compiler arguments does not contain '$expectedOptIn' - actual value: $compilerArgs"
}
}
}
}
@DisplayName("Should combine -opt-in arguments from languageSettings DSL")
@MppGradlePluginTests
@GradleTest
fun combinesOptInFromLanguageSettings(gradleVersion: GradleVersion) {
project(
projectName = "new-mpp-lib-and-app/sample-lib",
gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) {
buildGradle.appendText(
//language=Groovy
"""
|
|kotlin {
| sourceSets {
| jvm6Main {
| languageSettings.optIn("my.custom.OptInAnnotation")
| }
| }
|}
|
|tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class).configureEach {
| compilerOptions.optIn.add("another.custom.UnderOptIn")
|}
""".trimMargin()
)
build("compileKotlinJvm6", forceOutput = true) {
assertTasksExecuted(":compileKotlinJvm6")
assert(output.contains("-opt-in another.custom.UnderOptIn,my.custom.OptInAnnotation")) {
printBuildOutput()
"Output does not contain '-opt-in another.custom.UnderOptIn,my.custom.OptInAnnotation'!"
}
}
}
}
@DisplayName("Should combine -opt-in arguments from languageSettings DSL for Native")
@MppGradlePluginTests
@GradleTest
fun combinesOptInFromLanguageSettingsNative(gradleVersion: GradleVersion) {
project(
projectName = "new-mpp-lib-and-app/sample-lib",
gradleVersion = gradleVersion
) {
buildGradle.appendText(
//language=Groovy
"""
|
|kotlin {
| sourceSets {
| nativeMain {
| languageSettings.optIn("my.custom.OptInAnnotation")
| }
| linux64Main {
| languageSettings.optIn("my.custom.OptInAnnotation")
| }
| macos64Main {
| languageSettings.optIn("my.custom.OptInAnnotation")
| }
| }
|}
|
|tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class).configureEach {
| compilerOptions.optIn.add("another.custom.UnderOptIn")
|}
""".trimMargin()
)
build("compileNativeMainKotlinMetadata") {
assertTasksExecuted(":compileNativeMainKotlinMetadata")
assert(
output.contains("-opt-in=another.custom.UnderOptIn") &&
output.contains("-opt-in=my.custom.OptInAnnotation")
) {
printBuildOutput()
"Output does not contain '-opt-in=another.custom.UnderOptIn, -opt-in=my.custom.OptInAnnotation'!"
}
}
build("compileKotlinLinux64") {
assertTasksExecuted(":compileKotlinLinux64")
assert(
output.contains("-opt-in=another.custom.UnderOptIn") &&
output.contains("-opt-in=my.custom.OptInAnnotation")
) {
printBuildOutput()
"Output does not contain '-opt-in=another.custom.UnderOptIn, -opt-in=my.custom.OptInAnnotation'!"
}
}
}
}
@DisplayName("Should pass -opt-in from compiler options DSL in native project")
@NativeGradlePluginTests
@GradleTest
fun passesOptInAnnotationNative(gradleVersion: GradleVersion) {
nativeProject(
projectName = "native-link-simple",
gradleVersion = gradleVersion,
) {
buildGradle.appendText(
"""
|
|tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class).configureEach {
| compilerOptions.optIn.addAll("kotlin.RequiresOptIn", "my.CustomOptIn")
|}
""".trimMargin()
)
build("compileKotlinHost", forceOutput = true) {
val expectedOptIn = listOf("-opt-in=kotlin.RequiresOptIn", "-opt-in=my.CustomOptIn")
val optInArgs = output
.substringAfter("Arguments = [")
.substringBefore("]")
.lines()
.filter { it.trim() in expectedOptIn }
assert(optInArgs.size == 2) {
printBuildOutput()
"compiler arguments does not contain '${expectedOptIn.joinToString()}': ${optInArgs.joinToString()}"
}
}
}
}
}
@@ -810,11 +810,24 @@ open class NewMultiplatformIT : BaseGradleIT() {
)
listOf(
"compileCommonMainKotlinMetadata", "compileKotlinJvm6", "compileKotlinNodeJs", "compileKotlinLinux64"
"compileCommonMainKotlinMetadata", "compileKotlinJvm6", "compileKotlinNodeJs"
).forEach {
build(it) {
assertSuccessful()
assertTasksExecuted(":$it")
assertContains(
"-XXLanguage:+InlineClasses",
"-progressive",
"-opt-in kotlin.ExperimentalUnsignedTypes,kotlin.contracts.ExperimentalContracts",
"-Xno-inline"
)
}
}
listOf("compileNativeMainKotlinMetadata", "compileKotlinLinux64").forEach { task ->
build(task) {
assertSuccessful()
assertTasksExecuted(":$task")
assertContains(
"-XXLanguage:+InlineClasses",
"-progressive", "-opt-in=kotlin.ExperimentalUnsignedTypes",
@@ -1237,12 +1250,12 @@ open class NewMultiplatformIT : BaseGradleIT() {
}
assertEquals(
setOf("commonMain"),
setOf("commonMain", "nativeMain"),
sourceJarSourceRoots[null]
)
assertEquals(setOf("commonMain", "jvm6Main"), sourceJarSourceRoots["jvm6"])
assertEquals(setOf("commonMain", "nodeJsMain"), sourceJarSourceRoots["nodejs"])
assertEquals(setOf("commonMain", "linux64Main"), sourceJarSourceRoots["linux64"])
assertEquals(setOf("commonMain", "nativeMain", "linux64Main"), sourceJarSourceRoots["linux64"])
}
}
@@ -96,6 +96,10 @@ kotlin {
}
}
}
nativeMain { dependsOn commonMain }
linux64Main { dependsOn nativeMain }
macos64Main { dependsOn nativeMain }
}
}
@@ -0,0 +1,5 @@
package com.example.lib
fun welcomeToThisWorld() {
println("Hello world")
}
@@ -15,6 +15,9 @@ internal abstract class KotlinCommonCompilerOptionsDefault @javax.inject.Inject
override val languageVersion: org.gradle.api.provider.Property<org.jetbrains.kotlin.gradle.dsl.KotlinVersion> =
objectFactory.property(org.jetbrains.kotlin.gradle.dsl.KotlinVersion::class.java)
override val optIn: org.gradle.api.provider.ListProperty<kotlin.String> =
objectFactory.listProperty(kotlin.String::class.java).convention(emptyList<String>())
@Deprecated(message = "Compiler flag -Xuse-k2 is deprecated; please use language version 2.0 instead", level = DeprecationLevel.WARNING)
override val useK2: org.gradle.api.provider.Property<kotlin.Boolean> =
objectFactory.property(kotlin.Boolean::class.java).convention(false)
@@ -23,6 +26,7 @@ internal abstract class KotlinCommonCompilerOptionsDefault @javax.inject.Inject
super.fillCompilerArguments(args)
args.apiVersion = apiVersion.orNull?.version
args.languageVersion = languageVersion.orNull?.version
args.optIn = optIn.get().toTypedArray()
args.useK2 = useK2.get()
}
@@ -30,6 +34,7 @@ internal abstract class KotlinCommonCompilerOptionsDefault @javax.inject.Inject
super.fillDefaultValues(args)
args.apiVersion = null
args.languageVersion = null
args.optIn = emptyList<String>().toTypedArray()
args.useK2 = false
}
}
@@ -106,6 +106,7 @@ internal fun applyLanguageSettingsToCompilerOptions(
) = with(compilerOptions) {
languageVersion.convention(languageSettingsBuilder.languageVersion?.let { KotlinVersion.fromVersion(it) })
apiVersion.convention(languageSettingsBuilder.apiVersion?.let { KotlinVersion.fromVersion(it) })
optIn.addAll(languageSettingsBuilder.optInAnnotationsInUse)
val freeArgs = mutableListOf<String>().apply {
if (languageSettingsBuilder.progressiveMode) {
@@ -116,10 +117,6 @@ internal fun applyLanguageSettingsToCompilerOptions(
add("-XXLanguage:+$featureName")
}
languageSettingsBuilder.optInAnnotationsInUse.forEach { annotationName ->
add("-opt-in=$annotationName")
}
if (languageSettingsBuilder is DefaultLanguageSettingsBuilder) {
addAll(languageSettingsBuilder.freeCompilerArgs)
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.*
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
import org.jetbrains.kotlin.gradle.targets.native.internal.*
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.getResolvedArtifactsCompat
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
@@ -81,8 +82,7 @@ class KotlinMetadataTargetConfigurator :
compileKotlinTaskProvider.configure { it.onlyIf { isCompatibilityMetadataVariantEnabled } }
}
val allMetadataJar = target.project.tasks.withType<Jar>().named(ALL_METADATA_JAR_NAME)
val allMetadataJar = target.project.tasks.named<Jar>(ALL_METADATA_JAR_NAME)
createMetadataCompilationsForCommonSourceSets(target, allMetadataJar)
configureProjectStructureMetadataGeneration(target.project, allMetadataJar)
@@ -319,6 +319,15 @@ class KotlinMetadataTargetConfigurator :
compileDependencyFiles = project.files()
}
}
target.project.runOnceAfterEvaluated("Sync common compilation language settings to compiler options") {
target.compilations.all { compilation ->
applyLanguageSettingsToCompilerOptions(
compilation.defaultSourceSet.languageSettings,
compilation.compilerOptions.options
)
}
}
}
}
@@ -180,7 +180,6 @@ internal fun buildKotlinNativeCompileCommonArgs(
languageSettings.run {
addKey("-progressive", progressiveMode)
enabledLanguageFeatures.forEach { add("-XXLanguage:+$it") }
optInAnnotationsInUse.forEach { add("-opt-in=$it") }
}
addArgIfNotNull("-language-version", compilerOptions.languageVersion.orNull?.version)
@@ -188,6 +187,7 @@ internal fun buildKotlinNativeCompileCommonArgs(
addKey("-Werror", compilerOptions.allWarningsAsErrors.get())
addKey("-nowarn", compilerOptions.suppressWarnings.get())
addKey("-verbose", compilerOptions.verbose.get())
compilerOptions.optIn.get().forEach { add("-opt-in=$it") }
addAll(compilerOptions.freeCompilerArgs.get())
}
@@ -379,8 +379,12 @@ internal constructor(
val enabledLanguageFeatures: Set<String>
@Input get() = languageSettings.enabledLanguageFeatures
@Deprecated(
message = "Replaced with compilerOptions.optIn",
replaceWith = ReplaceWith("compilerOptions.optIn")
)
val optInAnnotationsInUse: Set<String>
@Input get() = languageSettings.optInAnnotationsInUse
@Internal get() = compilerOptions.optIn.get().toSet()
// endregion.
// region Kotlin options