From c9fcda80a8bf99ef202095c1fb49dcff495433d2 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Wed, 17 Jul 2024 00:25:07 -0400 Subject: [PATCH] Resolve typealiases and remove lenient mode After some discussion [here](https://github.com/google/dagger/issues/4356) I learned we should be handling this ourselves --- .../codegen/CircuitSymbolProcessorProvider.kt | 52 +++++++++++-------- docs/code-gen.md | 10 ---- samples/star/build.gradle.kts | 2 - 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/circuit-codegen/src/main/kotlin/com/slack/circuit/codegen/CircuitSymbolProcessorProvider.kt b/circuit-codegen/src/main/kotlin/com/slack/circuit/codegen/CircuitSymbolProcessorProvider.kt index 4b069b093..43f7aacba 100644 --- a/circuit-codegen/src/main/kotlin/com/slack/circuit/codegen/CircuitSymbolProcessorProvider.kt +++ b/circuit-codegen/src/main/kotlin/com/slack/circuit/codegen/CircuitSymbolProcessorProvider.kt @@ -26,6 +26,7 @@ import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSDeclaration import com.google.devtools.ksp.symbol.KSFunctionDeclaration import com.google.devtools.ksp.symbol.KSType +import com.google.devtools.ksp.symbol.KSTypeAlias import com.google.devtools.ksp.symbol.Visibility import com.squareup.anvil.annotations.ContributesMultibinding import com.squareup.kotlinpoet.AnnotationSpec @@ -128,8 +129,6 @@ private class CircuitSymbolProcessor( private val platforms: List, ) : SymbolProcessor { - private val lenient = options["circuit.codegen.lenient"]?.toBoolean() ?: false - override fun process(resolver: Resolver): List { val symbols = CircuitSymbols.create(resolver) ?: return emptyList() val codegenMode = @@ -174,7 +173,7 @@ private class CircuitSymbolProcessor( codegenMode: CodegenMode, ) { val circuitInjectAnnotation = - annotatedElement.getKSAnnotationsWithLeniency(CIRCUIT_INJECT_ANNOTATION).single() + annotatedElement.getKSAnnotationsOfType(CIRCUIT_INJECT_ANNOTATION.canonicalName).single() // If we annotated a class, check that the class isn't using assisted inject. If so, error and // return @@ -269,7 +268,7 @@ private class CircuitSymbolProcessor( annotation: KClass ): KSFunctionDeclaration? { return getConstructors().singleOrNull { constructor -> - constructor.isAnnotationPresentWithLeniency(annotation) + constructor.isAnnotationPresentOfType(annotation) } } @@ -278,7 +277,7 @@ private class CircuitSymbolProcessor( if (findConstructorAnnotatedWith(AssistedInject::class) != null) { val assistedFactory = declarations.filterIsInstance().find { - it.isAnnotationPresentWithLeniency(AssistedFactory::class) + it.isAnnotationPresentOfType(AssistedFactory::class) } val suffix = if (assistedFactory != null) " (${assistedFactory.qualifiedName?.asString()})" else "" @@ -291,24 +290,31 @@ private class CircuitSymbolProcessor( } } - private fun KSAnnotated.isAnnotationPresentWithLeniency(annotation: KClass) = - getKSAnnotationsWithLeniency(annotation).any() - - private fun KSAnnotated.getKSAnnotationsWithLeniency(annotation: KClass) = - getKSAnnotationsWithLeniency(annotation.asClassName()) - - private fun KSAnnotated.getKSAnnotationsWithLeniency( - annotation: ClassName - ): Sequence { - val simpleName = annotation.simpleName - return if (lenient) { - annotations.filter { it.shortName.asString() == simpleName } - } else { - val qualifiedName = annotation.canonicalName - this.annotations.filter { - it.shortName.getShortName() == simpleName && - it.annotationType.resolve().declaration.qualifiedName?.asString() == qualifiedName + private fun KSAnnotated.isAnnotationPresentOfType(annotation: KClass) = + getKSAnnotationsOfType(annotation).any() + + private fun KSAnnotated.getKSAnnotationsOfType(annotation: KClass) = + getKSAnnotationsOfType(annotation.qualifiedName!!) + + private fun KSAnnotated.getKSAnnotationsOfType(qualifiedName: String): Sequence { + return this.annotations.filter { + it.annotationType + .resolve() + .declaration + .resolveKSClassDeclaration() + ?.qualifiedName + ?.asString() == qualifiedName + } + } + + private fun KSDeclaration.resolveKSClassDeclaration(): KSClassDeclaration? { + return when (this) { + is KSClassDeclaration -> this + is KSTypeAlias -> { + // Note: doesn't work for generic aliased types, but we only use this for CircuitInject + type.resolve().declaration.resolveKSClassDeclaration() } + else -> null } } @@ -438,7 +444,7 @@ private class CircuitSymbolProcessor( declaration.checkVisibility(logger) { return null } - val isAssisted = declaration.isAnnotationPresentWithLeniency(AssistedFactory::class) + val isAssisted = declaration.isAnnotationPresentOfType(AssistedFactory::class) val creatorOrConstructor: KSFunctionDeclaration? val targetClass: KSClassDeclaration if (isAssisted) { diff --git a/docs/code-gen.md b/docs/code-gen.md index e08c63bdd..496414306 100644 --- a/docs/code-gen.md +++ b/docs/code-gen.md @@ -24,16 +24,6 @@ ksp { } ``` -If using Kotlin multiplatform with typealias annotations for Dagger annotations (i.e. expect -annotations in common with actual typealias declarations in JVM source sets), you can match on just -annotation short names alone to support this case via `circuit.codegen.lenient` mode. - -```kotlin -ksp { - arg("circuit.codegen.lenient", "true") -} -``` - ## Usage The primary entry point is the `CircuitInject` annotation. diff --git a/samples/star/build.gradle.kts b/samples/star/build.gradle.kts index 7ac01dc69..4e10ace39 100644 --- a/samples/star/build.gradle.kts +++ b/samples/star/build.gradle.kts @@ -291,8 +291,6 @@ afterEvaluate { } } -ksp { arg("circuit.codegen.lenient", "true") } - dependencies { for (target in kspTargets) { val targetConfigSuffix = if (target == "Metadata") "CommonMainMetadata" else target