diff --git a/CHANGELOG.md b/CHANGELOG.md index ce78f6bda..871092a98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ ### Changed ### Deprecated +- `ClassReference.functions` has been deprecated in favor of `ClassReference.memberFunctions` and `ClassReference.declaredMemberFunctions` +- `ClassReference.properties` has been deprecated in favor of `ClassReference.memberProperties` and `ClassReference.declaredMemberProperties` ### Removed diff --git a/compiler-utils/api/compiler-utils.api b/compiler-utils/api/compiler-utils.api index 0a2748a24..170869bc3 100644 --- a/compiler-utils/api/compiler-utils.api +++ b/compiler-utils/api/compiler-utils.api @@ -192,9 +192,13 @@ public abstract class com/squareup/anvil/compiler/internal/reference/ClassRefere public abstract fun getClassId ()Lorg/jetbrains/kotlin/name/ClassId; public abstract fun getConstructors ()Ljava/util/List; public abstract fun getContainingFileAsJavaFile ()Ljava/io/File; + public abstract fun getDeclaredMemberFunctions ()Ljava/util/List; + public abstract fun getDeclaredMemberProperties ()Ljava/util/List; public abstract fun getFqName ()Lorg/jetbrains/kotlin/name/FqName; public abstract fun getFunctions ()Ljava/util/List; protected abstract fun getInnerClassesAndObjects ()Ljava/util/List; + public final fun getMemberFunctions ()Ljava/util/List; + public final fun getMemberProperties ()Ljava/util/List; public abstract fun getModule ()Lcom/squareup/anvil/compiler/internal/reference/AnvilModuleDescriptor; public final fun getPackageFqName ()Lorg/jetbrains/kotlin/name/FqName; public abstract fun getProperties ()Ljava/util/List; @@ -223,6 +227,8 @@ public final class com/squareup/anvil/compiler/internal/reference/ClassReference public final fun getClazz ()Lorg/jetbrains/kotlin/descriptors/ClassDescriptor; public fun getConstructors ()Ljava/util/List; public fun getContainingFileAsJavaFile ()Ljava/io/File; + public fun getDeclaredMemberFunctions ()Ljava/util/List; + public fun getDeclaredMemberProperties ()Ljava/util/List; public fun getFqName ()Lorg/jetbrains/kotlin/name/FqName; public fun getFunctions ()Ljava/util/List; public fun getModule ()Lcom/squareup/anvil/compiler/internal/reference/AnvilModuleDescriptor; @@ -248,6 +254,8 @@ public final class com/squareup/anvil/compiler/internal/reference/ClassReference public final fun getClazz ()Lorg/jetbrains/kotlin/psi/KtClassOrObject; public fun getConstructors ()Ljava/util/List; public fun getContainingFileAsJavaFile ()Ljava/io/File; + public fun getDeclaredMemberFunctions ()Ljava/util/List; + public fun getDeclaredMemberProperties ()Ljava/util/List; public fun getFqName ()Lorg/jetbrains/kotlin/name/FqName; public fun getFunctions ()Ljava/util/List; public fun getModule ()Lcom/squareup/anvil/compiler/internal/reference/AnvilModuleDescriptor; diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotationArgumentReference.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotationArgumentReference.kt index 8a76234f4..ee9c7cfcd 100644 --- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotationArgumentReference.kt +++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/AnnotationArgumentReference.kt @@ -144,7 +144,7 @@ public sealed class AnnotationArgumentReference { } is KtObjectDeclaration -> { toClassReference(module) - .properties + .declaredMemberProperties .mapNotNull { it.property as? KtProperty } .findConstPropertyWithName(name) ?.initializer diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/ClassReference.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/ClassReference.kt index 46537ec41..c47fabacf 100644 --- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/ClassReference.kt +++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/ClassReference.kt @@ -66,8 +66,49 @@ public sealed class ClassReference : Comparable, AnnotatedRefere public val packageFqName: FqName get() = classId.packageFqName public abstract val constructors: List + + @Deprecated( + "renamed to `declaredMemberFunctions`. " + + "Use `memberFunctions` to include inherited functions.", + replaceWith = ReplaceWith("declaredMemberFunctions"), + ) public abstract val functions: List + + /** + * All functions that are declared in this class, including overrides. + * This list does not include inherited functions that are not overridden by this class. + */ + public abstract val declaredMemberFunctions: List + + /** + * All functions declared in this class or any of its super-types. + */ + public val memberFunctions: List by lazy(NONE) { + declaredMemberFunctions + directSuperTypeReferences() + .flatMap { it.asClassReference().memberFunctions } + } + + @Deprecated( + "renamed to `declaredMemberProperties`. \n" + + "Use `memberProperties` to include inherited properties.", + replaceWith = ReplaceWith("declaredMemberProperties"), + ) public abstract val properties: List + + /** + * All properties that are declared in this class, including overrides. + * This list does not include inherited properties that are not overridden by this class. + */ + public abstract val declaredMemberProperties: List + + /** + * All properties declared in this class or any of its super-types. + */ + public val memberProperties: List by lazy(NONE) { + declaredMemberProperties + directSuperTypeReferences() + .flatMap { it.asClassReference().memberProperties } + } + public abstract val typeParameters: List protected abstract val innerClassesAndObjects: List @@ -146,7 +187,13 @@ public sealed class ClassReference : Comparable, AnnotatedRefere clazz.containingFileAsJavaFile() } - override val functions: List by lazy(NONE) { + @Deprecated( + "renamed to `declaredMemberFunctions`. Use `memberFunctions` to include inherited functions.", + replaceWith = ReplaceWith("declaredMemberFunctions"), + ) + override val functions: List get() = declaredMemberFunctions + + override val declaredMemberFunctions: List by lazy(NONE) { clazz .children .filterIsInstance() @@ -158,7 +205,13 @@ public sealed class ClassReference : Comparable, AnnotatedRefere clazz.annotationEntries.map { it.toAnnotationReference(this, module) } } - override val properties: List by lazy(NONE) { + @Deprecated( + "renamed to `declaredMemberProperties`. \nUse `memberProperties` to include inherited properties.", + replaceWith = ReplaceWith("declaredMemberProperties"), + ) + override val properties: List get() = declaredMemberProperties + + override val declaredMemberProperties: List by lazy(NONE) { buildList { // Order kind of matters here, since the Descriptor APIs will list body/member properties // before the constructor properties. @@ -263,9 +316,14 @@ public sealed class ClassReference : Comparable, AnnotatedRefere ) } - override val functions: List by lazy(NONE) { + @Deprecated( + "renamed to `declaredMemberFunctions`. Use `memberFunctions` to include inherited functions.", + replaceWith = ReplaceWith("declaredMemberFunctions"), + ) + override val functions: List get() = declaredMemberFunctions + override val declaredMemberFunctions: List by lazy(NONE) { clazz.unsubstitutedMemberScope - .getContributedDescriptors(kindFilter = DescriptorKindFilter.FUNCTIONS) + .getDescriptorsFiltered(kindFilter = DescriptorKindFilter.FUNCTIONS) .filterIsInstance() .filterNot { it is ConstructorDescriptor } .map { it.toFunctionReference(this) } @@ -275,14 +333,19 @@ public sealed class ClassReference : Comparable, AnnotatedRefere clazz.annotations.map { it.toAnnotationReference(this, module) } } - override val properties: List by lazy(NONE) { + @Deprecated( + "renamed to `declaredMemberProperties`. \nUse `memberProperties` to include inherited properties.", + replaceWith = ReplaceWith("declaredMemberProperties"), + ) + override val properties: List + get() = declaredMemberProperties + + override val declaredMemberProperties: List by lazy(NONE) { clazz.unsubstitutedMemberScope .getDescriptorsFiltered(kindFilter = DescriptorKindFilter.VARIABLES) .filterIsInstance() - .filter { - // Remove inherited properties that aren't overridden in this class. - it.kind == DECLARATION - } + // Remove inherited properties that aren't overridden in this class. + .filter { it.kind == DECLARATION } .map { it.toPropertyReference(this) } } diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/MemberPropertyReference.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/MemberPropertyReference.kt index 39f54da21..12af5f893 100644 --- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/MemberPropertyReference.kt +++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/MemberPropertyReference.kt @@ -205,6 +205,8 @@ public fun PropertyDescriptor.toPropertyReference( internal fun MemberPropertyReference.toDescriptorOrNull(): Descriptor? { return when (this) { is Descriptor -> this - is Psi -> declaringClass.toDescriptorReferenceOrNull()?.properties?.find { it.name == name } + is Psi -> declaringClass.toDescriptorReferenceOrNull() + ?.declaredMemberProperties + ?.find { it.name == name } } } diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentCodeGen.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentCodeGen.kt index d0edc7642..e2979b50a 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentCodeGen.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentCodeGen.kt @@ -324,7 +324,7 @@ internal object ContributesSubcomponentCodeGen : AnvilApplicabilityChecker { ) } - val functions = componentInterface.functions + val functions = componentInterface.memberFunctions .filter { it.returnType().asClassReference() == this } if (functions.size >= 2) { @@ -377,7 +377,7 @@ internal object ContributesSubcomponentCodeGen : AnvilApplicabilityChecker { ) } - val functions = factory.functions + val functions = factory.memberFunctions .let { functions -> if (factory.isInterface()) { functions diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentHandlerGenerator.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentHandlerGenerator.kt index ff9e003ad..24cc0ca4a 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentHandlerGenerator.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentHandlerGenerator.kt @@ -298,7 +298,7 @@ internal class ContributesSubcomponentHandlerGenerator( ) } - val functions = componentInterface.functions + val functions = componentInterface.memberFunctions .filter { it.isAbstract() && it.visibility() == PUBLIC } .filter { val returnType = it.returnType().asClassReference() @@ -337,7 +337,7 @@ internal class ContributesSubcomponentHandlerGenerator( ) } - val createComponentFunctions = factory.functions + val createComponentFunctions = factory.memberFunctions .filter { it.isAbstract() } .filter { it.returnType().asClassReference().fqName == contributionFqName } 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 9e06b9948..73952f470 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 @@ -432,7 +432,7 @@ internal object AssistedFactoryCodeGen : AnvilApplicabilityChecker { val assistedFunctions = allSuperTypeClassReferences(includeSelf = true) .distinctBy { it.fqName } .flatMap { clazz -> - clazz.functions + clazz.declaredMemberFunctions .filter { it.isAbstract() && (it.visibility() == Visibility.PUBLIC || it.visibility() == Visibility.PROTECTED) 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 206228a01..5ee3085f0 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 @@ -178,7 +178,7 @@ internal object BindsMethodValidator : AnvilApplicabilityChecker { .forEach { clazz -> (clazz.companionObjects() + clazz) .asSequence() - .flatMap { it.functions } + .flatMap { it.declaredMemberFunctions } .filter { it.isAnnotatedWith(daggerBindsFqName) } .also { functions -> assertNoDuplicateFunctions(clazz, functions) 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 12ceef95d..763999f99 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 @@ -222,7 +222,7 @@ private fun ClassReference.declaredMemberInjectParameters( superParameters: List, implementingClass: ClassReference, ): List { - return properties + return declaredMemberProperties .filter { it.isAnnotatedWith(injectFqName) } .filter { it.visibility() != PRIVATE } .fold(listOf()) { acc, property -> diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/MapKeyCreatorCodeGen.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/MapKeyCreatorCodeGen.kt index 2fc1c77fd..7cd654cc4 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/MapKeyCreatorCodeGen.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/MapKeyCreatorCodeGen.kt @@ -231,7 +231,7 @@ internal object MapKeyCreatorCodeGen : AnvilApplicabilityChecker { if (clazz.isAnnotationClass()) { val added = creatorsToGenerate.add(clazz) if (added) { - for (property in clazz.properties) { + for (property in clazz.declaredMemberProperties) { val type = property.type().asClassReferenceOrNull() if (type?.isAnnotationClass() == true) { visitAnnotations(type) @@ -254,7 +254,7 @@ internal object MapKeyCreatorCodeGen : AnvilApplicabilityChecker { } .toSortedMap() .map { (className, clazz) -> - val properties = clazz.properties + val properties = clazz.declaredMemberProperties .map { AnnotationProperty(it) } .associateBy { it.name } generateCreatorFunction(className, properties) @@ -276,7 +276,7 @@ internal object MapKeyCreatorCodeGen : AnvilApplicabilityChecker { className: ClassName, annotationClass: ClassReference, ): FunSpec { - val properties = annotationClass.properties + val properties = annotationClass.declaredMemberProperties .map { AnnotationProperty(it) } .associateBy { it.name } return generateCreatorFunction(className, properties) 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 43e45e2fd..28c7bbbd8 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 @@ -133,7 +133,7 @@ internal object MembersInjectorCodeGen : AnvilApplicabilityChecker { // Only generate a MembersInjector if the target class declares its own member-injected // properties. If it does, then any properties from superclasses must be added as well // (clazz.memberInjectParameters() will do this). - clazz.properties + clazz.declaredMemberProperties .filter { it.visibility() != Visibility.PRIVATE } .any { it.isAnnotatedWith(injectFqName) } } 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 b7405b3ad..26e36ecdd 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 @@ -243,7 +243,7 @@ internal object ProvidesMethodFactoryCodeGen : AnvilApplicabilityChecker { .asSequence() val functions = types - .flatMap { it.functions } + .flatMap { it.declaredMemberFunctions } .filter { it.isAnnotatedWith(daggerProvidesFqName) } .onEach { function -> checkFunctionIsNotAbstract(clazz, function) @@ -261,7 +261,7 @@ internal object ProvidesMethodFactoryCodeGen : AnvilApplicabilityChecker { } val properties = types - .flatMap { it.properties } + .flatMap { it.declaredMemberProperties } .filter { property -> // Must be `@get:Provides`. property.getterAnnotations.any { it.fqName == daggerProvidesFqName } diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/reference/RealAnvilModuleDescriptor.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/reference/RealAnvilModuleDescriptor.kt index b827b7856..5b771ec44 100644 --- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/reference/RealAnvilModuleDescriptor.kt +++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/reference/RealAnvilModuleDescriptor.kt @@ -137,7 +137,7 @@ public class RealAnvilModuleDescriptor private constructor( } return classAndCompanions.firstNotNullOfOrNull { clazz -> - clazz.properties.firstOrNull { it.name == shortName } + clazz.declaredMemberProperties.firstOrNull { it.name == shortName } } } diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentGeneratorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentGeneratorTest.kt index 4d99b0462..da3a44259 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentGeneratorTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/codegen/ContributesSubcomponentGeneratorTest.kt @@ -493,6 +493,44 @@ class ContributesSubcomponentGeneratorTest( } } + @Test fun `a factory function may be defined in a super interface`() { + compile( + """ + package com.squareup.test + + import com.squareup.anvil.annotations.ContributesSubcomponent + import com.squareup.anvil.annotations.ContributesSubcomponent.Factory + import com.squareup.anvil.annotations.ContributesTo + import com.squareup.anvil.annotations.MergeComponent + + @ContributesSubcomponent(Any::class, parentScope = Unit::class) + interface SubcomponentInterface { + @ContributesTo(Unit::class) + interface AnyParentComponent { + fun createFactory(): ComponentFactory + } + + interface Creator { + fun createComponent(): SubcomponentInterface + } + + @Factory + interface ComponentFactory : Creator + } + + @MergeComponent(Unit::class) + interface ComponentInterface + """, + mode = mode, + ) { + assertThat(subcomponentInterface.hintSubcomponent?.java).isEqualTo(subcomponentInterface) + assertThat(subcomponentInterface.hintSubcomponentParentScope).isEqualTo(Unit::class) + + assertThat(subcomponentInterface.componentFactoryInterface.methods.map { it.name }) + .containsExactly("createComponent") + } + } + @Test fun `using Dagger's @Subcomponent_Factory is an error`() { compile( @@ -616,6 +654,9 @@ class ContributesSubcomponentGeneratorTest( private val Class<*>.parentComponentInterface: Class<*> get() = classLoader.loadClass("$canonicalName\$AnyParentComponent") + private val Class<*>.componentFactoryInterface: Class<*> + get() = classLoader.loadClass("$canonicalName\$ComponentFactory") + private val JvmCompilationResult.subcomponentInterface1: Class<*> get() = classLoader.loadClass("com.squareup.test.SubcomponentInterface1") diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/ClassReferenceTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/ClassReferenceTest.kt index 673a814e5..fa3e13d45 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/ClassReferenceTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/ClassReferenceTest.kt @@ -6,12 +6,15 @@ import com.squareup.anvil.compiler.internal.testing.simpleCodeGenerator import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.TypeSpec import com.tschuchort.compiletesting.KotlinCompilation.ExitCode.OK +import io.kotest.matchers.shouldBe import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.resolve.source.getPsi -import org.junit.Test +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestFactory -class ClassReferenceTest { +@Suppress("LocalVariableName") +class ClassReferenceTest : ReferenceTests { @Test fun `inner classes are parsed`() { compile( @@ -201,9 +204,11 @@ class ClassReferenceTest { assertThat(psiRef.isGenericClass()).isFalse() assertThat(descriptorRef.isGenericClass()).isFalse() - assertThat(psiRef.functions.single().returnType().isGenericType()).isFalse() assertThat( - descriptorRef.functions.single { it.name == "string" } + psiRef.declaredMemberFunctions.single().returnType().isGenericType(), + ).isFalse() + assertThat( + descriptorRef.declaredMemberFunctions.single { it.name == "string" } .returnType() .isGenericType(), ).isFalse() @@ -223,17 +228,21 @@ class ClassReferenceTest { ).isTrue() } "SomeClass3" -> { - assertThat(psiRef.functions.single().returnType().isGenericType()).isTrue() assertThat( - descriptorRef.functions.single { it.name == "list" } + psiRef.declaredMemberFunctions.single().returnType().isGenericType(), + ).isTrue() + assertThat( + descriptorRef.declaredMemberFunctions.single { it.name == "list" } .returnType() .isGenericType(), ).isTrue() } "SomeClass4" -> { - assertThat(psiRef.functions.single().returnType().isGenericType()).isTrue() assertThat( - descriptorRef.functions.single { it.name == "list" } + psiRef.declaredMemberFunctions.single().returnType().isGenericType(), + ).isTrue() + assertThat( + descriptorRef.declaredMemberFunctions.single { it.name == "list" } .returnType() .isGenericType(), ).isTrue() @@ -549,6 +558,228 @@ class ClassReferenceTest { assertThat(exitCode).isEqualTo(OK) } } + + @TestFactory + fun `declaredMemberFunctions does not include invisible inherited functions`() = testFactory { + + compile( + """ + package com.squareup.test + + interface Parent { + fun parentFunction1() + + fun parentFunction2() { } + } + + interface Child : Parent + """.trimIndent(), + ) { + val Child by classReferences + + Child.declaredMemberFunctions.map { it.fqName.asString() } shouldBe listOf() + } + } + + @TestFactory + fun `memberFunctions includes invisible inherited functions`() = testFactory { + + compile( + """ + package com.squareup.test + + interface Parent { + fun parentFunction1() + + fun parentFunction2() { } + } + + interface Child : Parent + """.trimIndent(), + ) { + val Child by classReferences + + Child.memberFunctions.map { it.fqName.asString() } shouldBe listOf( + "com.squareup.test.Parent.parentFunction1", + "com.squareup.test.Parent.parentFunction2", + ) + } + } + + @TestFactory + fun `memberFunctions does not duplicate inherited functions`() = testFactory { + + compile( + """ + package com.squareup.test + + interface Parent { + fun parentFunction1() + + fun parentFunction2() { } + } + + interface Child : Parent { + override fun parentFunction1() { } + } + """.trimIndent(), + ) { + val Child by classReferences + + Child.memberFunctions.map { it.fqName.asString() } shouldBe listOf( + "com.squareup.test.Child.parentFunction1", + "com.squareup.test.Parent.parentFunction1", + "com.squareup.test.Parent.parentFunction2", + ) + } + } + + @TestFactory + fun `declaredMemberFunctions includes overridden inherited functions`() = testFactory { + + compile( + """ + package com.squareup.test + + interface Parent { + fun parentFunction1() + + fun parentFunction2() { } + } + + interface Child : Parent { + override fun parentFunction1() { } + } + + class ChildClass : Parent { + override fun parentFunction1() { } + override fun toString() = "" + } + + """.trimIndent(), + ) { + val Child by classReferences + val ChildClass by classReferences + + Child.declaredMemberFunctions.map { it.fqName.asString() } shouldBe listOf( + "com.squareup.test.Child.parentFunction1", + ) + ChildClass.declaredMemberFunctions.map { it.fqName.asString() } shouldBe listOf( + "com.squareup.test.ChildClass.parentFunction1", + "com.squareup.test.ChildClass.toString", + ) + } + } + + @TestFactory + fun `declaredMemberProperties does not include invisible inherited properties`() = testFactory { + + compile( + """ + package com.squareup.test + + interface Parent { + val parentProperty1: CharSequence + + val parentProperty2: String + } + + interface Child : Parent + """.trimIndent(), + ) { + val Child by classReferences + + Child.declaredMemberProperties.map { it.fqName.asString() } shouldBe listOf() + } + } + + @TestFactory + fun `memberProperties includes invisible inherited properties`() = testFactory { + + compile( + """ + package com.squareup.test + + interface Parent { + val parentProperty1: CharSequence + + val parentProperty2: String + } + + interface Child : Parent + """.trimIndent(), + ) { + val Child by classReferences + + Child.memberProperties.map { it.fqName.asString() } shouldBe listOf( + "com.squareup.test.Parent.parentProperty1", + "com.squareup.test.Parent.parentProperty2", + ) + } + } + + @TestFactory + fun `memberProperties does not duplicate inherited properties`() = testFactory { + + compile( + """ + package com.squareup.test + + interface Parent { + val parentProperty1: CharSequence + + val parentProperty2: String + } + + interface Child : Parent { + override val parentProperty1: String + } + """.trimIndent(), + ) { + val Child by classReferences + + Child.memberProperties.map { it.fqName.asString() } shouldBe listOf( + "com.squareup.test.Child.parentProperty1", + "com.squareup.test.Parent.parentProperty1", + "com.squareup.test.Parent.parentProperty2", + ) + } + } + + @TestFactory + fun `declaredMemberProperties includes overridden inherited properties`() = testFactory { + + compile( + """ + package com.squareup.test + + interface Parent { + val parentProperty1: CharSequence + + val parentProperty2: String + } + + interface Child : Parent { + override val parentProperty1: String + } + + abstract class ChildClass : Parent { + abstract override val parentProperty1: String + } + + """.trimIndent(), + ) { + val Child by classReferences + val ChildClass by classReferences + + Child.declaredMemberProperties.map { it.fqName.asString() } shouldBe listOf( + "com.squareup.test.Child.parentProperty1", + ) + ChildClass.declaredMemberProperties.map { it.fqName.asString() } shouldBe listOf( + "com.squareup.test.ChildClass.parentProperty1", + ) + } + } } fun ClassReference.toDescriptorReference(): ClassReference.Descriptor { diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/MemberFunctionReferenceTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/MemberFunctionReferenceTest.kt index 8b425cb54..42a9779d6 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/MemberFunctionReferenceTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/MemberFunctionReferenceTest.kt @@ -99,20 +99,21 @@ class MemberFunctionReferenceTest { "SomeClass1" -> { // Notice that the size differs between the descriptor and Psi implementation. Both // implementations see different values and that's expected. - assertThat(psiRef.functions).hasSize(0) - assertThat(descriptorRef.functions).hasSize(3) - assertThat(descriptorRef.functions.map { it.name }).containsExactly( + assertThat(psiRef.declaredMemberFunctions).hasSize(0) + assertThat(descriptorRef.declaredMemberFunctions).hasSize(3) + assertThat(descriptorRef.declaredMemberFunctions.map { it.name }).containsExactly( "equals", "toString", "hashCode", ) } "SomeClass2" -> { - assertThat(psiRef.functions).hasSize(1) - assertThat(descriptorRef.functions).hasSize(4) + assertThat(psiRef.declaredMemberFunctions).hasSize(1) + assertThat(descriptorRef.declaredMemberFunctions).hasSize(4) - val psiFunction = psiRef.functions.single() - val descriptorFunction = descriptorRef.functions.single { it.name == "test" } + val psiFunction = psiRef.declaredMemberFunctions.single() + val descriptorFunction = descriptorRef.declaredMemberFunctions + .single { it.name == "test" } assertThat(psiFunction.name).isEqualTo("test") assertThat(descriptorFunction.name).isEqualTo("test") @@ -126,11 +127,12 @@ class MemberFunctionReferenceTest { .isEqualTo(Unit::class.fqName) } "SomeInterface" -> { - assertThat(psiRef.functions).hasSize(1) - assertThat(descriptorRef.functions).hasSize(4) + assertThat(psiRef.declaredMemberFunctions).hasSize(1) + assertThat(descriptorRef.declaredMemberFunctions).hasSize(4) - val psiFunction = psiRef.functions.single() - val descriptorFunction = descriptorRef.functions.single { it.name == "test" } + val psiFunction = psiRef.declaredMemberFunctions.single() + val descriptorFunction = descriptorRef.declaredMemberFunctions + .single { it.name == "test" } assertThat(psiFunction.name).isEqualTo("test") assertThat(descriptorFunction.name).isEqualTo("test") @@ -148,8 +150,8 @@ class MemberFunctionReferenceTest { assertThat(psiRef.enclosingClass()?.shortName).isEqualTo("SomeInterface") assertThat(descriptorRef.enclosingClass()?.shortName).isEqualTo("SomeInterface") - assertThat(psiRef.functions).hasSize(1) - assertThat(descriptorRef.functions).hasSize(4) + assertThat(psiRef.declaredMemberFunctions).hasSize(1) + assertThat(descriptorRef.declaredMemberFunctions).hasSize(4) } else -> throw NotImplementedError() } @@ -192,8 +194,9 @@ class MemberFunctionReferenceTest { when (psiRef.shortName) { "SomeClass1" -> { - val psiFunction = psiRef.functions.single() - val descriptorFunction = descriptorRef.functions.single { it.name == "test" } + val psiFunction = psiRef.declaredMemberFunctions.single() + val descriptorFunction = descriptorRef.declaredMemberFunctions + .single { it.name == "test" } assertThat(psiFunction.returnTypeOrNull()).isNull() assertThat(descriptorFunction.returnType().asClassReference().fqName) @@ -205,8 +208,9 @@ class MemberFunctionReferenceTest { assertThat(psiFunction.resolveGenericReturnTypeOrNull(psiRef)).isNull() } "SomeClass2", "SomeClass3" -> { - val psiFunction = psiRef.functions.single() - val descriptorFunction = descriptorRef.functions.single { it.name == "hello" } + val psiFunction = psiRef.declaredMemberFunctions.single() + val descriptorFunction = descriptorRef.declaredMemberFunctions + .single { it.name == "hello" } assertThat(psiFunction.returnType().asClassReference().fqName) .isEqualTo(FqName("kotlin.String")) @@ -214,8 +218,9 @@ class MemberFunctionReferenceTest { .isEqualTo(FqName("kotlin.String")) } "GenericInterface1" -> { - val psiFunction = psiRef.functions.single() - val descriptorFunction = descriptorRef.functions.single { it.name == "hello" } + val psiFunction = psiRef.declaredMemberFunctions.single() + val descriptorFunction = descriptorRef.declaredMemberFunctions + .single { it.name == "hello" } assertThat(psiFunction.returnType().asClassReferenceOrNull()).isNull() assertThat(descriptorFunction.returnType().asClassReferenceOrNull()).isNull() @@ -267,10 +272,11 @@ class MemberFunctionReferenceTest { ).isEqualTo(FqName("kotlin.String")) } "GenericInterface2" -> { - assertThat(psiRef.functions).hasSize(0) - assertThat(descriptorRef.functions).hasSize(4) + assertThat(psiRef.declaredMemberFunctions).hasSize(0) + assertThat(descriptorRef.declaredMemberFunctions).hasSize(4) - val descriptorFunction = descriptorRef.functions.single { it.name == "hello" } + val descriptorFunction = descriptorRef.declaredMemberFunctions + .single { it.name == "hello" } assertThat(descriptorFunction.returnType().asClassReferenceOrNull()).isNull() val implementingClass = FqName("com.squareup.test.SomeClass3") @@ -324,8 +330,9 @@ class MemberFunctionReferenceTest { when (psiRef.shortName) { "SomeClass1", "SomeClass2" -> { - val psiFunction = psiRef.functions.single() - val descriptorFunction = descriptorRef.functions.single { it.name == "hello" } + val psiFunction = psiRef.declaredMemberFunctions.single() + val descriptorFunction = + descriptorRef.declaredMemberFunctions.single { it.name == "hello" } assertThat( psiFunction.parameters.single().typeOrNull() @@ -346,8 +353,9 @@ class MemberFunctionReferenceTest { ).isNotNull() } "GenericInterface1" -> { - val psiFunction = psiRef.functions.single() - val descriptorFunction = descriptorRef.functions.single { it.name == "hello" } + val psiFunction = psiRef.declaredMemberFunctions.single() + val descriptorFunction = descriptorRef.declaredMemberFunctions + .single { it.name == "hello" } assertThat(psiFunction.parameters.single().type().asClassReferenceOrNull()) .isNull() @@ -397,10 +405,11 @@ class MemberFunctionReferenceTest { ).isNotNull() } "GenericInterface2" -> { - assertThat(psiRef.functions).hasSize(0) - assertThat(descriptorRef.functions).hasSize(4) + assertThat(psiRef.declaredMemberFunctions).hasSize(0) + assertThat(descriptorRef.declaredMemberFunctions).hasSize(4) - val descriptorFunction = descriptorRef.functions.single { it.name == "hello" } + val descriptorFunction = descriptorRef.declaredMemberFunctions + .single { it.name == "hello" } assertThat( descriptorFunction.parameters.single().type().asClassReferenceOrNull(), ).isNull() diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/MemberPropertyReferenceTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/MemberPropertyReferenceTest.kt index 5310669c5..be96ede35 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/MemberPropertyReferenceTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/MemberPropertyReferenceTest.kt @@ -6,6 +6,7 @@ import com.squareup.anvil.compiler.internal.testing.simpleCodeGenerator import com.tschuchort.compiletesting.KotlinCompilation.ExitCode.OK import org.junit.Test +@Suppress("RemoveRedundantQualifierName") class MemberPropertyReferenceTest { @Test fun `primary constructor val properties are properties`() { @@ -191,7 +192,7 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - assertThat(ref.properties.single().type().asTypeName().toString()) + assertThat(ref.declaredMemberProperties.single().type().asTypeName().toString()) .isEqualTo("kotlin.String") } @@ -223,7 +224,7 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val propertyType = ref.properties.single().type() + val propertyType = ref.declaredMemberProperties.single().type() assertThat(propertyType.asTypeName().toString()) .isEqualTo("com.squareup.test.Subject.`Nested\$Fancy`") @@ -260,7 +261,7 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val propertyType = ref.properties.single().type() + val propertyType = ref.declaredMemberProperties.single().type() assertThat(propertyType.asTypeName().toString()) .isEqualTo("com.squareup.test.Subject.`Nested\$Fancy`") @@ -297,7 +298,7 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val propertyType = ref.properties.single().type() + val propertyType = ref.declaredMemberProperties.single().type() assertThat(propertyType.asTypeName().toString()) .isEqualTo("com.squareup.test.Subject.`Nested\$Fancy`") @@ -435,13 +436,13 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val nameAnnotations = ref.properties.named("name") + val nameAnnotations = ref.declaredMemberProperties.named("name") .annotations .map { it.fqName.asString() } assertThat(nameAnnotations).containsExactly("javax.inject.Inject") - val ageAnnotations = ref.properties.named("age") + val ageAnnotations = ref.declaredMemberProperties.named("age") .annotations .map { it.fqName.asString() } @@ -475,7 +476,7 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val nameGetterAnnotations = ref.properties.named("name") + val nameGetterAnnotations = ref.declaredMemberProperties.named("name") .getterAnnotations .map { it.fqName.asString() } @@ -509,13 +510,13 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val nameGetterAnnotations = ref.properties.named("name") + val nameGetterAnnotations = ref.declaredMemberProperties.named("name") .getterAnnotations .map { it.fqName.asString() } assertThat(nameGetterAnnotations).containsExactly("javax.inject.Inject") - val nameAnnotations = ref.properties.named("name") + val nameAnnotations = ref.declaredMemberProperties.named("name") .annotations .map { it.fqName.asString() } @@ -549,7 +550,7 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val nameSetterAnnotations = ref.properties.named("name") + val nameSetterAnnotations = ref.declaredMemberProperties.named("name") .setterAnnotations .map { it.fqName.asString() } @@ -583,13 +584,13 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val nameSetterAnnotations = ref.properties.named("name") + val nameSetterAnnotations = ref.declaredMemberProperties.named("name") .setterAnnotations .map { it.fqName.asString() } assertThat(nameSetterAnnotations).containsExactly("javax.inject.Inject") - val nameAnnotations = ref.properties.named("name") + val nameAnnotations = ref.declaredMemberProperties.named("name") .annotations .map { it.fqName.asString() } @@ -623,7 +624,7 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val nameProperty = ref.properties.named("name") + val nameProperty = ref.declaredMemberProperties.named("name") assertThat(nameProperty.getterAnnotations).isEmpty() assertThat(nameProperty.setterAnnotations).isEmpty() @@ -657,13 +658,13 @@ class MemberPropertyReferenceTest { listOf(psiRef, descriptorRef).forEach { ref -> - val nameAnnotations = ref.properties.named("name") + val nameAnnotations = ref.declaredMemberProperties.named("name") .annotations .map { it.fqName.asString() } assertThat(nameAnnotations).containsExactly("javax.inject.Inject") - val ageAnnotations = ref.properties.named("age") + val ageAnnotations = ref.declaredMemberProperties.named("age") .annotations .map { it.fqName.asString() } @@ -751,7 +752,7 @@ class MemberPropertyReferenceTest { } } - private fun ClassReference.propertyTypeNames() = properties + private fun ClassReference.propertyTypeNames() = declaredMemberProperties .map { "${it.name}: ${it.type().asTypeName()}" } private fun List.named(name: String) = single { it.name == name } diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/ReferencesTestEnvironment.kt b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/ReferencesTestEnvironment.kt index 0285bdd94..8d8d4db97 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/ReferencesTestEnvironment.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/ReferencesTestEnvironment.kt @@ -40,11 +40,6 @@ class ReferencesTestEnvironment( ) : DefaultTestEnvironment(hasWorkingDir = hasWorkingDir), LanguageInjection by LanguageInjection(JavaFileFileInjection()) { - operator fun List.getValue( - thisRef: Any?, - property: KProperty<*>, - ): E = single { it.name == property.name } - operator fun Map.getValue( thisRef: Any?, property: KProperty<*>, @@ -79,13 +74,13 @@ class ReferencesTestEnvironment( ?.let { refsContainer -> val refsFun = when (referenceType) { - ReferenceType.Psi -> refsContainer.functions - ReferenceType.Descriptor -> refsContainer.toDescriptorReference().functions + ReferenceType.Psi -> refsContainer.declaredMemberFunctions + ReferenceType.Descriptor -> refsContainer.toDescriptorReference().declaredMemberFunctions } .singleOrNull { it.name == "refs" } ?: error { "RefsContainer.refs not found. " + - "Existing functions: ${refsContainer.functions.map { it.name }}" + "Existing functions: ${refsContainer.declaredMemberFunctions.map { it.name }}" } when (referenceType) { diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/TypeReferenceTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/TypeReferenceTest.kt index 702e265c3..0deb16ea0 100644 --- a/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/TypeReferenceTest.kt +++ b/compiler/src/test/java/com/squareup/anvil/compiler/internal/reference/TypeReferenceTest.kt @@ -227,19 +227,19 @@ class TypeReferenceTest { "SomeClass" -> { listOf(psiRef, psiRef.toDescriptorReference()).forEach { ref -> assertThat( - ref.properties.single { it.name == "map1" }.type().unwrappedTypes + ref.declaredMemberProperties.single { it.name == "map1" }.type().unwrappedTypes .map { it.asClassReference().shortName }, ).containsExactly("Any", "Any").inOrder() assertThat( - ref.properties.single { it.name == "map2" }.type().unwrappedTypes + ref.declaredMemberProperties.single { it.name == "map2" }.type().unwrappedTypes .map { it.asClassReference().shortName }, ).containsExactly("Int", "Any").inOrder() assertThat( - ref.properties.single { it.name == "map3" }.type().unwrappedTypes + ref.declaredMemberProperties.single { it.name == "map3" }.type().unwrappedTypes .map { it.asClassReference().shortName }, ).containsExactly("Any", "String").inOrder() assertThat( - ref.properties.single { it.name == "map4" }.type().unwrappedTypes + ref.declaredMemberProperties.single { it.name == "map4" }.type().unwrappedTypes .map { it.asClassReference().shortName }, ).containsExactly("Int", "String").inOrder() } @@ -279,15 +279,15 @@ class TypeReferenceTest { "SomeClass" -> { listOf(psiRef, psiRef.toDescriptorReference()).forEach { ref -> assertThat( - ref.properties.single { it.name == "map" }.type().unwrappedTypes + ref.declaredMemberProperties.single { it.name == "map" }.type().unwrappedTypes .map { it.asClassReference().shortName }, ).containsExactly("String", "Int").inOrder() assertThat( - ref.properties.single { it.name == "single1" }.type().unwrappedTypes + ref.declaredMemberProperties.single { it.name == "single1" }.type().unwrappedTypes .map { it.asClassReference().shortName }, ).containsExactly("Int", "String", "Long").inOrder() assertThat( - ref.properties.single { it.name == "single2" }.type().unwrappedTypes + ref.declaredMemberProperties.single { it.name == "single2" }.type().unwrappedTypes .map { it.asClassReference().shortName }, ).containsExactly("Int", "Int", "Int").inOrder() }