Skip to content

Commit

Permalink
#1968: public roots mode for bootstrap injector
Browse files Browse the repository at this point in the history
  • Loading branch information
pshirshov committed Aug 8, 2024
1 parent a202a0d commit e0d32e5
Show file tree
Hide file tree
Showing 35 changed files with 260 additions and 301 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import izumi.fundamentals.collections.nonempty.NEList
trait Planner {
def plan(input: PlannerInput): Either[NEList[DIError], Plan]

@inline final def plan(bindings: ModuleBase, activation: Activation, roots: Roots, locatorPrivacy: LocatorPrivacy): Either[NEList[DIError], Plan] = {
plan(PlannerInput(bindings, activation, roots, locatorPrivacy))
}

@inline final def plan(bindings: ModuleBase, roots: Roots): Either[NEList[DIError], Plan] = {
plan(bindings, Activation.empty, roots, LocatorPrivacy.PublicByDefault)
@inline final def plan(
bindings: ModuleBase,
roots: Roots,
activation: Activation = Activation.empty,
locatorPrivacy: LocatorPrivacy = LocatorPrivacy.PublicByDefault,
): Either[NEList[DIError], Plan] = {
plan(PlannerInput(bindings, roots, activation, locatorPrivacy))
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,59 +21,64 @@ import izumi.reflect.Tag
* On [[izumi.distage.model.plan.Roots.Everything]] garbage collection will not be performed – that would be equivalent to
* designating _all_ DIKeys as roots.
*/
final case class PlannerInput(
bindings: ModuleBase,
activation: Activation,
roots: Roots,
locatorPrivacy: LocatorPrivacy,
)
final case class PlannerInput(bindings: ModuleBase, roots: Roots, activation: Activation, locatorPrivacy: LocatorPrivacy)

object PlannerInput {
private val DefaultPrivacy = LocatorPrivacy.PublicByDefault

implicit class PlannerInputSyntax(private val input: PlannerInput) extends AnyVal {
def privateByDefault: PlannerInput = input.copy(locatorPrivacy = LocatorPrivacy.PrivateByDefault)
def publicByDefault: PlannerInput = input.copy(locatorPrivacy = LocatorPrivacy.PublicByDefault)
def withLocatorPrivacy(privacy: LocatorPrivacy): PlannerInput = input.copy(locatorPrivacy = privacy)
def privateByDefault: PlannerInput = withLocatorPrivacy(LocatorPrivacy.PrivateByDefault)
def publicByDefault: PlannerInput = withLocatorPrivacy(LocatorPrivacy.PublicByDefault)

def withActivation(activation: Activation): PlannerInput = input.copy(activation = activation)
def emptyActivation: PlannerInput = withActivation(Activation.empty)
}

def apply(bindings: ModuleBase, activation: Activation, roots: Roots): PlannerInput = PlannerInput(bindings, activation, roots, LocatorPrivacy.PublicByDefault)
/**
* Instantiate `roots` and the dependencies of `roots`, discarding bindings that are unrelated.
def apply(bindings: ModuleBase, roots: Roots, activation: Activation = Activation.empty, locatorPrivacy: LocatorPrivacy = DefaultPrivacy): PlannerInput =
new PlannerInput(bindings, roots, activation, locatorPrivacy)

/** Instantiate `T` and the dependencies of `T`, discarding bindings that are unrelated.
*
* Effectively, this selects and creates a *sub-graph* of the largest possible object graph that can be described by `bindings`
*/
def apply(bindings: ModuleBase, activation: Activation, roots: NESet[? <: DIKey]): PlannerInput =
PlannerInput(bindings, activation, Roots(roots), LocatorPrivacy.PublicByDefault)
def target[T: Tag](bindings: ModuleBase): PlannerInput =
PlannerInput(bindings, Roots.target[T], Activation.empty, DefaultPrivacy)

/**
* Instantiate `roots` and the dependencies of `roots`, discarding bindings that are unrelated.
/** Instantiate `T @Id(name)` and the dependencies of `T @Id(name)`, discarding bindings that are unrelated.
*
* Effectively, this selects and creates a *sub-graph* of the largest possible object graph that can be described by `bindings`
*
* @see [[izumi.distage.model.definition.Id @Id annotation]]
*/
def apply(bindings: ModuleBase, activation: Activation, roots: Set[? <: DIKey])(implicit d: DummyImplicit): PlannerInput =
PlannerInput(bindings, activation, Roots(roots), LocatorPrivacy.PublicByDefault)
def target[T: Tag](name: String)(bindings: ModuleBase): PlannerInput =
PlannerInput(bindings, Roots.target[T](name), Activation.empty, DefaultPrivacy)

/** Instantiate `root`, `roots` and their dependencies, discarding bindings that are unrelated.
/** Disable all dependency pruning. Every binding in `bindings` will be instantiated, without selection of the root components. There's almost always a better way to model things though. */
def everything(bindings: ModuleBase, activation: Activation = Activation.empty, locatorPrivacy: LocatorPrivacy = DefaultPrivacy): PlannerInput =
PlannerInput(bindings, Roots.Everything, activation, locatorPrivacy)

/**
* Instantiate `roots` and the dependencies of `roots`, discarding bindings that are unrelated.
*
* Effectively, this selects and creates a *sub-graph* of the largest possible object graph that can be described by `bindings`
*/
def apply(bindings: ModuleBase, activation: Activation, root: DIKey, roots: DIKey*): PlannerInput =
PlannerInput(bindings, activation, Roots(root, roots*), LocatorPrivacy.PublicByDefault)
def apply(bindings: ModuleBase, roots: NESet[? <: DIKey], activation: Activation): PlannerInput =
PlannerInput(bindings, Roots(roots), activation, DefaultPrivacy)

/** Instantiate `T` and the dependencies of `T`, discarding bindings that are unrelated.
/**
* Instantiate `roots` and the dependencies of `roots`, discarding bindings that are unrelated.
*
* Effectively, this selects and creates a *sub-graph* of the largest possible object graph that can be described by `bindings`
*/
def target[T: Tag](bindings: ModuleBase, activation: Activation): PlannerInput = PlannerInput(bindings, activation, DIKey.get[T])
def apply(bindings: ModuleBase, roots: Set[? <: DIKey], activation: Activation)(implicit d: DummyImplicit): PlannerInput =
PlannerInput(bindings, Roots(roots), activation, DefaultPrivacy)

/** Instantiate `T @Id(name)` and the dependencies of `T @Id(name)`, discarding bindings that are unrelated.
/** Instantiate `root`, `roots` and their dependencies, discarding bindings that are unrelated.
*
* Effectively, this selects and creates a *sub-graph* of the largest possible object graph that can be described by `bindings`
*
* @see [[izumi.distage.model.definition.Id @Id annotation]]
*/
def target[T: Tag](name: String)(bindings: ModuleBase, activation: Activation): PlannerInput = PlannerInput(bindings, activation, DIKey.get[T].named(name))
def apply(bindings: ModuleBase, activation: Activation, root: DIKey, roots: DIKey*): PlannerInput =
PlannerInput(bindings, Roots(root, roots*), activation, DefaultPrivacy)

/** Disable all dependency pruning. Every binding in `bindings` will be instantiated, without selection of the root components. There's almost always a better way to model things though. */
def everything(bindings: ModuleBase, activation: Activation = Activation.empty): PlannerInput =
PlannerInput(bindings, activation, Roots.Everything, LocatorPrivacy.PublicByDefault)
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ trait LocatorDef extends AbstractLocator with AbstractBindingDefDSL[LocatorDef.B
val nodes = ops.map(op => (op._1.target, op._1))
Plan(
DG(s, s.transposed, GraphMeta(nodes.toMap)),
PlannerInput(Module.make(ops.map(_._2).toSet), Activation.empty, Roots.Everything, LocatorPrivacy.PublicByDefault),
PlannerInput(Module.make(ops.map(_._2).toSet), Roots.Everything, Activation.empty, LocatorPrivacy.PublicByDefault),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import izumi.distage.model.definition.*
import izumi.distage.model.definition.Binding.{EmptySetBinding, ImplBinding, SetElementBinding, SingletonBinding}
import izumi.distage.model.definition.dsl.AbstractBindingDefDSL.*
import izumi.distage.model.definition.dsl.AbstractBindingDefDSL.SetElementInstruction.ElementAddTags
import izumi.distage.model.definition.dsl.AbstractBindingDefDSL.SetInstruction.{AddTagsAll, SetIdAll}
import izumi.distage.model.definition.dsl.AbstractBindingDefDSL.SetInstruction.{AddTagOntoSet, SetIdAll}
import izumi.distage.model.definition.dsl.AbstractBindingDefDSL.SingletonInstruction.*
import izumi.distage.model.exceptions.dsl.InvalidFunctoidModifier
import izumi.distage.model.providers.Functoid
import izumi.distage.model.reflection.{DIKey, MultiSetImplId}
import izumi.distage.model.reflection.SetKeyMeta
import izumi.distage.model.reflection.{DIKey, MultiSetImplId, SetKeyMeta}
import izumi.fundamentals.platform.language.{CodePositionMaterializer, SourceFilePosition}
import izumi.reflect.Tag

Expand Down Expand Up @@ -448,7 +447,7 @@ object AbstractBindingDefDSL {
val emptySetBinding = setOps.foldLeft(initial: EmptySetBinding[DIKey.BasicKey]) {
(b, instr) =>
instr match {
case AddTagsAll(tags) => b.addTags(tags)
case AddTagOntoSet(tags) => b.addTags(tags)
case SetIdAll(id) => b.withTarget(DIKey.TypeKey(b.key.tpe).named(id))
}
}
Expand Down Expand Up @@ -564,7 +563,7 @@ object AbstractBindingDefDSL {

sealed trait SetInstruction
object SetInstruction {
final case class AddTagsAll(tags: Set[BindingTag]) extends SetInstruction
final case class AddTagOntoSet(tags: Set[BindingTag]) extends SetInstruction
final case class SetIdAll(id: Identifier) extends SetInstruction
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,8 @@ object ModuleDefDSL {
"modifyBy",
"addDependency",
"addDependencies",
"exposed",
"confined",
)

final class MakeDSL[T](
Expand Down Expand Up @@ -785,8 +787,11 @@ object ModuleDefDSL {

final class SetDSL[T](
protected val mutableState: SetRef
) extends SetDSLMutBase[T] {

) extends SetDSLMutBase[T]
with Tagging[SetDSL[T]] {
def tagged(tags: BindingTag*): SetDSL[T] = {
addOp(SetInstruction.AddTagOntoSet(tags.toSet))(new SetDSL[T](_))
}
def named(name: Identifier): SetNamedDSL[T] = {
addOp(SetInstruction.SetIdAll(name))(new SetNamedDSL[T](_))
}
Expand All @@ -796,6 +801,11 @@ object ModuleDefDSL {
final class SetNamedDSL[T](
override protected val mutableState: SetRef
) extends SetDSLMutBase[T]
with Tagging[SetNamedDSL[T]] {
def tagged(tags: BindingTag*): SetNamedDSL[T] = {
addOp(SetInstruction.AddTagOntoSet(tags.toSet))(new SetNamedDSL[T](_))
}
}

final class SetElementDSL[T](
override protected val mutableState: SetRef,
Expand Down
Loading

0 comments on commit e0d32e5

Please sign in to comment.