/*
* Copyright (C) 2022 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dagger.functional.kotlinsrc.cycle
import dagger.Binds
import dagger.Component
import dagger.Lazy
import dagger.Module
import dagger.Provides
import dagger.Subcomponent
import dagger.multibindings.IntoMap
import dagger.multibindings.StringKey
import javax.inject.Inject
import javax.inject.Provider
import kotlin.jvm.JvmSuppressWildcards
/**
* Cycle classes used for testing cyclic dependencies.
*
* `A <= (E <= D <= B <= C <= Provider, Lazy), (B <= C <= Provider, Lazy)`
* `S <= Provider, Lazy`
*/
@Suppress("BadInject")
class Cycles private constructor() {
class A @Inject constructor(val e: E, val b: B)
class B @Inject constructor(val c: C)
class C @Inject constructor(val aProvider: Provider) {
@Inject lateinit var aLazy: Lazy
@Inject lateinit var aLazyProvider: Provider>
}
class D @Inject constructor(val b: B)
class E @Inject constructor(val d: D)
class S @Inject constructor(val sProvider: Provider) {
@Inject lateinit var sLazy: Lazy
}
class X @Inject constructor(val y: Y)
class Y @Inject constructor(
val mapOfProvidersOfX: Map>,
val mapOfProvidersOfY: Map>
)
@Module
internal abstract class CycleMapModule {
@Binds
@IntoMap
@StringKey("X")
abstract fun x(x: X): X
@Binds
@IntoMap
@StringKey("Y")
abstract fun y(y: Y): Y
}
@Component(modules = [CycleMapModule::class])
interface CycleMapComponent {
fun y(): Y
}
@Component(modules = [CycleModule::class])
interface CycleComponent {
fun a(): A
fun c(): C
fun child(): ChildCycleComponent
}
@Module
internal object CycleModule {
@Provides
fun provideObjectWithCycle(
@Suppress("UNUSED_PARAMETER") someObject: Provider
): Any = "object"
}
@Component
interface SelfCycleComponent {
fun s(): S
}
@Subcomponent
interface ChildCycleComponent {
fun a(): A
fun someObject(): Any
}
interface Foo
class Bar @Inject constructor(
@Suppress("UNUSED_PARAMETER") fooProvider: Provider
) : Foo
/**
* A component with a cycle in which a `@Binds` binding depends on the binding that has to be
* deferred.
*/
@Component(modules = [BindsCycleModule::class])
interface BindsCycleComponent {
fun bar(): Bar
}
@Module
internal abstract class BindsCycleModule {
@Binds abstract fun foo(bar: Bar): Foo
}
}