Skip to content

Commit 85b17ce

Browse files
authored
Introduce animalsniffer checks to coroutines and compile against Java… (#2963)
* Introduce animalsniffer checks to coroutines and compile against Java 8 source and binary target, but still avoiding Java 7+ API * Do not use deprecated target, language desugaring will handle default interface methods and Math/Long/Int static methods * Partially migrate to .gradle.kts Fixes #1589
1 parent e6592c4 commit 85b17ce

File tree

14 files changed

+93
-16
lines changed

14 files changed

+93
-16
lines changed

build.gradle

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
*/
44

55

6+
import org.jetbrains.kotlin.config.KotlinCompilerVersion
67
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
8+
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
79
import org.jetbrains.kotlin.konan.target.HostManager
810
import org.jetbrains.dokka.gradle.DokkaTaskPartial
911

@@ -54,6 +56,7 @@ buildscript {
5456
classpath "org.jetbrains.kotlinx:kotlinx-knit:$knit_version"
5557
classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version"
5658
classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$binary_compatibility_validator_version"
59+
classpath "ru.vyarus:gradle-animalsniffer-plugin:1.5.3" // Android API check
5760

5861
// JMH plugins
5962
classpath "com.github.jengelman.gradle.plugins:shadow:5.1.0"
@@ -101,6 +104,8 @@ allprojects {
101104
}
102105

103106
apply plugin: "binary-compatibility-validator"
107+
apply plugin: 'base'
108+
104109
apiValidation {
105110
ignoredProjects += unpublished + ["kotlinx-coroutines-bom"]
106111
if (build_snapshot_train) {
@@ -126,7 +131,7 @@ allprojects {
126131
// Add dependency to core source sets. Core is configured in kx-core/build.gradle
127132
configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != coreModule }) {
128133
evaluationDependsOn(":$coreModule")
129-
if (it.name in multiplatform) {
134+
if (isMultiplatform(it)) {
130135
apply plugin: "kotlin-multiplatform"
131136
apply from: rootProject.file("gradle/compile-jvm-multiplatform.gradle")
132137
apply from: rootProject.file("gradle/compile-common.gradle")
@@ -162,8 +167,8 @@ configure(subprojects.findAll { !sourceless.contains(it.name) }) {
162167
apply plugin: 'kotlinx-atomicfu'
163168

164169
// Configure options for all Kotlin compilation tasks
165-
tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all {
166-
kotlinOptions.freeCompilerArgs += OptInPresetKt.optInAnnotations.collect { "-Xopt-in=" + it }
170+
tasks.withType(AbstractKotlinCompile).all {
171+
kotlinOptions.freeCompilerArgs += OptInPreset.optInAnnotations.collect { "-Xopt-in=" + it }
167172
kotlinOptions.freeCompilerArgs += "-progressive"
168173
// Disable KT-36770 for RxJava2 integration
169174
kotlinOptions.freeCompilerArgs += "-XXLanguage:-ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated"
@@ -207,7 +212,7 @@ if (build_snapshot_train) {
207212

208213
// Redefine source sets because we are not using 'kotlin/main/fqn' folder convention
209214
configure(subprojects.findAll {
210-
!sourceless.contains(it.name) && !multiplatform.contains(it.name) &&
215+
!sourceless.contains(it.name) && !isMultiplatform(it) &&
211216
it.name != "benchmarks" &&
212217
it.name != "example-frontend-js"
213218
}) {
@@ -262,7 +267,7 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) {
262267
}
263268

264269
List<String> jarTasks
265-
if (it.name in multiplatform) {
270+
if (isMultiplatform(it)) {
266271
jarTasks = ["jvmJar", "metadataJar"]
267272
} else if (it.name == "kotlinx-coroutines-debug") {
268273
// We shadow debug module instead of just packaging it
@@ -282,7 +287,7 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) {
282287
}
283288

284289
// Report Kotlin compiler version when building project
285-
println("Using Kotlin compiler version: $org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION")
290+
println("Using Kotlin compiler version: $KotlinCompilerVersion.VERSION")
286291

287292
// --------------- Cache redirector ---------------
288293

@@ -296,7 +301,7 @@ def publishTasks = getTasksByName("publish", true) + getTasksByName("publishNpm"
296301

297302
task deploy(dependsOn: publishTasks)
298303

299-
apply plugin: 'base'
304+
apply plugin: 'animalsniffer-convention'
300305

301306
clean.dependsOn gradle.includedBuilds.collect { it.task(':clean') }
302307

buildSrc/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,5 @@ dependencies {
4646
implementation(kotlin("gradle-plugin", version("kotlin")))
4747
implementation("org.jetbrains.dokka:dokka-gradle-plugin:${version("dokka")}")
4848
implementation("org.jetbrains.dokka:dokka-core:${version("dokka")}")
49+
implementation("ru.vyarus:gradle-animalsniffer-plugin:1.5.3") // Android API check
4950
}

buildSrc/src/main/kotlin/OptInPreset.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
33
*/
4+
@file:JvmName("OptInPreset")
45

56
val optInAnnotations = listOf(
67
"kotlin.RequiresOptIn",
@@ -10,4 +11,4 @@ val optInAnnotations = listOf(
1011
"kotlinx.coroutines.ExperimentalCoroutinesApi",
1112
"kotlinx.coroutines.ObsoleteCoroutinesApi",
1213
"kotlinx.coroutines.InternalCoroutinesApi",
13-
"kotlinx.coroutines.FlowPreview")
14+
"kotlinx.coroutines.FlowPreview")

buildSrc/src/main/kotlin/Projects.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
33
*/
44
@file:JvmName("Projects")
5-
import org.gradle.api.Project
5+
import org.gradle.api.*
66

77
fun Project.version(target: String): String =
88
property("${target}_version") as String
@@ -18,3 +18,14 @@ val internal = setOf("kotlinx.coroutines", "benchmarks", "integration-testing")
1818
val unpublished = internal + setOf("example-frontend-js", "android-unit-tests")
1919

2020
val Project.isMultiplatform: Boolean get() = name in multiplatform
21+
22+
// Projects that we do not check for Android API level 14 check due to various limitations
23+
val androidNonCompatibleProjects = setOf(
24+
"kotlinx-coroutines-debug",
25+
"kotlinx-coroutines-swing",
26+
"kotlinx-coroutines-javafx",
27+
"kotlinx-coroutines-jdk8",
28+
"kotlinx-coroutines-jdk9",
29+
"kotlinx-coroutines-reactor",
30+
"kotlinx-coroutines-test"
31+
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
import ru.vyarus.gradle.plugin.animalsniffer.*
6+
7+
subprojects {
8+
// Skip JDK 8 projects or unpublished ones
9+
if (!shouldSniff()) return@subprojects
10+
apply(plugin = "ru.vyarus.animalsniffer")
11+
configure<AnimalSnifferExtension> {
12+
sourceSets = listOf((project.extensions.getByName("sourceSets") as SourceSetContainer).getByName("main"))
13+
}
14+
val signature: Configuration by configurations
15+
dependencies {
16+
signature("net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature")
17+
signature("org.codehaus.mojo.signature:java17:1.0@signature")
18+
}
19+
}
20+
21+
fun Project.shouldSniff(): Boolean {
22+
// Skip all non-JVM projects
23+
if (platformOf(project) != "jvm") return false
24+
val name = project.name
25+
if (name in unpublished || name in sourceless || name in androidNonCompatibleProjects) return false
26+
return true
27+
}

buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ plugins {
1111
}
1212

1313
java {
14-
sourceCompatibility = JavaVersion.VERSION_1_6
15-
targetCompatibility = JavaVersion.VERSION_1_6
14+
sourceCompatibility = JavaVersion.VERSION_1_8
15+
targetCompatibility = JavaVersion.VERSION_1_8
1616
}
1717

1818
dependencies {

gradle/compile-jvm-multiplatform.gradle

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5-
sourceCompatibility = 1.6
6-
targetCompatibility = 1.6
5+
sourceCompatibility = 1.8
6+
targetCompatibility = 1.8
77

88
kotlin {
99
jvm {}
1010
sourceSets {
11+
jvmMain.dependencies {
12+
compileOnly "org.codehaus.mojo:animal-sniffer-annotations:1.20"
13+
}
14+
1115
jvmTest.dependencies {
1216
api "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
1317
// Workaround to make addSuppressed work in tests

kotlinx-coroutines-core/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ kotlin {
9090
}
9191
}
9292
}
93+
94+
jvm {
95+
// For animal sniffer
96+
withJava()
97+
}
9398
}
9499

95100
configurations {

kotlinx-coroutines-core/common/src/flow/SharingStarted.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
package kotlinx.coroutines.flow
66

77
import kotlinx.coroutines.*
8-
import kotlinx.coroutines.flow.internal.*
8+
import kotlinx.coroutines.internal.IgnoreJreRequirement
99
import kotlin.time.*
1010

1111
/**
@@ -204,5 +204,6 @@ private class StartedWhileSubscribed(
204204
stopTimeout == other.stopTimeout &&
205205
replayExpiration == other.replayExpiration
206206

207+
@IgnoreJreRequirement // desugared hashcode implementation
207208
override fun hashCode(): Int = stopTimeout.hashCode() * 31 + replayExpiration.hashCode()
208209
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines.internal
6+
7+
// Ignore JRE requirements for animal-sniffer, compileOnly dependency
8+
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE)
9+
@OptionalExpectation
10+
internal expect annotation class IgnoreJreRequirement()

0 commit comments

Comments
 (0)