diff --git a/build.gradle b/build.gradle index 9dd9e74517..1bec7a3700 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,9 @@ */ +import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.dokka.gradle.DokkaTaskPartial @@ -54,6 +56,7 @@ buildscript { classpath "org.jetbrains.kotlinx:kotlinx-knit:$knit_version" classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version" classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$binary_compatibility_validator_version" + classpath "ru.vyarus:gradle-animalsniffer-plugin:1.5.3" // Android API check // JMH plugins classpath "com.github.jengelman.gradle.plugins:shadow:5.1.0" @@ -101,6 +104,8 @@ allprojects { } apply plugin: "binary-compatibility-validator" +apply plugin: 'base' + apiValidation { ignoredProjects += unpublished + ["kotlinx-coroutines-bom"] if (build_snapshot_train) { @@ -126,7 +131,7 @@ allprojects { // Add dependency to core source sets. Core is configured in kx-core/build.gradle configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != coreModule }) { evaluationDependsOn(":$coreModule") - if (it.name in multiplatform) { + if (isMultiplatform(it)) { apply plugin: "kotlin-multiplatform" apply from: rootProject.file("gradle/compile-jvm-multiplatform.gradle") apply from: rootProject.file("gradle/compile-common.gradle") @@ -162,8 +167,8 @@ configure(subprojects.findAll { !sourceless.contains(it.name) }) { apply plugin: 'kotlinx-atomicfu' // Configure options for all Kotlin compilation tasks - tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all { - kotlinOptions.freeCompilerArgs += OptInPresetKt.optInAnnotations.collect { "-Xopt-in=" + it } + tasks.withType(AbstractKotlinCompile).all { + kotlinOptions.freeCompilerArgs += OptInPreset.optInAnnotations.collect { "-Xopt-in=" + it } kotlinOptions.freeCompilerArgs += "-progressive" // Disable KT-36770 for RxJava2 integration kotlinOptions.freeCompilerArgs += "-XXLanguage:-ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated" @@ -207,7 +212,7 @@ if (build_snapshot_train) { // Redefine source sets because we are not using 'kotlin/main/fqn' folder convention configure(subprojects.findAll { - !sourceless.contains(it.name) && !multiplatform.contains(it.name) && + !sourceless.contains(it.name) && !isMultiplatform(it) && it.name != "benchmarks" && it.name != "example-frontend-js" }) { @@ -262,7 +267,7 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { } List jarTasks - if (it.name in multiplatform) { + if (isMultiplatform(it)) { jarTasks = ["jvmJar", "metadataJar"] } else if (it.name == "kotlinx-coroutines-debug") { // We shadow debug module instead of just packaging it @@ -282,7 +287,7 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { } // Report Kotlin compiler version when building project -println("Using Kotlin compiler version: $org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION") +println("Using Kotlin compiler version: $KotlinCompilerVersion.VERSION") // --------------- Cache redirector --------------- @@ -296,7 +301,7 @@ def publishTasks = getTasksByName("publish", true) + getTasksByName("publishNpm" task deploy(dependsOn: publishTasks) -apply plugin: 'base' +apply plugin: 'animalsniffer-convention' clean.dependsOn gradle.includedBuilds.collect { it.task(':clean') } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index c54e226af1..c2808c004a 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -46,4 +46,5 @@ dependencies { implementation(kotlin("gradle-plugin", version("kotlin"))) implementation("org.jetbrains.dokka:dokka-gradle-plugin:${version("dokka")}") implementation("org.jetbrains.dokka:dokka-core:${version("dokka")}") + implementation("ru.vyarus:gradle-animalsniffer-plugin:1.5.3") // Android API check } diff --git a/buildSrc/src/main/kotlin/OptInPreset.kt b/buildSrc/src/main/kotlin/OptInPreset.kt index ee2aab11cf..fdcdb8ecf8 100644 --- a/buildSrc/src/main/kotlin/OptInPreset.kt +++ b/buildSrc/src/main/kotlin/OptInPreset.kt @@ -1,6 +1,7 @@ /* * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +@file:JvmName("OptInPreset") val optInAnnotations = listOf( "kotlin.RequiresOptIn", @@ -10,4 +11,4 @@ val optInAnnotations = listOf( "kotlinx.coroutines.ExperimentalCoroutinesApi", "kotlinx.coroutines.ObsoleteCoroutinesApi", "kotlinx.coroutines.InternalCoroutinesApi", - "kotlinx.coroutines.FlowPreview") \ No newline at end of file + "kotlinx.coroutines.FlowPreview") diff --git a/buildSrc/src/main/kotlin/Projects.kt b/buildSrc/src/main/kotlin/Projects.kt index d5494e16cd..d19e00ca46 100644 --- a/buildSrc/src/main/kotlin/Projects.kt +++ b/buildSrc/src/main/kotlin/Projects.kt @@ -2,7 +2,7 @@ * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmName("Projects") -import org.gradle.api.Project +import org.gradle.api.* fun Project.version(target: String): String = property("${target}_version") as String @@ -18,3 +18,14 @@ val internal = setOf("kotlinx.coroutines", "benchmarks", "integration-testing") val unpublished = internal + setOf("example-frontend-js", "android-unit-tests") val Project.isMultiplatform: Boolean get() = name in multiplatform + +// Projects that we do not check for Android API level 14 check due to various limitations +val androidNonCompatibleProjects = setOf( + "kotlinx-coroutines-debug", + "kotlinx-coroutines-swing", + "kotlinx-coroutines-javafx", + "kotlinx-coroutines-jdk8", + "kotlinx-coroutines-jdk9", + "kotlinx-coroutines-reactor", + "kotlinx-coroutines-test" +) diff --git a/buildSrc/src/main/kotlin/animalsniffer-convention.gradle.kts b/buildSrc/src/main/kotlin/animalsniffer-convention.gradle.kts new file mode 100644 index 0000000000..32b4931e57 --- /dev/null +++ b/buildSrc/src/main/kotlin/animalsniffer-convention.gradle.kts @@ -0,0 +1,27 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +import ru.vyarus.gradle.plugin.animalsniffer.* + +subprojects { + // Skip JDK 8 projects or unpublished ones + if (!shouldSniff()) return@subprojects + apply(plugin = "ru.vyarus.animalsniffer") + configure { + sourceSets = listOf((project.extensions.getByName("sourceSets") as SourceSetContainer).getByName("main")) + } + val signature: Configuration by configurations + dependencies { + signature("net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature") + signature("org.codehaus.mojo.signature:java17:1.0@signature") + } +} + +fun Project.shouldSniff(): Boolean { + // Skip all non-JVM projects + if (platformOf(project) != "jvm") return false + val name = project.name + if (name in unpublished || name in sourceless || name in androidNonCompatibleProjects) return false + return true +} diff --git a/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts b/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts index c7744f8702..90847f4567 100644 --- a/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts @@ -11,8 +11,8 @@ plugins { } java { - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } dependencies { diff --git a/gradle/compile-jvm-multiplatform.gradle b/gradle/compile-jvm-multiplatform.gradle index 5e65042746..88b717976d 100644 --- a/gradle/compile-jvm-multiplatform.gradle +++ b/gradle/compile-jvm-multiplatform.gradle @@ -2,12 +2,16 @@ * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -sourceCompatibility = 1.6 -targetCompatibility = 1.6 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 kotlin { jvm {} sourceSets { + jvmMain.dependencies { + compileOnly "org.codehaus.mojo:animal-sniffer-annotations:1.20" + } + jvmTest.dependencies { api "org.jetbrains.kotlin:kotlin-test:$kotlin_version" // Workaround to make addSuppressed work in tests diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index 4435ad7fa1..fdb6f39787 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -90,6 +90,11 @@ kotlin { } } } + + jvm { + // For animal sniffer + withJava() + } } configurations { diff --git a/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt b/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt index f4c6f2ee8d..a5ae63667f 100644 --- a/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt +++ b/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt @@ -5,7 +5,7 @@ package kotlinx.coroutines.flow import kotlinx.coroutines.* -import kotlinx.coroutines.flow.internal.* +import kotlinx.coroutines.internal.IgnoreJreRequirement import kotlin.time.* /** @@ -204,5 +204,6 @@ private class StartedWhileSubscribed( stopTimeout == other.stopTimeout && replayExpiration == other.replayExpiration + @IgnoreJreRequirement // desugared hashcode implementation override fun hashCode(): Int = stopTimeout.hashCode() * 31 + replayExpiration.hashCode() } diff --git a/kotlinx-coroutines-core/common/src/internal/InternalAnnotations.common.kt b/kotlinx-coroutines-core/common/src/internal/InternalAnnotations.common.kt new file mode 100644 index 0000000000..1df81c9cc4 --- /dev/null +++ b/kotlinx-coroutines-core/common/src/internal/InternalAnnotations.common.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.internal + +// Ignore JRE requirements for animal-sniffer, compileOnly dependency +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE) +@OptionalExpectation +internal expect annotation class IgnoreJreRequirement() diff --git a/kotlinx-coroutines-core/common/src/internal/Symbol.kt b/kotlinx-coroutines-core/common/src/internal/Symbol.kt index 84db2ef6cc..b629951fbd 100644 --- a/kotlinx-coroutines-core/common/src/internal/Symbol.kt +++ b/kotlinx-coroutines-core/common/src/internal/Symbol.kt @@ -4,12 +4,14 @@ package kotlinx.coroutines.internal +import kotlin.jvm.* + /** * A symbol class that is used to define unique constants that are self-explanatory in debugger. * * @suppress **This is unstable API and it is subject to change.** */ -internal class Symbol(val symbol: String) { +internal class Symbol(@JvmField val symbol: String) { override fun toString(): String = "<$symbol>" @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") diff --git a/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt b/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt index 4864c0abd6..d562207f8b 100644 --- a/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt +++ b/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt @@ -5,7 +5,6 @@ package kotlinx.coroutines import kotlinx.coroutines.internal.* -import kotlinx.coroutines.scheduling.* import kotlin.coroutines.* import kotlin.coroutines.jvm.internal.CoroutineStackFrame @@ -159,6 +158,7 @@ internal actual val CoroutineContext.coroutineName: String? get() { private const val DEBUG_THREAD_NAME_SEPARATOR = " @" +@IgnoreJreRequirement // desugared hashcode implementation internal data class CoroutineId( val id: Long ) : ThreadContextElement, AbstractCoroutineContextElement(CoroutineId) { diff --git a/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt b/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt index d592bf657a..4b0ce3f31e 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines.debug import android.annotation.* import kotlinx.coroutines.debug.internal.* +import org.codehaus.mojo.animal_sniffer.* import sun.misc.* import java.lang.instrument.* import java.lang.instrument.ClassFileTransformer @@ -17,6 +18,7 @@ import java.security.* */ @Suppress("unused") @SuppressLint("all") +@IgnoreJRERequirement // Never touched on Android internal object AgentPremain { private val enableCreationStackTraces = runCatching { diff --git a/kotlinx-coroutines-core/jvm/src/internal/InternalAnnotations.kt b/kotlinx-coroutines-core/jvm/src/internal/InternalAnnotations.kt new file mode 100644 index 0000000000..41707f7b89 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/src/internal/InternalAnnotations.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.internal + +@Suppress("ACTUAL_WITHOUT_EXPECT") // Not the same name to WA the bug in the compiler +internal actual typealias IgnoreJreRequirement = org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement