wvlet.airframe.AirframeMacros.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of airframe_2.11 Show documentation
Show all versions of airframe_2.11 Show documentation
Dependency injection library tailored to Scala
The newest version!
/*
* 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 wvlet.airframe
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
import scala.reflect.macros.{blackbox => sm}
private[wvlet] object AirframeMacros {
private[wvlet] class BindHelper[C <: Context](val c: C) {
import c.universe._
def shouldGenerateTrait(t: c.Type): Boolean = {
val a = t.typeSymbol
// Find the public default constructor that has no arguments
val hasPublicDefaultConstructor = t.members
.find(_.isConstructor)
.map(_.asMethod).exists { m => m.isPublic && m.paramLists.size == 1 && m.paramLists(0).size == 0 }
val hasAbstractMethods = t.members.exists(x => x.isMethod && x.isAbstract && !x.isAbstractOverride)
val isTaggedType = t.typeSymbol.fullName.startsWith("wvlet.airframe.surface.tag.")
val isSealedType = t.typeSymbol.isClass && t.typeSymbol.asClass.isSealed
val shouldInstantiateTrait = if (!a.isStatic) {
// = Non static type
// If X is non static type (= local class or trait),
// we need to instantiate it first in order to populate its $outer variables
// We cannot instantiate path-dependent types
if (t.toString.contains("#")) {
false
} else {
hasPublicDefaultConstructor
}
} else if (a.isAbstract) {
// = Abstract type
// We cannot build abstract type X that has abstract methods, so bind[X].to[ConcreteType]
// needs to be found in the design
// If there is no abstract methods, it might be a trait without any method
!hasAbstractMethods
} else {
// We cannot instantiate any trait or class without the default constructor
// So binding needs to be found in the Design.
hasPublicDefaultConstructor
}
// Tagged type or sealed class binding should be found in Design
!isTaggedType && !isSealedType && shouldInstantiateTrait
}
def bind(session: c.Tree, t: c.Type): c.Tree = {
q"""{
val session = ${session}
${newInstanceBinder(t)}(session)
}"""
}
def findSession: c.Tree = {
q"""wvlet.airframe.Session.findSession(this)"""
}
def newInstanceBinder(t: c.Type): c.Tree = {
if (shouldGenerateTrait(t)) {
q"""{
ss : wvlet.airframe.Session =>
ss.getOrElse(${surfaceOf(t)},
(new $t with wvlet.airframe.DISupport { def session = ss }).asInstanceOf[$t]
)
}"""
} else {
q"""{ session : wvlet.airframe.Session => session.get[$t](${surfaceOf(t)}) }"""
}
}
def createNewInstanceOf(t: c.Type): c.Tree = {
if (shouldGenerateTrait(t)) {
q"""{
ss : wvlet.airframe.Session =>
ss.createNewInstanceOf(${surfaceOf(t)},
(new $t with wvlet.airframe.DISupport { def session = ss }).asInstanceOf[$t]
)
}"""
} else {
q"""{ session : wvlet.airframe.Session => session.createNewInstanceOf[$t](${surfaceOf(t)}) }"""
}
}
/**
* Register a factory for generating a trait that can embed the current session.
* This step is necessary for instantiating trait, which has no default constructor.
*
* This method will return the surface of t
*/
def registerTraitFactory(t: c.Type): c.Tree = {
if (shouldGenerateTrait(t)) {
q""" {
val s = ${surfaceOf(t)}
wvlet.airframe.getOrElseUpdateTraitFactoryCache(s,
{ ss: wvlet.airframe.Session => (new $t with wvlet.airframe.DISupport { def session = ss }).asInstanceOf[Any] }
)
s
}
"""
} else {
q"""{${surfaceOf(t)}}"""
}
}
def surfaceOf(t: c.Type): c.Tree = {
q"wvlet.airframe.surface.Surface.of[$t]"
}
def provider1Binding[A: c.WeakTypeTag, D1: c.WeakTypeTag](
factory: c.Tree,
singleton: Boolean,
eager: Boolean
): c.Tree = {
val t = implicitly[c.WeakTypeTag[A]].tpe
val ev1 = implicitly[c.WeakTypeTag[D1]].tpe
q"""{
val self = ${c.prefix.tree}
val d1 = ${registerTraitFactory(ev1)}
import wvlet.airframe.Binder._
self.design.addBinding[${t}](ProviderBinding(DependencyFactory(self.from, Seq(d1), ${factory}), ${singleton}, ${eager}, self.sourceCode))
}
"""
}
def provider2Binding[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag](
factory: c.Tree,
singleton: Boolean,
eager: Boolean
): c.Tree = {
val t = implicitly[c.WeakTypeTag[A]].tpe
val ev1 = implicitly[c.WeakTypeTag[D1]].tpe
val ev2 = implicitly[c.WeakTypeTag[D2]].tpe
q"""{
val self = ${c.prefix.tree}
val d1 = ${registerTraitFactory(ev1)}
val d2 = ${registerTraitFactory(ev2)}
import wvlet.airframe.Binder._
self.design.addBinding[${t}](ProviderBinding(DependencyFactory(self.from, Seq(d1, d2), ${factory}), ${singleton}, ${eager}, self.sourceCode))
}
"""
}
def provider3Binding[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag](
factory: c.Tree,
singleton: Boolean,
eager: Boolean
): c.Tree = {
val t = implicitly[c.WeakTypeTag[A]].tpe
val ev1 = implicitly[c.WeakTypeTag[D1]].tpe
val ev2 = implicitly[c.WeakTypeTag[D2]].tpe
val ev3 = implicitly[c.WeakTypeTag[D3]].tpe
q"""{
val self = ${c.prefix.tree}
val d1 = ${registerTraitFactory(ev1)}
val d2 = ${registerTraitFactory(ev2)}
val d3 = ${registerTraitFactory(ev3)}
import wvlet.airframe.Binder._
self.design.addBinding[${t}](ProviderBinding(DependencyFactory(self.from, Seq(d1, d2, d3), ${factory}), ${singleton}, ${eager}, self.sourceCode))
}
"""
}
def provider4Binding[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag, D4: c.WeakTypeTag](
factory: c.Tree,
singleton: Boolean,
eager: Boolean
): c.Tree = {
val t = implicitly[c.WeakTypeTag[A]].tpe
val ev1 = implicitly[c.WeakTypeTag[D1]].tpe
val ev2 = implicitly[c.WeakTypeTag[D2]].tpe
val ev3 = implicitly[c.WeakTypeTag[D3]].tpe
val ev4 = implicitly[c.WeakTypeTag[D4]].tpe
q"""{
val self = ${c.prefix.tree}
val d1 = ${registerTraitFactory(ev1)}
val d2 = ${registerTraitFactory(ev2)}
val d3 = ${registerTraitFactory(ev3)}
val d4 = ${registerTraitFactory(ev4)}
import wvlet.airframe.Binder._
self.design.addBinding[${t}](ProviderBinding(DependencyFactory(self.from, Seq(d1, d2, d3, d4), ${factory}), ${singleton}, ${eager}, self.sourceCode))
}
"""
}
def provider5Binding[
A: c.WeakTypeTag,
D1: c.WeakTypeTag,
D2: c.WeakTypeTag,
D3: c.WeakTypeTag,
D4: c.WeakTypeTag,
D5: c.WeakTypeTag
](
factory: c.Tree,
singleton: Boolean,
eager: Boolean
): c.Tree = {
val t = implicitly[c.WeakTypeTag[A]].tpe
val ev1 = implicitly[c.WeakTypeTag[D1]].tpe
val ev2 = implicitly[c.WeakTypeTag[D2]].tpe
val ev3 = implicitly[c.WeakTypeTag[D3]].tpe
val ev4 = implicitly[c.WeakTypeTag[D4]].tpe
val ev5 = implicitly[c.WeakTypeTag[D5]].tpe
q"""{
val self = ${c.prefix.tree}
val d1 = ${registerTraitFactory(ev1)}
val d2 = ${registerTraitFactory(ev2)}
val d3 = ${registerTraitFactory(ev3)}
val d4 = ${registerTraitFactory(ev4)}
val d5 = ${registerTraitFactory(ev5)}
import wvlet.airframe.Binder._
self.design.addBinding[${t}](ProviderBinding(DependencyFactory(self.from, Seq(d1, d2, d3, d4, d5), ${factory}), ${singleton}, ${eager}, self.sourceCode))
}
"""
}
def fullTypeNameOf(typeEv: c.Type): String = {
typeEv match {
case TypeRef(prefix, typeSymbol, args) =>
if (args.isEmpty) {
typeSymbol.fullName
} else {
val typeArgs = args.map(fullTypeNameOf(_)).mkString(",")
s"${typeSymbol.fullName}[${typeArgs}]"
}
case other =>
typeEv.typeSymbol.fullName
}
}
}
def registerTraitFactoryImpl[A: c.WeakTypeTag](c: sm.Context): c.Tree = {
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
h.registerTraitFactory(t)
}
def designBindImpl[A: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val __surface = ${h.registerTraitFactory(t)}
new wvlet.airframe.Binder(${c.prefix}, __surface, ${sourceCode(c)}).asInstanceOf[wvlet.airframe.Binder[$t]]
}"""
}
def designRemoveImpl[A: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val d = ${c.prefix}
val target = ${h.surfaceOf(t)}
new wvlet.airframe.Design(d.designOptions, d.binding.filterNot(_.from == target), d.hooks)
}
"""
}
def binderToImpl[B: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[B]].tpe
val h = new BindHelper[c.type](c)
q""" {
val self = ${c.prefix}
val to = ${h.registerTraitFactory(t)}
self.design.addBinding[${t}](wvlet.airframe.Binder.ClassBinding(self.from, to, self.sourceCode))
}"""
}
def binderToSingletonOfImpl[B: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[B]].tpe
val h = new BindHelper[c.type](c)
q""" {
val self = ${c.prefix.tree}
val to = ${h.registerTraitFactory(t)}
if(self.from == to) {
wvlet.log.Logger("wvlet.airframe.Binder").warn("Binding to the same type is not allowed: " + to.toString)
throw new wvlet.airframe.AirframeException.CYCLIC_DEPENDENCY(List(to), ${sourceCode(c)})
}
self.design.addBinding[${t}](wvlet.airframe.Binder.SingletonBinding(self.from, to, false, self.sourceCode))
}"""
}
def binderToEagerSingletonOfImpl[B: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[B]].tpe
val h = new BindHelper[c.type](c)
q""" {
val self = ${c.prefix.tree}
val to = ${h.registerTraitFactory(t)}
if(self.from == to) {
wvlet.log.Logger("wvlet.airframe.Binder").warn("Binding to the same type is not allowed: " + to.toString)
throw new wvlet.airframe.AirframeException.CYCLIC_DEPENDENCY(List(to), ${sourceCode(c)})
}
self.design.addBinding[${t}](wvlet.airframe.Binder.SingletonBinding(self.from, to, true, self.sourceCode))
}"""
}
def bindToProvider1[A: c.WeakTypeTag, D1: c.WeakTypeTag](c: sm.Context)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider1Binding[A, D1](factory, false, false)
}
def bindToProvider2[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider2Binding[A, D1, D2](factory, false, false)
}
def bindToProvider3[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider3Binding[A, D1, D2, D3](factory, false, false)
}
def bindToProvider4[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag, D4: c.WeakTypeTag](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider4Binding[A, D1, D2, D3, D4](factory, false, false)
}
def bindToProvider5[
A: c.WeakTypeTag,
D1: c.WeakTypeTag,
D2: c.WeakTypeTag,
D3: c.WeakTypeTag,
D4: c.WeakTypeTag,
D5: c.WeakTypeTag
](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider5Binding[A, D1, D2, D3, D4, D5](factory, false, false)
}
def bindToSingletonProvider1[A: c.WeakTypeTag, D1: c.WeakTypeTag](c: sm.Context)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider1Binding[A, D1](factory, true, false)
}
def bindToSingletonProvider2[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider2Binding[A, D1, D2](factory, true, false)
}
def bindToSingletonProvider3[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider3Binding[A, D1, D2, D3](factory, true, false)
}
def bindToSingletonProvider4[
A: c.WeakTypeTag,
D1: c.WeakTypeTag,
D2: c.WeakTypeTag,
D3: c.WeakTypeTag,
D4: c.WeakTypeTag
](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider4Binding[A, D1, D2, D3, D4](factory, true, false)
}
def bindToSingletonProvider5[
A: c.WeakTypeTag,
D1: c.WeakTypeTag,
D2: c.WeakTypeTag,
D3: c.WeakTypeTag,
D4: c.WeakTypeTag,
D5: c.WeakTypeTag
](c: sm.Context)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider5Binding[A, D1, D2, D3, D4, D5](factory, true, false)
}
def bindToEagerSingletonProvider1[A: c.WeakTypeTag, D1: c.WeakTypeTag](c: sm.Context)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider1Binding[A, D1](factory, true, true)
}
def bindToEagerSingletonProvider2[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider2Binding[A, D1, D2](factory, true, true)
}
def bindToEagerSingletonProvider3[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider3Binding[A, D1, D2, D3](factory, true, true)
}
def bindToEagerSingletonProvider4[
A: c.WeakTypeTag,
D1: c.WeakTypeTag,
D2: c.WeakTypeTag,
D3: c.WeakTypeTag,
D4: c.WeakTypeTag
](
c: sm.Context
)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider4Binding[A, D1, D2, D3, D4](factory, true, true)
}
def bindToEagerSingletonProvider5[
A: c.WeakTypeTag,
D1: c.WeakTypeTag,
D2: c.WeakTypeTag,
D3: c.WeakTypeTag,
D4: c.WeakTypeTag,
D5: c.WeakTypeTag
](c: sm.Context)(factory: c.Tree): c.Tree = {
val h = new BindHelper[c.type](c)
h.provider5Binding[A, D1, D2, D3, D4, D5](factory, true, true)
}
/**
* Used when Session location is known
*
* @param c
* @tparam A
* @return
*/
def buildImpl[A: c.WeakTypeTag](c: sm.Context): c.Tree = {
val t = implicitly[c.WeakTypeTag[A]].tpe
new BindHelper[c.type](c).bind(c.prefix.tree, t)
}
def buildWithSession[A: c.WeakTypeTag](c: sm.Context)(body: c.Expr[A => Any]): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
// Bind the code block to a local variable to resolve the issue #373
val e = q"""
{
val codeBlock = ${body}
(${c.prefix}).withSession { session =>
val a = session.build[${t}]
codeBlock(a)
}
}
"""
e
}
def runWithSession[A: c.WeakTypeTag, B: c.WeakTypeTag](c: sm.Context)(body: c.Expr[A => B]): c.Tree = {
import c.universe._
val a = implicitly[c.WeakTypeTag[A]].tpe
val b = implicitly[c.WeakTypeTag[B]].tpe
// Bind the code block to a local variable to resolve the issue #373
val e = q"""
{
val codeBlock = ${body}
(${c.prefix}).withSession { session =>
val a = session.build[${a}]
codeBlock(a)
}
}.asInstanceOf[${b}]
"""
e
}
def addLifeCycle[A: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val session = ${h.findSession}
new wvlet.airframe.LifeCycleBinder(${c.prefix}.dep, ${h.surfaceOf(t)}, session)
}
"""
}
def addInitLifeCycle[A: c.WeakTypeTag](c: sm.Context)(body: c.Tree): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val session = ${h.findSession}
val dep = ${c.prefix}.dep
session.lifeCycleManager.addInitHook(wvlet.airframe.lifecycle.EventHookHolder(${h.surfaceOf(t)}, dep, ${body}))
dep
}
"""
}
def addInjectLifeCycle[A: c.WeakTypeTag](c: sm.Context)(body: c.Tree): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val session = ${h.findSession}
val dep = ${c.prefix}.dep
session.lifeCycleManager.addInjectHook(wvlet.airframe.lifecycle.EventHookHolder(${h.surfaceOf(t)}, dep, ${body}))
dep
}
"""
}
def addStartLifeCycle[A: c.WeakTypeTag](c: sm.Context)(body: c.Tree): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val session = ${h.findSession}
val dep = ${c.prefix}.dep
session.lifeCycleManager.addStartHook(wvlet.airframe.lifecycle.EventHookHolder(${h.surfaceOf(t)}, dep, ${body}))
dep
}
"""
}
def addStartLifeCycleForFactory[F: c.WeakTypeTag](c: sm.Context)(body: c.Tree): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[F]].tpe
val i1 = t.typeArgs(0)
val a = t.typeArgs(1)
val h = new BindHelper[c.type](c)
q"""{
val session = ${h.findSession}
val dep = ${c.prefix}.dep
session.lifeCycleManager.addStartHook(wvlet.airframe.lifecycle.EventHookHolder(${h.surfaceOf(t)}, dep, ${body}))
dep
}
"""
}
def addPreShutdownLifeCycle[A: c.WeakTypeTag](c: sm.Context)(body: c.Tree): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val session = ${h.findSession}
val dep = ${c.prefix}.dep
session.lifeCycleManager.addPreShutdownHook(wvlet.airframe.lifecycle.EventHookHolder(${h.surfaceOf(t)}, dep, ${body}))
dep
}
"""
}
def addShutdownLifeCycle[A: c.WeakTypeTag](c: sm.Context)(body: c.Tree): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val session = ${h.findSession}
val dep = ${c.prefix}.dep
session.lifeCycleManager.addShutdownHook(wvlet.airframe.lifecycle.EventHookHolder(${h.surfaceOf(t)}, dep, ${body}))
dep
}
"""
}
def bindImpl[A: c.WeakTypeTag](c: sm.Context): c.Tree = {
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
h.bind(h.findSession, t)
}
def bind0Impl[A: c.WeakTypeTag](c: sm.Context)(provider: c.Tree): c.Tree = {
import c.universe._
val t = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val session = ${h.findSession}
session.getOrElse(${h.surfaceOf(t)}, $provider)
}
"""
}
def bind1Impl[A: c.WeakTypeTag, D1: c.WeakTypeTag](c: sm.Context)(provider: c.Tree): c.Tree = {
import c.universe._
val h = new BindHelper[c.type](c)
val t = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val dep1 = h.newInstanceBinder(d1)
q"""{
val session = ${h.findSession}
session.getOrElse(${h.surfaceOf(t)}, $provider($dep1(session)))
}
"""
}
def bind2Impl[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag](c: sm.Context)(provider: c.Tree): c.Tree = {
import c.universe._
val h = new BindHelper[c.type](c)
val t = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val d2 = implicitly[c.WeakTypeTag[D2]].tpe
val dep1 = h.newInstanceBinder(d1)
val dep2 = h.newInstanceBinder(d2)
q"""{
val session = ${h.findSession}
session.getOrElse(${h.surfaceOf(t)}, $provider($dep1(session), $dep2(session)))
}
"""
}
def bind3Impl[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag](
c: sm.Context
)(provider: c.Tree): c.Tree = {
import c.universe._
val h = new BindHelper[c.type](c)
val t = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val d2 = implicitly[c.WeakTypeTag[D2]].tpe
val d3 = implicitly[c.WeakTypeTag[D3]].tpe
val dep1 = h.newInstanceBinder(d1)
val dep2 = h.newInstanceBinder(d2)
val dep3 = h.newInstanceBinder(d3)
q"""{
val session = ${h.findSession}
session.getOrElse(${h.surfaceOf(t)}, $provider($dep1(session),$dep2(session),$dep3(session)))
}
"""
}
def bind4Impl[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag, D4: c.WeakTypeTag](
c: sm.Context
)(provider: c.Tree): c.Tree = {
import c.universe._
val h = new BindHelper[c.type](c)
val t = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val d2 = implicitly[c.WeakTypeTag[D2]].tpe
val d3 = implicitly[c.WeakTypeTag[D3]].tpe
val d4 = implicitly[c.WeakTypeTag[D4]].tpe
val dep1 = h.newInstanceBinder(d1)
val dep2 = h.newInstanceBinder(d2)
val dep3 = h.newInstanceBinder(d3)
val dep4 = h.newInstanceBinder(d4)
q"""{
val session = ${h.findSession}
session.getOrElse(${h.surfaceOf(t)},
$provider($dep1(session),$dep2(session),$dep3(session),$dep4(session))
)
}
"""
}
def bind5Impl[
A: c.WeakTypeTag,
D1: c.WeakTypeTag,
D2: c.WeakTypeTag,
D3: c.WeakTypeTag,
D4: c.WeakTypeTag,
D5: c.WeakTypeTag
](c: sm.Context)(provider: c.Tree): c.Tree = {
import c.universe._
val h = new BindHelper[c.type](c)
val t = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val d2 = implicitly[c.WeakTypeTag[D2]].tpe
val d3 = implicitly[c.WeakTypeTag[D3]].tpe
val d4 = implicitly[c.WeakTypeTag[D4]].tpe
val d5 = implicitly[c.WeakTypeTag[D5]].tpe
val dep1 = h.newInstanceBinder(d1)
val dep2 = h.newInstanceBinder(d2)
val dep3 = h.newInstanceBinder(d3)
val dep4 = h.newInstanceBinder(d4)
val dep5 = h.newInstanceBinder(d5)
q"""{
val session = ${h.findSession}
session.getOrElse(${h.surfaceOf(t)},
$provider($dep1(session),$dep2(session),$dep3(session),$dep4(session),$dep5(session))
)
}
"""
}
def bindLocal0Impl[A: c.WeakTypeTag](c: sm.Context)(provider: c.Tree): c.Tree = {
import c.universe._
val a = implicitly[c.WeakTypeTag[A]].tpe
val h = new BindHelper[c.type](c)
q"""{
val surface = ${h.surfaceOf(a)}
val session = ${h.findSession}
val newChildDesign = wvlet.airframe.newDesign.bind(surface).toLazyInstance(${provider})
val localSession = session.newSharedChildSession(newChildDesign)
localSession.get[$a](surface)
}
"""
}
def bindLocal1Impl[A: c.WeakTypeTag, D1: c.WeakTypeTag](c: sm.Context)(provider: c.Tree): c.Tree = {
import c.universe._
val a = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val h = new BindHelper[c.type](c)
val dep1 = h.newInstanceBinder(d1)
q"""{
val surface = ${h.surfaceOf(a)}
val session = ${h.findSession}
val newChildDesign = wvlet.airframe.newDesign.bind(surface).toLazyInstance($provider($dep1(session)))
val localSession = session.newSharedChildSession(newChildDesign)
localSession.get[$a](surface)
}
"""
}
def bindLocal2Impl[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag](
c: sm.Context
)(provider: c.Tree): c.Tree = {
import c.universe._
val a = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val d2 = implicitly[c.WeakTypeTag[D2]].tpe
val h = new BindHelper[c.type](c)
val dep1 = h.newInstanceBinder(d1)
val dep2 = h.newInstanceBinder(d2)
q"""{
val surface = ${h.surfaceOf(a)}
val session = ${h.findSession}
val newChildDesign = wvlet.airframe.newDesign.bind(surface).toLazyInstance($provider($dep1(session), $dep2(session)))
val localSession = session.newSharedChildSession(newChildDesign)
localSession.get[$a](surface)
}
"""
}
def bindLocal3Impl[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag](
c: sm.Context
)(provider: c.Tree): c.Tree = {
import c.universe._
val a = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val d2 = implicitly[c.WeakTypeTag[D2]].tpe
val d3 = implicitly[c.WeakTypeTag[D3]].tpe
val h = new BindHelper[c.type](c)
val dep1 = h.newInstanceBinder(d1)
val dep2 = h.newInstanceBinder(d2)
val dep3 = h.newInstanceBinder(d3)
q"""{
val surface = ${h.surfaceOf(a)}
val session = ${h.findSession}
val newChildDesign = wvlet.airframe.newDesign.bind(surface).toLazyInstance($provider($dep1(session), $dep2(session), $dep3(session)))
val localSession = session.newSharedChildSession(newChildDesign)
localSession.get[$a](surface)
}
"""
}
def bindLocal4Impl[A: c.WeakTypeTag, D1: c.WeakTypeTag, D2: c.WeakTypeTag, D3: c.WeakTypeTag, D4: c.WeakTypeTag](
c: sm.Context
)(provider: c.Tree): c.Tree = {
import c.universe._
val a = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val d2 = implicitly[c.WeakTypeTag[D2]].tpe
val d3 = implicitly[c.WeakTypeTag[D3]].tpe
val d4 = implicitly[c.WeakTypeTag[D4]].tpe
val h = new BindHelper[c.type](c)
val dep1 = h.newInstanceBinder(d1)
val dep2 = h.newInstanceBinder(d2)
val dep3 = h.newInstanceBinder(d3)
val dep4 = h.newInstanceBinder(d4)
q"""{
val surface = ${h.surfaceOf(a)}
val session = ${h.findSession}
val newChildDesign = wvlet.airframe.newDesign.bind(surface).toLazyInstance($provider($dep1(session), $dep2(session), $dep3(session), $dep4(session)))
val localSession = session.newSharedChildSession(newChildDesign)
localSession.get[$a](surface)
}
"""
}
def bindLocal5Impl[
A: c.WeakTypeTag,
D1: c.WeakTypeTag,
D2: c.WeakTypeTag,
D3: c.WeakTypeTag,
D4: c.WeakTypeTag,
D5: c.WeakTypeTag
](
c: sm.Context
)(provider: c.Tree): c.Tree = {
import c.universe._
val a = implicitly[c.WeakTypeTag[A]].tpe
val d1 = implicitly[c.WeakTypeTag[D1]].tpe
val d2 = implicitly[c.WeakTypeTag[D2]].tpe
val d3 = implicitly[c.WeakTypeTag[D3]].tpe
val d4 = implicitly[c.WeakTypeTag[D4]].tpe
val d5 = implicitly[c.WeakTypeTag[D5]].tpe
val h = new BindHelper[c.type](c)
val dep1 = h.newInstanceBinder(d1)
val dep2 = h.newInstanceBinder(d2)
val dep3 = h.newInstanceBinder(d3)
val dep4 = h.newInstanceBinder(d4)
val dep5 = h.newInstanceBinder(d5)
q"""{
val surface = ${h.surfaceOf(a)}
val session = ${h.findSession}
val newChildDesign = wvlet.airframe.newDesign.bind(surface).toLazyInstance($provider($dep1(session), $dep2(session), $dep3(session), $dep4(session), $dep5(session)))
val localSession = session.newSharedChildSession(newChildDesign)
localSession.get[$a](surface)
}
"""
}
def bindFactoryImpl[F: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
import scala.language.higherKinds
val t = implicitly[c.WeakTypeTag[F]].tpe // F = Function[I1, A]
val i1 = t.typeArgs(0) // I1
val a = t.typeArgs(1) // A
val h = new BindHelper[c.type](c)
q"""{ i1: ${i1} =>
val session = ${h.findSession}.newSharedChildSession(wvlet.airframe.newDesign.bind(${h.surfaceOf(i1)}).toLazyInstance(i1))
${h.createNewInstanceOf(a)}(session)
}
"""
}
def bindFactory2Impl[F: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
import scala.language.higherKinds
val t = implicitly[c.WeakTypeTag[F]].tpe // F = Function[(I1, I2), A]
val i1 = t.typeArgs(0) // I1
val i2 = t.typeArgs(1) // I2
val a = t.typeArgs(2) // A
val h = new BindHelper[c.type](c)
q"""{ (i1: ${i1}, i2: ${i2}) =>
val session = ${h.findSession}.newSharedChildSession(
wvlet.airframe.newDesign
.bind(${h.surfaceOf(i1)}).toLazyInstance(i1)
.bind(${h.surfaceOf(i2)}).toLazyInstance(i2)
)
${h.createNewInstanceOf(a)}(session)
}
"""
}
def bindFactory3Impl[F: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
import scala.language.higherKinds
val t = implicitly[c.WeakTypeTag[F]].tpe // F = Function[(I1, I2, I3), A]
val i1 = t.typeArgs(0) // I1
val i2 = t.typeArgs(1) // I2
val i3 = t.typeArgs(2) // I3
val a = t.typeArgs(3) // A
val h = new BindHelper[c.type](c)
q"""{ (i1: ${i1}, i2: ${i2}, i3:${i3}) =>
val session = ${h.findSession}.newSharedChildSession(
wvlet.airframe.newDesign
.bind(${h.surfaceOf(i1)}).toLazyInstance(i1)
.bind(${h.surfaceOf(i2)}).toLazyInstance(i2)
.bind(${h.surfaceOf(i3)}).toLazyInstance(i3)
)
${h.createNewInstanceOf(a)}(session)
}
"""
}
def bindFactory4Impl[F: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
import scala.language.higherKinds
val t = implicitly[c.WeakTypeTag[F]].tpe // F = Function[(I1, I2, I3, I4), A]
val i1 = t.typeArgs(0) // I1
val i2 = t.typeArgs(1) // I2
val i3 = t.typeArgs(2) // I3
val i4 = t.typeArgs(3) // I4
val a = t.typeArgs(4) // A
val h = new BindHelper[c.type](c)
q"""{ (i1: ${i1}, i2: ${i2}, i3:${i3}, i4:${i4}) =>
val session = ${h.findSession}.newSharedChildSession(
wvlet.airframe.newDesign
.bind(${h.surfaceOf(i1)}).toLazyInstance(i1)
.bind(${h.surfaceOf(i2)}).toLazyInstance(i2)
.bind(${h.surfaceOf(i3)}).toLazyInstance(i3)
.bind(${h.surfaceOf(i4)}).toLazyInstance(i4)
)
${h.createNewInstanceOf(a)}(session)
}
"""
}
def bindFactory5Impl[F: c.WeakTypeTag](c: sm.Context): c.Tree = {
import c.universe._
import scala.language.higherKinds
val t = implicitly[c.WeakTypeTag[F]].tpe // F = Function[(I1, I2, I3, I4, I4), A]
val i1 = t.typeArgs(0) // I1
val i2 = t.typeArgs(1) // I2
val i3 = t.typeArgs(2) // I3
val i4 = t.typeArgs(3) // I4
val i5 = t.typeArgs(4) // I5
val a = t.typeArgs(5) // A
val h = new BindHelper[c.type](c)
q"""{ (i1: ${i1}, i2: ${i2}, i3:${i3}, i4:${i4}, i5:${i5}) =>
val session = ${h.findSession}.newSharedChildSession(
wvlet.airframe.newDesign
.bind(${h.surfaceOf(i1)}).toLazyInstance(i1)
.bind(${h.surfaceOf(i2)}).toLazyInstance(i2)
.bind(${h.surfaceOf(i3)}).toLazyInstance(i3)
.bind(${h.surfaceOf(i4)}).toLazyInstance(i4)
.bind(${h.surfaceOf(i5)}).toLazyInstance(i5)
)
${h.createNewInstanceOf(a)}(session)
}
"""
}
def sourceCode(c: sm.Context): c.Tree = {
import c.universe._
c.internal.enclosingOwner
val pos = c.enclosingPosition
q"wvlet.airframe.SourceCode(${pos.source.path}, ${pos.source.file.name}, ${pos.line}, ${pos.column})"
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy