diff --git a/adapters/build.gradle.kts b/adapters/build.gradle.kts index f75fc4d..d78ea6f 100644 --- a/adapters/build.gradle.kts +++ b/adapters/build.gradle.kts @@ -15,8 +15,9 @@ */ plugins { - `java-library` + kotlin("jvm") id("com.vanniktech.maven.publish") + id("ru.vyarus.animalsniffer") } dependencies { diff --git a/adapters/japicmp/build.gradle.kts b/adapters/japicmp/build.gradle.kts new file mode 100644 index 0000000..d20d748 --- /dev/null +++ b/adapters/japicmp/build.gradle.kts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import me.champeau.gradle.japicmp.JapicmpTask + +plugins { + `java-library` + id("me.champeau.gradle.japicmp") +} + +val baseline = configurations.create("baseline") +val latest = configurations.create("latest") + +dependencies { + baseline("com.squareup.moshi:moshi-adapters:1.11.0") { + isTransitive = false + isForce = true + } + latest(project(":adapters")) +} + +val japicmp = tasks.register("japicmp") { + dependsOn("jar") + oldClasspath = baseline + newClasspath = latest + onlyBinaryIncompatibleModified = true + failOnModification = true + txtOutputFile = file("$buildDir/reports/japi.txt") + ignoreMissingClasses = true + includeSynthetic = true +} + +tasks.named("check").configure { + dependsOn(japicmp) +} diff --git a/build.gradle.kts b/build.gradle.kts index 8b1467e..85c96f6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,11 +17,15 @@ import com.diffplug.gradle.spotless.JavaExtension import org.gradle.jvm.tasks.Jar import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.net.URL buildscript { dependencies { classpath(kotlin("gradle-plugin", version = Dependencies.Kotlin.version)) + // https://github.com/melix/japicmp-gradle-plugin/issues/36 + classpath("com.google.guava:guava:28.2-jre") } } @@ -29,6 +33,8 @@ plugins { id("com.vanniktech.maven.publish") version "0.13.0" apply false id("org.jetbrains.dokka") version "1.4.10" apply false id("com.diffplug.spotless") version "5.6.0" + id("ru.vyarus.animalsniffer") version "1.5.1" apply false + id("me.champeau.gradle.japicmp") version "0.2.8" apply false } spotless { @@ -128,6 +134,28 @@ subprojects { } } + pluginManager.withPlugin("ru.vyarus.animalsniffer") { + dependencies { + "compileOnly"(Dependencies.AnimalSniffer.annotations) + "signature"(Dependencies.AnimalSniffer.java7Signature) + } + } + + pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { + tasks.withType().configureEach { + kotlinOptions { + @Suppress("SuspiciousCollectionReassignment") + freeCompilerArgs += listOf("-progressive") + } + } + + configure { + if (project.name != "examples") { + explicitApi() + } + } + } + // Configure publishing pluginManager.withPlugin("com.vanniktech.maven.publish") { // Configure automatic-module-name, but only for published modules diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 787ed9d..29ff23c 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -21,6 +21,11 @@ object Dependencies { const val ktlintVersion = "0.39.0" const val okio = "com.squareup.okio:okio:2.10.0" + object AnimalSniffer { + const val annotations = "org.codehaus.mojo:animal-sniffer-annotations:1.16" + const val java7Signature = "org.codehaus.mojo.signature:java17:1.0@signature" + } + object AutoService { private const val version = "1.0-rc7" const val annotations = "com.google.auto.service:auto-service-annotations:$version" @@ -35,7 +40,6 @@ object Dependencies { object Kotlin { const val version = "1.4.10" - const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib:$version" const val metadata = "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0" } diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index dc7a8a8..2ff2dfa 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -14,19 +14,11 @@ * limitations under the License. */ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { kotlin("jvm") kotlin("kapt") } -tasks.withType().configureEach { - kotlinOptions { - freeCompilerArgs = listOf("-progressive") - } -} - dependencies { kapt(project(":kotlin:codegen")) compileOnly(Dependencies.jsr305) diff --git a/kotlin/codegen/build.gradle.kts b/kotlin/codegen/build.gradle.kts index 94bb818..66c477d 100644 --- a/kotlin/codegen/build.gradle.kts +++ b/kotlin/codegen/build.gradle.kts @@ -25,16 +25,11 @@ plugins { id("com.github.johnrengelman.shadow") version "6.0.0" } -configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - tasks.withType().configureEach { kotlinOptions { jvmTarget = "1.8" - freeCompilerArgs = listOf( - "-progressive", + @Suppress("SuspiciousCollectionReassignment") + freeCompilerArgs += listOf( "-Xopt-in=com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview" ) } diff --git a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/JsonClassCodegenProcessor.kt b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/JsonClassCodegenProcessor.kt index e3d2e47..6479ec5 100644 --- a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/JsonClassCodegenProcessor.kt +++ b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/JsonClassCodegenProcessor.kt @@ -46,9 +46,9 @@ import javax.tools.Diagnostic */ @AutoService(Processor::class) @IncrementalAnnotationProcessor(ISOLATING) -class JsonClassCodegenProcessor : AbstractProcessor() { +public class JsonClassCodegenProcessor : AbstractProcessor() { - companion object { + public companion object { /** * This annotation processing argument can be specified to have a `@Generated` annotation * included in the generated code. It is not encouraged unless you need it for static analysis @@ -58,7 +58,7 @@ class JsonClassCodegenProcessor : AbstractProcessor() { * * `"javax.annotation.processing.Generated"` (JRE 9+) * * `"javax.annotation.Generated"` (JRE <9) */ - const val OPTION_GENERATED = "moshi.generated" + public const val OPTION_GENERATED: String = "moshi.generated" private val POSSIBLE_GENERATED_NAMES = arrayOf( ClassName("javax.annotation.processing", "Generated"), ClassName("javax.annotation", "Generated") @@ -73,11 +73,11 @@ class JsonClassCodegenProcessor : AbstractProcessor() { private val annotation = JsonClass::class.java private var generatedType: ClassName? = null - override fun getSupportedAnnotationTypes() = setOf(annotation.canonicalName) + override fun getSupportedAnnotationTypes(): Set = setOf(annotation.canonicalName) override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest() - override fun getSupportedOptions() = setOf(OPTION_GENERATED) + override fun getSupportedOptions(): Set = setOf(OPTION_GENERATED) override fun init(processingEnv: ProcessingEnvironment) { super.init(processingEnv) diff --git a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TypeRenderer.kt b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TypeRenderer.kt index 5a9bf0e..d9ca043 100644 --- a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TypeRenderer.kt +++ b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TypeRenderer.kt @@ -37,7 +37,7 @@ import com.squareup.moshi.Types * Rendering is pluggable so that type variables can either be resolved or emitted as other code * blocks. */ -abstract class TypeRenderer { +internal abstract class TypeRenderer { abstract fun renderTypeVariable(typeVariable: TypeVariableName): CodeBlock fun render(typeName: TypeName, forceBox: Boolean = false): CodeBlock { diff --git a/kotlin/reflect/src/main/java/com/squareup/moshi/KotlinJsonAdapter.kt b/kotlin/reflect/src/main/java/com/squareup/moshi/KotlinJsonAdapter.kt index 110a78b..03dbd5a 100644 --- a/kotlin/reflect/src/main/java/com/squareup/moshi/KotlinJsonAdapter.kt +++ b/kotlin/reflect/src/main/java/com/squareup/moshi/KotlinJsonAdapter.kt @@ -21,5 +21,5 @@ import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory message = "this moved to avoid a package name conflict in the Java Platform Module System.", replaceWith = ReplaceWith("com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory") ) -class KotlinJsonAdapterFactory : +public class KotlinJsonAdapterFactory : JsonAdapter.Factory by KotlinJsonAdapterFactory() diff --git a/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapter.kt b/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapter.kt index cdf3b1c..222f66d 100644 --- a/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapter.kt +++ b/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapter.kt @@ -179,7 +179,7 @@ internal class KotlinJsonAdapter( } } -class KotlinJsonAdapterFactory : JsonAdapter.Factory { +public class KotlinJsonAdapterFactory : JsonAdapter.Factory { override fun create(type: Type, annotations: MutableSet, moshi: Moshi): JsonAdapter<*>? { if (annotations.isNotEmpty()) return null diff --git a/kotlin/tests/build.gradle.kts b/kotlin/tests/build.gradle.kts index 1805400..dc67c60 100644 --- a/kotlin/tests/build.gradle.kts +++ b/kotlin/tests/build.gradle.kts @@ -23,7 +23,8 @@ plugins { tasks.withType().configureEach { kotlinOptions { - freeCompilerArgs = listOf( + @Suppress("SuspiciousCollectionReassignment") + freeCompilerArgs += listOf( "-Werror", "-Xopt-in=kotlin.ExperimentalStdlibApi", "-Xinline-classes" diff --git a/moshi/build.gradle.kts b/moshi/build.gradle.kts index 1ea5be5..0971821 100644 --- a/moshi/build.gradle.kts +++ b/moshi/build.gradle.kts @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { kotlin("jvm") id("com.vanniktech.maven.publish") + id("ru.vyarus.animalsniffer") } tasks.withType() @@ -26,18 +27,14 @@ tasks.withType() .configureEach { kotlinOptions { @Suppress("SuspiciousCollectionReassignment") // It's not suspicious - freeCompilerArgs += listOf( - "-Xopt-in=kotlin.ExperimentalStdlibApi" - ) + freeCompilerArgs += listOf("-Xopt-in=kotlin.ExperimentalStdlibApi") } } dependencies { compileOnly(Dependencies.jsr305) - compileOnly(Dependencies.Kotlin.stdlib) api(Dependencies.okio) - testImplementation(Dependencies.Kotlin.stdlib) testCompileOnly(Dependencies.jsr305) testImplementation(Dependencies.Testing.junit) testImplementation(Dependencies.Testing.truth) diff --git a/moshi/gradle.properties b/moshi/gradle.properties index b84f977..4938af0 100644 --- a/moshi/gradle.properties +++ b/moshi/gradle.properties @@ -18,7 +18,3 @@ POM_NAME=Moshi POM_ARTIFACT_ID=moshi POM_PACKAGING=jar AUTOMATIC_MODULE_NAME=com.squareup.moshi - -# Kotlin adds the stdlib dep by default in 1.4.0+, but we want to effectively make it compileOnly -# for our case to avoid imposing it on consumers. -kotlin.stdlib.default.dependency=false diff --git a/moshi/japicmp/build.gradle.kts b/moshi/japicmp/build.gradle.kts new file mode 100644 index 0000000..2332afc --- /dev/null +++ b/moshi/japicmp/build.gradle.kts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +import me.champeau.gradle.japicmp.JapicmpTask + +plugins { + `java-library` + id("me.champeau.gradle.japicmp") +} + +val baseline = configurations.create("baseline") +val latest = configurations.create("latest") + +dependencies { + baseline("com.squareup.moshi:moshi:1.11.0") { + isTransitive = false + isForce = true + } + latest(project(":moshi")) +} + +val japicmp = tasks.register("japicmp") { + dependsOn("jar") + oldClasspath = baseline + newClasspath = latest + onlyBinaryIncompatibleModified = true + failOnModification = true + txtOutputFile = file("$buildDir/reports/japi.txt") + ignoreMissingClasses = true + includeSynthetic = true + classExcludes = listOf( + "com.squareup.moshi.internal.NonNullJsonAdapter", // Internal. + "com.squareup.moshi.internal.NullSafeJsonAdapter", // Internal. + "com.squareup.moshi.internal.Util" // Internal. + ) +} + +tasks.named("check").configure { + dependsOn(japicmp) +} diff --git a/moshi/src/main/java/com/squareup/moshi/-MoshiKotlinExtensions.kt b/moshi/src/main/java/com/squareup/moshi/-MoshiKotlinExtensions.kt index 3a5989a..e6db542 100644 --- a/moshi/src/main/java/com/squareup/moshi/-MoshiKotlinExtensions.kt +++ b/moshi/src/main/java/com/squareup/moshi/-MoshiKotlinExtensions.kt @@ -26,17 +26,17 @@ import kotlin.reflect.typeOf * itself is handled, nested types (such as in generics) are not resolved. */ @ExperimentalStdlibApi -inline fun Moshi.adapter(): JsonAdapter = adapter(typeOf()) +public inline fun Moshi.adapter(): JsonAdapter = adapter(typeOf()) @ExperimentalStdlibApi -inline fun Moshi.Builder.addAdapter(adapter: JsonAdapter): Moshi.Builder = add(typeOf().javaType, adapter) +public inline fun Moshi.Builder.addAdapter(adapter: JsonAdapter): Moshi.Builder = add(typeOf().javaType, adapter) /** * @return a [JsonAdapter] for [ktype], creating it if necessary. Note that while nullability of * [ktype] itself is handled, nested types (such as in generics) are not resolved. */ @ExperimentalStdlibApi -fun Moshi.adapter(ktype: KType): JsonAdapter { +public fun Moshi.adapter(ktype: KType): JsonAdapter { val adapter = adapter(ktype.javaType) return if (adapter is NullSafeJsonAdapter || adapter is NonNullJsonAdapter) { // TODO CR - Assume that these know what they're doing? Or should we defensively avoid wrapping for matching nullability? diff --git a/moshi/src/main/java/com/squareup/moshi/-MoshiKotlinTypesExtensions.kt b/moshi/src/main/java/com/squareup/moshi/-MoshiKotlinTypesExtensions.kt index 6bfd38e..5be471a 100644 --- a/moshi/src/main/java/com/squareup/moshi/-MoshiKotlinTypesExtensions.kt +++ b/moshi/src/main/java/com/squareup/moshi/-MoshiKotlinTypesExtensions.kt @@ -25,13 +25,13 @@ import kotlin.reflect.javaType import kotlin.reflect.typeOf /** Returns the raw [Class] type of this type. */ -val Type.rawType: Class<*> get() = Types.getRawType(this) +public val Type.rawType: Class<*> get() = Types.getRawType(this) /** * Checks if [this] contains [T]. Returns the subset of [this] without [T], or null if * [this] does not contain [T]. */ -inline fun Set.nextAnnotations(): Set? = Types.nextAnnotations(this, T::class.java) +public inline fun Set.nextAnnotations(): Set? = Types.nextAnnotations(this, T::class.java) /** * Returns a type that represents an unknown type that extends [T]. For example, if @@ -39,7 +39,7 @@ inline fun Set.nextAnnotations(): Set subtypeOf(): WildcardType { +public inline fun subtypeOf(): WildcardType { var type = typeOf().javaType if (type is Class<*>) { type = Util.boxIfPrimitive(type) @@ -52,7 +52,7 @@ inline fun subtypeOf(): WildcardType { * [String], this returns `in String`. */ @ExperimentalStdlibApi -inline fun supertypeOf(): WildcardType { +public inline fun supertypeOf(): WildcardType { var type = typeOf().javaType if (type is Class<*>) { type = Util.boxIfPrimitive(type) @@ -62,10 +62,10 @@ inline fun supertypeOf(): WildcardType { /** Returns a [GenericArrayType] with [this] as its [GenericArrayType.getGenericComponentType]. */ @ExperimentalStdlibApi -fun KType.asArrayType(): GenericArrayType = javaType.asArrayType() +public fun KType.asArrayType(): GenericArrayType = javaType.asArrayType() /** Returns a [GenericArrayType] with [this] as its [GenericArrayType.getGenericComponentType]. */ -fun KClass<*>.asArrayType(): GenericArrayType = java.asArrayType() +public fun KClass<*>.asArrayType(): GenericArrayType = java.asArrayType() /** Returns a [GenericArrayType] with [this] as its [GenericArrayType.getGenericComponentType]. */ -fun Type.asArrayType(): GenericArrayType = Types.arrayOf(this) +public fun Type.asArrayType(): GenericArrayType = Types.arrayOf(this) diff --git a/settings.gradle.kts b/settings.gradle.kts index c97c500..c65b017 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,7 +23,9 @@ pluginManagement { rootProject.name = "moshi-root" include(":moshi") +include(":moshi:japicmp") include(":adapters") +include(":adapters:japicmp") include(":examples") include(":kotlin:reflect") include(":kotlin:codegen")