diff --git a/.gitignore b/.gitignore index 8a0bef022..0fd945136 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,4 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser +.idea/deploymentTargetDropDown.xml diff --git a/compiler/build.gradle.kts b/compiler/build.gradle.kts index d49962d6a..343f809e9 100644 --- a/compiler/build.gradle.kts +++ b/compiler/build.gradle.kts @@ -7,6 +7,7 @@ plugins { dependencies { implementation(projects.core) implementation(projects.thirdParty.retrofit) + implementation(projects.thirdParty.ktorfit) implementation(projects.thirdParty.androidx.room) implementation(projects.thirdParty.android.testing) testFixturesApi(projects.compiler.common.testUtils) diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/Errors.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/Errors.kt index fba024452..d75f03798 100644 --- a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/Errors.kt +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/Errors.kt @@ -58,18 +58,34 @@ object Errors { "Replacement target $replacedObject must be annotated with @AutoBind" } - object Retrofit { - const val nonInterface = "Only interfaces can be annotated with @AutoProvideService." - const val privateType = "@AutoProvideService annotated types must not be private." - const val emptyService = "@AutoProvideService annotated types must have at least one method." - const val propertiesNotAllowed = "Retrofit services cannot contain properties." - const val invalidServiceMethod = "Methods in retrofit services must be annotated with a HTTP method annotation such as @GET." - const val scopeAndReusable = "You cannot mix a scope and @Reusable on the same type. Remove the scope or @Reusable." - - fun invalidScope(scope: String, component: String, neededScope: String) = + interface ApiService { + val nonInterface: String + val privateType: String + val emptyService: String + val propertiesNotAllowed: String + val invalidServiceMethod: String + val scopeAndReusable: String + fun invalidScope(scope: String, component: String, neededScope: String): String + + } + + object Retrofit : ApiService{ + override val nonInterface = "Only interfaces can be annotated with @AutoProvideService." + override val privateType = "@AutoProvideService annotated types must not be private." + override val emptyService = "@AutoProvideService annotated types must have at least one method." + override val propertiesNotAllowed = "Retrofit services cannot contain properties." + override val invalidServiceMethod = "Methods in retrofit services must be annotated with a HTTP method annotation such as @GET." + override val scopeAndReusable = "You cannot mix a scope and @Reusable on the same type. Remove the scope or @Reusable." + + override fun invalidScope(scope: String, component: String, neededScope: String) = "You cannot use @$scope when installing in $component, use @$neededScope instead." } + object Ktorfit : ApiService by Retrofit { + override val propertiesNotAllowed = "Ktorfit services cannot contain properties." + override val invalidServiceMethod = "Methods in ktorfit services must be annotated with a HTTP method annotation such as @GET." + } + object AndroidX { object Room { const val notADatabase = "Types annotated @AutoProvideDao must be annotated with @Database and directly extend RoomDatabase." diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/kapt/AutoDaggerAnnotationProcessor.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/kapt/AutoDaggerAnnotationProcessor.kt index 2caf7b93b..6367bf35e 100644 --- a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/kapt/AutoDaggerAnnotationProcessor.kt +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/kapt/AutoDaggerAnnotationProcessor.kt @@ -12,6 +12,8 @@ import se.ansman.dagger.auto.compiler.autoinitialize.AutoInitializeProcessor import se.ansman.dagger.auto.compiler.autoinitialize.renderer.JavaAutoInitializeModuleRenderer import se.ansman.dagger.auto.compiler.common.Options import se.ansman.dagger.auto.compiler.common.kapt.processing.KaptEnvironment +import se.ansman.dagger.auto.compiler.ktorfit.KtorfitProcessor +import se.ansman.dagger.auto.compiler.ktorfit.renderer.JavaKtorfitModuleRenderer import se.ansman.dagger.auto.compiler.replaces.ReplacesProcessor import se.ansman.dagger.auto.compiler.retrofit.RetrofitProcessor import se.ansman.dagger.auto.compiler.retrofit.renderer.JavaRetrofitModuleRenderer @@ -30,6 +32,7 @@ class AutoDaggerAnnotationProcessor : BasicAnnotationProcessor() { AutoDaggerProcessorStep(environment, AutoBindProcessor(environment, JavaAutoBindModuleModuleRenderer)), AutoDaggerProcessorStep(environment, ReplacesProcessor(environment, JavaAutoBindModuleModuleRenderer)), AutoDaggerProcessorStep(environment, RetrofitProcessor(environment, JavaRetrofitModuleRenderer)), + AutoDaggerProcessorStep(environment, KtorfitProcessor(environment, JavaKtorfitModuleRenderer)), AutoDaggerProcessorStep(environment, AndroidXRoomProcessor(environment, JavaAndroidXRoomDatabaseModuleRenderer)), ) } diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ksp/AutoDaggerSymbolProcessor.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ksp/AutoDaggerSymbolProcessor.kt index 5e8b4affc..c5e200405 100644 --- a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ksp/AutoDaggerSymbolProcessor.kt +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ksp/AutoDaggerSymbolProcessor.kt @@ -13,6 +13,8 @@ import se.ansman.dagger.auto.compiler.autoinitialize.renderer.KotlinAutoInitiali import se.ansman.dagger.auto.compiler.common.ksp.KspProcessor import se.ansman.dagger.auto.compiler.common.ksp.processing.KspEnvironment import se.ansman.dagger.auto.compiler.common.ksp.processing.KspResolver +import se.ansman.dagger.auto.compiler.ktorfit.KtorfitProcessor +import se.ansman.dagger.auto.compiler.ktorfit.renderer.KotlinKtorfitObjectRenderer import se.ansman.dagger.auto.compiler.replaces.ReplacesProcessor import se.ansman.dagger.auto.compiler.retrofit.RetrofitProcessor import se.ansman.dagger.auto.compiler.retrofit.renderer.KotlinRetrofitObjectRenderer @@ -36,6 +38,10 @@ class AutoDaggerSymbolProcessor(environment: SymbolProcessorEnvironment) : Symbo environment = this.environment, renderer = KotlinRetrofitObjectRenderer ), + KtorfitProcessor( + environment = this.environment, + renderer = KotlinKtorfitObjectRenderer + ), AndroidXRoomProcessor( environment = this.environment, renderer = KotlinAndroidXRoomDatabaseModuleRenderer diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/KtorfitProcessor.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/KtorfitProcessor.kt new file mode 100644 index 000000000..01dcbb92b --- /dev/null +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/KtorfitProcessor.kt @@ -0,0 +1,29 @@ +package se.ansman.dagger.auto.compiler.ktorfit + +import se.ansman.dagger.auto.compiler.Errors +import se.ansman.dagger.auto.compiler.common.processing.AutoDaggerEnvironment +import se.ansman.dagger.auto.compiler.ktorfit.renderer.KtorfitModuleRenderer +import se.ansman.dagger.auto.compiler.retrofit.BaseApiServiceProcessor +import se.ansman.dagger.auto.ktorfit.AutoProvideService + +class KtorfitProcessor( + environment: AutoDaggerEnvironment, + renderer: KtorfitModuleRenderer, +) : BaseApiServiceProcessor( + environment = environment, + renderer = renderer, + annotation = AutoProvideService::class, + serviceAnnotations = setOf( + "de.jensklingenberg.ktorfit.http.DELETE", + "de.jensklingenberg.ktorfit.http.GET", + "de.jensklingenberg.ktorfit.http.HEAD", + "de.jensklingenberg.ktorfit.http.HTTP", + "de.jensklingenberg.ktorfit.http.OPTIONS", + "de.jensklingenberg.ktorfit.http.PATCH", + "de.jensklingenberg.ktorfit.http.POST", + "de.jensklingenberg.ktorfit.http.PUT", + ), + modulePrefix = "AutoBindKtorfit", + logger = environment.logger.withTag("ktorfit"), + errors = Errors.Ktorfit, +) diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/JavaKtorfitModuleRenderer.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/JavaKtorfitModuleRenderer.kt new file mode 100644 index 000000000..755fdb59c --- /dev/null +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/JavaKtorfitModuleRenderer.kt @@ -0,0 +1,21 @@ +package se.ansman.dagger.auto.compiler.ktorfit.renderer + +import com.squareup.javapoet.AnnotationSpec +import com.squareup.javapoet.ClassName +import com.squareup.javapoet.CodeBlock +import com.squareup.javapoet.JavaFile +import com.squareup.javapoet.ParameterSpec +import com.squareup.javapoet.TypeName +import se.ansman.dagger.auto.compiler.common.kapt.JavaPoetRenderEngine +import se.ansman.dagger.auto.compiler.common.rendering.HiltJavaModuleBuilder +import javax.lang.model.element.Element + +object JavaKtorfitModuleRenderer : + KtorfitModuleRenderer( + JavaPoetRenderEngine, + HiltJavaModuleBuilder.Factory + ) { + + override fun provideService(serviceClass: ClassName, serviceFactoryParameter: ParameterSpec): CodeBlock = + CodeBlock.of("return \$N.create(null)", serviceFactoryParameter) +} \ No newline at end of file diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/KotlinKtorfitObjectRenderer.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/KotlinKtorfitObjectRenderer.kt new file mode 100644 index 000000000..8c89b43f1 --- /dev/null +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/KotlinKtorfitObjectRenderer.kt @@ -0,0 +1,21 @@ +package se.ansman.dagger.auto.compiler.ktorfit.renderer + +import com.google.devtools.ksp.symbol.KSDeclaration +import com.squareup.kotlinpoet.AnnotationSpec +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.ParameterSpec +import com.squareup.kotlinpoet.TypeName +import se.ansman.dagger.auto.compiler.common.ksp.KotlinPoetRenderEngine +import se.ansman.dagger.auto.compiler.common.rendering.HiltKotlinModuleBuilder + +object KotlinKtorfitObjectRenderer : + KtorfitModuleRenderer( + KotlinPoetRenderEngine, + HiltKotlinModuleBuilder.Factory + ) { + + override fun provideService(serviceClass: ClassName, serviceFactoryParameter: ParameterSpec): CodeBlock = + CodeBlock.of("return %N.create()", serviceFactoryParameter) +} \ No newline at end of file diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/KtorfitModuleRenderer.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/KtorfitModuleRenderer.kt new file mode 100644 index 000000000..4cc3d3dcb --- /dev/null +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/ktorfit/renderer/KtorfitModuleRenderer.kt @@ -0,0 +1,16 @@ +package se.ansman.dagger.auto.compiler.ktorfit.renderer + +import se.ansman.dagger.auto.compiler.common.processing.RenderEngine +import se.ansman.dagger.auto.compiler.common.rendering.HiltModuleBuilder +import se.ansman.dagger.auto.compiler.retrofit.renderer.BaseApiServiceModuleRenderer + +abstract class KtorfitModuleRenderer( + renderEngine: RenderEngine, + builderFactory: HiltModuleBuilder.Factory, +) : BaseApiServiceModuleRenderer( + renderEngine, + builderFactory +) { + override val serviceFactory: ClassName + get() = renderEngine.className("de.jensklingenberg.ktorfit.Ktorfit") +} \ No newline at end of file diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/BaseApiServiceProcessor.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/BaseApiServiceProcessor.kt new file mode 100644 index 000000000..98cd706d7 --- /dev/null +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/BaseApiServiceProcessor.kt @@ -0,0 +1,142 @@ +package se.ansman.dagger.auto.compiler.retrofit + +import dagger.Reusable +import dagger.hilt.components.SingletonComponent +import se.ansman.dagger.auto.compiler.Errors +import se.ansman.dagger.auto.compiler.common.Processor +import se.ansman.dagger.auto.compiler.common.processing.AutoDaggerEnvironment +import se.ansman.dagger.auto.compiler.common.processing.AutoDaggerLogger +import se.ansman.dagger.auto.compiler.common.processing.AutoDaggerResolver +import se.ansman.dagger.auto.compiler.common.processing.ClassDeclaration +import se.ansman.dagger.auto.compiler.common.processing.ClassDeclaration.Kind +import se.ansman.dagger.auto.compiler.common.processing.Function +import se.ansman.dagger.auto.compiler.common.processing.Property +import se.ansman.dagger.auto.compiler.common.processing.getAnnotation +import se.ansman.dagger.auto.compiler.common.processing.getQualifiers +import se.ansman.dagger.auto.compiler.common.processing.getValue +import se.ansman.dagger.auto.compiler.common.processing.isAnnotatedWith +import se.ansman.dagger.auto.compiler.common.processing.isFullyPrivate +import se.ansman.dagger.auto.compiler.common.processing.isFullyPublic +import se.ansman.dagger.auto.compiler.common.processing.lookupType +import se.ansman.dagger.auto.compiler.common.processing.nodesAnnotatedWith +import se.ansman.dagger.auto.compiler.common.processing.rootPeerClass +import se.ansman.dagger.auto.compiler.common.rendering.HiltModuleBuilder +import se.ansman.dagger.auto.compiler.retrofit.models.ApiServiceModule +import se.ansman.dagger.auto.compiler.retrofit.renderer.BaseApiServiceModuleRenderer +import se.ansman.dagger.auto.compiler.utils.ComponentValidator.validateComponent +import javax.inject.Scope +import kotlin.reflect.KClass + +abstract class BaseApiServiceProcessor( + private val environment: AutoDaggerEnvironment, + private val renderer: BaseApiServiceModuleRenderer, + private val annotation: KClass, + serviceAnnotations: Set, + private val modulePrefix: String, + private val logger: AutoDaggerLogger, + private val errors: Errors.ApiService, +) : Processor { + override val annotations: Set = setOf(annotation.java.canonicalName) + + private val serviceAnnotations by lazy { + serviceAnnotations.map { environment.className(it) } + } + + override fun process(resolver: AutoDaggerResolver) { + logger.info("@AutoProvideService processing started") + resolver.nodesAnnotatedWith(annotation) + .map { it as ClassDeclaration } + .map { service -> + logger.info("Processing ${service.className}") + val targetComponent = service + .getAnnotation(annotation)!! + .getValue>("inComponent") + ?: resolver.lookupType(SingletonComponent::class) + + service.validateService() + targetComponent.validateComponent(service, logger) + + ApiServiceModule( + moduleName = environment.rootPeerClass( + service.className, + environment.simpleNames(service.className).joinToString( + prefix = modulePrefix, + separator = "" + ) + ), + installation = HiltModuleBuilder.Installation.InstallIn(targetComponent.className), + originatingTopLevelClassName = environment.topLevelClassName(service.className), + originatingElement = service.node, + serviceClass = service.className, + isPublic = service.isFullyPublic, + qualifiers = service.getQualifiers(), + scope = service.findScope(targetComponent) + ) + } + .map(renderer::render) + .forEach(environment::write) + } + + private fun ClassDeclaration.validateService() { + if (kind != Kind.Interface) logger.error(errors.nonInterface, node) + if (isGeneric) logger.error(Errors.genericType(annotation), node) + if (isFullyPrivate) logger.error(errors.privateType, node) + if (declaredNodes.isEmpty()) logger.error(errors.emptyService, node) + for (node in declaredNodes) { + logger.info("Validating enclosed element $node") + when (node) { + is Function -> if (serviceAnnotations.none(node::isAnnotatedWith)) { + logger.error(errors.invalidServiceMethod, node.node) + } + + is Property -> logger.error( + errors.propertiesNotAllowed, + node.node + ) + + else -> error("Unexpected node: $node") + } + } + } + + private fun ClassDeclaration.findScope( + targetComponent: ClassDeclaration + ): AnnotationSpec? = + annotations + .filter { annotation -> + when { + annotation.isOfType(Reusable::class) -> true + annotation.isAnnotatedWith(Scope::class) -> { + // This will have logged and error about an invalid component + val neededScope = targetComponent.annotations + .find { it.isAnnotatedWith(Scope::class) } + ?: return@filter false + + if (neededScope.className != annotation.className) { + logger.error( + errors.invalidScope( + scope = annotation.simpleName, + component = environment.simpleName(targetComponent.className), + neededScope = neededScope.simpleName + ), node + ) + return@filter false + } + true + } + + else -> false + } + } + .let { + when (it.size) { + 0 -> null + 1 -> it.single() + else -> { + logger.error(errors.scopeAndReusable, node) + null + } + } + } + ?.toAnnotationSpec() +} \ No newline at end of file diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/RetrofitProcessor.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/RetrofitProcessor.kt index ca370fc42..ac4d1d2a5 100644 --- a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/RetrofitProcessor.kt +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/RetrofitProcessor.kt @@ -1,144 +1,28 @@ package se.ansman.dagger.auto.compiler.retrofit -import dagger.Reusable -import dagger.hilt.components.SingletonComponent import se.ansman.dagger.auto.compiler.Errors -import se.ansman.dagger.auto.compiler.common.Processor import se.ansman.dagger.auto.compiler.common.processing.AutoDaggerEnvironment -import se.ansman.dagger.auto.compiler.common.processing.AutoDaggerResolver -import se.ansman.dagger.auto.compiler.common.processing.ClassDeclaration -import se.ansman.dagger.auto.compiler.common.processing.ClassDeclaration.Kind -import se.ansman.dagger.auto.compiler.common.processing.Function -import se.ansman.dagger.auto.compiler.common.processing.Property -import se.ansman.dagger.auto.compiler.common.processing.getAnnotation -import se.ansman.dagger.auto.compiler.common.processing.getQualifiers -import se.ansman.dagger.auto.compiler.common.processing.getValue -import se.ansman.dagger.auto.compiler.common.processing.isAnnotatedWith -import se.ansman.dagger.auto.compiler.common.processing.isFullyPrivate -import se.ansman.dagger.auto.compiler.common.processing.isFullyPublic -import se.ansman.dagger.auto.compiler.common.processing.lookupType -import se.ansman.dagger.auto.compiler.common.processing.nodesAnnotatedWith -import se.ansman.dagger.auto.compiler.common.processing.rootPeerClass -import se.ansman.dagger.auto.compiler.common.rendering.HiltModuleBuilder -import se.ansman.dagger.auto.compiler.retrofit.models.RetrofitModule import se.ansman.dagger.auto.compiler.retrofit.renderer.RetrofitModuleRenderer -import se.ansman.dagger.auto.compiler.utils.ComponentValidator.validateComponent import se.ansman.dagger.auto.retrofit.AutoProvideService -import javax.inject.Scope class RetrofitProcessor( - private val environment: AutoDaggerEnvironment, - private val renderer: RetrofitModuleRenderer, -) : Processor { - private val validRetrofitAnnotations by lazy { - Companion.validRetrofitAnnotations.map { environment.className(it) } - } - private val logger = environment.logger.withTag("retrofit") - override val annotations: Set = setOf( - AutoProvideService::class.java.canonicalName, - ) - - override fun process(resolver: AutoDaggerResolver) { - logger.info("@AutoProvideService processing started") - resolver.nodesAnnotatedWith(AutoProvideService::class) - .map { it as ClassDeclaration } - .map { service -> - logger.info("Processing ${service.className}") - val targetComponent = service - .getAnnotation(AutoProvideService::class)!! - .getValue>("inComponent") - ?: resolver.lookupType(SingletonComponent::class) - - service.validateService() - targetComponent.validateComponent(service, logger) - - RetrofitModule( - moduleName = environment.rootPeerClass( - service.className, - environment.simpleNames(service.className).joinToString( - prefix = "AutoBindRetrofit", - separator = "" - ) - ), - installation = HiltModuleBuilder.Installation.InstallIn(targetComponent.className), - originatingTopLevelClassName = environment.topLevelClassName(service.className), - originatingElement = service.node, - serviceClass = service.className, - isPublic = service.isFullyPublic, - qualifiers = service.getQualifiers(), - scope = service.findScope(targetComponent) - ) - } - .map(renderer::render) - .forEach(environment::write) - } - - private fun ClassDeclaration.validateService() { - if (!(kind == Kind.Interface)) logger.error(Errors.Retrofit.nonInterface, node) - if (isGeneric) logger.error(Errors.genericType(AutoProvideService::class), node) - if (isFullyPrivate) logger.error(Errors.Retrofit.privateType, node) - if (declaredNodes.isEmpty()) logger.error(Errors.Retrofit.emptyService, node) - for (node in declaredNodes) { - logger.info("Validating enclosed element $node") - when (node) { - is Function -> if (validRetrofitAnnotations.none(node::isAnnotatedWith)) { - logger.error(Errors.Retrofit.invalidServiceMethod, node.node) - } - - is Property -> logger.error(Errors.Retrofit.propertiesNotAllowed, node.node) - else -> error("Unexpected node: $node") - } - } - } - - private fun ClassDeclaration.findScope( - targetComponent: ClassDeclaration - ): AnnotationSpec? = - annotations - .filter { annotation -> - when { - annotation.isOfType(Reusable::class) -> true - annotation.isAnnotatedWith(Scope::class) -> { - // This will have logged and error about an invalid component - val neededScope = targetComponent.annotations - .find { it.isAnnotatedWith(Scope::class) } - ?: return@filter false - - if (neededScope.className != annotation.className) { - logger.error(Errors.Retrofit.invalidScope( - scope = annotation.simpleName, - component = environment.simpleName(targetComponent.className), - neededScope = neededScope.simpleName - ), node) - return@filter false - } - true - } - else -> false - } - } - .let { - when (it.size) { - 0 -> null - 1 -> it.single() - else -> { - logger.error(Errors.Retrofit.scopeAndReusable, node) - null - } - } - } - ?.toAnnotationSpec() - - companion object { - private val validRetrofitAnnotations = setOf( - "retrofit2.http.DELETE", - "retrofit2.http.GET", - "retrofit2.http.HEAD", - "retrofit2.http.HTTP", - "retrofit2.http.OPTIONS", - "retrofit2.http.PATCH", - "retrofit2.http.POST", - "retrofit2.http.PUT", - ) - } -} + environment: AutoDaggerEnvironment, + renderer: RetrofitModuleRenderer, +) : BaseApiServiceProcessor( + environment = environment, + renderer = renderer, + annotation = AutoProvideService::class, + serviceAnnotations = setOf( + "retrofit2.http.DELETE", + "retrofit2.http.GET", + "retrofit2.http.HEAD", + "retrofit2.http.HTTP", + "retrofit2.http.OPTIONS", + "retrofit2.http.PATCH", + "retrofit2.http.POST", + "retrofit2.http.PUT", + ), + modulePrefix = "AutoBindRetrofit", + logger = environment.logger.withTag("retrofit"), + errors = Errors.Retrofit, +) diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/models/RetrofitModule.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/models/ApiServiceModule.kt similarity index 89% rename from compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/models/RetrofitModule.kt rename to compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/models/ApiServiceModule.kt index 292a172da..4c91af815 100644 --- a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/models/RetrofitModule.kt +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/models/ApiServiceModule.kt @@ -3,7 +3,7 @@ package se.ansman.dagger.auto.compiler.retrofit.models import se.ansman.dagger.auto.compiler.common.models.HiltModule import se.ansman.dagger.auto.compiler.common.rendering.HiltModuleBuilder -data class RetrofitModule( +data class ApiServiceModule( override val moduleName: ClassName, override val installation: HiltModuleBuilder.Installation, override val originatingTopLevelClassName: ClassName, diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/BaseApiServiceModuleRenderer.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/BaseApiServiceModuleRenderer.kt new file mode 100644 index 000000000..d81ba5f1b --- /dev/null +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/BaseApiServiceModuleRenderer.kt @@ -0,0 +1,26 @@ +package se.ansman.dagger.auto.compiler.retrofit.renderer + +import se.ansman.dagger.auto.compiler.common.processing.RenderEngine +import se.ansman.dagger.auto.compiler.common.rendering.HiltModuleBuilder +import se.ansman.dagger.auto.compiler.common.rendering.Renderer +import se.ansman.dagger.auto.compiler.retrofit.models.ApiServiceModule + +abstract class BaseApiServiceModuleRenderer( + protected val renderEngine: RenderEngine, + private val builderFactory: HiltModuleBuilder.Factory, +) : Renderer, SourceFile> { + protected abstract val serviceFactory: ClassName + + final override fun render(input: ApiServiceModule): SourceFile = + builderFactory + .create(input) + .addProvider( + name = "provide${renderEngine.simpleName(input.serviceClass)}", + parameters = listOf(HiltModuleBuilder.DaggerType(serviceFactory, input.qualifiers)), + returnType = HiltModuleBuilder.DaggerType(input.serviceClass, setOfNotNull(input.scope)), + isPublic = input.isPublic, + ) { parameters -> provideService(input.serviceClass, parameters.single()) } + .build() + + protected abstract fun provideService(serviceClass: ClassName, serviceFactoryParameter: ParameterSpec): CodeBlock +} \ No newline at end of file diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/JavaRetrofitModuleRenderer.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/JavaRetrofitModuleRenderer.kt index b02ab9bbb..aceee9f41 100644 --- a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/JavaRetrofitModuleRenderer.kt +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/JavaRetrofitModuleRenderer.kt @@ -16,6 +16,6 @@ object JavaRetrofitModuleRenderer : HiltJavaModuleBuilder.Factory ) { - override fun provideService(serviceClass: ClassName, retrofitParameter: ParameterSpec): CodeBlock = - CodeBlock.of("return \$N.create(\$T.class)", retrofitParameter, serviceClass) + override fun provideService(serviceClass: ClassName, serviceFactoryParameter: ParameterSpec): CodeBlock = + CodeBlock.of("return \$N.create(\$T.class)", serviceFactoryParameter, serviceClass) } \ No newline at end of file diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/KotlinRetrofitObjectRenderer.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/KotlinRetrofitObjectRenderer.kt index c1ded4ed6..c0bde2615 100644 --- a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/KotlinRetrofitObjectRenderer.kt +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/KotlinRetrofitObjectRenderer.kt @@ -17,6 +17,6 @@ object KotlinRetrofitObjectRenderer : HiltKotlinModuleBuilder.Factory ) { - override fun provideService(serviceClass: ClassName, retrofitParameter: ParameterSpec): CodeBlock = - CodeBlock.of("return %N.%M()", retrofitParameter, MemberName("retrofit2", "create")) + override fun provideService(serviceClass: ClassName, serviceFactoryParameter: ParameterSpec): CodeBlock = + CodeBlock.of("return %N.%M()", serviceFactoryParameter, MemberName("retrofit2", "create")) } \ No newline at end of file diff --git a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/RetrofitModuleRenderer.kt b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/RetrofitModuleRenderer.kt index 0ff85332d..dcc01c738 100644 --- a/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/RetrofitModuleRenderer.kt +++ b/compiler/src/main/kotlin/se/ansman/dagger/auto/compiler/retrofit/renderer/RetrofitModuleRenderer.kt @@ -2,29 +2,14 @@ package se.ansman.dagger.auto.compiler.retrofit.renderer import se.ansman.dagger.auto.compiler.common.processing.RenderEngine import se.ansman.dagger.auto.compiler.common.rendering.HiltModuleBuilder -import se.ansman.dagger.auto.compiler.common.rendering.Renderer -import se.ansman.dagger.auto.compiler.retrofit.models.RetrofitModule abstract class RetrofitModuleRenderer( - private val renderEngine: RenderEngine, - private val builderFactory: HiltModuleBuilder.Factory, -) : Renderer, SourceFile> { - - final override fun render(input: RetrofitModule): SourceFile = - builderFactory - .create(input) - .addProvider( - name = "provide${renderEngine.simpleName(input.serviceClass)}", - parameters = listOf( - HiltModuleBuilder.DaggerType( - renderEngine.className("retrofit2.Retrofit"), - input.qualifiers, - ) - ), - returnType = HiltModuleBuilder.DaggerType(input.serviceClass, setOfNotNull(input.scope)), - isPublic = input.isPublic, - ) { parameters -> provideService(input.serviceClass, parameters.single()) } - .build() - - protected abstract fun provideService(serviceClass: ClassName, retrofitParameter: ParameterSpec): CodeBlock + renderEngine: RenderEngine, + builderFactory: HiltModuleBuilder.Factory, +) : BaseApiServiceModuleRenderer( + renderEngine, + builderFactory +) { + override val serviceFactory: ClassName + get() = renderEngine.className("retrofit2.Retrofit") } \ No newline at end of file diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ceb0b36a7..6ddd90deb 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -5,10 +5,6 @@ plugins { id("library.publishing") } -kotlin { - explicitApi() -} - dependencies { implementation(libs.dagger) kapt(libs.dagger.compiler) diff --git a/gradle-plugin/src/main/kotlin/library.compiler.gradle.kts b/gradle-plugin/src/main/kotlin/library.compiler.gradle.kts index 9cb3d17cb..d6ca90edf 100644 --- a/gradle-plugin/src/main/kotlin/library.compiler.gradle.kts +++ b/gradle-plugin/src/main/kotlin/library.compiler.gradle.kts @@ -10,12 +10,6 @@ plugins { val libs = the() -tasks.withType().configureEach { - if (providers.gradleProperty("updateExpectedTestFiles").orNull?.toBoolean() == true) { - systemProperty("writeExpectedFilesTo", file("src/test/resources/tests")) - } -} - dependencies { implementation(projects.compiler.common.copy( targetConfiguration = "shadow" diff --git a/gradle-plugin/src/main/kotlin/library.gradle.kts b/gradle-plugin/src/main/kotlin/library.gradle.kts index d347b3109..5cf0fdda4 100644 --- a/gradle-plugin/src/main/kotlin/library.gradle.kts +++ b/gradle-plugin/src/main/kotlin/library.gradle.kts @@ -55,6 +55,9 @@ tasks.withType().configureEach { "--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", "--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" ) + if (providers.gradleProperty("updateExpectedTestFiles").orNull?.toBoolean() == true) { + systemProperty("writeExpectedFilesTo", file("src/test/resources/tests")) + } } fun Lint.configure() { diff --git a/gradle-plugin/src/main/kotlin/library.publishing.gradle.kts b/gradle-plugin/src/main/kotlin/library.publishing.gradle.kts index bc356fc5c..adda9f1b1 100644 --- a/gradle-plugin/src/main/kotlin/library.publishing.gradle.kts +++ b/gradle-plugin/src/main/kotlin/library.publishing.gradle.kts @@ -4,6 +4,7 @@ import com.android.build.gradle.internal.scope.ProjectInfo.Companion.getBaseName import com.github.jengelman.gradle.plugins.shadow.ShadowExtension import org.gradle.accessors.dm.LibrariesForLibs import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName import se.ansman.dagger.auto.gradle.cachedProvider import se.ansman.dagger.auto.gradle.execWithOutput diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 01719debb..39bc3a4b2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,7 @@ androidx-test = "1.5.0" kotlinpoet = "1.16.0" room = "2.6.1" retrofit = "2.11.0" +ktorfit = "1.12.0" projectAccessors = "1.1.0" [plugins] @@ -85,6 +86,8 @@ room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } projectAccessors = { module = "co.hinge.gradle.project-accessors:project-accessors", version.ref = "projectAccessors" } +ktorfit = { module = "de.jensklingenberg.ktorfit:ktorfit-lib", version.ref = "ktorfit" } + [bundles] compileTesting = ["compileTesting", "compileTesting-ksp"] kotlinpoet = ["kotlinpoet", "kotlinpoet-ksp"] diff --git a/settings.gradle.kts b/settings.gradle.kts index d1f681028..82650d538 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -31,6 +31,7 @@ include(":compiler:common:test-utils") include(":third-party:android") include(":third-party:android:testing") include(":third-party:retrofit") +include(":third-party:ktorfit") include(":third-party:androidx:viewmodel") include(":third-party:androidx:room") include(":tests") \ No newline at end of file diff --git a/src/doc/docs/integrations/ktorfit.md b/src/doc/docs/integrations/ktorfit.md new file mode 100644 index 000000000..3a3cc9a17 --- /dev/null +++ b/src/doc/docs/integrations/ktorfit.md @@ -0,0 +1,74 @@ +# Integration with Ktorfit +If you use [Ktorfit](https://foso.github.io/Ktorfit/) to define your API services, you can use the +`@AutoProvideService` to automatically contribute your services to the Dagger graph. + +Firstly add the required dependency: +```kotlin +dependencies { + implementation("se.ansman.dagger.auto:ktorfit:{{gradle.version}}") + kapt("se.ansman.dagger.auto:compiler:{{gradle.version}}") + // or if you use KSP + ksp("se.ansman.dagger.auto:compiler:{{gradle.version}}") +} +``` + +Then annotate your service with `@AutoProvideService`: +```kotlin +@AutoProvideService +class ApiService { + @GET("users") + suspend fun getUsers(): List +} +``` + +You'll also need to provide a Ktorfit instance to the component you want to inject the service into: +```kotlin +@Module +@InstallIn(SingletonComponent::class) +object KtorfitModule { + @Provides + @Singleton + fun provideKtorfit(): Ktorfit = Ktorfit.Builder() + // Perform any setup you need + .baseUrl("https://api.example.com/") + .build() +} +``` + +## Changing the target component +By default, services are installed in the `SingletonComponent`. If you'd like to change this you can do so by +specifying the `inComponent` parameter: +```kotlin +@AutoProvideService(inComponent = SomeOtherComponent::class) +class ApiService { + // Service methods +} +``` + +## Qualifiers +If you have multiple ktorfit instances and use qualifiers to differentiate them, you can specify the qualifier on the +service: +```kotlin +@AutoProvideService +@Named("api1") +class ApiService { + // Service methods +} +``` + +## Making the service scoped or reusable +If you'd like to cache/reuse the service instances you can annotate the service with a scope or `@Reusable`: +```kotlin +@Singleton // This must match the `inComponent` parameter of @AutoProvideService +@AutoProvideService +class ApiService { + // Service methods +} + +// Or if you want to make it reusable +@Reusable +@AutoProvideService +class ApiService { + // Service methods +} +``` \ No newline at end of file diff --git a/src/doc/mkdocs.yml b/src/doc/mkdocs.yml index d99740b5e..679670491 100644 --- a/src/doc/mkdocs.yml +++ b/src/doc/mkdocs.yml @@ -117,6 +117,7 @@ nav: - Room: integrations/androidx/room.md - ViewModel: integrations/androidx/viewmodel.md - Retrofit: integrations/retrofit.md + - Ktorfit: integrations/ktorfit.md - Limitations: limitations.md - About: - Release Notes: https://github.com/ansman/auto-dagger/releases diff --git a/tests/build.gradle.kts b/tests/build.gradle.kts index 76cfa3a97..76933f485 100644 --- a/tests/build.gradle.kts +++ b/tests/build.gradle.kts @@ -18,6 +18,7 @@ plugins { android { defaultConfig { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + minSdk = 21 } flavorDimensions += "type" productFlavors { @@ -55,7 +56,9 @@ dependencies { implementation(projects.thirdParty.androidx.viewmodel) implementation(projects.thirdParty.androidx.room) implementation(projects.thirdParty.retrofit) + implementation(projects.thirdParty.ktorfit) implementation(libs.retrofit) + implementation(libs.ktorfit) implementation(libs.androidx.lifecycle.viewmodel) implementation(libs.room) ksp(libs.room.compiler) diff --git a/tests/src/main/kotlin/se/ansman/dagger/auto/ExampleApplication.kt b/tests/src/main/kotlin/se/ansman/dagger/auto/ExampleApplication.kt index 30d1d4c43..9d86afa87 100644 --- a/tests/src/main/kotlin/se/ansman/dagger/auto/ExampleApplication.kt +++ b/tests/src/main/kotlin/se/ansman/dagger/auto/ExampleApplication.kt @@ -3,13 +3,13 @@ package se.ansman.dagger.auto import android.app.Application import dagger.hilt.android.HiltAndroidApp import se.ansman.dagger.auto.androidx.room.UserDao -import se.ansman.dagger.auto.retrofit.ExampleApiService +import se.ansman.dagger.auto.retrofit.ExampleRetrofitApiService import javax.inject.Inject @HiltAndroidApp class ExampleApplication : Application() { @Inject - lateinit var apiService: ExampleApiService + lateinit var apiService: ExampleRetrofitApiService @Inject lateinit var users: UserDao diff --git a/tests/src/main/kotlin/se/ansman/dagger/auto/ktorfit/ExampleKtorfitApiService.kt b/tests/src/main/kotlin/se/ansman/dagger/auto/ktorfit/ExampleKtorfitApiService.kt new file mode 100644 index 000000000..08d4d8bee --- /dev/null +++ b/tests/src/main/kotlin/se/ansman/dagger/auto/ktorfit/ExampleKtorfitApiService.kt @@ -0,0 +1,9 @@ +package se.ansman.dagger.auto.ktorfit + +import de.jensklingenberg.ktorfit.http.GET + +@AutoProvideService +interface ExampleKtorfitApiService { + @GET("/users") + suspend fun getUsers(): List +} \ No newline at end of file diff --git a/tests/src/main/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitModule.kt b/tests/src/main/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitModule.kt new file mode 100644 index 000000000..25328f732 --- /dev/null +++ b/tests/src/main/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitModule.kt @@ -0,0 +1,19 @@ +package se.ansman.dagger.auto.ktorfit + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import de.jensklingenberg.ktorfit.Ktorfit +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object KtorfitModule { + @Provides + @Singleton + fun provideKtorfit(): Ktorfit = + Ktorfit.Builder() + .baseUrl("https://jsonplaceholder.typicode.com") + .build() +} \ No newline at end of file diff --git a/tests/src/main/kotlin/se/ansman/dagger/auto/retrofit/ExampleApiService.kt b/tests/src/main/kotlin/se/ansman/dagger/auto/retrofit/ExampleRetrofitApiService.kt similarity index 79% rename from tests/src/main/kotlin/se/ansman/dagger/auto/retrofit/ExampleApiService.kt rename to tests/src/main/kotlin/se/ansman/dagger/auto/retrofit/ExampleRetrofitApiService.kt index d1dd377d8..44014219a 100644 --- a/tests/src/main/kotlin/se/ansman/dagger/auto/retrofit/ExampleApiService.kt +++ b/tests/src/main/kotlin/se/ansman/dagger/auto/retrofit/ExampleRetrofitApiService.kt @@ -3,7 +3,7 @@ package se.ansman.dagger.auto.retrofit import retrofit2.http.GET @AutoProvideService -interface ExampleApiService { +interface ExampleRetrofitApiService { @GET("/users") suspend fun getUsers(): List } \ No newline at end of file diff --git a/tests/src/test/kotlin/se/ansman/dagger/auto/SampleProjectTest.kt b/tests/src/test/kotlin/se/ansman/dagger/auto/SampleProjectTest.kt index 64a30db3b..91c88201e 100644 --- a/tests/src/test/kotlin/se/ansman/dagger/auto/SampleProjectTest.kt +++ b/tests/src/test/kotlin/se/ansman/dagger/auto/SampleProjectTest.kt @@ -18,6 +18,8 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config +import se.ansman.dagger.auto.ktorfit.ExampleKtorfitApiService +import se.ansman.dagger.auto.retrofit.ExampleRetrofitApiService import java.io.Closeable import javax.inject.Inject import javax.inject.Provider @@ -35,6 +37,14 @@ class SampleProjectTest { @Inject lateinit var repository: Provider + @Suppress("unused") + @Inject + lateinit var retrofitService: Provider + + @Suppress("unused") + @Inject + lateinit var ktorfitService: Provider + @Inject lateinit var replaceableRepository: Provider diff --git a/third-party/ktorfit/api/ktorfit.api b/third-party/ktorfit/api/ktorfit.api new file mode 100644 index 000000000..36acb798f --- /dev/null +++ b/third-party/ktorfit/api/ktorfit.api @@ -0,0 +1,4 @@ +public abstract interface annotation class se/ansman/dagger/auto/ktorfit/AutoProvideService : java/lang/annotation/Annotation { + public abstract fun inComponent ()Ljava/lang/Class; +} + diff --git a/third-party/ktorfit/build.gradle.kts b/third-party/ktorfit/build.gradle.kts new file mode 100644 index 000000000..ea9723672 --- /dev/null +++ b/third-party/ktorfit/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + kotlin("jvm") + id("library.api") + id("library.publishing") +} + +dependencies { + implementation(libs.dagger.hilt.core) + testImplementation(testFixtures(projects.compiler)) + testImplementation(libs.ktorfit) +} \ No newline at end of file diff --git a/third-party/ktorfit/src/main/kotlin/se/ansman/dagger/auto/ktorfit/AutoProvideService.kt b/third-party/ktorfit/src/main/kotlin/se/ansman/dagger/auto/ktorfit/AutoProvideService.kt new file mode 100644 index 000000000..3d22cc45f --- /dev/null +++ b/third-party/ktorfit/src/main/kotlin/se/ansman/dagger/auto/ktorfit/AutoProvideService.kt @@ -0,0 +1,74 @@ +package se.ansman.dagger.auto.ktorfit + +import dagger.hilt.GeneratesRootInput +import dagger.hilt.components.SingletonComponent +import kotlin.reflect.KClass + +/** + * Marks a [Ktorfit](https://foso.github.io/Ktorfit/) Service for automatic contribution to your dependency graph. + * + * Simply add this annotation to the API services you want to inject and auto-dagger will generate the necessary modules. + * + * Example: + * ``` + * @AutoProvideService + * class ApiService { + * @GET("users") + * suspend fun getUsers(): List + * } + * + * // You'll also need to provide a Ktorfit instance to the component you want to inject the service into: + * @Module + * @InstallIn(SingletonComponent::class) + * object KtorfitModule { + * @Provides + * @Singleton + * fun provideKtorfit(): Ktorfit = Ktorfit.Builder() + * .baseUrl("https://api.example.com/") + * .build() + * } + * ``` + * + * ## Changing the target component + * By default, services are installed in the [SingletonComponent]. If you'd like to change this you can do so by + * specifying the `inComponent` parameter: + * ``` + * @AutoProvideService(inComponent = SomeOtherComponent::class) + * class ApiService {} + * ``` + * + * ## Qualifiers + * If you have multiple ktorfit instances and use qualifiers to differentiate them, you can specify the qualifier on the + * service: + * ``` + * @AutoProvideService + * @Named("api1") + * class ApiService {} + * ``` + * + * ## Making the service scoped or reusable + * If you'd like to cache/reuse the service instances you can annotate the service with a scope or `@Reusable`: + * ``` + * @Singleton // This must match the `inComponent` parameter of @AutoProvideService + * @AutoProvideService + * class ApiService { + * // Service methods + * } + * + * // Or if you want to just make it reusable + * @Reusable + * @AutoProvideService + * class ApiService { + * // Service methods + * } + * ``` + * + * @param inComponent The component to install the service in. Defaults to [SingletonComponent]. + * @since 1.1.0 + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +@GeneratesRootInput +public annotation class AutoProvideService( + val inComponent: KClass<*> = SingletonComponent::class, +) diff --git a/third-party/ktorfit/src/test/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitResourceTests.kt b/third-party/ktorfit/src/test/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitResourceTests.kt new file mode 100644 index 000000000..f84f863dc --- /dev/null +++ b/third-party/ktorfit/src/test/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitResourceTests.kt @@ -0,0 +1,5 @@ +package se.ansman.dagger.auto.ktorfit + +import se.ansman.dagger.auto.compiler.ResourceBasedTests + +class KtorfitResourceTests : ResourceBasedTests() \ No newline at end of file diff --git a/third-party/ktorfit/src/test/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitTest.kt b/third-party/ktorfit/src/test/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitTest.kt new file mode 100644 index 000000000..ba09cd8a9 --- /dev/null +++ b/third-party/ktorfit/src/test/kotlin/se/ansman/dagger/auto/ktorfit/KtorfitTest.kt @@ -0,0 +1,138 @@ +package se.ansman.dagger.auto.ktorfit + +import org.junit.jupiter.api.io.TempDir +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ArgumentsSource +import se.ansman.dagger.auto.compiler.AutoDaggerCompilationFactoryProvider +import se.ansman.dagger.auto.compiler.Errors +import se.ansman.dagger.auto.compiler.common.testutils.Compilation +import java.io.File + +class KtorfitTest { + @TempDir + lateinit var tempDirectory: File + + @ParameterizedTest + @ArgumentsSource(AutoDaggerCompilationFactoryProvider::class) + fun `type must be an interface`(compilationFactory: Compilation.Factory) { + compilationFactory.create(tempDirectory) + .compile( + """ + package se.ansman.dagger.auto.ktorfit + + @AutoProvideService + abstract class ApiService { + @de.jensklingenberg.ktorfit.http.GET("users") + suspend fun getUsers(): List + } + """ + ) + .assertFailedWithMessage(Errors.Ktorfit.nonInterface) + } + + @ParameterizedTest + @ArgumentsSource(AutoDaggerCompilationFactoryProvider::class) + fun `type must not be generic`(compilationFactory: Compilation.Factory) { + compilationFactory.create(tempDirectory) + .compile( + """ + package se.ansman.dagger.auto.ktorfit + + @AutoProvideService + interface ApiService { + @de.jensklingenberg.ktorfit.http.GET("users") + suspend fun getUsers(): List + } + """ + ) + .assertFailedWithMessage(Errors.genericType(AutoProvideService::class)) + } + + @ParameterizedTest + @ArgumentsSource(AutoDaggerCompilationFactoryProvider::class) + fun `type must not be private`(compilationFactory: Compilation.Factory) { + compilationFactory.create(tempDirectory) + .compile( + """ + package se.ansman.dagger.auto.ktorfit + + @AutoProvideService + private interface ApiService { + @de.jensklingenberg.ktorfit.http.GET("users") + suspend fun getUsers(): List + } + """ + ) + .assertFailedWithMessage(Errors.Ktorfit.privateType) + } + + @ParameterizedTest + @ArgumentsSource(AutoDaggerCompilationFactoryProvider::class) + fun `type must have declared methods`(compilationFactory: Compilation.Factory) { + compilationFactory.create(tempDirectory) + .compile( + """ + package se.ansman.dagger.auto.ktorfit + + @AutoProvideService + interface ApiService + """ + ) + .assertFailedWithMessage(Errors.Ktorfit.emptyService) + } + + @ParameterizedTest + @ArgumentsSource(AutoDaggerCompilationFactoryProvider::class) + fun `methods must be annotated`(compilationFactory: Compilation.Factory) { + compilationFactory.create(tempDirectory) + .compile( + """ + package se.ansman.dagger.auto.ktorfit + + @AutoProvideService + interface ApiService { + suspend fun getUsers(): List + } + """ + ) + .assertFailedWithMessage(Errors.Ktorfit.invalidServiceMethod) + } + + @ParameterizedTest + @ArgumentsSource(AutoDaggerCompilationFactoryProvider::class) + fun `cannot have reusable and a scope`(compilationFactory: Compilation.Factory) { + compilationFactory.create(tempDirectory) + .compile( + """ + package se.ansman.dagger.auto.ktorfit + + @javax.inject.Singleton + @dagger.Reusable + @AutoProvideService + interface ApiService { + @de.jensklingenberg.ktorfit.http.GET("users") + suspend fun getUsers(): List + } + """ + ) + .assertFailedWithMessage(Errors.Ktorfit.scopeAndReusable) + } + + @ParameterizedTest + @ArgumentsSource(AutoDaggerCompilationFactoryProvider::class) + fun `invalid scope`(compilationFactory: Compilation.Factory) { + compilationFactory.create(tempDirectory) + .compile( + """ + package se.ansman.dagger.auto.ktorfit + + @dagger.hilt.android.scopes.FragmentScoped + @AutoProvideService + interface ApiService { + suspend fun getUsers(): List + } + """ + ) + .assertFailedWithMessage(Errors.Ktorfit.invalidScope("FragmentScoped", "SingletonComponent", "Singleton")) + } +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/ApiService.kt b/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/ApiService.kt new file mode 100644 index 000000000..7d4a20dd1 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/ApiService.kt @@ -0,0 +1,11 @@ +package tests.ktorfit.custom_component + +import dagger.hilt.android.components.FragmentComponent +import de.jensklingenberg.ktorfit.http.GET +import se.ansman.dagger.auto.ktorfit.AutoProvideService + +@AutoProvideService(inComponent = FragmentComponent::class) +interface ApiService { + @GET("users") + suspend fun getUsers(): List +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/kapt/AutoBindKtorfitApiService.java.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/kapt/AutoBindKtorfitApiService.java.txt new file mode 100644 index 000000000..9c9332b95 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/kapt/AutoBindKtorfitApiService.java.txt @@ -0,0 +1,24 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.custom_component; + +import dagger.Module; +import dagger.Provides; +import dagger.hilt.InstallIn; +import dagger.hilt.android.components.FragmentComponent; +import dagger.hilt.codegen.OriginatingElement; +import de.jensklingenberg.ktorfit.Ktorfit; + +@Module +@InstallIn(FragmentComponent.class) +@OriginatingElement( + topLevelClass = ApiService.class +) +public abstract class AutoBindKtorfitApiService { + private AutoBindKtorfitApiService() { + } + + @Provides + public static ApiService provideApiService(Ktorfit ktorfit) { + return ktorfit.create(null); + } +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/ksp/AutoBindKtorfitApiService.kt.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/ksp/AutoBindKtorfitApiService.kt.txt new file mode 100644 index 000000000..b859a1917 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/custom_component/ksp/AutoBindKtorfitApiService.kt.txt @@ -0,0 +1,17 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.custom_component + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.components.FragmentComponent +import dagger.hilt.codegen.OriginatingElement +import de.jensklingenberg.ktorfit.Ktorfit + +@Module +@InstallIn(FragmentComponent::class) +@OriginatingElement(topLevelClass = ApiService::class) +public object AutoBindKtorfitApiService { + @Provides + public fun provideApiService(ktorfit: Ktorfit): ApiService = ktorfit.create() +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/ApiService.kt b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/ApiService.kt new file mode 100644 index 000000000..0058b3d98 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/ApiService.kt @@ -0,0 +1,10 @@ +package tests.ktorfit.non_public + +import de.jensklingenberg.ktorfit.http.GET +import se.ansman.dagger.auto.ktorfit.AutoProvideService + +@AutoProvideService +internal interface ApiService { + @GET("users") + suspend fun getUsers(): List +} diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/kapt/AutoBindKtorfitApiService.java.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/kapt/AutoBindKtorfitApiService.java.txt new file mode 100644 index 000000000..8ed9444ec --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/kapt/AutoBindKtorfitApiService.java.txt @@ -0,0 +1,24 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.non_public; + +import dagger.Module; +import dagger.Provides; +import dagger.hilt.InstallIn; +import dagger.hilt.codegen.OriginatingElement; +import dagger.hilt.components.SingletonComponent; +import de.jensklingenberg.ktorfit.Ktorfit; + +@Module +@InstallIn(SingletonComponent.class) +@OriginatingElement( + topLevelClass = ApiService.class +) +public abstract class AutoBindKtorfitApiService { + private AutoBindKtorfitApiService() { + } + + @Provides + public static ApiService provideApiService(Ktorfit ktorfit) { + return ktorfit.create(null); + } +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/ksp/AutoBindKtorfitApiService.kt.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/ksp/AutoBindKtorfitApiService.kt.txt new file mode 100644 index 000000000..89e56d0dd --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public/ksp/AutoBindKtorfitApiService.kt.txt @@ -0,0 +1,17 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.non_public + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.codegen.OriginatingElement +import dagger.hilt.components.SingletonComponent +import de.jensklingenberg.ktorfit.Ktorfit + +@Module +@InstallIn(SingletonComponent::class) +@OriginatingElement(topLevelClass = ApiService::class) +public object AutoBindKtorfitApiService { + @Provides + internal fun provideApiService(ktorfit: Ktorfit): ApiService = ktorfit.create() +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/ApiService.kt b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/ApiService.kt new file mode 100644 index 000000000..c5e42e18c --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/ApiService.kt @@ -0,0 +1,14 @@ +package tests.ktorfit.non_public_parent + +import de.jensklingenberg.ktorfit.http.GET +import se.ansman.dagger.auto.ktorfit.AutoProvideService + +internal object Wrapper1 { + object Wrapper2 { + @AutoProvideService + interface ApiService { + @GET("users") + suspend fun getUsers(): List + } + } +} diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/kapt/AutoBindKtorfitWrapper1Wrapper2ApiService.java.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/kapt/AutoBindKtorfitWrapper1Wrapper2ApiService.java.txt new file mode 100644 index 000000000..95601fed9 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/kapt/AutoBindKtorfitWrapper1Wrapper2ApiService.java.txt @@ -0,0 +1,24 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.non_public_parent; + +import dagger.Module; +import dagger.Provides; +import dagger.hilt.InstallIn; +import dagger.hilt.codegen.OriginatingElement; +import dagger.hilt.components.SingletonComponent; +import de.jensklingenberg.ktorfit.Ktorfit; + +@Module +@InstallIn(SingletonComponent.class) +@OriginatingElement( + topLevelClass = Wrapper1.class +) +public abstract class AutoBindKtorfitWrapper1Wrapper2ApiService { + private AutoBindKtorfitWrapper1Wrapper2ApiService() { + } + + @Provides + public static Wrapper1.Wrapper2.ApiService provideApiService(Ktorfit ktorfit) { + return ktorfit.create(null); + } +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/ksp/AutoBindKtorfitWrapper1Wrapper2ApiService.kt.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/ksp/AutoBindKtorfitWrapper1Wrapper2ApiService.kt.txt new file mode 100644 index 000000000..b6c8f976d --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/non_public_parent/ksp/AutoBindKtorfitWrapper1Wrapper2ApiService.kt.txt @@ -0,0 +1,17 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.non_public_parent + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.codegen.OriginatingElement +import dagger.hilt.components.SingletonComponent +import de.jensklingenberg.ktorfit.Ktorfit + +@Module +@InstallIn(SingletonComponent::class) +@OriginatingElement(topLevelClass = Wrapper1::class) +public object AutoBindKtorfitWrapper1Wrapper2ApiService { + @Provides + internal fun provideApiService(ktorfit: Ktorfit): Wrapper1.Wrapper2.ApiService = ktorfit.create() +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/ApiService.kt b/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/ApiService.kt new file mode 100644 index 000000000..ada2f1b50 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/ApiService.kt @@ -0,0 +1,12 @@ +package tests.ktorfit.qualifiers + +import de.jensklingenberg.ktorfit.http.GET +import se.ansman.dagger.auto.ktorfit.AutoProvideService +import javax.inject.Named + +@AutoProvideService +@Named("api1") +interface ApiService { + @GET("users") + suspend fun getUsers(): List +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/kapt/AutoBindKtorfitApiService.java.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/kapt/AutoBindKtorfitApiService.java.txt new file mode 100644 index 000000000..f13fe01eb --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/kapt/AutoBindKtorfitApiService.java.txt @@ -0,0 +1,25 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.qualifiers; + +import dagger.Module; +import dagger.Provides; +import dagger.hilt.InstallIn; +import dagger.hilt.codegen.OriginatingElement; +import dagger.hilt.components.SingletonComponent; +import de.jensklingenberg.ktorfit.Ktorfit; +import javax.inject.Named; + +@Module +@InstallIn(SingletonComponent.class) +@OriginatingElement( + topLevelClass = ApiService.class +) +public abstract class AutoBindKtorfitApiService { + private AutoBindKtorfitApiService() { + } + + @Provides + public static ApiService provideApiService(@Named("api1") Ktorfit ktorfit) { + return ktorfit.create(null); + } +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/ksp/AutoBindKtorfitApiService.kt.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/ksp/AutoBindKtorfitApiService.kt.txt new file mode 100644 index 000000000..543177533 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/qualifiers/ksp/AutoBindKtorfitApiService.kt.txt @@ -0,0 +1,18 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.qualifiers + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.codegen.OriginatingElement +import dagger.hilt.components.SingletonComponent +import de.jensklingenberg.ktorfit.Ktorfit +import javax.inject.Named + +@Module +@InstallIn(SingletonComponent::class) +@OriginatingElement(topLevelClass = ApiService::class) +public object AutoBindKtorfitApiService { + @Provides + public fun provideApiService(@Named("api1") ktorfit: Ktorfit): ApiService = ktorfit.create() +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/ApiService.kt b/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/ApiService.kt new file mode 100644 index 000000000..91ea9bbf1 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/ApiService.kt @@ -0,0 +1,12 @@ +package tests.ktorfit.reusable + +import dagger.Reusable +import de.jensklingenberg.ktorfit.http.GET +import se.ansman.dagger.auto.ktorfit.AutoProvideService + +@Reusable +@AutoProvideService +interface ApiService { + @GET("users") + suspend fun getUsers(): List +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/kapt/AutoBindKtorfitApiService.java.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/kapt/AutoBindKtorfitApiService.java.txt new file mode 100644 index 000000000..909500c74 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/kapt/AutoBindKtorfitApiService.java.txt @@ -0,0 +1,26 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.reusable; + +import dagger.Module; +import dagger.Provides; +import dagger.Reusable; +import dagger.hilt.InstallIn; +import dagger.hilt.codegen.OriginatingElement; +import dagger.hilt.components.SingletonComponent; +import de.jensklingenberg.ktorfit.Ktorfit; + +@Module +@InstallIn(SingletonComponent.class) +@OriginatingElement( + topLevelClass = ApiService.class +) +public abstract class AutoBindKtorfitApiService { + private AutoBindKtorfitApiService() { + } + + @Provides + @Reusable + public static ApiService provideApiService(Ktorfit ktorfit) { + return ktorfit.create(null); + } +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/ksp/AutoBindKtorfitApiService.kt.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/ksp/AutoBindKtorfitApiService.kt.txt new file mode 100644 index 000000000..3e6aeac88 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/reusable/ksp/AutoBindKtorfitApiService.kt.txt @@ -0,0 +1,19 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.reusable + +import dagger.Module +import dagger.Provides +import dagger.Reusable +import dagger.hilt.InstallIn +import dagger.hilt.codegen.OriginatingElement +import dagger.hilt.components.SingletonComponent +import de.jensklingenberg.ktorfit.Ktorfit + +@Module +@InstallIn(SingletonComponent::class) +@OriginatingElement(topLevelClass = ApiService::class) +public object AutoBindKtorfitApiService { + @Provides + @Reusable + public fun provideApiService(ktorfit: Ktorfit): ApiService = ktorfit.create() +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/ApiService.kt b/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/ApiService.kt new file mode 100644 index 000000000..7568dfdd5 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/ApiService.kt @@ -0,0 +1,12 @@ +package tests.ktorfit.scoped + +import de.jensklingenberg.ktorfit.http.GET +import se.ansman.dagger.auto.ktorfit.AutoProvideService +import javax.inject.Singleton + +@Singleton +@AutoProvideService +interface ApiService { + @GET("users") + suspend fun getUsers(): List +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/kapt/AutoBindKtorfitApiService.java.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/kapt/AutoBindKtorfitApiService.java.txt new file mode 100644 index 000000000..8e4bb4085 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/kapt/AutoBindKtorfitApiService.java.txt @@ -0,0 +1,26 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.scoped; + +import dagger.Module; +import dagger.Provides; +import dagger.hilt.InstallIn; +import dagger.hilt.codegen.OriginatingElement; +import dagger.hilt.components.SingletonComponent; +import de.jensklingenberg.ktorfit.Ktorfit; +import javax.inject.Singleton; + +@Module +@InstallIn(SingletonComponent.class) +@OriginatingElement( + topLevelClass = ApiService.class +) +public abstract class AutoBindKtorfitApiService { + private AutoBindKtorfitApiService() { + } + + @Provides + @Singleton + public static ApiService provideApiService(Ktorfit ktorfit) { + return ktorfit.create(null); + } +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/ksp/AutoBindKtorfitApiService.kt.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/ksp/AutoBindKtorfitApiService.kt.txt new file mode 100644 index 000000000..c28c5fe01 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/scoped/ksp/AutoBindKtorfitApiService.kt.txt @@ -0,0 +1,19 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.scoped + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.codegen.OriginatingElement +import dagger.hilt.components.SingletonComponent +import de.jensklingenberg.ktorfit.Ktorfit +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +@OriginatingElement(topLevelClass = ApiService::class) +public object AutoBindKtorfitApiService { + @Provides + @Singleton + public fun provideApiService(ktorfit: Ktorfit): ApiService = ktorfit.create() +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/ApiService.kt b/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/ApiService.kt new file mode 100644 index 000000000..d7d628c49 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/ApiService.kt @@ -0,0 +1,10 @@ +package tests.ktorfit.simple + +import de.jensklingenberg.ktorfit.http.GET +import se.ansman.dagger.auto.ktorfit.AutoProvideService + +@AutoProvideService +interface ApiService { + @GET("users") + suspend fun getUsers(): List +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/kapt/AutoBindKtorfitApiService.java.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/kapt/AutoBindKtorfitApiService.java.txt new file mode 100644 index 000000000..69891b705 --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/kapt/AutoBindKtorfitApiService.java.txt @@ -0,0 +1,24 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.simple; + +import dagger.Module; +import dagger.Provides; +import dagger.hilt.InstallIn; +import dagger.hilt.codegen.OriginatingElement; +import dagger.hilt.components.SingletonComponent; +import de.jensklingenberg.ktorfit.Ktorfit; + +@Module +@InstallIn(SingletonComponent.class) +@OriginatingElement( + topLevelClass = ApiService.class +) +public abstract class AutoBindKtorfitApiService { + private AutoBindKtorfitApiService() { + } + + @Provides + public static ApiService provideApiService(Ktorfit ktorfit) { + return ktorfit.create(null); + } +} \ No newline at end of file diff --git a/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/ksp/AutoBindKtorfitApiService.kt.txt b/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/ksp/AutoBindKtorfitApiService.kt.txt new file mode 100644 index 000000000..ddce4fc0b --- /dev/null +++ b/third-party/ktorfit/src/test/resources/tests/ktorfit/simple/ksp/AutoBindKtorfitApiService.kt.txt @@ -0,0 +1,17 @@ +// Code generated by Auto Dagger. Do not edit. +package tests.ktorfit.simple + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.codegen.OriginatingElement +import dagger.hilt.components.SingletonComponent +import de.jensklingenberg.ktorfit.Ktorfit + +@Module +@InstallIn(SingletonComponent::class) +@OriginatingElement(topLevelClass = ApiService::class) +public object AutoBindKtorfitApiService { + @Provides + public fun provideApiService(ktorfit: Ktorfit): ApiService = ktorfit.create() +} \ No newline at end of file diff --git a/third-party/retrofit/build.gradle.kts b/third-party/retrofit/build.gradle.kts index 1f68a6380..e3672168f 100644 --- a/third-party/retrofit/build.gradle.kts +++ b/third-party/retrofit/build.gradle.kts @@ -4,10 +4,6 @@ plugins { id("library.publishing") } -kotlin { - explicitApi() -} - dependencies { implementation(libs.dagger.hilt.core) testImplementation(testFixtures(projects.compiler)) diff --git a/update-expected-test-files.sh b/update-expected-test-files.sh index 64bb262a4..1df4d9f25 100755 --- a/update-expected-test-files.sh +++ b/update-expected-test-files.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -./gradlew --continue -q :compiler:cleanProcessTestResources :compiler:test -PupdateExpectedTestFiles=true \ No newline at end of file +./gradlew --continue -q cleanProcessTestResources test -PupdateExpectedTestFiles=true \ No newline at end of file