From 622e6633088123ec3a25c37e56bc3a8851adb357 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 5 Feb 2024 20:25:42 -0500 Subject: [PATCH] Update to dagger 2.50 (#830) * Update dagger + force later guava version in tests * Generate new Dagger createFactoryProvider functions * Prohibit extension functions for @Binds * Disable KspComponentProcessor in KSP tests --- .../dependencies/runtimeClasspath.txt | 2 +- .../internal/testing/AnvilCompilation.kt | 7 +- compiler/build.gradle.kts | 2 + compiler/dependencies/runtimeClasspath.txt | 2 +- .../codegen/dagger/AssistedFactoryCodeGen.kt | 27 +-- .../codegen/dagger/BindsMethodValidator.kt | 10 +- .../dagger/ProvidesMethodFactoryCodeGen.kt | 13 ++ .../dagger/AssistedFactoryGeneratorTest.kt | 186 +++++++++++++++--- .../dagger/BindsMethodValidatorTest.kt | 80 +------- .../dagger/MembersInjectorGeneratorTest.kt | 7 +- .../ProvidesMethodFactoryGeneratorTest.kt | 31 +++ gradle/libs.versions.toml | 4 +- 12 files changed, 250 insertions(+), 121 deletions(-) diff --git a/compiler-utils/dependencies/runtimeClasspath.txt b/compiler-utils/dependencies/runtimeClasspath.txt index e29debed2..373626dd5 100644 --- a/compiler-utils/dependencies/runtimeClasspath.txt +++ b/compiler-utils/dependencies/runtimeClasspath.txt @@ -1,4 +1,4 @@ -com.google.dagger:dagger:2.46.1 +com.google.dagger:dagger:2.50 com.squareup:kotlinpoet-jvm:1.16.0 com.squareup:kotlinpoet:1.16.0 javax.inject:javax.inject:1 diff --git a/compiler-utils/src/testFixtures/java/com/squareup/anvil/compiler/internal/testing/AnvilCompilation.kt b/compiler-utils/src/testFixtures/java/com/squareup/anvil/compiler/internal/testing/AnvilCompilation.kt index f93c97971..ce7c53c2a 100644 --- a/compiler-utils/src/testFixtures/java/com/squareup/anvil/compiler/internal/testing/AnvilCompilation.kt +++ b/compiler-utils/src/testFixtures/java/com/squareup/anvil/compiler/internal/testing/AnvilCompilation.kt @@ -16,6 +16,7 @@ import com.tschuchort.compiletesting.kspArgs import com.tschuchort.compiletesting.kspWithCompilation import com.tschuchort.compiletesting.symbolProcessorProviders import dagger.internal.codegen.ComponentProcessor +import dagger.internal.codegen.KspComponentProcessor import org.intellij.lang.annotations.Language import org.jetbrains.kotlin.config.JvmTarget import java.io.File @@ -107,7 +108,11 @@ public class AnvilCompilation internal constructor( ServiceLoader.load( SymbolProcessorProvider::class.java, SymbolProcessorProvider::class.java.classLoader, - ), + ) + // TODO for now, we don't want to run the dagger KSP processor while we're testing + // KSP. This will change when we start supporting dagger-KSP, at which point we can + // change this filter to be based on https://github.com/square/anvil/pull/713 + .filterNot { it is KspComponentProcessor.Provider }, ) addAll(mode.symbolProcessorProviders) } diff --git a/compiler/build.gradle.kts b/compiler/build.gradle.kts index f92566a93..839cc852f 100644 --- a/compiler/build.gradle.kts +++ b/compiler/build.gradle.kts @@ -53,6 +53,8 @@ dependencies { testImplementation(testFixtures(project(":compiler-utils"))) testImplementation(libs.dagger2.compiler) + // Force later guava version for Dagger's needs + testImplementation(libs.guava) testImplementation(libs.kotlin.annotationProcessingEmbeddable) testImplementation(libs.kotlin.compileTesting) testImplementation(libs.kotlin.compileTesting.ksp) diff --git a/compiler/dependencies/runtimeClasspath.txt b/compiler/dependencies/runtimeClasspath.txt index 63e592a25..8dffc7c4d 100644 --- a/compiler/dependencies/runtimeClasspath.txt +++ b/compiler/dependencies/runtimeClasspath.txt @@ -1,4 +1,4 @@ -com.google.dagger:dagger:2.46.1 +com.google.dagger:dagger:2.50 com.squareup:kotlinpoet-jvm:1.16.0 com.squareup:kotlinpoet-ksp:1.16.0 com.squareup:kotlinpoet:1.16.0 diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/AssistedFactoryCodeGen.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/AssistedFactoryCodeGen.kt index a6721a75a..a9d9f83f1 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/AssistedFactoryCodeGen.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/AssistedFactoryCodeGen.kt @@ -558,19 +558,24 @@ internal object AssistedFactoryCodeGen : AnvilApplicabilityChecker { .build(), ) .apply { + fun createFactory(name: String, providerTypeName: ClassName): FunSpec { + return FunSpec.builder(name) + .jvmStatic() + .addTypeVariables(typeParameters) + .addParameter(DELEGATE_FACTORY_NAME, generatedFactoryTypeName) + .returns(providerTypeName.parameterizedBy(baseFactoryTypeName)) + .addStatement( + "return %T.create(%T($DELEGATE_FACTORY_NAME))", + InstanceFactory::class, + implParameterizedTypeName, + ) + .build() + } TypeSpec.companionObjectBuilder() + .addFunction(createFactory("create", Provider::class.asClassName())) + // New in Dagger 2.50: factories for dagger.internal.Provider .addFunction( - FunSpec.builder("create") - .jvmStatic() - .addTypeVariables(typeParameters) - .addParameter(DELEGATE_FACTORY_NAME, generatedFactoryTypeName) - .returns(Provider::class.asClassName().parameterizedBy(baseFactoryTypeName)) - .addStatement( - "return %T.create(%T($DELEGATE_FACTORY_NAME))", - InstanceFactory::class, - implParameterizedTypeName, - ) - .build(), + createFactory("createFactoryProvider", dagger.internal.Provider::class.asClassName()), ) .build() .let { diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/BindsMethodValidator.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/BindsMethodValidator.kt index 558ba1ec3..2c8d30397 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/BindsMethodValidator.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/BindsMethodValidator.kt @@ -59,9 +59,15 @@ internal class BindsMethodValidator : PrivateCodeGenerator() { ) } + if (function.function.isExtensionDeclaration()) { + throw AnvilCompilationExceptionFunctionReference( + message = "@Binds methods can not be an extension function", + functionReference = function, + ) + } + val hasSingleBindingParameter = - (function.parameters.size == 1 && !function.function.isExtensionDeclaration()) || - (function.parameters.isEmpty() && function.function.isExtensionDeclaration()) + function.parameters.size == 1 && !function.function.isExtensionDeclaration() if (!hasSingleBindingParameter) { throw AnvilCompilationExceptionFunctionReference( message = "@Binds methods must have exactly one parameter, " + diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/ProvidesMethodFactoryCodeGen.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/ProvidesMethodFactoryCodeGen.kt index 87b49a998..1a04dfdeb 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/ProvidesMethodFactoryCodeGen.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/ProvidesMethodFactoryCodeGen.kt @@ -65,6 +65,7 @@ import dagger.internal.Factory import dagger.internal.Preconditions import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration import java.io.File internal object ProvidesMethodFactoryCodeGen : AnvilApplicabilityChecker { @@ -151,6 +152,12 @@ internal object ProvidesMethodFactoryCodeGen : AnvilApplicabilityChecker { } private fun CallableReference.Companion.from(function: KSFunctionDeclaration): CallableReference { + if (function.extensionReceiver != null) { + throw KspAnvilException( + message = "@Provides methods cannot be extension functions", + node = function, + ) + } val type = function.returnType?.resolve() ?: throw KspAnvilException( message = "Error occurred in type resolution and could not resolve return type.", node = function, @@ -281,6 +288,12 @@ internal object ProvidesMethodFactoryCodeGen : AnvilApplicabilityChecker { } private fun CallableReference.Companion.from(function: MemberFunctionReference.Psi): CallableReference { + if (function.function.isExtensionDeclaration()) { + throw AnvilCompilationExceptionFunctionReference( + message = "@Provides methods can not be an extension function", + functionReference = function, + ) + } val type = function.returnTypeOrNull() ?: throw AnvilCompilationExceptionFunctionReference( message = "Dagger provider methods must specify the return type explicitly when using " + "Anvil. The return type cannot be inferred implicitly.", diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt index 2e51eb719..0cf1b2dd0 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt @@ -139,12 +139,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -186,12 +190,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -229,12 +237,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -273,12 +285,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .last { it.name == "create" } @@ -313,12 +329,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val lambdaArg = { num: Int -> num.toString() } val assistedServiceInstance = factoryImplClass.declaredMethods @@ -355,12 +375,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val lambdaArg: suspend (Int) -> String = { num: Int -> num.toString() } val assistedServiceInstance = factoryImplClass.declaredMethods @@ -397,12 +421,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val lambdaArg = { num: Int -> num.toString() } val assistedServiceInstance = factoryImplClass.declaredMethods @@ -439,12 +467,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val lambdaArg = { num: Int -> num.toString() } val assistedServiceInstance = factoryImplClass.declaredMethods @@ -481,12 +513,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val lambdaArg = null val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } @@ -522,12 +558,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val lambdaArg = { num: Int -> num.toString() } val assistedServiceInstance = factoryImplClass.declaredMethods @@ -563,11 +603,15 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val generatedFactoryInstance = assistedService.factoryClass().createInstance() val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) } } @@ -602,12 +646,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .last { it.name == "invoke" } @@ -645,12 +693,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "hephaestus" } @@ -685,12 +737,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -725,12 +781,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -767,12 +827,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -876,12 +940,16 @@ public final class AssistedServiceFactory_Impl implement val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -916,12 +984,16 @@ public final class AssistedServiceFactory_Impl implement val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -973,12 +1045,16 @@ public final class AssistedServiceFactory_Impl implement val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1019,12 +1095,16 @@ public final class AssistedServiceFactory_Impl implement val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1064,12 +1144,16 @@ public final class AssistedServiceFactory_Impl implement val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1170,12 +1254,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1352,12 +1440,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1401,12 +1493,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1443,12 +1539,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1485,12 +1585,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1530,12 +1634,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1570,12 +1678,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1912,12 +2024,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -1978,12 +2094,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } @@ -2042,12 +2162,16 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance) val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic } - assertThat(staticMethods).hasSize(1) + assertThat(staticMethods).hasSize(2) val factoryProvider = staticMethods.single { it.name == "create" } .invoke(null, generatedFactoryInstance) as Provider<*> assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val newFactoryProvider = staticMethods.single { it.name == "createFactoryProvider" } + .invoke(null, generatedFactoryInstance) as dagger.internal.Provider<*> + assertThat(newFactoryProvider.get()::class.java).isEqualTo(factoryImplClass) + val assistedServiceInstance = factoryImplClass.declaredMethods .filterNot { it.isStatic } .single { it.name == "create" } diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/BindsMethodValidatorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/BindsMethodValidatorTest.kt index 90f2438eb..7bab17050 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/BindsMethodValidatorTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/BindsMethodValidatorTest.kt @@ -6,6 +6,7 @@ import com.squareup.anvil.compiler.internal.testing.compileAnvil import com.squareup.anvil.compiler.isError import com.squareup.anvil.compiler.isFullTestRun import com.tschuchort.compiletesting.JvmCompilationResult +import com.tschuchort.compiletesting.KotlinCompilation.ExitCode.COMPILATION_ERROR import com.tschuchort.compiletesting.KotlinCompilation.ExitCode.OK import org.intellij.lang.annotations.Language import org.junit.Test @@ -177,35 +178,6 @@ class BindsMethodValidatorTest( } } - @Test - fun `an extension function binding with a parameter fails to compile`() { - compile( - """ - package com.squareup.test - - import dagger.Binds - import dagger.Module - import javax.inject.Inject - - class Foo @Inject constructor() : Bar - class Hammer @Inject constructor() : Bar - interface Bar - - @Module - abstract class BarModule { - @Binds - abstract fun Foo.bindsBar(impl2: Hammer): Bar - } - """, - ) { - assertThat(exitCode).isError() - assertThat(messages).contains( - "@Binds methods must have exactly one parameter, " + - "whose type is assignable to the return type", - ) - } - } - @Test fun `a binding with no return type fails to compile`() { compile( @@ -234,8 +206,8 @@ class BindsMethodValidatorTest( } @Test - fun `an extension function binding is valid`() { - val moduleResult = compile( + fun `an extension function binding is invalid`() { + compile( """ package com.squareup.test @@ -253,25 +225,8 @@ class BindsMethodValidatorTest( } """, ) { - assertThat(exitCode).isEqualTo(OK) - } - - compile( - """ - package com.squareup.test - - import dagger.Component - import javax.inject.Singleton - - @Component(modules = [BarModule::class]) - interface ComponentInterface { - fun bar(): Bar - } - """, - previousCompilationResult = moduleResult, - enableDagger = true, - ) { - assertThat(exitCode).isEqualTo(OK) + assertThat(exitCode).isEqualTo(COMPILATION_ERROR) + assertThat(messages).contains("@Binds methods can not be an extension function") } } @@ -322,8 +277,8 @@ class BindsMethodValidatorTest( } @Test - fun `an extension function binding with a qualifier is valid`() { - val moduleResult = compile( + fun `an extension function binding with a qualifier is invalid`() { + compile( """ package com.squareup.test @@ -354,25 +309,8 @@ class BindsMethodValidatorTest( } """, ) { - assertThat(exitCode).isEqualTo(OK) - } - - compile( - """ - package com.squareup.test - - import dagger.Component - - @Component(modules = [BarModule::class]) - interface ComponentInterface { - @Marker - fun bar(): Bar - } - """, - previousCompilationResult = moduleResult, - enableDagger = true, - ) { - assertThat(exitCode).isEqualTo(OK) + assertThat(exitCode).isEqualTo(COMPILATION_ERROR) + assertThat(messages).contains("@Binds methods can not be an extension function") } } diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/MembersInjectorGeneratorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/MembersInjectorGeneratorTest.kt index 7e7784942..b76816cb9 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/MembersInjectorGeneratorTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/MembersInjectorGeneratorTest.kt @@ -19,6 +19,7 @@ import com.tschuchort.compiletesting.KotlinCompilation.ExitCode.OK import dagger.Lazy import dagger.MembersInjector import org.intellij.lang.annotations.Language +import org.junit.Assume.assumeTrue import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @@ -2224,7 +2225,8 @@ public final class InjectClass_MembersInjector implements MembersInject @Test fun `a member injector is generated for a class with a typealias superclass`() { - + // TODO remove after next dagger release with a fix https://github.com/google/dagger/issues/4199 + assumeTrue(mode is AnvilCompilationMode.Embedded) compile( """ package com.squareup.test @@ -2296,7 +2298,8 @@ public final class InjectClass_MembersInjector implements MembersInject @Test fun `a member injector is generated for a class with a typealias superclass in another module`() { - + // TODO remove after next dagger release with a fix https://github.com/google/dagger/issues/4199 + assumeTrue(mode is AnvilCompilationMode.Embedded) val otherModuleResult = compile( """ package com.squareup.test diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/ProvidesMethodFactoryGeneratorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/ProvidesMethodFactoryGeneratorTest.kt index 6b40a3aa1..2894ab3ee 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/ProvidesMethodFactoryGeneratorTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/ProvidesMethodFactoryGeneratorTest.kt @@ -10,6 +10,7 @@ import com.squareup.anvil.compiler.dagger.UppercasePackage.lowerCaseClassInUpper import com.squareup.anvil.compiler.daggerModule1 import com.squareup.anvil.compiler.innerModule import com.squareup.anvil.compiler.internal.testing.AnvilCompilationMode +import com.squareup.anvil.compiler.internal.testing.AnvilCompilationMode.Ksp import com.squareup.anvil.compiler.internal.testing.compileAnvil import com.squareup.anvil.compiler.internal.testing.createInstance import com.squareup.anvil.compiler.internal.testing.isStatic @@ -18,6 +19,7 @@ import com.squareup.anvil.compiler.isError import com.squareup.anvil.compiler.useDaggerAndKspParams import com.tschuchort.compiletesting.JvmCompilationResult import com.tschuchort.compiletesting.KotlinCompilation.ExitCode +import com.tschuchort.compiletesting.KotlinCompilation.ExitCode.COMPILATION_ERROR import dagger.Lazy import dagger.internal.Factory import org.intellij.lang.annotations.Language @@ -3510,6 +3512,35 @@ public final class DaggerModule1_ProvideFunctionFactory implements Factory