diff --git a/src/functionalTest/groovy/com/autonomousapps/android/AnnotationProcessorSpec.groovy b/src/functionalTest/groovy/com/autonomousapps/android/AnnotationProcessorSpec.groovy index 614091fa2..75c6606a6 100644 --- a/src/functionalTest/groovy/com/autonomousapps/android/AnnotationProcessorSpec.groovy +++ b/src/functionalTest/groovy/com/autonomousapps/android/AnnotationProcessorSpec.groovy @@ -197,4 +197,38 @@ final class AnnotationProcessorSpec extends AbstractAndroidSpec { where: [gradleVersion, agpVersion] << gradleAgpMatrix() } + + def "kotlin parcelize is redundant when Parcelize annotation is unused (#gradleVersion AGP #agpVersion)"() { + given: + def project = new KotlinParcelizeIsRedundantProject(agpVersion) + androidProject = project.newProject() + + when: + build(gradleVersion, androidProject, 'buildHealth') + + then: + def actualAdvice = androidProject.adviceFor(project.appSpec) + def expectedAdvice = project.expectedAdvice + assertThat(actualAdvice).containsExactlyElementsIn(expectedAdvice) + + where: + [gradleVersion, agpVersion] << gradleAgpMatrix() + } + + def "kotlin parcelize is not redundant when Parcelize annotation is used (#gradleVersion AGP #agpVersion)"() { + given: + def project = new KotlinParcelizeIsNotRedundantProject(agpVersion) + androidProject = project.newProject() + + when: + build(gradleVersion, androidProject, 'buildHealth') + + then: + def actualAdvice = androidProject.adviceFor(project.appSpec) + def expectedAdvice = project.expectedAdvice + assertThat(actualAdvice).containsExactlyElementsIn(expectedAdvice) + + where: + [gradleVersion, agpVersion] << gradleAgpMatrix() + } } diff --git a/src/functionalTest/kotlin/com/autonomousapps/fixtures/annotationProcessorProjects.kt b/src/functionalTest/kotlin/com/autonomousapps/fixtures/annotationProcessorProjects.kt index 284ebde57..b22674535 100644 --- a/src/functionalTest/kotlin/com/autonomousapps/fixtures/annotationProcessorProjects.kt +++ b/src/functionalTest/kotlin/com/autonomousapps/fixtures/annotationProcessorProjects.kt @@ -319,6 +319,89 @@ class KaptIsRedundantWithUnusedProcsProject(agpVersion: String) { val expectedAdvice = setOf(PluginAdvice.redundantKapt()) } +class KotlinParcelizeIsNotRedundantProject(agpVersion: String) { + + fun newProject() = AndroidProject( + rootSpec = rootSpec, + appSpec = appSpec + ) + + val rootSpec = RootSpec(agpVersion = agpVersion) + + private val sources = mapOf( + "Thing.kt" to """ + package $DEFAULT_PACKAGE_NAME + + import android.os.Parcelable + import kotlinx.parcelize.Parcelize + + @Parcelize + data class Thing(val id: String) : Parcelable + """.trimIndent() + ) + + val appSpec = AppSpec( + plugins = setOf("kotlin-parcelize"), + sources = sources, + dependencies = listOf( + "implementation" to "org.jetbrains.kotlin:kotlin-stdlib:${Plugin.KOTLIN_VERSION}", + "implementation" to APPCOMPAT + ) + ) + + val expectedAdvice = emptySet() +} + +class KotlinParcelizeIsRedundantProject(agpVersion: String) { + + fun newProject() = AndroidProject( + rootSpec = rootSpec, + appSpec = appSpec + ) + + val rootSpec = RootSpec(agpVersion = agpVersion) + + private val sources = mapOf( + "Thing.kt" to """ + package $DEFAULT_PACKAGE_NAME + + import android.os.Parcel + import android.os.Parcelable + + data class Thing(val id: String) : Parcelable { + constructor(parcel: Parcel) : this(parcel.readString()!!) + + override fun describeContents() = 0 + + override fun writeToParcel(dest: Parcel, flags: Int) { + dest.writeString(id) + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): Thing { + return Thing(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + } + """.trimIndent() + ) + + val appSpec = AppSpec( + plugins = setOf("kotlin-parcelize"), + sources = sources, + dependencies = listOf( + "implementation" to "org.jetbrains.kotlin:kotlin-stdlib:${Plugin.KOTLIN_VERSION}", + "implementation" to APPCOMPAT + ) + ) + + val expectedAdvice = setOf(PluginAdvice.redundantKotlinParcelize()) +} + private val transitiveDagger = ModuleCoordinates("com.google.dagger:dagger", "2.24", GradleVariantIdentification(emptySet(), emptyMap())) private val transitiveInject = ModuleCoordinates("javax.inject:javax.inject", "1", GradleVariantIdentification(emptySet(), emptyMap())) private val transitiveInject2 = ModuleCoordinates("javax.inject:javax.inject", "1", GradleVariantIdentification(emptySet(), emptyMap())) diff --git a/src/main/kotlin/com/autonomousapps/advice/PluginAdvice.kt b/src/main/kotlin/com/autonomousapps/advice/PluginAdvice.kt index fe7236c50..bf2fdda80 100644 --- a/src/main/kotlin/com/autonomousapps/advice/PluginAdvice.kt +++ b/src/main/kotlin/com/autonomousapps/advice/PluginAdvice.kt @@ -13,6 +13,7 @@ data class PluginAdvice( const val JAVA_LIBRARY = "java-library" const val KOTLIN_JVM = "org.jetbrains.kotlin.jvm" const val KOTLIN_KAPT = "kotlin-kapt" + const val KOTLIN_PARCELIZE = "kotlin-parcelize" @JvmStatic fun redundantJavaLibrary() = PluginAdvice( @@ -34,6 +35,13 @@ data class PluginAdvice( reason = "this project has the kotlin-kapt (org.jetbrains.kotlin.kapt) plugin applied, but " + "there are no used annotation processors." ) + + @JvmStatic + fun redundantKotlinParcelize() = PluginAdvice( + redundantPlugin = KOTLIN_PARCELIZE, + reason = "this project has the kotlin-parcelize (org.jetbrains.kotlin.plugin.parcelize) plugin applied, but " + + "there are no classes annotated with @Parcelize." + ) } override fun compareTo(other: PluginAdvice): Int {