1 /* 2 * Copyright (C) 2022 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.functional.kotlinsrc.cycle 18 19 import dagger.Binds 20 import dagger.Component 21 import dagger.Lazy 22 import dagger.Module 23 import dagger.Provides 24 import dagger.Subcomponent 25 import dagger.multibindings.IntoMap 26 import dagger.multibindings.StringKey 27 import javax.inject.Inject 28 import javax.inject.Provider 29 import kotlin.jvm.JvmSuppressWildcards 30 31 /** 32 * Cycle classes used for testing cyclic dependencies. 33 * 34 * `A <= (E <= D <= B <= C <= Provider<A>, Lazy<A>), (B <= C <= Provider<A>, Lazy<A>)` 35 * `S <= Provider<S>, Lazy<S>` 36 */ 37 @Suppress("BadInject") 38 class Cycles private constructor() { 39 class A @Inject constructor(val e: E, val b: B) 40 class B @Inject constructor(val c: C) 41 class C @Inject constructor(val aProvider: Provider<A>) { 42 @Inject lateinit var aLazy: Lazy<A> 43 @Inject lateinit var aLazyProvider: Provider<Lazy<A>> 44 } 45 class D @Inject constructor(val b: B) 46 class E @Inject constructor(val d: D) 47 class S @Inject constructor(val sProvider: Provider<S>) { 48 @Inject lateinit var sLazy: Lazy<S> 49 } 50 class X @Inject constructor(val y: Y) 51 class Y @Inject constructor( 52 val mapOfProvidersOfX: Map<String, @JvmSuppressWildcards Provider<X>>, 53 val mapOfProvidersOfY: Map<String, @JvmSuppressWildcards Provider<Y>> 54 ) 55 56 @Module 57 internal abstract class CycleMapModule { 58 @Binds 59 @IntoMap 60 @StringKey("X") xnull61 abstract fun x(x: X): X 62 63 @Binds 64 @IntoMap 65 @StringKey("Y") 66 abstract fun y(y: Y): Y 67 } 68 69 @Component(modules = [CycleMapModule::class]) 70 interface CycleMapComponent { 71 fun y(): Y 72 } 73 74 @Component(modules = [CycleModule::class]) 75 interface CycleComponent { anull76 fun a(): A 77 fun c(): C 78 fun child(): ChildCycleComponent 79 } 80 81 @Module 82 internal object CycleModule { 83 @Provides 84 fun provideObjectWithCycle( 85 @Suppress("UNUSED_PARAMETER") someObject: Provider<Any> 86 ): Any = "object" 87 } 88 89 @Component 90 interface SelfCycleComponent { snull91 fun s(): S 92 } 93 94 @Subcomponent 95 interface ChildCycleComponent { 96 fun a(): A 97 fun someObject(): Any 98 } 99 100 interface Foo 101 class Bar @Inject constructor( 102 @Suppress("UNUSED_PARAMETER") fooProvider: Provider<Foo> 103 ) : Foo 104 105 /** 106 * A component with a cycle in which a `@Binds` binding depends on the binding that has to be 107 * deferred. 108 */ 109 @Component(modules = [BindsCycleModule::class]) 110 interface BindsCycleComponent { barnull111 fun bar(): Bar 112 } 113 114 @Module 115 internal abstract class BindsCycleModule { 116 @Binds abstract fun foo(bar: Bar): Foo 117 } 118 } 119