Introduce Kotlin compiler options with Gradle Properties API types
Old one is deprecated and delegates to new options. All new options are marked with task input types, so they could be used as `@Nested` input. Generated options are using specific types in generated compiler options. This should simplify code completion and provide meaningful hints to user. At this point repository compilation will fail. ^KT-27301 In Progress
This commit is contained in:
+603
-183
@@ -11,149 +11,110 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.util.*
|
||||
import kotlin.reflect.KAnnotatedElement
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.KVisibility
|
||||
import kotlin.reflect.full.declaredMemberProperties
|
||||
import kotlin.reflect.full.withNullability
|
||||
|
||||
// Additional properties that should be included in interface
|
||||
@Suppress("unused")
|
||||
interface AdditionalGradleProperties {
|
||||
@GradleOption(EmptyList::class)
|
||||
@GradleOption(
|
||||
value = DefaultValues.EmptyStringListDefault::class,
|
||||
gradleInputType = GradleInputTypes.INPUT
|
||||
)
|
||||
@Argument(value = "", description = "A list of additional compiler arguments")
|
||||
var freeCompilerArgs: List<String>
|
||||
|
||||
object EmptyList : DefaultValues("emptyList()")
|
||||
}
|
||||
|
||||
private data class GeneratedOptions(
|
||||
val optionsName: FqName,
|
||||
val deprecatedOptionsName: FqName,
|
||||
val properties: List<KProperty1<*, *>>
|
||||
)
|
||||
|
||||
private const val GRADLE_API_SRC_DIR = "libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin"
|
||||
private const val GRADLE_PLUGIN_SRC_DIR = "libraries/tools/kotlin-gradle-plugin/src/common/kotlin"
|
||||
private const val OPTIONS_PACKAGE_PREFIX = "org.jetbrains.kotlin.gradle.dsl"
|
||||
private const val IMPLEMENTATION_SUFFIX = "Default"
|
||||
|
||||
fun generateKotlinGradleOptions(withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit) {
|
||||
val apiSrcDir = File("libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin")
|
||||
val srcDir = File("libraries/tools/kotlin-gradle-plugin/src/common/kotlin")
|
||||
val apiSrcDir = File(GRADLE_API_SRC_DIR)
|
||||
val srcDir = File(GRADLE_PLUGIN_SRC_DIR)
|
||||
|
||||
// common interface
|
||||
val commonInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions")
|
||||
val commonOptions = gradleOptions<CommonToolArguments>()
|
||||
val additionalOptions = gradleOptions<AdditionalGradleProperties>()
|
||||
withPrinterToFile(file(apiSrcDir, commonInterfaceFqName)) {
|
||||
generateInterface(
|
||||
commonInterfaceFqName,
|
||||
commonOptions + additionalOptions
|
||||
)
|
||||
}
|
||||
val commonToolOptions = generateKotlinCommonToolOptions(apiSrcDir, withPrinterToFile)
|
||||
val commonToolImplFqName = generateKotlinCommonToolOptionsImpl(
|
||||
srcDir,
|
||||
commonToolOptions.optionsName,
|
||||
commonToolOptions.properties,
|
||||
withPrinterToFile
|
||||
)
|
||||
|
||||
println("### Attributes common for JVM, JS, and JS DCE\n")
|
||||
generateMarkdown(commonOptions + additionalOptions)
|
||||
val commonCompilerOptions = generateKotlinCommonOptions(
|
||||
apiSrcDir,
|
||||
commonToolOptions,
|
||||
withPrinterToFile
|
||||
)
|
||||
val commonCompilerOptionsImplFqName = generateKotlinCommonOptionsImpl(
|
||||
srcDir,
|
||||
commonCompilerOptions.optionsName,
|
||||
commonToolImplFqName,
|
||||
commonCompilerOptions.properties,
|
||||
withPrinterToFile
|
||||
)
|
||||
|
||||
val commonCompilerInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions")
|
||||
val commonCompilerOptions = gradleOptions<CommonCompilerArguments>()
|
||||
withPrinterToFile(file(apiSrcDir, commonCompilerInterfaceFqName)) {
|
||||
generateInterface(
|
||||
commonCompilerInterfaceFqName,
|
||||
commonCompilerOptions,
|
||||
parentType = commonInterfaceFqName
|
||||
)
|
||||
}
|
||||
val jvmOptions = generateKotlinJvmOptions(
|
||||
apiSrcDir,
|
||||
commonCompilerOptions,
|
||||
withPrinterToFile
|
||||
)
|
||||
generateKotlinJvmOptionsImpl(
|
||||
srcDir,
|
||||
jvmOptions.optionsName,
|
||||
commonCompilerOptionsImplFqName,
|
||||
jvmOptions.properties,
|
||||
withPrinterToFile
|
||||
)
|
||||
|
||||
println("\n### Attributes common for JVM and JS\n")
|
||||
generateMarkdown(commonCompilerOptions)
|
||||
val jsOptions = generateKotlinJsOptions(
|
||||
apiSrcDir,
|
||||
commonCompilerOptions,
|
||||
withPrinterToFile
|
||||
)
|
||||
generateKotlinJsOptionsImpl(
|
||||
srcDir,
|
||||
jsOptions.optionsName,
|
||||
commonCompilerOptionsImplFqName,
|
||||
jsOptions.properties,
|
||||
withPrinterToFile
|
||||
)
|
||||
|
||||
// generate jvm interface
|
||||
val jvmInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions")
|
||||
val jvmOptions = gradleOptions<K2JVMCompilerArguments>()
|
||||
withPrinterToFile(file(apiSrcDir, jvmInterfaceFqName)) {
|
||||
generateInterface(
|
||||
jvmInterfaceFqName,
|
||||
jvmOptions,
|
||||
parentType = commonCompilerInterfaceFqName
|
||||
)
|
||||
}
|
||||
|
||||
// generate jvm impl
|
||||
val k2JvmCompilerArgumentsFqName = FqName(K2JVMCompilerArguments::class.qualifiedName!!)
|
||||
val jvmImplFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsBase")
|
||||
withPrinterToFile(file(srcDir, jvmImplFqName)) {
|
||||
generateImpl(
|
||||
jvmImplFqName,
|
||||
jvmInterfaceFqName,
|
||||
k2JvmCompilerArgumentsFqName,
|
||||
commonOptions + commonCompilerOptions + jvmOptions
|
||||
)
|
||||
}
|
||||
|
||||
println("\n### Attributes specific for JVM\n")
|
||||
generateMarkdown(jvmOptions)
|
||||
|
||||
// generate js interface
|
||||
val jsInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJsOptions")
|
||||
val jsOptions = gradleOptions<K2JSCompilerArguments>()
|
||||
withPrinterToFile(file(apiSrcDir, jsInterfaceFqName)) {
|
||||
generateInterface(
|
||||
jsInterfaceFqName,
|
||||
jsOptions,
|
||||
parentType = commonCompilerInterfaceFqName
|
||||
)
|
||||
}
|
||||
|
||||
val k2JsCompilerArgumentsFqName = FqName(K2JSCompilerArguments::class.qualifiedName!!)
|
||||
val jsImplFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJsOptionsBase")
|
||||
withPrinterToFile(file(srcDir, jsImplFqName)) {
|
||||
generateImpl(
|
||||
jsImplFqName,
|
||||
jsInterfaceFqName,
|
||||
k2JsCompilerArgumentsFqName,
|
||||
commonOptions + commonCompilerOptions + jsOptions
|
||||
)
|
||||
}
|
||||
|
||||
println("\n### Attributes specific for JS\n")
|
||||
generateMarkdown(jsOptions)
|
||||
|
||||
// generate JS DCE interface and implementation
|
||||
val jsDceInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptions")
|
||||
val jsDceOptions = gradleOptions<K2JSDceArguments>()
|
||||
withPrinterToFile(file(apiSrcDir, jsDceInterfaceFqName)) {
|
||||
generateInterface(
|
||||
jsDceInterfaceFqName,
|
||||
jsDceOptions,
|
||||
parentType = commonInterfaceFqName
|
||||
)
|
||||
}
|
||||
|
||||
val k2JsDceArgumentsFqName = FqName(K2JSDceArguments::class.qualifiedName!!)
|
||||
val jsDceImplFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptionsBase")
|
||||
withPrinterToFile(file(srcDir, jsDceImplFqName)) {
|
||||
generateImpl(
|
||||
jsDceImplFqName,
|
||||
jsDceInterfaceFqName,
|
||||
k2JsDceArgumentsFqName,
|
||||
commonOptions + jsDceOptions
|
||||
)
|
||||
}
|
||||
|
||||
// generate multiplatform common interface and implementation
|
||||
val multiplatformCommonInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformCommonOptions")
|
||||
val multiplatformCommonOptions = gradleOptions<K2MetadataCompilerArguments>()
|
||||
withPrinterToFile(file(srcDir, multiplatformCommonInterfaceFqName)) {
|
||||
generateInterface(
|
||||
multiplatformCommonInterfaceFqName,
|
||||
multiplatformCommonOptions,
|
||||
parentType = commonCompilerInterfaceFqName
|
||||
)
|
||||
}
|
||||
|
||||
val k2metadataCompilerArgumentsFqName = FqName(K2MetadataCompilerArguments::class.qualifiedName!!)
|
||||
val multiplatformCommonImplFqName = FqName(multiplatformCommonInterfaceFqName.asString() + "Base")
|
||||
withPrinterToFile(file(srcDir, multiplatformCommonImplFqName)) {
|
||||
generateImpl(
|
||||
multiplatformCommonImplFqName,
|
||||
multiplatformCommonInterfaceFqName,
|
||||
k2metadataCompilerArgumentsFqName,
|
||||
commonOptions + commonCompilerOptions + multiplatformCommonOptions
|
||||
)
|
||||
}
|
||||
val jsDceOptions = generateJsDceOptions(
|
||||
apiSrcDir,
|
||||
commonToolOptions,
|
||||
withPrinterToFile
|
||||
)
|
||||
generateJsDceOptionsImpl(
|
||||
srcDir,
|
||||
jsDceOptions.optionsName,
|
||||
commonCompilerOptionsImplFqName,
|
||||
jsDceOptions.properties,
|
||||
withPrinterToFile
|
||||
)
|
||||
|
||||
val multiplatformCommonOptions = generateMultiplatformCommonOptions(
|
||||
apiSrcDir,
|
||||
commonCompilerOptions,
|
||||
withPrinterToFile
|
||||
)
|
||||
generateMultiplatformCommonOptionsImpl(
|
||||
srcDir,
|
||||
multiplatformCommonOptions.optionsName,
|
||||
commonCompilerOptionsImplFqName,
|
||||
multiplatformCommonOptions.properties,
|
||||
withPrinterToFile
|
||||
)
|
||||
}
|
||||
|
||||
fun main() {
|
||||
@@ -171,6 +132,314 @@ fun main() {
|
||||
generateKotlinGradleOptions(::getPrinter)
|
||||
}
|
||||
|
||||
private fun generateKotlinCommonToolOptions(
|
||||
apiSrcDir: File,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
): GeneratedOptions {
|
||||
val commonInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.CompilerCommonToolOptions")
|
||||
val commonOptions = gradleOptions<CommonToolArguments>()
|
||||
val additionalOptions = gradleOptions<AdditionalGradleProperties>()
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, commonInterfaceFqName)) {
|
||||
generateInterface(
|
||||
commonInterfaceFqName,
|
||||
commonOptions + additionalOptions
|
||||
)
|
||||
}
|
||||
|
||||
val deprecatedCommonInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.KotlinCommonToolOptions")
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, deprecatedCommonInterfaceFqName)) {
|
||||
generateDeprecatedInterface(
|
||||
deprecatedCommonInterfaceFqName,
|
||||
commonInterfaceFqName,
|
||||
commonOptions + additionalOptions,
|
||||
parentType = null,
|
||||
)
|
||||
}
|
||||
|
||||
println("### Attributes common for JVM, JS, and JS DCE\n")
|
||||
generateMarkdown(commonOptions + additionalOptions)
|
||||
|
||||
return GeneratedOptions(commonInterfaceFqName, deprecatedCommonInterfaceFqName, (commonOptions + additionalOptions))
|
||||
}
|
||||
|
||||
private fun generateKotlinCommonToolOptionsImpl(
|
||||
srcDir: File,
|
||||
commonToolOptionsInterfaceFqName: FqName,
|
||||
options: List<KProperty1<*, *>>,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
): FqName {
|
||||
val k2CommonToolCompilerArgumentsFqName = FqName(CommonToolArguments::class.qualifiedName!!)
|
||||
val commonToolImplFqName = FqName("${commonToolOptionsInterfaceFqName.asString()}$IMPLEMENTATION_SUFFIX")
|
||||
withPrinterToFile(fileFromFqName(srcDir, commonToolImplFqName)) {
|
||||
generateImpl(
|
||||
commonToolImplFqName,
|
||||
null,
|
||||
commonToolOptionsInterfaceFqName,
|
||||
k2CommonToolCompilerArgumentsFqName,
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
return commonToolImplFqName
|
||||
}
|
||||
|
||||
private fun generateKotlinCommonOptions(
|
||||
apiSrcDir: File,
|
||||
commonToolGeneratedOptions: GeneratedOptions,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
): GeneratedOptions {
|
||||
val commonCompilerInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.CompilerCommonOptions")
|
||||
val commonCompilerOptions = gradleOptions<CommonCompilerArguments>()
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, commonCompilerInterfaceFqName)) {
|
||||
generateInterface(
|
||||
commonCompilerInterfaceFqName,
|
||||
commonCompilerOptions,
|
||||
parentType = commonToolGeneratedOptions.optionsName,
|
||||
)
|
||||
}
|
||||
|
||||
val deprecatedCommonCompilerInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.KotlinCommonOptions")
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, deprecatedCommonCompilerInterfaceFqName)) {
|
||||
generateDeprecatedInterface(
|
||||
deprecatedCommonCompilerInterfaceFqName,
|
||||
commonCompilerInterfaceFqName,
|
||||
commonCompilerOptions,
|
||||
parentType = commonToolGeneratedOptions.deprecatedOptionsName
|
||||
)
|
||||
}
|
||||
|
||||
println("\n### Attributes common for JVM and JS\n")
|
||||
generateMarkdown(commonCompilerOptions)
|
||||
|
||||
return GeneratedOptions(commonCompilerInterfaceFqName, deprecatedCommonCompilerInterfaceFqName, commonCompilerOptions)
|
||||
}
|
||||
|
||||
private fun generateKotlinCommonOptionsImpl(
|
||||
srcDir: File,
|
||||
commonOptionsInterfaceFqName: FqName,
|
||||
commonToolImpl: FqName,
|
||||
options: List<KProperty1<*, *>>,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
): FqName {
|
||||
val k2CommonCompilerArgumentsFqName = FqName(CommonCompilerArguments::class.qualifiedName!!)
|
||||
val commonCompilerImplFqName = FqName("${commonOptionsInterfaceFqName.asString()}$IMPLEMENTATION_SUFFIX")
|
||||
withPrinterToFile(fileFromFqName(srcDir, commonCompilerImplFqName)) {
|
||||
generateImpl(
|
||||
commonCompilerImplFqName,
|
||||
commonToolImpl,
|
||||
commonOptionsInterfaceFqName,
|
||||
k2CommonCompilerArgumentsFqName,
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
return commonCompilerImplFqName
|
||||
}
|
||||
|
||||
private fun generateKotlinJvmOptions(
|
||||
apiSrcDir: File,
|
||||
commonCompilerGeneratedOptions: GeneratedOptions,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
): GeneratedOptions {
|
||||
val jvmInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.CompilerJvmOptions")
|
||||
val jvmOptions = gradleOptions<K2JVMCompilerArguments>()
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, jvmInterfaceFqName)) {
|
||||
generateInterface(
|
||||
jvmInterfaceFqName,
|
||||
jvmOptions,
|
||||
parentType = commonCompilerGeneratedOptions.optionsName,
|
||||
)
|
||||
}
|
||||
|
||||
val deprecatedJvmInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.KotlinJvmOptions")
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, deprecatedJvmInterfaceFqName)) {
|
||||
generateDeprecatedInterface(
|
||||
deprecatedJvmInterfaceFqName,
|
||||
jvmInterfaceFqName,
|
||||
jvmOptions,
|
||||
parentType = commonCompilerGeneratedOptions.deprecatedOptionsName
|
||||
)
|
||||
}
|
||||
|
||||
println("\n### Attributes specific for JVM\n")
|
||||
generateMarkdown(jvmOptions)
|
||||
|
||||
return GeneratedOptions(jvmInterfaceFqName, deprecatedJvmInterfaceFqName, jvmOptions)
|
||||
}
|
||||
|
||||
private fun generateKotlinJvmOptionsImpl(
|
||||
srcDir: File,
|
||||
jvmInterfaceFqName: FqName,
|
||||
commonCompilerImpl: FqName,
|
||||
jvmOptions: List<KProperty1<*, *>>,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val k2JvmCompilerArgumentsFqName = FqName(K2JVMCompilerArguments::class.qualifiedName!!)
|
||||
val jvmImplFqName = FqName("${jvmInterfaceFqName.asString()}$IMPLEMENTATION_SUFFIX")
|
||||
withPrinterToFile(fileFromFqName(srcDir, jvmImplFqName)) {
|
||||
generateImpl(
|
||||
jvmImplFqName,
|
||||
commonCompilerImpl,
|
||||
jvmInterfaceFqName,
|
||||
k2JvmCompilerArgumentsFqName,
|
||||
jvmOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateKotlinJsOptions(
|
||||
apiSrcDir: File,
|
||||
commonCompilerOptions: GeneratedOptions,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
): GeneratedOptions {
|
||||
val jsInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.CompilerJsOptions")
|
||||
val jsOptions = gradleOptions<K2JSCompilerArguments>()
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, jsInterfaceFqName)) {
|
||||
generateInterface(
|
||||
jsInterfaceFqName,
|
||||
jsOptions,
|
||||
parentType = commonCompilerOptions.optionsName,
|
||||
)
|
||||
}
|
||||
|
||||
val deprecatedJsInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.KotlinJsOptions")
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, deprecatedJsInterfaceFqName)) {
|
||||
generateDeprecatedInterface(
|
||||
deprecatedJsInterfaceFqName,
|
||||
jsInterfaceFqName,
|
||||
jsOptions,
|
||||
parentType = commonCompilerOptions.deprecatedOptionsName,
|
||||
)
|
||||
}
|
||||
|
||||
println("\n### Attributes specific for JS\n")
|
||||
generateMarkdown(jsOptions)
|
||||
|
||||
return GeneratedOptions(jsInterfaceFqName, deprecatedJsInterfaceFqName, jsOptions)
|
||||
}
|
||||
|
||||
private fun generateKotlinJsOptionsImpl(
|
||||
srcDir: File,
|
||||
jsInterfaceFqName: FqName,
|
||||
commonCompilerImpl: FqName,
|
||||
jsOptions: List<KProperty1<*, *>>,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val k2JsCompilerArgumentsFqName = FqName(K2JSCompilerArguments::class.qualifiedName!!)
|
||||
val jsImplFqName = FqName("${jsInterfaceFqName.asString()}$IMPLEMENTATION_SUFFIX")
|
||||
withPrinterToFile(fileFromFqName(srcDir, jsImplFqName)) {
|
||||
generateImpl(
|
||||
jsImplFqName,
|
||||
commonCompilerImpl,
|
||||
jsInterfaceFqName,
|
||||
k2JsCompilerArgumentsFqName,
|
||||
jsOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateJsDceOptions(
|
||||
apiSrcDir: File,
|
||||
commonToolOptions: GeneratedOptions,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
): GeneratedOptions {
|
||||
val jsDceInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.CompilerJsDceOptions")
|
||||
val jsDceOptions = gradleOptions<K2JSDceArguments>()
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, jsDceInterfaceFqName)) {
|
||||
generateInterface(
|
||||
jsDceInterfaceFqName,
|
||||
jsDceOptions,
|
||||
parentType = commonToolOptions.optionsName,
|
||||
)
|
||||
}
|
||||
|
||||
val deprecatedJsDceInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.KotlinJsDceOptions")
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, deprecatedJsDceInterfaceFqName)) {
|
||||
generateDeprecatedInterface(
|
||||
deprecatedJsDceInterfaceFqName,
|
||||
jsDceInterfaceFqName,
|
||||
jsDceOptions,
|
||||
parentType = commonToolOptions.deprecatedOptionsName,
|
||||
)
|
||||
}
|
||||
|
||||
println("\n### Attributes specific for JS/DCE\n")
|
||||
generateMarkdown(jsDceOptions)
|
||||
|
||||
return GeneratedOptions(jsDceInterfaceFqName, deprecatedJsDceInterfaceFqName, jsDceOptions)
|
||||
}
|
||||
|
||||
private fun generateJsDceOptionsImpl(
|
||||
srcDir: File,
|
||||
jsDceInterfaceFqName: FqName,
|
||||
commonCompilerImpl: FqName,
|
||||
jsDceOptions: List<KProperty1<*, *>>,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val k2JsDceArgumentsFqName = FqName(K2JSDceArguments::class.qualifiedName!!)
|
||||
val jsDceImplFqName = FqName("${jsDceInterfaceFqName.asString()}$IMPLEMENTATION_SUFFIX")
|
||||
withPrinterToFile(fileFromFqName(srcDir, jsDceImplFqName)) {
|
||||
generateImpl(
|
||||
jsDceImplFqName,
|
||||
commonCompilerImpl,
|
||||
jsDceInterfaceFqName,
|
||||
k2JsDceArgumentsFqName,
|
||||
jsDceOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateMultiplatformCommonOptions(
|
||||
apiSrcDir: File,
|
||||
commonCompilerOptions: GeneratedOptions,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
): GeneratedOptions {
|
||||
val multiplatformCommonInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.CompilerMultiplatformCommonOptions")
|
||||
val multiplatformCommonOptions = gradleOptions<K2MetadataCompilerArguments>()
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, multiplatformCommonInterfaceFqName)) {
|
||||
generateInterface(
|
||||
multiplatformCommonInterfaceFqName,
|
||||
multiplatformCommonOptions,
|
||||
parentType = commonCompilerOptions.optionsName,
|
||||
)
|
||||
}
|
||||
|
||||
val deprecatedMultiplatformCommonInterfaceFqName = FqName("$OPTIONS_PACKAGE_PREFIX.KotlinMultiplatformCommonOptions")
|
||||
withPrinterToFile(fileFromFqName(apiSrcDir, deprecatedMultiplatformCommonInterfaceFqName)) {
|
||||
generateDeprecatedInterface(
|
||||
deprecatedMultiplatformCommonInterfaceFqName,
|
||||
multiplatformCommonInterfaceFqName,
|
||||
parentType = commonCompilerOptions.deprecatedOptionsName,
|
||||
properties = multiplatformCommonOptions
|
||||
)
|
||||
}
|
||||
|
||||
println("\n### Attributes specific for Multiplatform/Common\n")
|
||||
generateMarkdown(multiplatformCommonOptions)
|
||||
|
||||
return GeneratedOptions(multiplatformCommonInterfaceFqName, deprecatedMultiplatformCommonInterfaceFqName, multiplatformCommonOptions)
|
||||
}
|
||||
|
||||
private fun generateMultiplatformCommonOptionsImpl(
|
||||
srcDir: File,
|
||||
multiplatformCommonInterfaceFqName: FqName,
|
||||
commonCompilerImpl: FqName,
|
||||
multiplatformCommonOptions: List<KProperty1<*, *>>,
|
||||
withPrinterToFile: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val k2metadataCompilerArgumentsFqName = FqName(K2MetadataCompilerArguments::class.qualifiedName!!)
|
||||
val multiplatformCommonImplFqName = FqName("${multiplatformCommonInterfaceFqName.asString()}$IMPLEMENTATION_SUFFIX")
|
||||
withPrinterToFile(fileFromFqName(srcDir, multiplatformCommonImplFqName)) {
|
||||
generateImpl(
|
||||
multiplatformCommonImplFqName,
|
||||
commonCompilerImpl,
|
||||
multiplatformCommonInterfaceFqName,
|
||||
k2metadataCompilerArgumentsFqName,
|
||||
multiplatformCommonOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : Any> List<KProperty1<T, *>>.filterToBeDeleted() = filter { prop ->
|
||||
prop.findAnnotation<GradleDeprecatedOption>()
|
||||
?.let { LanguageVersion.fromVersionString(it.removeAfter) }
|
||||
@@ -179,110 +448,237 @@ private inline fun <reified T : Any> List<KProperty1<T, *>>.filterToBeDeleted()
|
||||
}
|
||||
|
||||
private inline fun <reified T : Any> gradleOptions(): List<KProperty1<T, *>> =
|
||||
T::class.declaredMemberProperties.filter { it.findAnnotation<GradleOption>() != null }.filterToBeDeleted().sortedBy { it.name }
|
||||
T::class
|
||||
.declaredMemberProperties
|
||||
.filter {
|
||||
it.findAnnotation<GradleOption>() != null
|
||||
}
|
||||
.filterToBeDeleted()
|
||||
.sortedBy { it.name }
|
||||
|
||||
internal fun file(baseDir: File, fqName: FqName): File {
|
||||
internal fun fileFromFqName(baseDir: File, fqName: FqName): File {
|
||||
val fileRelativePath = fqName.asString().replace(".", "/") + ".kt"
|
||||
return File(baseDir, fileRelativePath)
|
||||
}
|
||||
|
||||
private fun Printer.generateInterface(type: FqName, properties: List<KProperty1<*, *>>, parentType: FqName? = null) {
|
||||
private fun Printer.generateInterface(
|
||||
type: FqName,
|
||||
properties: List<KProperty1<*, *>>,
|
||||
parentType: FqName? = null,
|
||||
) {
|
||||
val afterType = parentType?.let { " : $it" }
|
||||
generateDeclaration("interface", type, afterType = afterType) {
|
||||
for (property in properties) {
|
||||
println()
|
||||
generateDoc(property)
|
||||
generateOptionDeprecation(property)
|
||||
generatePropertyDeclaration(property)
|
||||
generatePropertyProvider(property)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Printer.generateDeprecatedInterface(
|
||||
type: FqName,
|
||||
compilerOptionType: FqName,
|
||||
properties: List<KProperty1<*, *>>,
|
||||
parentType: FqName? = null,
|
||||
) {
|
||||
val afterType = parentType?.let { " : $it" }
|
||||
val modifier = """
|
||||
@Deprecated("Use ${compilerOptionType.shortName()} instead", level = DeprecationLevel.WARNING)
|
||||
interface
|
||||
""".trimIndent()
|
||||
generateDeclaration(modifier, type, afterType = afterType) {
|
||||
|
||||
println("${if (parentType != null) "override " else ""}val options: $compilerOptionType")
|
||||
properties.forEach {
|
||||
println()
|
||||
generatePropertyGetterAndSetter(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Printer.generateImpl(
|
||||
type: FqName,
|
||||
parentImplFqName: FqName?,
|
||||
parentType: FqName,
|
||||
argsType: FqName,
|
||||
properties: List<KProperty1<*, *>>
|
||||
) {
|
||||
generateDeclaration("internal abstract class", type, afterType = ": $parentType") {
|
||||
fun KProperty1<*, *>.backingField(): String = "${this.name}Field"
|
||||
|
||||
val modifiers = "internal abstract class"
|
||||
val afterType = if (parentImplFqName != null) {
|
||||
": $parentImplFqName(objectFactory), $parentType"
|
||||
} else {
|
||||
": $parentType"
|
||||
}
|
||||
generateDeclaration(
|
||||
modifiers,
|
||||
type,
|
||||
constructorDeclaration = "@javax.inject.Inject constructor(\n objectFactory: org.gradle.api.model.ObjectFactory\n)",
|
||||
afterType = afterType
|
||||
) {
|
||||
for (property in properties) {
|
||||
println()
|
||||
val propertyType = property.gradleReturnType
|
||||
if (propertyType.endsWith("?")) {
|
||||
generateOptionDeprecation(property)
|
||||
generatePropertyDeclaration(property, modifiers = "override", value = "null")
|
||||
} else {
|
||||
val backingField = property.backingField()
|
||||
val visibilityModified = property.gradleBackingFieldVisibility.name.lowercase(Locale.US)
|
||||
println("$visibilityModified var $backingField: $propertyType? = null")
|
||||
generateOptionDeprecation(property)
|
||||
generatePropertyDeclaration(property, modifiers = "override")
|
||||
withIndent {
|
||||
println("get() = $backingField ?: ${property.gradleDefaultValue}")
|
||||
println("set(value) {")
|
||||
withIndent { println("$backingField = value") }
|
||||
println("}")
|
||||
}
|
||||
}
|
||||
generatePropertyProviderImpl(property)
|
||||
}
|
||||
|
||||
println()
|
||||
println("internal open fun updateArguments(args: $argsType) {")
|
||||
println("internal fun fillCompilerArguments(args: $argsType) {")
|
||||
withIndent {
|
||||
if (parentImplFqName != null) println("super.fillCompilerArguments(args)")
|
||||
for (property in properties) {
|
||||
val backingField = if (property.gradleReturnType.endsWith("?")) property.name else property.backingField()
|
||||
println("$backingField?.let { args.${property.name} = it }")
|
||||
val defaultValue = property.gradleValues
|
||||
if (property.name != "freeCompilerArgs") {
|
||||
val getter = if (property.gradleReturnType.endsWith("?")) ".orNull" else ".get()"
|
||||
val toArg = defaultValue.toArgumentConverter?.substringAfter("this") ?: ""
|
||||
println("args.${property.name} = ${property.name}$getter$toArg")
|
||||
} else {
|
||||
println("args.freeArgs += ${property.name}.get()")
|
||||
}
|
||||
}
|
||||
|
||||
addAdditionalJvmArgs(type)
|
||||
}
|
||||
println("}")
|
||||
|
||||
println()
|
||||
println("internal fun fillDefaultValues(args: $argsType) {")
|
||||
withIndent {
|
||||
if (parentImplFqName != null) println("super.fillDefaultValues(args)")
|
||||
properties
|
||||
.filter { it.name != "freeCompilerArgs" }
|
||||
.forEach {
|
||||
val defaultValue = it.gradleValues
|
||||
var value = defaultValue.defaultValue
|
||||
if (value != "null" && defaultValue.toArgumentConverter != null) {
|
||||
value = "$value${defaultValue.toArgumentConverter!!.substringAfter("this")}"
|
||||
}
|
||||
println("args.${it.name} = $value")
|
||||
}
|
||||
|
||||
addAdditionalJvmArgs(type)
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
}
|
||||
|
||||
println()
|
||||
println("internal fun $argsType.fillDefaultValues() {")
|
||||
withIndent {
|
||||
for (property in properties) {
|
||||
println("${property.name} = ${property.gradleDefaultValue}")
|
||||
}
|
||||
// Adding required 'noStdlib' and 'noReflect' compiler arguments for JVM compilation
|
||||
// Otherwise compilation via build tools will fail
|
||||
if (type.shortName().toString() == "KotlinJvmOptionsBase") {
|
||||
println("noStdlib = true")
|
||||
println("noReflect = true")
|
||||
}
|
||||
private fun Printer.addAdditionalJvmArgs(implType: FqName) {
|
||||
// Adding required 'noStdlib' and 'noReflect' compiler arguments for JVM compilation
|
||||
// Otherwise compilation via build tools will fail
|
||||
if (implType.shortName().toString() == "CompilerJvmOptions$IMPLEMENTATION_SUFFIX") {
|
||||
println()
|
||||
println("// Arguments with always default values when used from build tools")
|
||||
println("args.noStdlib = true")
|
||||
println("args.noReflect = true")
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
|
||||
internal fun Printer.generateDeclaration(
|
||||
modifiers: String,
|
||||
type: FqName,
|
||||
constructorDeclaration: String? = null,
|
||||
afterType: String? = null,
|
||||
generateBody: Printer.() -> Unit
|
||||
) {
|
||||
println("// DO NOT EDIT MANUALLY!")
|
||||
println("// Generated by org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt")
|
||||
println(
|
||||
"""
|
||||
// DO NOT EDIT MANUALLY!
|
||||
// Generated by org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt
|
||||
// To regenerate run 'generateGradleOptions' task
|
||||
@file:Suppress("RemoveRedundantQualifierName", "Deprecation", "DuplicatedCode")
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
if (!type.parent().isRoot) {
|
||||
println("package ${type.parent()}")
|
||||
println()
|
||||
}
|
||||
println("@Suppress(\"DEPRECATION\")")
|
||||
print("$modifiers ${type.shortName()} ")
|
||||
afterType?.let { print("$afterType ") }
|
||||
println("{")
|
||||
print("$modifiers ${type.shortName()}")
|
||||
constructorDeclaration?.let { print(" $it ") }
|
||||
afterType?.let { print("$afterType") }
|
||||
println(" {")
|
||||
withIndent {
|
||||
generateBody()
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
|
||||
private fun Printer.generatePropertyDeclaration(property: KProperty1<*, *>, modifiers: String = "", value: String? = null) {
|
||||
val returnType = property.gradleReturnType
|
||||
val initialValue = if (value != null) " = $value" else ""
|
||||
println("$modifiers var ${property.name}: $returnType$initialValue")
|
||||
private fun Printer.generatePropertyProvider(
|
||||
property: KProperty1<*, *>,
|
||||
modifiers: String = ""
|
||||
) {
|
||||
if (property.gradleDefaultValue == "null" &&
|
||||
property.gradleInputType == GradleInputTypes.INPUT
|
||||
) {
|
||||
println("@get:org.gradle.api.tasks.Optional")
|
||||
}
|
||||
println("@get:${property.gradleInputType}")
|
||||
println("${modifiers.appendWhitespaceIfNotBlank}val ${property.name}: ${property.gradleLazyReturnType}")
|
||||
}
|
||||
|
||||
private fun Printer.generatePropertyProviderImpl(
|
||||
property: KProperty1<*, *>,
|
||||
modifiers: String = ""
|
||||
) {
|
||||
generateOptionDeprecation(property)
|
||||
println(
|
||||
"override ${modifiers.appendWhitespaceIfNotBlank}val ${property.name}: ${property.gradleLazyReturnType} ="
|
||||
)
|
||||
withIndent {
|
||||
val convention = if (property.gradleDefaultValue != "null") {
|
||||
".convention(${property.gradleDefaultValue})"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
println(
|
||||
"objectFactory${property.gradleLazyReturnTypeInstantiator}$convention"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Printer.generatePropertyGetterAndSetter(
|
||||
property: KProperty1<*, *>,
|
||||
modifiers: String = "",
|
||||
) {
|
||||
val defaultValue = property.gradleValues
|
||||
val returnType = property.gradleReturnType
|
||||
|
||||
if (defaultValue.type != defaultValue.kotlinOptionsType) {
|
||||
assert(defaultValue.fromKotlinOptionConverterProp != null)
|
||||
assert(defaultValue.toKotlinOptionConverterProp != null)
|
||||
}
|
||||
|
||||
if (defaultValue.fromKotlinOptionConverterProp != null) {
|
||||
println("private val ${defaultValue.kotlinOptionsType}.${property.name}CompilerOption get() = ${defaultValue.fromKotlinOptionConverterProp}")
|
||||
println()
|
||||
println("private val ${defaultValue.type}.${property.name}KotlinOption get() = ${defaultValue.toKotlinOptionConverterProp}")
|
||||
println()
|
||||
}
|
||||
|
||||
generateDoc(property)
|
||||
generateOptionDeprecation(property)
|
||||
println("${modifiers.appendWhitespaceIfNotBlank}var ${property.name}: $returnType")
|
||||
val propGetter = if (returnType.endsWith("?")) ".orNull" else ".get()"
|
||||
val getter = if (defaultValue.fromKotlinOptionConverterProp != null) {
|
||||
"$propGetter.${property.name}KotlinOption"
|
||||
} else {
|
||||
propGetter
|
||||
}
|
||||
val setter = if (defaultValue.toKotlinOptionConverterProp != null) {
|
||||
".set(value.${property.name}CompilerOption)"
|
||||
} else {
|
||||
".set(value)"
|
||||
}
|
||||
withIndent {
|
||||
println("get() = options.${property.name}$getter")
|
||||
println("set(value) = options.${property.name}$setter")
|
||||
}
|
||||
}
|
||||
|
||||
private val String.appendWhitespaceIfNotBlank get() = if (isNotBlank()) "$this " else ""
|
||||
|
||||
private fun Printer.generateOptionDeprecation(property: KProperty1<*, *>) {
|
||||
property.findAnnotation<GradleDeprecatedOption>()
|
||||
?.let { DeprecatedOptionAnnotator.generateOptionAnnotation(it) }
|
||||
@@ -335,15 +731,6 @@ private val KProperty1<*, *>.gradleValues: DefaultValues
|
||||
private val KProperty1<*, *>.gradleDefaultValue: String
|
||||
get() = gradleValues.defaultValue
|
||||
|
||||
private val KProperty1<*, *>.gradleBackingFieldVisibility: KVisibility
|
||||
get() {
|
||||
val fieldVisibility = findAnnotation<GradleOption>()!!.backingFieldVisibility
|
||||
require(fieldVisibility != KVisibility.PUBLIC) {
|
||||
"Backing field should not have public visibility!"
|
||||
}
|
||||
return fieldVisibility
|
||||
}
|
||||
|
||||
private val KProperty1<*, *>.gradleReturnType: String
|
||||
get() {
|
||||
// Set nullability based on Gradle default value
|
||||
@@ -354,6 +741,39 @@ private val KProperty1<*, *>.gradleReturnType: String
|
||||
return type
|
||||
}
|
||||
|
||||
private val KProperty1<*, *>.gradleLazyReturnType: String
|
||||
get() {
|
||||
val returnType = gradleValues.type
|
||||
val classifier = returnType.classifier
|
||||
return when {
|
||||
classifier is KClass<*> && classifier == List::class ->
|
||||
"org.gradle.api.provider.ListProperty<${returnType.arguments.first().type!!.withNullability(false)}>"
|
||||
classifier is KClass<*> && classifier == Set::class ->
|
||||
"org.gradle.api.provider.SetProperty<${returnType.arguments.first().type!!.withNullability(false)}>"
|
||||
classifier is KClass<*> && classifier == Map::class ->
|
||||
"org.gradle.api.provider.MapProperty<${returnType.arguments[0]}, ${returnType.arguments[1]}"
|
||||
else -> "org.gradle.api.provider.Property<${returnType.withNullability(false)}>"
|
||||
}
|
||||
}
|
||||
|
||||
private val KProperty1<*, *>.gradleLazyReturnTypeInstantiator: String
|
||||
get() {
|
||||
val returnType = gradleValues.type
|
||||
val classifier = returnType.classifier
|
||||
return when {
|
||||
classifier is KClass<*> && classifier == List::class ->
|
||||
".listProperty(${returnType.arguments.first().type!!.withNullability(false)}::class.java)"
|
||||
classifier is KClass<*> && classifier == Set::class ->
|
||||
".setProperty(${returnType.arguments.first().type!!.withNullability(false)}::class.java)"
|
||||
classifier is KClass<*> && classifier == Map::class ->
|
||||
".mapProperty(${returnType.arguments[0]}::class.java, ${returnType.arguments[1]}::class.java)"
|
||||
else -> ".property(${returnType.withNullability(false)}::class.java)"
|
||||
}
|
||||
}
|
||||
|
||||
private val KProperty1<*, *>.gradleInputType: String get() =
|
||||
findAnnotation<GradleOption>()!!.gradleInputType
|
||||
|
||||
private inline fun <reified T> KAnnotatedElement.findAnnotation(): T? =
|
||||
annotations.filterIsInstance<T>().firstOrNull()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ internal fun generateJsMainFunctionExecutionMode(
|
||||
filePrinter: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val modeFqName = FqName("org.jetbrains.kotlin.gradle.dsl.JsMainFunctionExecutionMode")
|
||||
filePrinter(file(apiDir, modeFqName)) {
|
||||
filePrinter(fileFromFqName(apiDir, modeFqName)) {
|
||||
generateDeclaration("enum class", modeFqName, afterType = "(val mode: String)") {
|
||||
val modes = hashMapOf(
|
||||
K2JsArgumentConstants::CALL.name to K2JsArgumentConstants.CALL,
|
||||
@@ -45,7 +45,7 @@ internal fun generateJsModuleKind(
|
||||
filePrinter: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val jsModuleKindFqName = FqName("org.jetbrains.kotlin.gradle.dsl.JsModuleKind")
|
||||
filePrinter(file(apiDir, jsModuleKindFqName)) {
|
||||
filePrinter(fileFromFqName(apiDir, jsModuleKindFqName)) {
|
||||
generateDeclaration("enum class", jsModuleKindFqName, afterType = "(val kind: String)") {
|
||||
val kinds = hashMapOf(
|
||||
K2JsArgumentConstants::MODULE_PLAIN.name to K2JsArgumentConstants.MODULE_PLAIN,
|
||||
@@ -78,7 +78,7 @@ internal fun generateJsSourceMapEmbedMode(
|
||||
filePrinter: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val jsSourceMapEmbedKindFqName = FqName("org.jetbrains.kotlin.gradle.dsl.JsSourceMapEmbedMode")
|
||||
filePrinter(file(apiDir, jsSourceMapEmbedKindFqName)) {
|
||||
filePrinter(fileFromFqName(apiDir, jsSourceMapEmbedKindFqName)) {
|
||||
generateDeclaration("enum class", jsSourceMapEmbedKindFqName, afterType = "(val mode: String)") {
|
||||
val modes = hashMapOf(
|
||||
K2JsArgumentConstants::SOURCE_MAP_SOURCE_CONTENT_ALWAYS.name to K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_ALWAYS,
|
||||
@@ -109,7 +109,7 @@ internal fun generateJsDiagnosticMode(
|
||||
filePrinter: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val diagnosticModeFqName = FqName("org.jetbrains.kotlin.gradle.dsl.JsDiagnosticMode")
|
||||
filePrinter(file(apiDir, diagnosticModeFqName)) {
|
||||
filePrinter(fileFromFqName(apiDir, diagnosticModeFqName)) {
|
||||
generateDeclaration("enum class", diagnosticModeFqName, afterType = "(val mode: String)") {
|
||||
val mods = hashMapOf(
|
||||
K2JsArgumentConstants::RUNTIME_DIAGNOSTIC_EXCEPTION.name to K2JsArgumentConstants.RUNTIME_DIAGNOSTIC_EXCEPTION,
|
||||
|
||||
@@ -15,7 +15,7 @@ internal fun generateJvmTarget(
|
||||
filePrinter: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val jvmTargetFqName = FqName("org.jetbrains.kotlin.gradle.dsl.JvmTarget")
|
||||
filePrinter(file(apiDir, jvmTargetFqName)) {
|
||||
filePrinter(fileFromFqName(apiDir, jvmTargetFqName)) {
|
||||
generateDeclaration("enum class", jvmTargetFqName, afterType = "(val target: String)") {
|
||||
val jvmTargetValues = JvmTarget.values()
|
||||
val deprecatedJvmTargetValues = JvmTarget.values().subtract(JvmTarget.supportedValues().toSet())
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ internal fun generateKotlinVersion(
|
||||
filePrinter: (targetFile: File, Printer.() -> Unit) -> Unit
|
||||
) {
|
||||
val kotlinVersionFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinVersion")
|
||||
filePrinter(file(apiDir, kotlinVersionFqName)) {
|
||||
filePrinter(fileFromFqName(apiDir, kotlinVersionFqName)) {
|
||||
generateDeclaration("enum class", kotlinVersionFqName, afterType = "(val version: String)") {
|
||||
val languageVersions = LanguageVersion.values()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user