From 6947ab00d0e111dd317c6249447dc389e6f6a007 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 23 Aug 2021 17:09:59 -0400 Subject: [PATCH] Modernize build a bit (#1383) --- .github/workflows/build.yml | 5 +- adapters/build.gradle.kts | 8 +-- adapters/japicmp/build.gradle.kts | 2 +- build.gradle.kts | 32 +++-------- buildSrc/build.gradle.kts | 27 --------- buildSrc/src/main/kotlin/Dependencies.kt | 55 ------------------- examples/build.gradle.kts | 2 +- gradle/libs.versions.toml | 53 ++++++++++++++++++ kotlin/codegen/build.gradle.kts | 39 ++++++------- .../kotlin/codegen/api/AdapterGenerator.kt | 5 +- .../moshi/kotlin/codegen/api/kotlintypes.kt | 2 + .../squareup/moshi/kotlin/codegen/metadata.kt | 6 +- kotlin/reflect/build.gradle.kts | 4 +- kotlin/tests/build.gradle.kts | 6 +- moshi/build.gradle.kts | 10 ++-- moshi/japicmp/build.gradle.kts | 2 +- moshi/records-tests/build.gradle.kts | 6 +- settings.gradle.kts | 2 + 18 files changed, 113 insertions(+), 153 deletions(-) delete mode 100644 buildSrc/build.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/Dependencies.kt create mode 100644 gradle/libs.versions.toml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ecbb75a..67d4840 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,4 @@ jobs: - name: Publish (default branch only) if: github.repository == 'square/moshi' && github.ref == 'refs/heads/master' && matrix.java-version == '16' - run: ./gradlew uploadArchives - env: - ORG_GRADLE_PROJECT_SONATYPE_NEXUS_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} - ORG_GRADLE_PROJECT_SONATYPE_NEXUS_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} + run: ./gradlew publishToMavenCentral -PmavenCentralUsername=${{ secrets.SONATYPE_NEXUS_USERNAME }} -PmavenCentralPassword=${{ secrets.SONATYPE_NEXUS_PASSWORD }} diff --git a/adapters/build.gradle.kts b/adapters/build.gradle.kts index aeb4d63..db4d92b 100644 --- a/adapters/build.gradle.kts +++ b/adapters/build.gradle.kts @@ -20,10 +20,10 @@ plugins { } dependencies { - compileOnly(Dependencies.jsr305) + compileOnly(libs.jsr305) api(project(":moshi")) - testCompileOnly(Dependencies.jsr305) - testImplementation(Dependencies.Testing.junit) - testImplementation(Dependencies.Testing.truth) + testCompileOnly(libs.jsr305) + testImplementation(libs.junit) + testImplementation(libs.truth) } diff --git a/adapters/japicmp/build.gradle.kts b/adapters/japicmp/build.gradle.kts index 27ac67e..d163820 100644 --- a/adapters/japicmp/build.gradle.kts +++ b/adapters/japicmp/build.gradle.kts @@ -25,7 +25,7 @@ val baseline = configurations.create("baseline") val latest = configurations.create("latest") dependencies { - baseline("com.squareup.moshi:moshi-adapters:1.11.0") { + baseline("com.squareup.moshi:moshi-adapters:1.12.0") { isTransitive = false isForce = true } diff --git a/build.gradle.kts b/build.gradle.kts index 12d7ead..8e396d9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -23,17 +23,17 @@ import java.net.URL buildscript { dependencies { - classpath(kotlin("gradle-plugin", version = Dependencies.Kotlin.version)) + classpath(kotlin("gradle-plugin", version = libs.versions.kotlin.get())) // https://github.com/melix/japicmp-gradle-plugin/issues/36 classpath("com.google.guava:guava:28.2-jre") } } plugins { - id("com.vanniktech.maven.publish") version "0.14.2" apply false - id("org.jetbrains.dokka") version "1.4.32" apply false - id("com.diffplug.spotless") version "5.12.4" - id("me.champeau.gradle.japicmp") version "0.2.9" apply false + alias(libs.plugins.mavenPublish) apply false + alias(libs.plugins.dokka) apply false + alias(libs.plugins.spotless) + alias(libs.plugins.japicmp) apply false } spotless { @@ -67,7 +67,7 @@ spotless { "**/TypesTest.java" ) val configureCommonJavaFormat: JavaExtension.() -> Unit = { - googleJavaFormat("1.11.0") + googleJavaFormat(libs.versions.gjf.get()) } java { configureCommonJavaFormat() @@ -86,7 +86,7 @@ spotless { target(*externalJavaFiles) } kotlin { - ktlint(Dependencies.ktlintVersion).userData(mapOf("indent_size" to "2")) + ktlint(libs.versions.ktlint.get()).userData(mapOf("indent_size" to "2")) target("**/*.kt") trimTrailingWhitespace() endWithNewline() @@ -95,7 +95,7 @@ spotless { targetExclude("**/Dependencies.kt", "**/spotless.kt", "**/build/**") } kotlinGradle { - ktlint(Dependencies.ktlintVersion).userData(mapOf("indent_size" to "2")) + ktlint(libs.versions.ktlint.get()).userData(mapOf("indent_size" to "2")) target("**/*.gradle.kts") trimTrailingWhitespace() endWithNewline() @@ -106,20 +106,6 @@ spotless { subprojects { repositories { mavenCentral() - // Required for Dokka - exclusiveContent { - forRepository { - maven { - name = "JCenter" - setUrl("https://jcenter.bintray.com/") - } - } - filter { - includeModule("org.jetbrains.kotlinx", "kotlinx-html-jvm") - includeGroup("org.jetbrains.dokka") - includeModule("org.jetbrains", "markdown") - } - } } // Apply with "java" instead of just "java-library" so kotlin projects get it too @@ -141,7 +127,7 @@ subprojects { kotlinOptions { @Suppress("SuspiciousCollectionReassignment") freeCompilerArgs += listOf("-progressive") - jvmTarget = "1.8" + jvmTarget = libs.versions.jvmTarget.get() } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index c71531e..0000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2020 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -plugins { - `kotlin-dsl` -} - -kotlinDslPluginOptions { - experimentalWarning.set(false) -} - -repositories { - mavenCentral() -} diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt deleted file mode 100644 index 998d087..0000000 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2020 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -object Dependencies { - - const val asm = "org.ow2.asm:asm:7.1" - const val jsr305 = "com.google.code.findbugs:jsr305:3.0.2" - const val ktlintVersion = "0.41.0" - const val okio = "com.squareup.okio:okio:2.10.0" - - object AutoService { - private const val version = "1.0" - const val annotations = "com.google.auto.service:auto-service-annotations:$version" - const val processor = "com.google.auto.service:auto-service:$version" - } - - object Incap { - private const val version = "0.3" - const val annotations = "net.ltgt.gradle.incap:incap:$version" - const val processor = "net.ltgt.gradle.incap:incap-processor:$version" - } - - object Kotlin { - const val version = "1.5.0" - const val metadata = "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.3.0" - } - - object KotlinPoet { - private const val version = "1.8.0" - const val kotlinPoet = "com.squareup:kotlinpoet:$version" - const val metadata = "com.squareup:kotlinpoet-metadata-specs:$version" - const val metadataSpecs = "com.squareup:kotlinpoet-metadata-specs:$version" - const val elementsClassInspector = "com.squareup:kotlinpoet-classinspector-elements:$version" - } - - object Testing { - const val assertj = "org.assertj:assertj-core:3.11.1" - const val compileTesting = "com.github.tschuchortdev:kotlin-compile-testing:1.4.3" - const val junit = "junit:junit:4.13.2" - const val truth = "com.google.truth:truth:1.0.1" - } -} diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 2ff2dfa..fb7c5e8 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -21,7 +21,7 @@ plugins { dependencies { kapt(project(":kotlin:codegen")) - compileOnly(Dependencies.jsr305) + compileOnly(libs.jsr305) implementation(project(":moshi")) implementation(project(":adapters")) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..f66e32b --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,53 @@ +# Copyright (C) 2021 Square, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[versions] +autoService = "1.0" +gjf = "1.11.0" +incap = "0.3" +jvmTarget = "1.8" +kotlin = "1.5.21" +kotlinCompileTesting = "1.4.3" +kotlinpoet = "1.9.0" +ktlint = "0.41.0" + +[plugins] +dokka = { id = "org.jetbrains.dokka", version = "1.5.0" } +japicmp = { id = "me.champeau.gradle.japicmp", version = "0.2.9" } +mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.17.0" } +mavenShadow = { id = "com.github.johnrengelman.shadow", version = "7.0.0" } +spotless = { id = "com.diffplug.spotless", version = "5.14.2" } + +[libraries] +asm = "org.ow2.asm:asm:9.2" +autoCommon = "com.google.auto:auto-common:1.1" +autoService = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoService" } +autoService-processor = { module = "com.google.auto.service:auto-service", version.ref = "autoService" } +incap = { module = "net.ltgt.gradle.incap:incap", version.ref = "incap" } +incap-processor = { module = "net.ltgt.gradle.incap:incap-processor", version.ref = "incap" } +jsr305 = "com.google.code.findbugs:jsr305:3.0.2" +kotlin-compilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlin" } +kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } +kotlinpoet = { module = "com.squareup:kotlinpoet", version.ref = "kotlinpoet" } +kotlinpoet-elementsClassInspector = { module = "com.squareup:kotlinpoet-classinspector-elements", version.ref = "kotlinpoet" } +kotlinpoet-metadata-core = { module = "com.squareup:kotlinpoet-metadata", version.ref = "kotlinpoet" } +kotlinpoet-metadata-specs = { module = "com.squareup:kotlinpoet-metadata-specs", version.ref = "kotlinpoet" } +kotlinxMetadata = "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.3.0" +okio = "com.squareup.okio:okio:2.10.0" + +# Test libs +assertj = "org.assertj:assertj-core:3.11.1" +junit = "junit:junit:4.13.2" +kotlinCompileTesting = { module = "com.github.tschuchortdev:kotlin-compile-testing", version.ref = "kotlinCompileTesting" } +truth = "com.google.truth:truth:1.1.3" diff --git a/kotlin/codegen/build.gradle.kts b/kotlin/codegen/build.gradle.kts index 1ae9b29..4a9389f 100644 --- a/kotlin/codegen/build.gradle.kts +++ b/kotlin/codegen/build.gradle.kts @@ -22,14 +22,15 @@ plugins { kotlin("jvm") kotlin("kapt") id("com.vanniktech.maven.publish") - id("com.github.johnrengelman.shadow") version "7.0.0" + alias(libs.plugins.mavenShadow) } tasks.withType().configureEach { kotlinOptions { @Suppress("SuspiciousCollectionReassignment") freeCompilerArgs += listOf( - "-Xopt-in=com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview" + "-Xopt-in=kotlin.RequiresOptIn", + "-Xopt-in=com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview", ) } } @@ -57,38 +58,38 @@ dependencies { // https://youtrack.jetbrains.com/issue/KT-41702 api(project(":moshi")) api(kotlin("reflect")) - shade(Dependencies.Kotlin.metadata) { + shade(libs.kotlinxMetadata) { exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib") } - api(Dependencies.KotlinPoet.kotlinPoet) - shade(Dependencies.KotlinPoet.metadata) { + api(libs.kotlinpoet) + shade(libs.kotlinpoet.metadata.core) { exclude(group = "org.jetbrains.kotlin") exclude(group = "com.squareup", module = "kotlinpoet") } - shade(Dependencies.KotlinPoet.metadataSpecs) { + shade(libs.kotlinpoet.metadata.specs) { exclude(group = "org.jetbrains.kotlin") exclude(group = "com.squareup", module = "kotlinpoet") } - api(Dependencies.KotlinPoet.elementsClassInspector) - shade(Dependencies.KotlinPoet.elementsClassInspector) { + api(libs.kotlinpoet.elementsClassInspector) + shade(libs.kotlinpoet.elementsClassInspector) { exclude(group = "org.jetbrains.kotlin") exclude(group = "com.squareup", module = "kotlinpoet") exclude(group = "com.google.guava") } - api(Dependencies.asm) + api(libs.asm) - api(Dependencies.AutoService.annotations) - kapt(Dependencies.AutoService.processor) - api(Dependencies.Incap.annotations) - kapt(Dependencies.Incap.processor) + api(libs.autoService) + kapt(libs.autoService.processor) + api(libs.incap) + kapt(libs.incap.processor) // Copy these again as they're not automatically included since they're shaded - testImplementation(Dependencies.KotlinPoet.metadata) - testImplementation(Dependencies.KotlinPoet.metadataSpecs) - testImplementation(Dependencies.KotlinPoet.elementsClassInspector) - testImplementation(Dependencies.Testing.junit) - testImplementation(Dependencies.Testing.truth) - testImplementation(Dependencies.Testing.compileTesting) + testImplementation(libs.kotlinpoet.metadata.core) + testImplementation(libs.kotlinpoet.metadata.specs) + testImplementation(libs.kotlinpoet.elementsClassInspector) + testImplementation(libs.junit) + testImplementation(libs.truth) + testImplementation(libs.kotlinCompileTesting) } val relocateShadowJar = tasks.register("relocateShadowJar") { diff --git a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt index afca47f..6c63e62 100644 --- a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt +++ b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt @@ -85,7 +85,10 @@ internal class AdapterGenerator( // KotlinPoet always generates explicit public modifiers for public members. "RedundantVisibilityModifier", // For LambdaTypeNames we have to import kotlin.functions.* types - "PLATFORM_CLASS_MAPPED_TO_KOTLIN" + "PLATFORM_CLASS_MAPPED_TO_KOTLIN", + // Cover for calling fromJson() on a Nothing property type. Theoretically nonsensical but we + // support it + "IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION" ).let { suppressions -> AnnotationSpec.builder(Suppress::class) .useSiteTarget(FILE) diff --git a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/kotlintypes.kt b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/kotlintypes.kt index dc18524..078fccf 100644 --- a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/kotlintypes.kt +++ b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/kotlintypes.kt @@ -23,6 +23,7 @@ import com.squareup.kotlinpoet.CHAR import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.DOUBLE +import com.squareup.kotlinpoet.DelicateKotlinPoetApi import com.squareup.kotlinpoet.FLOAT import com.squareup.kotlinpoet.INT import com.squareup.kotlinpoet.KModifier @@ -79,6 +80,7 @@ internal fun TypeName.defaultPrimitiveValue(): CodeBlock = else -> CodeBlock.of("null") } +@OptIn(DelicateKotlinPoetApi::class) internal fun TypeName.asTypeBlock(): CodeBlock { if (annotations.isNotEmpty()) { return copy(annotations = emptyList()).asTypeBlock() diff --git a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/metadata.kt b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/metadata.kt index 5444688..2734fdf 100644 --- a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/metadata.kt +++ b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/metadata.kt @@ -17,6 +17,7 @@ package com.squareup.moshi.kotlin.codegen import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.DelicateKotlinPoetApi import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.LambdaTypeName import com.squareup.kotlinpoet.ParameterizedTypeName @@ -117,6 +118,7 @@ internal fun primaryConstructor( } /** Returns a target type for `element`, or null if it cannot be used with code gen. */ +@OptIn(DelicateKotlinPoetApi::class) @KotlinPoetMetadataPreview internal fun targetType( messager: Messager, @@ -233,7 +235,6 @@ internal fun targetType( val resolvedTypes = mutableListOf() val superTypes = appliedType.supertypes(types) .filterNot { supertype -> - @Suppress("DEPRECATION") // Appropriate in this case supertype.element.asClassName() == OBJECT_CLASS || // Don't load properties for java.lang.Object. supertype.element.kind != ElementKind.CLASS // Don't load properties for interface types. } @@ -273,7 +274,6 @@ internal fun targetType( val superSuperClass = supertype.element.superclass as DeclaredType // Convert to an element and back to wipe the typed generics off of this - @Suppress("DEPRECATION") // Appropriate in this case val untyped = superSuperClass.asElement().asType().asTypeName() as ParameterizedTypeName resolvedTypes += ResolvedTypeMapping( target = untyped.rawType, @@ -289,7 +289,6 @@ internal fun targetType( } for ((localAppliedType, supertypeApi) in superTypes.entries) { - @Suppress("DEPRECATION") // Appropriate in this case val appliedClassName = localAppliedType.element.asClassName() val supertypeProperties = declaredProperties( constructor = constructor, @@ -317,7 +316,6 @@ internal fun targetType( if (forceInternal) KModifier.INTERNAL else visibility } - @Suppress("DEPRECATION") // Appropriate in this case return TargetType( typeName = element.asType().asTypeName(), constructor = constructor, diff --git a/kotlin/reflect/build.gradle.kts b/kotlin/reflect/build.gradle.kts index a2f17db..70fa901 100644 --- a/kotlin/reflect/build.gradle.kts +++ b/kotlin/reflect/build.gradle.kts @@ -24,6 +24,6 @@ dependencies { api(kotlin("reflect")) testImplementation(kotlin("test")) - testImplementation(Dependencies.Testing.junit) - testImplementation(Dependencies.Testing.truth) + testImplementation(libs.junit) + testImplementation(libs.truth) } diff --git a/kotlin/tests/build.gradle.kts b/kotlin/tests/build.gradle.kts index 9a2379f..907a363 100644 --- a/kotlin/tests/build.gradle.kts +++ b/kotlin/tests/build.gradle.kts @@ -41,7 +41,7 @@ dependencies { testImplementation(project(":moshi")) testImplementation(project(":kotlin:reflect")) testImplementation(kotlin("reflect")) - testImplementation(Dependencies.Testing.junit) - testImplementation(Dependencies.Testing.assertj) - testImplementation(Dependencies.Testing.truth) + testImplementation(libs.junit) + testImplementation(libs.assertj) + testImplementation(libs.truth) } diff --git a/moshi/build.gradle.kts b/moshi/build.gradle.kts index c951ddf..dbba809 100644 --- a/moshi/build.gradle.kts +++ b/moshi/build.gradle.kts @@ -72,10 +72,10 @@ tasks.withType() dependencies { // So the j16 source set can "see" main Moshi sources "java16Implementation"(mainSourceSet.output) - compileOnly(Dependencies.jsr305) - api(Dependencies.okio) + compileOnly(libs.jsr305) + api(libs.okio) - testCompileOnly(Dependencies.jsr305) - testImplementation(Dependencies.Testing.junit) - testImplementation(Dependencies.Testing.truth) + testCompileOnly(libs.jsr305) + testImplementation(libs.junit) + testImplementation(libs.truth) } diff --git a/moshi/japicmp/build.gradle.kts b/moshi/japicmp/build.gradle.kts index 032aa69..49b2a61 100644 --- a/moshi/japicmp/build.gradle.kts +++ b/moshi/japicmp/build.gradle.kts @@ -25,7 +25,7 @@ val baseline = configurations.create("baseline") val latest = configurations.create("latest") dependencies { - baseline("com.squareup.moshi:moshi:1.11.0") { + baseline("com.squareup.moshi:moshi:1.12.0") { isTransitive = false isForce = true } diff --git a/moshi/records-tests/build.gradle.kts b/moshi/records-tests/build.gradle.kts index 7b6b541..9d01a8d 100644 --- a/moshi/records-tests/build.gradle.kts +++ b/moshi/records-tests/build.gradle.kts @@ -24,7 +24,7 @@ tasks.withType().configureEach { dependencies { testImplementation(project(":moshi")) - testCompileOnly(Dependencies.jsr305) - testImplementation(Dependencies.Testing.junit) - testImplementation(Dependencies.Testing.truth) + testCompileOnly(libs.jsr305) + testImplementation(libs.junit) + testImplementation(libs.truth) } diff --git a/settings.gradle.kts b/settings.gradle.kts index d37a0f5..def4049 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -31,3 +31,5 @@ include(":examples") include(":kotlin:reflect") include(":kotlin:codegen") include(":kotlin:tests") + +enableFeaturePreview("VERSION_CATALOGS")