Allow to force values in kotlin-compiler-arguments-plugin

Added readme how to use with external projects
This commit is contained in:
Yahor Berdnikau
2023-03-24 16:08:04 +01:00
committed by Space Team
parent ca59092318
commit b5e36a3c1b
4 changed files with 111 additions and 26 deletions
@@ -1,3 +1,49 @@
## Description
Contains a plugin for Gradle tests to set Kotlin arguments (api and language version) via 'gradle.properties'
Contains a plugin for Gradle tests to set Kotlin arguments (api and language version) via 'gradle.properties'
or via `-P` command line flag.
### Available properties
- `kotlin.test.languageVersion` - sets `-language-version` to the given value
- `kotlin.test.apiVersion` - sets '-api-version' to the given value
- `kotlin.test.overrideUserValue` - make the best effort to override values set explicitly by the user in the build script
### Plugin usage in the external projects
Plugin is also possible to use not only in the tests, but on the external projects.
To do this follow these steps:
- Run `./gradlew :gradle:kotlin-compiler-args-properties:install` (short variant `./gradlew :gr:k-c-a-p:i`)
- In the external project modify `settings.gradle.kts` following way:
```kotlin
pluginManagement {
repositories {
mavenLocal()
// other repos defined by the project
}
plugins {
id("org.jetbrains.kotlin.test.kotlin-compiler-args-properties") version "1.9.255-SNAPSHOT"
// other plugin declarations by the project
}
}
```
- In the external project modify root `build.gradle.kts` following way:
```kotlin
plugins {
id("org.jetbrains.kotlin.test.kotlin-compiler-args-properties")
// Other plugin declarations by the project
}
allprojects {
apply(plugin = "org.jetbrains.kotlin.test.kotlin-compiler-args-properties")
repositories {
mavenLocal()
}
}
```
This plugin should be also added similar way into any included build.
**NOTE**: Build logic (for example `buildSrc`) and projects building Gradle plugins written in Kotlin should not apply this plugin,
as Gradle Kotlin runtime most probably will not be compatible with values under-the-test (for example language version '2.0').
@@ -7,7 +7,7 @@ plugins {
dependencies {
commonApi(project(":kotlin-gradle-plugin-api"))
commonApi(project(":kotlin-gradle-plugin"))
commonCompileOnly(project(":kotlin-gradle-plugin"))
commonCompileOnly(gradleKotlinDsl())
}
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.gradle.arguments
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.provider.ProviderFactory
import org.gradle.kotlin.dsl.withType
@@ -30,12 +30,27 @@ class GradleKotlinCompilerArgumentsPlugin @Inject constructor(
}
private fun Project.configureKotlinVersions(properties: KotlinTaskProperties) {
plugins.withType<KotlinBasePlugin>().configureEach(configureTask(properties))
plugins.withType<KotlinBasePlugin>().configureEach {
if (properties.kotlinOverrideUserValues.get()) {
forceConfigureTask(properties)
} else {
configureTask(properties)
}
}
}
private fun Project.configureTask(properties: KotlinTaskProperties): Action<KotlinBasePlugin> = Action {
private fun Project.configureTask(properties: KotlinTaskProperties) {
tasks.withType<KotlinCompilationTask<*>>().configureEach {
configureKotlinOption(properties, it.compilerOptions)
configureKotlinOptions(properties, it.compilerOptions)
}
}
private fun Project.forceConfigureTask(properties: KotlinTaskProperties) {
// Wrapping into afterEvaluate to reduce amount of exception trying to modify value from the user-script
afterEvaluate {
tasks.withType<KotlinCompilationTask<*>>().configureEach {
configureKotlinOptions(properties, it.compilerOptions, true)
}
}
}
@@ -51,8 +66,21 @@ class GradleKotlinCompilerArgumentsPlugin @Inject constructor(
return extensions.projectCompilerOptions()?.apiVersion ?: providers.provider { null }
}
private fun Project.configureKotlinOption(properties: KotlinTaskProperties, taskOptions: KotlinCommonCompilerOptions) {
taskOptions.languageVersion.convention(properties.kotlinLanguageVersion.orElse(projectLevelLanguageVersion()))
taskOptions.apiVersion.convention(properties.kotlinApiVersion.orElse(projectLevelApiVersion()))
private fun Project.configureKotlinOptions(
properties: KotlinTaskProperties,
taskOptions: KotlinCommonCompilerOptions,
shouldSetValue: Boolean = false
) {
taskOptions.languageVersion.configureValue(properties.kotlinLanguageVersion.orElse(projectLevelLanguageVersion()), shouldSetValue)
taskOptions.apiVersion.configureValue(properties.kotlinApiVersion.orElse(projectLevelApiVersion()), shouldSetValue)
}
private fun <T : Any> Property<T>.configureValue(
source: Provider<T>,
shouldSetValue: Boolean
): Property<T> = if (shouldSetValue) {
value(source)
} else {
convention(source)
}
}
@@ -10,26 +10,37 @@ import org.gradle.api.provider.ProviderFactory
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
class KotlinTaskProperties(providerFactory: ProviderFactory) {
val kotlinLanguageVersion: Provider<KotlinVersion> = readKotlinVersionProperty(KOTLIN_LANGUAGE_VERSION_PROPERTY, providerFactory)
val kotlinApiVersion: Provider<KotlinVersion> = readKotlinVersionProperty(KOTLIN_API_VERSION_PROPERTY, providerFactory)
class KotlinTaskProperties(
private val providerFactory: ProviderFactory
) {
private val toKotlinVersionMapper: (String) -> KotlinVersion = { KotlinVersion.fromVersion(it) }
private val toBooleanMapper: (String) -> Boolean = { it.toBoolean() }
val kotlinLanguageVersion: Provider<KotlinVersion> = readProperty(KOTLIN_LANGUAGE_VERSION_PROPERTY, toKotlinVersionMapper)
val kotlinApiVersion: Provider<KotlinVersion> = readProperty(KOTLIN_API_VERSION_PROPERTY, toKotlinVersionMapper)
val kotlinOverrideUserValues: Provider<Boolean> = readProperty(KOTLIN_OVERRIDE_USER_VALUES, toBooleanMapper).orElse(false)
private fun <T : Any> readProperty(
propertyName: String,
mapper: (String) -> T
): Provider<T> {
return providerFactory.gradleProperty(propertyName)
.configurationCacheCompat<String>()
.map(mapper)
}
private fun <T : Any> Provider<T>.configurationCacheCompat(): Provider<T> {
return if (GradleVersion.current() < GradleVersion.version("7.4")) {
@Suppress("DEPRECATION")
this.forUseAtConfigurationTime()
} else {
this
}
}
companion object {
private const val KOTLIN_LANGUAGE_VERSION_PROPERTY = "kotlin.test.languageVersion"
private const val KOTLIN_API_VERSION_PROPERTY = "kotlin.test.apiVersion"
@Suppress("DEPRECATION")
private fun readKotlinVersionProperty(propertyName: String, providerFactory: ProviderFactory): Provider<KotlinVersion> {
return if (GradleVersion.current() < GradleVersion.version("7.4")) {
providerFactory.gradleProperty(propertyName)
.forUseAtConfigurationTime()
.map { KotlinVersion.fromVersion(it as String) }
} else {
providerFactory.gradleProperty(propertyName)
.map { KotlinVersion.fromVersion(it as String) }
}
}
private const val KOTLIN_OVERRIDE_USER_VALUES = "kotlin.test.overrideUserValues"
}
}