From 36264e7df3fc22eec3906269c89dd3844ce54e8f Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Thu, 24 Oct 2024 15:24:16 -0400 Subject: [PATCH] Initial support for Jakarta annotations (#79) --- compiler-utils/api/compiler-utils.api | 6 ++ .../dependencies/runtimeClasspath.txt | 3 +- .../anvil/compiler/internal/FqName.kt | 12 +++- .../internal/ksp/KSAnnotationExtensions.kt | 16 ++++-- .../anvil/compiler/internal/ksp/KspUtil.kt | 22 +++++++- .../internal/reference/AnnotatedReference.kt | 3 + .../internal/reference/AnnotationReference.kt | 8 +-- compiler/build.gradle.kts | 1 + compiler/dependencies/runtimeClasspath.txt | 3 +- .../java/com/squareup/anvil/compiler/Utils.kt | 20 +++++-- .../codegen/ClassReferenceExtensions.kt | 4 +- .../codegen/dagger/AssistedFactoryCodeGen.kt | 3 +- .../codegen/dagger/DaggerGenerationUtils.kt | 56 +++++++++---------- .../dagger/InjectConstructorFactoryCodeGen.kt | 7 +-- .../codegen/dagger/MembersInjectorCodeGen.kt | 7 ++- .../compiler/codegen/dagger/Parameter.kt | 3 +- gradle/libs.versions.toml | 3 +- 17 files changed, 116 insertions(+), 61 deletions(-) diff --git a/compiler-utils/api/compiler-utils.api b/compiler-utils/api/compiler-utils.api index 89b8c17ca..184101407 100644 --- a/compiler-utils/api/compiler-utils.api +++ b/compiler-utils/api/compiler-utils.api @@ -132,13 +132,17 @@ public final class com/squareup/anvil/compiler/internal/ksp/KspUtilKt { public static final fun getFqName (Lcom/google/devtools/ksp/symbol/KSClassDeclaration;)Lorg/jetbrains/kotlin/name/FqName; public static final fun getFqName (Lcom/google/devtools/ksp/symbol/KSType;)Lorg/jetbrains/kotlin/name/FqName; public static final fun getKSAnnotationsByQualifiedName (Lcom/google/devtools/ksp/symbol/KSAnnotated;Ljava/lang/String;)Lkotlin/sequences/Sequence; + public static final fun getKSAnnotationsByQualifiedName (Lcom/google/devtools/ksp/symbol/KSAnnotated;Ljava/util/Set;)Lkotlin/sequences/Sequence; public static final fun getKSAnnotationsByType (Lcom/google/devtools/ksp/symbol/KSAnnotated;Lkotlin/reflect/KClass;)Lkotlin/sequences/Sequence; public static final fun getReportableReturnTypeNode (Lcom/google/devtools/ksp/symbol/KSFunctionDeclaration;)Lcom/google/devtools/ksp/symbol/KSNode; public static final fun getResolvableAnnotations (Lcom/google/devtools/ksp/symbol/KSAnnotated;)Lkotlin/sequences/Sequence; + public static final fun getSymbolsWithAnnotations (Lcom/google/devtools/ksp/processing/Resolver;Ljava/util/Set;)Lkotlin/sequences/Sequence; public static final fun injectConstructors (Lcom/google/devtools/ksp/processing/Resolver;)Ljava/util/List; public static final fun isAnnotationClass (Lcom/google/devtools/ksp/symbol/KSClassDeclaration;)Z public static final fun isAnnotationPresent (Lcom/google/devtools/ksp/symbol/KSAnnotated;Ljava/lang/String;)Z + public static final fun isAnnotationPresent (Lcom/google/devtools/ksp/symbol/KSAnnotated;Ljava/util/Set;)Z public static final fun isAnnotationPresent (Lcom/google/devtools/ksp/symbol/KSAnnotated;Lkotlin/reflect/KClass;)Z + public static final fun isAnnotationPresentFqName (Lcom/google/devtools/ksp/symbol/KSAnnotated;Ljava/util/Set;)Z public static final fun isExtensionDeclaration (Lcom/google/devtools/ksp/symbol/KSFunctionDeclaration;)Z public static final fun isLateInit (Lcom/google/devtools/ksp/symbol/KSModifierListOwner;)Z public static final fun mergeAnnotations (Lcom/google/devtools/ksp/symbol/KSAnnotated;)Ljava/util/List; @@ -159,10 +163,12 @@ public final class com/squareup/anvil/compiler/internal/ksp/KspUtilKt { public abstract interface class com/squareup/anvil/compiler/internal/reference/AnnotatedReference { public abstract fun getAnnotations ()Ljava/util/List; + public fun isAnnotatedWith (Ljava/util/Set;)Z public fun isAnnotatedWith (Lorg/jetbrains/kotlin/name/FqName;)Z } public final class com/squareup/anvil/compiler/internal/reference/AnnotatedReference$DefaultImpls { + public static fun isAnnotatedWith (Lcom/squareup/anvil/compiler/internal/reference/AnnotatedReference;Ljava/util/Set;)Z public static fun isAnnotatedWith (Lcom/squareup/anvil/compiler/internal/reference/AnnotatedReference;Lorg/jetbrains/kotlin/name/FqName;)Z } diff --git a/compiler-utils/dependencies/runtimeClasspath.txt b/compiler-utils/dependencies/runtimeClasspath.txt index cdf9735a6..178cecf0c 100644 --- a/compiler-utils/dependencies/runtimeClasspath.txt +++ b/compiler-utils/dependencies/runtimeClasspath.txt @@ -1,8 +1,9 @@ -com.google.dagger:dagger:2.51.1 +com.google.dagger:dagger:2.52 com.google.devtools.ksp:symbol-processing-api:1.9.24-1.0.20 com.squareup:kotlinpoet-jvm:1.16.0 com.squareup:kotlinpoet-ksp:1.16.0 com.squareup:kotlinpoet:1.16.0 +jakarta.inject:jakarta.inject-api:2.0.1 javax.inject:javax.inject:1 org.jetbrains.intellij.deps:trove4j:1.0.20200330 org.jetbrains.kotlin:kotlin-bom:1.9.24 diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/FqName.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/FqName.kt index 1a245ac89..b7fd9b1a8 100644 --- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/FqName.kt +++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/FqName.kt @@ -19,14 +19,22 @@ import javax.inject.Inject import javax.inject.Qualifier import javax.inject.Scope import kotlin.reflect.KClass +import jakarta.inject.Qualifier as JakartaQualifier +import jakarta.inject.Scope as JakartaScope internal val jvmSuppressWildcardsFqName = JvmSuppressWildcards::class.fqName internal val publishedApiFqName = PublishedApi::class.fqName -internal val qualifierFqName = Qualifier::class.fqName +internal val qualifierFqNames = setOf( + Qualifier::class.fqName, + JakartaQualifier::class.fqName, +) internal val mapKeyFqName = MapKey::class.fqName internal val daggerProvidesFqName = Provides::class.fqName internal val daggerLazyFqName = Lazy::class.fqName -internal val daggerScopeFqName = Scope::class.fqName +internal val scopeFqNames = setOf( + Scope::class.fqName, + JakartaScope::class.fqName, +) internal val injectFqName = Inject::class.fqName internal val contributesToFqName = ContributesTo::class.fqName diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/ksp/KSAnnotationExtensions.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/ksp/KSAnnotationExtensions.kt index 162414f7c..b451ec7dc 100644 --- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/ksp/KSAnnotationExtensions.kt +++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/ksp/KSAnnotationExtensions.kt @@ -10,9 +10,9 @@ import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSType import com.google.devtools.ksp.symbol.KSValueArgument import com.squareup.anvil.annotations.ContributesBinding -import com.squareup.anvil.compiler.internal.daggerScopeFqName import com.squareup.anvil.compiler.internal.mapKeyFqName -import com.squareup.anvil.compiler.internal.qualifierFqName +import com.squareup.anvil.compiler.internal.qualifierFqNames +import com.squareup.anvil.compiler.internal.scopeFqNames import com.squareup.kotlinpoet.ClassName import org.jetbrains.kotlin.name.FqName @@ -207,14 +207,18 @@ public fun KSAnnotation.argumentAt( } private fun KSAnnotation.isTypeAnnotatedWith( - annotationFqName: FqName, + vararg annotationFqName: FqName, +): Boolean = isTypeAnnotatedWith(annotationFqName.toSet()) + +private fun KSAnnotation.isTypeAnnotatedWith( + annotationFqNames: Set, ): Boolean = annotationType.resolve() .declaration - .isAnnotationPresent(annotationFqName.asString()) + .isAnnotationPresent(annotationFqNames.toSet()) -public fun KSAnnotation.isQualifier(): Boolean = isTypeAnnotatedWith(qualifierFqName) +public fun KSAnnotation.isQualifier(): Boolean = isTypeAnnotatedWith(qualifierFqNames) public fun KSAnnotation.isMapKey(): Boolean = isTypeAnnotatedWith(mapKeyFqName) -public fun KSAnnotation.isDaggerScope(): Boolean = isTypeAnnotatedWith(daggerScopeFqName) +public fun KSAnnotation.isDaggerScope(): Boolean = isTypeAnnotatedWith(scopeFqNames) public fun KSAnnotated.qualifierAnnotation(): KSAnnotation? = resolvableAnnotations.singleOrNull { it.isQualifier() } diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/ksp/KspUtil.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/ksp/KspUtil.kt index da51d3ce2..4ffecd98a 100644 --- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/ksp/KspUtil.kt +++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/ksp/KspUtil.kt @@ -62,6 +62,15 @@ public fun KSAnnotated.getKSAnnotationsByType( */ public fun KSAnnotated.getKSAnnotationsByQualifiedName( qualifiedName: String, +): Sequence { + return getKSAnnotationsByQualifiedName(setOf(qualifiedName)) +} + +/** + * Returns a sequence of [KSAnnotations][KSAnnotation] of the given [qualifiedName]. + */ +public fun KSAnnotated.getKSAnnotationsByQualifiedName( + qualifiedNames: Set, ): Sequence { // Don't use resolvableAnnotations here to save the double resolve() call return annotations.filter { @@ -72,13 +81,20 @@ public fun KSAnnotated.getKSAnnotationsByQualifiedName( if (type.isError) return@filter false // Resolve the KSClassDeclaration to ensure we peek through typealiases - type.resolveKSClassDeclaration()?.qualifiedName?.asString() == qualifiedName + type.resolveKSClassDeclaration()?.qualifiedName?.asString() in qualifiedNames } } public fun KSAnnotated.isAnnotationPresent(qualifiedName: String): Boolean = getKSAnnotationsByQualifiedName(qualifiedName).firstOrNull() != null +@JvmName("isAnnotationPresentFqName") +public fun KSAnnotated.isAnnotationPresent(qualifiedNames: Set): Boolean = + isAnnotationPresent(qualifiedNames.mapTo(mutableSetOf()) { it.asString() }) + +public fun KSAnnotated.isAnnotationPresent(qualifiedNames: Set): Boolean = + getKSAnnotationsByQualifiedName(qualifiedNames).firstOrNull() != null + public inline fun KSAnnotated.isAnnotationPresent(): Boolean { return isAnnotationPresent(T::class) } @@ -478,3 +494,7 @@ public fun Resolver.requireClassDeclaration(fqName: FqName, node: KSNode?): KSCl } } } + +public fun Resolver.getSymbolsWithAnnotations(fqNames: Set): Sequence { + return fqNames.asSequence().flatMap { getSymbolsWithAnnotation(it.asString()) } +} diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotatedReference.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotatedReference.kt index 069b7386b..de7197aee 100644 --- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotatedReference.kt +++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotatedReference.kt @@ -12,4 +12,7 @@ public interface AnnotatedReference { public val annotations: List public fun isAnnotatedWith(fqName: FqName): Boolean = annotations.any { it.fqName == fqName } + public fun isAnnotatedWith( + fqNames: Set, + ): Boolean = annotations.any { it.fqName in fqNames } } diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotationReference.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotationReference.kt index 6619fe2c7..872a0ddb3 100644 --- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotationReference.kt +++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotationReference.kt @@ -6,16 +6,16 @@ import com.squareup.anvil.compiler.internal.contributesBindingFqName import com.squareup.anvil.compiler.internal.contributesMultibindingFqName import com.squareup.anvil.compiler.internal.contributesSubcomponentFqName import com.squareup.anvil.compiler.internal.contributesToFqName -import com.squareup.anvil.compiler.internal.daggerScopeFqName import com.squareup.anvil.compiler.internal.mapKeyFqName import com.squareup.anvil.compiler.internal.mergeComponentFqName import com.squareup.anvil.compiler.internal.mergeInterfacesFqName import com.squareup.anvil.compiler.internal.mergeModulesFqName import com.squareup.anvil.compiler.internal.mergeSubcomponentFqName -import com.squareup.anvil.compiler.internal.qualifierFqName +import com.squareup.anvil.compiler.internal.qualifierFqNames import com.squareup.anvil.compiler.internal.reference.AnnotationReference.Descriptor import com.squareup.anvil.compiler.internal.reference.AnnotationReference.Psi import com.squareup.anvil.compiler.internal.requireFqName +import com.squareup.anvil.compiler.internal.scopeFqNames import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.MemberName import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -87,9 +87,9 @@ public sealed class AnnotationReference { public fun exclude(parameterIndex: Int = excludeIndex(fqName)): List = argumentAt("exclude", parameterIndex)?.value>().orEmpty() - public fun isQualifier(): Boolean = classReference.isAnnotatedWith(qualifierFqName) + public fun isQualifier(): Boolean = classReference.isAnnotatedWith(qualifierFqNames) public fun isMapKey(): Boolean = classReference.isAnnotatedWith(mapKeyFqName) - public fun isDaggerScope(): Boolean = classReference.isAnnotatedWith(daggerScopeFqName) + public fun isDaggerScope(): Boolean = classReference.isAnnotatedWith(scopeFqNames) public fun toAnnotationSpec(): AnnotationSpec { return AnnotationSpec diff --git a/compiler/build.gradle.kts b/compiler/build.gradle.kts index 661a2bd57..848fd8f12 100644 --- a/compiler/build.gradle.kts +++ b/compiler/build.gradle.kts @@ -45,6 +45,7 @@ dependencies { implementation(platform(libs.kotlin.bom)) implementation(libs.dagger2) implementation(libs.jsr250) + implementation(libs.jakarta) implementation(libs.kotlinpoet) implementation(libs.kotlinpoet.ksp) diff --git a/compiler/dependencies/runtimeClasspath.txt b/compiler/dependencies/runtimeClasspath.txt index 77b61f1f4..4109547c4 100644 --- a/compiler/dependencies/runtimeClasspath.txt +++ b/compiler/dependencies/runtimeClasspath.txt @@ -1,8 +1,9 @@ -com.google.dagger:dagger:2.51.1 +com.google.dagger:dagger:2.52 com.google.devtools.ksp:symbol-processing-api:1.9.24-1.0.20 com.squareup:kotlinpoet-jvm:1.16.0 com.squareup:kotlinpoet-ksp:1.16.0 com.squareup:kotlinpoet:1.16.0 +jakarta.inject:jakarta.inject-api:2.0.1 javax.annotation:jsr250-api:1.0 javax.inject:javax.inject:1 org.jetbrains.intellij.deps:trove4j:1.0.20200330 diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/Utils.kt b/compiler/src/main/java/com/squareup/anvil/compiler/Utils.kt index 76a8851bf..180f88b52 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/Utils.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/Utils.kt @@ -27,7 +27,9 @@ import dagger.internal.DoubleCheck import java.io.File import javax.inject.Inject import javax.inject.Provider -import javax.inject.Qualifier +import dagger.internal.Provider as DaggerProvider +import jakarta.inject.Inject as JakartaInject +import jakarta.inject.Provider as JakartaProvider internal val mergeComponentFqName = MergeComponent::class.fqName internal val mergeComponentFactoryFqName = MergeComponent.Factory::class.fqName @@ -69,14 +71,22 @@ internal val daggerBindsFqName = Binds::class.fqName internal val daggerProvidesFqName = Provides::class.fqName internal val daggerLazyFqName = Lazy::class.fqName internal val daggerLazyClassName = Lazy::class.asClassName() -internal val injectFqName = Inject::class.fqName -internal val qualifierFqName = Qualifier::class.fqName +internal val injectFqNames = setOf( + Inject::class.fqName, + JakartaInject::class.fqName, +) internal val mapKeyFqName = MapKey::class.fqName internal val assistedFqName = Assisted::class.fqName internal val assistedFactoryFqName = AssistedFactory::class.fqName internal val assistedInjectFqName = AssistedInject::class.fqName -internal val providerFqName = Provider::class.fqName -internal val providerClassName = Provider::class.asClassName() +internal val daggerProviderClassName = DaggerProvider::class.asClassName() +internal val javaxProviderClassName = Provider::class.asClassName() +internal val providerClassNames = setOf( + Provider::class.asClassName(), + JakartaProvider::class.asClassName(), + DaggerProvider::class.asClassName(), +) +internal val providerFqNames = providerClassNames.mapToSet { it.fqName } internal val jvmSuppressWildcardsFqName = JvmSuppressWildcards::class.fqName internal val jvmFieldFqName = JvmField::class.fqName internal val publishedApiFqName = PublishedApi::class.fqName diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ClassReferenceExtensions.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ClassReferenceExtensions.kt index e622b5916..f0464f635 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ClassReferenceExtensions.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ClassReferenceExtensions.kt @@ -3,7 +3,7 @@ package com.squareup.anvil.compiler.codegen import com.squareup.anvil.compiler.anyFqName import com.squareup.anvil.compiler.assistedInjectFqName import com.squareup.anvil.compiler.contributesMultibindingFqName -import com.squareup.anvil.compiler.injectFqName +import com.squareup.anvil.compiler.injectFqNames import com.squareup.anvil.compiler.internal.reference.AnnotationReference import com.squareup.anvil.compiler.internal.reference.AnvilCompilationExceptionClassReference import com.squareup.anvil.compiler.internal.reference.ClassReference @@ -116,7 +116,7 @@ internal fun ClassReference.atLeastOneAnnotation( */ internal fun Collection.injectConstructor(): T? { val constructors = filter { - it.isAnnotatedWith(injectFqName) || it.isAnnotatedWith(assistedInjectFqName) + it.isAnnotatedWith(injectFqNames) || it.isAnnotatedWith(assistedInjectFqName) } return when (constructors.size) { 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 99c38c2c6..dba354e54 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 @@ -74,7 +74,6 @@ import dagger.internal.InstanceFactory import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.psi.KtFile import java.io.File -import javax.inject.Provider internal object AssistedFactoryCodeGen : AnvilApplicabilityChecker { @@ -591,7 +590,7 @@ internal object AssistedFactoryCodeGen : AnvilApplicabilityChecker { .build() } TypeSpec.companionObjectBuilder() - .addFunction(createFactory("create", Provider::class.asClassName())) + .addFunction(createFactory("create", javax.inject.Provider::class.asClassName())) // New in Dagger 2.50: factories for dagger.internal.Provider .addFunction( createFactory("createFactoryProvider", dagger.internal.Provider::class.asClassName()), diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/DaggerGenerationUtils.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/DaggerGenerationUtils.kt index 41a0782fb..f7ed5197f 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/DaggerGenerationUtils.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/DaggerGenerationUtils.kt @@ -17,7 +17,7 @@ import com.squareup.anvil.compiler.assistedFqName import com.squareup.anvil.compiler.daggerDoubleCheckFqNameString import com.squareup.anvil.compiler.daggerLazyClassName import com.squareup.anvil.compiler.daggerLazyFqName -import com.squareup.anvil.compiler.injectFqName +import com.squareup.anvil.compiler.injectFqNames import com.squareup.anvil.compiler.internal.capitalize import com.squareup.anvil.compiler.internal.joinSimpleNames import com.squareup.anvil.compiler.internal.ksp.KspAnvilException @@ -46,32 +46,33 @@ import com.squareup.anvil.compiler.internal.reference.joinSimpleNames import com.squareup.anvil.compiler.internal.requireRawType import com.squareup.anvil.compiler.internal.unwrappedTypes import com.squareup.anvil.compiler.internal.withJvmSuppressWildcardsIfNeeded +import com.squareup.anvil.compiler.javaxProviderClassName import com.squareup.anvil.compiler.jvmFieldFqName -import com.squareup.anvil.compiler.providerClassName -import com.squareup.anvil.compiler.providerFqName +import com.squareup.anvil.compiler.providerClassNames +import com.squareup.anvil.compiler.providerFqNames import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.ParameterizedTypeName import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.TypeName -import com.squareup.kotlinpoet.asClassName import com.squareup.kotlinpoet.ksp.TypeParameterResolver import com.squareup.kotlinpoet.ksp.toAnnotationSpec import com.squareup.kotlinpoet.ksp.toClassName import com.squareup.kotlinpoet.ksp.toTypeParameterResolver -import dagger.Lazy import dagger.assisted.Assisted import dagger.internal.ProviderOfLazy import org.jetbrains.kotlin.name.FqName -import javax.inject.Inject -import javax.inject.Provider -internal fun TypeName.wrapInProvider(): ParameterizedTypeName { - return Provider::class.asClassName().parameterizedBy(this) +internal fun TypeName.wrapInProvider(providerType: ClassName): ParameterizedTypeName { + return providerType.parameterizedBy(this) } internal fun TypeName.wrapInLazy(): ParameterizedTypeName { - return Lazy::class.asClassName().parameterizedBy(this) + return wrapIn(daggerLazyClassName) +} + +private fun TypeName.wrapIn(target: ClassName): ParameterizedTypeName { + return target.parameterizedBy(this) } internal fun List.mapToConstructorParameters(): List { @@ -85,7 +86,7 @@ private fun ParameterReference.toConstructorParameter( ): ConstructorParameter { val type = type() - val isWrappedInProvider = type.asClassReferenceOrNull()?.fqName == providerFqName + val isWrappedInProvider = type.asClassReferenceOrNull()?.fqName in providerFqNames val isWrappedInLazy = type.asClassReferenceOrNull()?.fqName == daggerLazyFqName val isLazyWrappedInProvider = isWrappedInProvider && type.unwrappedTypes.first().asClassReferenceOrNull()?.fqName == daggerLazyFqName @@ -107,7 +108,7 @@ private fun ParameterReference.toConstructorParameter( name = uniqueName, originalName = name, typeName = typeName, - providerTypeName = typeName.wrapInProvider(), + providerTypeName = typeName.wrapInProvider(javaxProviderClassName), lazyTypeName = typeName.wrapInLazy(), isWrappedInProvider = isWrappedInProvider, isWrappedInLazy = isWrappedInLazy, @@ -141,7 +142,7 @@ private fun KSValueParameter.toConstructorParameter( val paramTypeName = type.contextualToTypeName(this, typeParameterResolver) val rawType = paramTypeName.requireRawType() - val isWrappedInProvider = rawType == providerClassName + val isWrappedInProvider = rawType in providerClassNames val isWrappedInLazy = rawType == daggerLazyClassName val isLazyWrappedInProvider = isWrappedInProvider && (paramTypeName.unwrappedTypes.first().requireRawType()) == daggerLazyClassName @@ -164,7 +165,7 @@ private fun KSValueParameter.toConstructorParameter( name = uniqueName, originalName = name!!.asString(), typeName = typeName, - providerTypeName = typeName.wrapInProvider(), + providerTypeName = typeName.wrapInProvider(javaxProviderClassName), lazyTypeName = typeName.wrapInLazy(), isWrappedInProvider = isWrappedInProvider, isWrappedInLazy = isWrappedInLazy, @@ -228,7 +229,7 @@ private fun ClassReference.declaredMemberInjectParameters( implementingClass: ClassReference, ): List { return properties - .filter { it.isAnnotatedWith(injectFqName) } + .filter { it.isAnnotatedWith(injectFqNames) } .filter { it.visibility() != PRIVATE } .fold(listOf()) { acc, property -> val uniqueName = property.name.uniqueParameterName(superParameters, acc) @@ -279,8 +280,8 @@ private fun KSClassDeclaration.declaredMemberInjectParameters( val implementingType = implementingClass.asType(emptyList()) return getDeclaredProperties() .filter { - it.isAnnotationPresent() || - it.setter?.isAnnotationPresent() == true + it.isAnnotationPresent(injectFqNames) || + it.setter?.isAnnotationPresent(injectFqNames) == true } .filter { it.getVisibility() != Visibility.PRIVATE } .fold(mutableListOf()) { acc, property -> @@ -354,7 +355,7 @@ private fun MemberPropertyReference.toMemberInjectParameter( if ( !isLateinit() && !isAnnotatedWith(jvmFieldFqName) && - setterAnnotations.none { it.fqName == injectFqName } + setterAnnotations.none { it.fqName in injectFqNames } ) { // Technically this works with Anvil and we could remove this check. But we prefer consistency // with Dagger. @@ -367,8 +368,7 @@ private fun MemberPropertyReference.toMemberInjectParameter( val originalName = name val type = type() - - val isWrappedInProvider = type.asClassReferenceOrNull()?.fqName == providerFqName + val isWrappedInProvider = type.asClassReferenceOrNull()?.fqName in providerFqNames val isWrappedInLazy = type.asClassReferenceOrNull()?.fqName == daggerLazyFqName val isLazyWrappedInProvider = isWrappedInProvider && type.unwrappedTypes.first().asClassReferenceOrNull()?.fqName == daggerLazyFqName @@ -409,7 +409,7 @@ private fun MemberPropertyReference.toMemberInjectParameter( memberInjectorClassName, ) - val isSetterInjected = this.setterAnnotations.any { it.fqName == injectFqName } + val isSetterInjected = this.setterAnnotations.any { it.fqName in injectFqNames } // setter delegates require a "set" prefix for their inject function val accessName = if (isSetterInjected) { @@ -422,7 +422,7 @@ private fun MemberPropertyReference.toMemberInjectParameter( .filter { it.isQualifier() } .map { it.toAnnotationSpec() } - val providerTypeName = typeName.wrapInProvider() + val providerTypeName = typeName.wrapInProvider(javaxProviderClassName) return MemberInjectParameter( name = uniqueName, @@ -440,7 +440,7 @@ private fun MemberPropertyReference.toMemberInjectParameter( accessName = accessName, qualifierAnnotationSpecs = qualifierAnnotations, injectedFieldSignature = fqName, - resolvedProviderTypeName = resolvedTypeName?.wrapInProvider() ?: providerTypeName, + resolvedProviderTypeName = resolvedTypeName?.wrapInProvider(javaxProviderClassName) ?: providerTypeName, ) } @@ -454,7 +454,7 @@ private fun KSPropertyDeclaration.toMemberInjectParameter( if ( !isLateInit() && !isAnnotationPresent() && - setter?.isAnnotationPresent() != true + setter?.isAnnotationPresent(injectFqNames) != true ) { // Technically this works with Anvil and we could remove this check. But we prefer consistency // with Dagger. @@ -473,7 +473,7 @@ private fun KSPropertyDeclaration.toMemberInjectParameter( val propertyTypeName = resolvedType.contextualToTypeName(this, classParams) val rawType = propertyTypeName.requireRawType() - val isWrappedInProvider = rawType == providerClassName + val isWrappedInProvider = rawType in providerClassNames val isWrappedInLazy = rawType == daggerLazyClassName val isLazyWrappedInProvider = isWrappedInProvider && (propertyTypeName.unwrappedTypes.first().requireRawType()) == daggerLazyClassName @@ -514,7 +514,7 @@ private fun KSPropertyDeclaration.toMemberInjectParameter( memberInjectorClassName, ) - val isSetterInjected = this.setter?.isAnnotationPresent() == true + val isSetterInjected = this.setter?.isAnnotationPresent(injectFqNames) == true // setter delegates require a "set" prefix for their inject function val accessName = if (isSetterInjected) { @@ -528,7 +528,7 @@ private fun KSPropertyDeclaration.toMemberInjectParameter( .map { it.toAnnotationSpec() } .toList() - val providerTypeName = typeName.wrapInProvider() + val providerTypeName = typeName.wrapInProvider(javaxProviderClassName) return MemberInjectParameter( name = uniqueName, @@ -546,7 +546,7 @@ private fun KSPropertyDeclaration.toMemberInjectParameter( accessName = accessName, qualifierAnnotationSpecs = qualifierAnnotations, injectedFieldSignature = FqName(qualifiedName!!.asString()), - resolvedProviderTypeName = resolvedTypeName?.wrapInProvider() ?: providerTypeName, + resolvedProviderTypeName = resolvedTypeName?.wrapInProvider(javaxProviderClassName) ?: providerTypeName, ) } diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/InjectConstructorFactoryCodeGen.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/InjectConstructorFactoryCodeGen.kt index 15ea43090..c172221d3 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/InjectConstructorFactoryCodeGen.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/InjectConstructorFactoryCodeGen.kt @@ -16,7 +16,7 @@ import com.squareup.anvil.compiler.codegen.PrivateCodeGenerator import com.squareup.anvil.compiler.codegen.injectConstructor import com.squareup.anvil.compiler.codegen.ksp.AnvilSymbolProcessor import com.squareup.anvil.compiler.codegen.ksp.AnvilSymbolProcessorProvider -import com.squareup.anvil.compiler.injectFqName +import com.squareup.anvil.compiler.injectFqNames import com.squareup.anvil.compiler.internal.containingFileAsJavaFile import com.squareup.anvil.compiler.internal.createAnvilSpec import com.squareup.anvil.compiler.internal.joinSimpleNames @@ -45,7 +45,6 @@ import dagger.internal.Factory import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.psi.KtFile import java.io.File -import javax.inject.Inject internal object InjectConstructorFactoryCodeGen : AnvilApplicabilityChecker { override fun isApplicable(context: AnvilContext) = context.generateFactories @@ -60,7 +59,7 @@ internal object InjectConstructorFactoryCodeGen : AnvilApplicabilityChecker { val deferred = mutableListOf() resolver.injectConstructors() .forEach { (clazz, constructor) -> - if (!constructor.isAnnotationPresent()) { + if (!constructor.isAnnotationPresent(injectFqNames)) { // Only generating @Inject constructors return@forEach } @@ -112,7 +111,7 @@ internal object InjectConstructorFactoryCodeGen : AnvilApplicabilityChecker { .mapNotNull { clazz -> clazz.constructors .injectConstructor() - ?.takeIf { it.isAnnotatedWith(injectFqName) } + ?.takeIf { it.isAnnotatedWith(injectFqNames) } ?.let { generateFactoryClass(codeGenDir, clazz, it) } diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/MembersInjectorCodeGen.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/MembersInjectorCodeGen.kt index bfa649a2f..1474a0446 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/MembersInjectorCodeGen.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/MembersInjectorCodeGen.kt @@ -19,10 +19,11 @@ import com.squareup.anvil.compiler.api.createGeneratedFile import com.squareup.anvil.compiler.codegen.PrivateCodeGenerator import com.squareup.anvil.compiler.codegen.ksp.AnvilSymbolProcessor import com.squareup.anvil.compiler.codegen.ksp.AnvilSymbolProcessorProvider -import com.squareup.anvil.compiler.injectFqName +import com.squareup.anvil.compiler.injectFqNames import com.squareup.anvil.compiler.internal.capitalize import com.squareup.anvil.compiler.internal.createAnvilSpec import com.squareup.anvil.compiler.internal.joinSimpleNames +import com.squareup.anvil.compiler.internal.ksp.getSymbolsWithAnnotations import com.squareup.anvil.compiler.internal.reference.ClassReference import com.squareup.anvil.compiler.internal.reference.Visibility import com.squareup.anvil.compiler.internal.reference.asClassName @@ -60,7 +61,7 @@ internal object MembersInjectorCodeGen : AnvilApplicabilityChecker { override fun processChecked(resolver: Resolver): List { val deferred = mutableListOf() - resolver.getSymbolsWithAnnotation(injectFqName.asString()) + resolver.getSymbolsWithAnnotations(injectFqNames) .mapNotNull { when (it) { is KSPropertySetter -> { @@ -153,7 +154,7 @@ internal object MembersInjectorCodeGen : AnvilApplicabilityChecker { // (clazz.memberInjectParameters() will do this). clazz.properties .filter { it.visibility() != Visibility.PRIVATE } - .any { it.isAnnotatedWith(injectFqName) } + .any { it.isAnnotatedWith(injectFqNames) } } .map { clazz -> diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/Parameter.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/Parameter.kt index d483dea23..ffe4660d9 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/Parameter.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/Parameter.kt @@ -1,6 +1,7 @@ package com.squareup.anvil.compiler.codegen.dagger import com.squareup.anvil.compiler.codegen.dagger.Parameter.AssistedParameterKey +import com.squareup.anvil.compiler.javaxProviderClassName import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.ParameterizedTypeName @@ -29,7 +30,7 @@ internal sealed interface Parameter { val originalTypeName: TypeName get() = when { - isLazyWrappedInProvider -> lazyTypeName.wrapInProvider() + isLazyWrappedInProvider -> lazyTypeName.wrapInProvider(javaxProviderClassName) isWrappedInProvider -> providerTypeName isWrappedInLazy -> lazyTypeName else -> typeName diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 23b28bb8f..a6249e410 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ autoService = "1.1.1" autoValue = "1.11.0" buildconfig = "5.3.5" classgraph = "4.8.172" -dagger = "2.51.1" +dagger = "2.52" dropbox-dependencyGuard = "0.5.0" dokka = "1.9.20" espresso = "3.5.1" @@ -101,6 +101,7 @@ gradlePublishRaw = { module = "com.gradle.publish:plugin-publish-plugin", versio guava = "com.google.guava:guava:33.2.1-jre" inject = "javax.inject:javax.inject:1" +jakarta = "jakarta.inject:jakarta.inject-api:2.0.1" jsr250 = "javax.annotation:jsr250-api:1.0" junit = "junit:junit:4.13.2"