Skip to content

Commit

Permalink
Merge branch 'develop' into feature/scala3-recompilation-token
Browse files Browse the repository at this point in the history
  • Loading branch information
neko-kai committed Dec 6, 2023
2 parents 37916f5 + c1f1996 commit da711e1
Show file tree
Hide file tree
Showing 254 changed files with 4,781 additions and 4,773 deletions.
2 changes: 1 addition & 1 deletion .build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function init {
export SCALA3=$(cat project/Deps.sc | grep 'val scala300 ' | sed -r 's/.*\"(.*)\".**/\1/')

# details on github runners: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
export _JAVA_OPTIONS="-Xmx3500M -XX:ReservedCodeCacheSize=256M -XX:MaxMetaspaceSize=1024M"
export _JAVA_OPTIONS="-Xmx4000M -XX:ReservedCodeCacheSize=256M -XX:MaxMetaspaceSize=1024M"

printenv

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ jobs:
# flags: unittests
- name: Upload dependency graph
uses: scalacenter/sbt-dependency-submission@ab086b50c947c9774b70f39fc7f6e20ca2706c91
if: github.ref == 'develop'
build-js:
runs-on: ubuntu-latest
needs: [ 'checksecret' ]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ including the following components:
2. [distage-testkit](https://izumi.7mind.io/distage/distage-testkit) – Hyper-pragmatic pure FP Test framework. Shares heavy resources globally across all test suites; lets you easily swap implementations of component; uses your effect type for parallelism.
3. [distage-framework-docker](https://izumi.7mind.io/distage/distage-framework-docker) – A distage extension for using docker containers in tests or for local application runs, comes with example Postgres, Cassandra, Kafka & DynamoDB containers.
4. [LogStage](https://izumi.7mind.io/logstage/) – Automatic structural logs from Scala string interpolations,
5. [BIO](https://izumi.7mind.io/bio/) - A typeclass hierarchy for tagless final style with Bifunctor and Trifunctor effect types. Focused on ergonomics and ease of use with zero boilerplate.
6. [izumi-reflect](https://github.com/zio/izumi-reflect) (moved to [zio/izumi-reflect](https://github.com/zio/izumi-reflect)) - Portable, lightweight and kind-polymorphic alternative to `scala-reflect`'s Typetag for Scala, Scala.js, Scala Native and Dotty
5. [BIO](https://izumi.7mind.io/bio/) - A typeclass hierarchy for tagless final style with Bifunctor effect types. Focused on ergonomics and ease of use with zero boilerplate.
6. [izumi-reflect](https://github.com/zio/izumi-reflect) (moved to [zio/izumi-reflect](https://github.com/zio/izumi-reflect)) - Portable, lightweight and kind-polymorphic alternative to `scala-reflect`'s Typetag for Scala, Scala.js, Scala Native and Scala 3
7. [IdeaLingua](https://izumi.7mind.io/idealingua/) (moved to [7mind/idealingua-v1](https://github.com/7mind/idealingua-v1)) – API Definition, Data Modeling and RPC language, optimized for fast prototyping – like gRPC or Swagger, but with a human face. Generates RPC servers and clients for Go, TypeScript, C# and Scala,
8. [Opinionated SBT plugins](https://izumi.7mind.io/sbt/) (moved to [7mind/sbtgen](https://github.com/7mind/sbtgen)) – Reduces verbosity of SBT builds and introduces new features – inter-project shared test scopes and BOM plugins (from Maven)
9. [Percept-Plan-Execute-Repeat (PPER)](https://izumi.7mind.io/pper/) – A pattern that enables modeling very complex domains and orchestrate deadly complex processes a lot easier than you're used to.
Expand Down
195 changes: 114 additions & 81 deletions build.sbt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,20 @@ import zio.ZEnvironment

import scala.language.experimental.macros as enableMacros

sealed trait AnyConstructorBase[T] extends Any with ClassConstructorOptionalMakeDSL[T] {
def provider: Functoid[T]
}

/**
* An implicitly summonable constructor for a type `T`, can generate constructors for:
*
* - concrete classes (using [[ClassConstructor]])
* - traits and abstract classes ([[https://izumi.7mind.io/distage/basics.html#auto-traits Auto-Traits feature]], using [[TraitConstructor]])
*
* Since version `1.1.0`, does not generate constructors "factory-like" traits and abstract classes, instead use [[FactoryConstructor]].
*
* Use [[ZEnvConstructor]] to generate constructors for `zio.ZEnvironment` values.
* An implicitly summonable constructor for a concrete class `T`
*
* @example
* {{{
* import distage.{AnyConstructor, Functoid, Injector, ModuleDef}
* import distage.{ClassConstructor, Functoid, Injector, ModuleDef}
*
* class A(val i: Int)
*
* val constructor: Functoid[A] = AnyConstructor[A]
* val constructor: Functoid[A] = ClassConstructor[A]
*
* val lifecycle = Injector().produceGet[A](new ModuleDef {
* make[A].from(constructor)
Expand All @@ -42,22 +39,7 @@ import scala.language.experimental.macros as enableMacros
*
* @return [[izumi.distage.model.providers.Functoid]][T] value
*/
sealed trait AnyConstructor[T] extends Any with AnyConstructorOptionalMakeDSL[T] {
def provider: Functoid[T]
}

object AnyConstructor {
def apply[T](implicit ctor: AnyConstructor[T]): Functoid[T] = ctor.provider

implicit def materialize[T]: AnyConstructor[T] = macro AnyConstructorMacro.mkAnyConstructor[T]
}

/**
* An implicitly summonable constructor for a concrete class `T`
*
* @see [[AnyConstructor]]
*/
final class ClassConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructor[T]
final class ClassConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructorBase[T]

object ClassConstructor {
def apply[T](implicit ctor: ClassConstructor[T]): Functoid[T] = ctor.provider
Expand All @@ -70,9 +52,10 @@ object ClassConstructor {
*
* @see [[https://izumi.7mind.io/distage/basics.html#auto-traits Auto-Traits feature]]
* @see [[izumi.distage.model.definition.impl]] recommended documenting annotation for use with [[TraitConstructor]]
* @see [[AnyConstructor]]
*
* @return [[izumi.distage.model.providers.Functoid]][T] value
*/
final class TraitConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructor[T]
final class TraitConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructorBase[T]

object TraitConstructor {
def apply[T](implicit ctor: TraitConstructor[T]): Functoid[T] = ctor.provider
Expand All @@ -94,9 +77,10 @@ object TraitConstructor {
*
* @see [[https://izumi.7mind.io/distage/basics.html#auto-factories Auto-Factories feature]]
* @see [[izumi.distage.model.definition.impl]] recommended documenting annotation for use with [[FactoryConstructor]]
* @see [[AnyConstructor]]
*
* @return [[izumi.distage.model.providers.Functoid]][T] value
*/
final class FactoryConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructor[T]
final class FactoryConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructorBase[T]

object FactoryConstructor {
def apply[T](implicit ctor: FactoryConstructor[T]): Functoid[T] = ctor.provider
Expand All @@ -110,9 +94,8 @@ object FactoryConstructor {
* `zio.ZEnvironment` heterogeneous map values may be used by ZIO or other Reader-like effects
*
* @see [[https://izumi.7mind.io/distage/basics.html#zio-environment-bindings ZIO Environment bindings]]
* @see [[AnyConstructor]]
*/
final class ZEnvConstructor[T](val provider: Functoid[ZEnvironment[T]]) extends AnyVal with AnyConstructor[ZEnvironment[T]]
final class ZEnvConstructor[T](val provider: Functoid[ZEnvironment[T]]) extends AnyVal with AnyConstructorBase[ZEnvironment[T]]

object ZEnvConstructor {
def apply[T](implicit ctor: ZEnvConstructor[T]): Functoid[ZEnvironment[T]] = ctor.provider
Expand All @@ -122,19 +105,19 @@ object ZEnvConstructor {
implicit def materialize[T]: ZEnvConstructor[T] = macro ZEnvConstructorMacro.mkZEnvConstructor[T]
}

private[constructors] sealed trait AnyConstructorOptionalMakeDSL[T] extends Any {
private[constructors] sealed trait ClassConstructorOptionalMakeDSL[T] extends Any {
def provider: Functoid[T]
}

object AnyConstructorOptionalMakeDSL {
private[constructors] final class Impl[T](val provider: Functoid[T]) extends AnyVal with AnyConstructorOptionalMakeDSL[T]
object ClassConstructorOptionalMakeDSL {
private[constructors] final class Impl[T](val provider: Functoid[T]) extends AnyVal with ClassConstructorOptionalMakeDSL[T]

@inline def apply[T](functoid: Functoid[T]): AnyConstructorOptionalMakeDSL.Impl[T] = {
new AnyConstructorOptionalMakeDSL.Impl[T](functoid)
@inline def apply[T](functoid: Functoid[T]): ClassConstructorOptionalMakeDSL.Impl[T] = {
new ClassConstructorOptionalMakeDSL.Impl[T](functoid)
}

def errorConstructor[T](tpe: String, nonWhitelistedMethods: List[String]): AnyConstructorOptionalMakeDSL.Impl[T] = {
AnyConstructorOptionalMakeDSL[T](Functoid.lift(throwError(tpe, nonWhitelistedMethods)))
def errorConstructor[T](tpe: String, nonWhitelistedMethods: List[String]): ClassConstructorOptionalMakeDSL.Impl[T] = {
ClassConstructorOptionalMakeDSL[T](Functoid.lift(throwError(tpe, nonWhitelistedMethods)))
}

def throwError(tpe: String, nonWhitelistedMethods: List[String]): Nothing = {
Expand All @@ -149,5 +132,5 @@ object AnyConstructorOptionalMakeDSL {
)
}

implicit def materialize[T]: AnyConstructorOptionalMakeDSL.Impl[T] = macro AnyConstructorMacro.anyConstructorOptionalMakeDSL[T]
implicit def materialize[T]: ClassConstructorOptionalMakeDSL.Impl[T] = macro MakeMacro.classConstructorOptionalMakeDSL[T]
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,55 @@ object ClassConstructorMacro {
def mkClassConstructor[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[ClassConstructor[T]] = {
import c.universe._

val macroUniverse = StaticDIUniverse(c)
val reflectionProvider = ReflectionProviderDefaultImpl(macroUniverse)

val targetType = ReflectionUtil.norm(c.universe: c.universe.type)(weakTypeOf[T].dealias)
requireConcreteTypeConstructor(c)("ClassConstructor", targetType)

(targetType match {
case t: SingletonTypeApi =>
val functoid = symbolOf[Functoid.type].asClass.module
val term = t match {
case t: ThisTypeApi => This(t.sym)
case t: ConstantTypeApi => q"${t.value}"
case _ => q"${t.termSymbol}"
}
c.Expr[ClassConstructor[T]] {
q"{ new ${weakTypeOf[ClassConstructor[T]]}($functoid.singleton[$targetType]($term)) }"
}

case _ =>
val macroUniverse = StaticDIUniverse(c)
val impls = ClassConstructorMacros(c)(macroUniverse)
import impls.{c => _, u => _, _}

val reflectionProvider = ReflectionProviderDefaultImpl(macroUniverse)
if (!reflectionProvider.isConcrete(targetType)) {
c.abort(
c.enclosingPosition,
s"""Tried to derive constructor function for class $targetType, but the class is an
|abstract class or a trait! Only concrete classes (`class` keyword) are supported""".stripMargin,
)
}

val logger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.distage.constructors`.name)

val provider: c.Expr[Functoid[T]] = mkClassConstructorProvider(reflectionProvider)(targetType)

val res = c.Expr[ClassConstructor[T]](q"{ new ${weakTypeOf[ClassConstructor[T]]}($provider) }")
logger.log(s"Final syntax tree of class for $targetType:\n$res")
res
}): @nowarn("msg=outer reference")
if (reflectionProvider.isConcrete(targetType)) {
(targetType match {
case t: SingletonTypeApi =>
val functoid = symbolOf[Functoid.type].asClass.module
val term = t match {
case t: ThisTypeApi => This(t.sym)
case t: ConstantTypeApi => q"${t.value}"
case _ => q"${t.termSymbol}"
}
c.Expr[ClassConstructor[T]] {
q"{ new ${weakTypeOf[ClassConstructor[T]]}($functoid.singleton[$targetType]($term)) }"
}

case _ =>
val impls = ClassConstructorMacros(c)(macroUniverse)

val provider: c.Expr[Functoid[T]] = impls.mkClassConstructorProvider(reflectionProvider)(targetType)

val res = c.Expr[ClassConstructor[T]](q"{ new ${weakTypeOf[ClassConstructor[T]]}($provider) }")

val logger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.distage.constructors`.name)
logger.log(s"Final syntax tree of class for $targetType:\n$res")

res
}): @nowarn("msg=outer reference")
} else if (reflectionProvider.isWireableAbstract(targetType)) {
c.abort(
c.enclosingPosition,
s"ClassConstructor failure: $targetType is a trait or an abstract class, use `makeTrait` or `make[X].fromTrait` to wire traits.",
)
} else if (reflectionProvider.isFactory(targetType)) {
c.abort(
c.enclosingPosition,
s"ClassConstructor failure: $targetType is a Factory, use `makeFactory` or `make[X].fromFactory` to wire factories.",
)
} else {
c.abort(
c.enclosingPosition,
s"""ClassConstructor failure: couldn't derive a constructor for $targetType!
|It's neither a concrete class, nor a wireable trait or abstract class!""".stripMargin,
)
}

}

}
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
package izumi.distage.constructors.macros

import scala.annotation.nowarn
import izumi.distage.constructors.{AnyConstructor, AnyConstructorOptionalMakeDSL, DebugProperties}
import izumi.distage.constructors.{ClassConstructorOptionalMakeDSL, DebugProperties}
import izumi.distage.model.definition.dsl.ModuleDefDSL
import izumi.distage.model.reflection.universe.StaticDIUniverse
import izumi.distage.reflection.ReflectionProviderDefaultImpl
import izumi.fundamentals.reflection.{ReflectionUtil, TrivialMacroLogger}
import izumi.fundamentals.reflection.TrivialMacroLogger

import scala.annotation.nowarn
import scala.reflect.api.Universe
import scala.reflect.macros.blackbox

@nowarn("msg=deprecated.*since 2.11")
object AnyConstructorMacro {
object MakeMacro {

def make[B[_], T: c.WeakTypeTag](c: blackbox.Context): c.Expr[B[T]] = {
import c.universe._
c.Expr[B[T]](q"""${c.prefix}._make[${weakTypeOf[T]}](${c.inferImplicitValue(weakTypeOf[AnyConstructorOptionalMakeDSL[T]], silent = false)}.provider)""")
import c.universe.*
c.Expr[B[T]](q"""${c.prefix}._make[${weakTypeOf[T]}](${c.inferImplicitValue(weakTypeOf[ClassConstructorOptionalMakeDSL[T]], silent = false)}.provider)""")
}

def anyConstructorOptionalMakeDSL[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[AnyConstructorOptionalMakeDSL.Impl[T]] = {
import c.universe._
def classConstructorOptionalMakeDSL[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[ClassConstructorOptionalMakeDSL.Impl[T]] = {
import c.universe.*

val logger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.distage.constructors`.name)

val enclosingClass = c.enclosingClass
// We expect this macro to be called only and __ONLY__ from `AnyConstructorMacro.make`
// We expect this macro to be called only and __ONLY__ from `MakeMacro.make`
// we're going to use the position of the `make` call to search for subsequent methods
// instead of the position of the implicit search itself (which is unstable and
// sometimes doesn't exist, for example during scaladoc compilation)
Expand Down Expand Up @@ -62,12 +60,12 @@ object AnyConstructorMacro {

val tpe = weakTypeOf[T]

c.Expr[AnyConstructorOptionalMakeDSL.Impl[T]] {
c.Expr[ClassConstructorOptionalMakeDSL.Impl[T]] {
maybeNonwhiteListedMethods match {
case None =>
c.abort(
c.enclosingPosition,
s"""Couldn't find position of the `make` call when summoning AnyConstructorOptionalMakeDSL[$tpe]
s"""Couldn't find position of the `make` call when summoning ClassConstructorOptionalMakeDSL[$tpe]
|Got tree: $maybeTree
|Result of search: $maybeNonwhiteListedMethods
|Searched for position: $positionOfMakeCall
Expand All @@ -79,42 +77,14 @@ object AnyConstructorMacro {
if (nonwhiteListedMethods.isEmpty) {
logger.log(s"""For $tpe found no `.from`-like calls in $maybeTree""".stripMargin)

q"""_root_.izumi.distage.constructors.AnyConstructorOptionalMakeDSL.apply[$tpe](${mkAnyConstructor[T](c)}.provider)"""
q"""_root_.izumi.distage.constructors.ClassConstructorOptionalMakeDSL.apply[$tpe](${ClassConstructorMacro.mkClassConstructor[T](c)}.provider)"""
} else {
logger.log(s"For $tpe found `.from`-like calls, generating ERROR constructor: $nonwhiteListedMethods")

q"""_root_.izumi.distage.constructors.AnyConstructorOptionalMakeDSL.errorConstructor[$tpe](${tpe.toString}, $nonwhiteListedMethods)"""
q"""_root_.izumi.distage.constructors.ClassConstructorOptionalMakeDSL.errorConstructor[$tpe](${tpe.toString}, $nonwhiteListedMethods)"""
}
}
}
}

def mkAnyConstructor[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[AnyConstructor[T]] = {
import c.universe._

val macroUniverse = StaticDIUniverse(c)
val reflectionProvider = ReflectionProviderDefaultImpl(macroUniverse)

val targetType = ReflectionUtil.norm(c.universe: c.universe.type)(weakTypeOf[T].dealias)
requireConcreteTypeConstructor(c)("AnyConstructor", targetType)

if (reflectionProvider.isConcrete(targetType)) {
ClassConstructorMacro.mkClassConstructor[T](c)
} else if (reflectionProvider.isWireableAbstract(targetType)) {
TraitConstructorMacro.mkTraitConstructor[T](c)
} else if (reflectionProvider.isFactory(targetType)) {
c.abort(
c.enclosingPosition,
s"""AnyConstructor failure: $targetType is a Factory, use makeFactory or fromFactory to wire factories.""".stripMargin,
)
} else {
c.abort(
c.enclosingPosition,
s"""AnyConstructor failure: couldn't generate a constructor for $targetType!
|It's neither a concrete class, nor a wireable trait or abstract class!""".stripMargin,
)
}

}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package izumi.distage.model.definition.dsl

import izumi.distage.constructors.macros.AnyConstructorMacro
import izumi.distage.constructors.macros.MakeMacro

import scala.language.experimental.macros

trait AbstractBindingDefDSLMacro[BindDSL[_]] {
final protected[this] def make[T]: BindDSL[T] = macro AnyConstructorMacro.make[BindDSL, T]
final protected[this] def make[T]: BindDSL[T] = macro MakeMacro.make[BindDSL, T]
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package izumi.distage.model.definition.dsl

trait AnyKindShim {
object AnyKindShim {
type LifecycleF[_] = Any
}

object AnyKindShim extends AnyKindShim
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ trait LifecycleTagLowPriority {
macro LifecycleTagMacro.fakeResourceTagMacroIntellijWorkaroundImpl[R]
}

// // fixme wtf
//trait TrifunctorHasLifecycleTagLowPriority1 {
// implicit final def fakeResourceTagMacroIntellijWorkaround[R <: Lifecycle[Any, Any], T]: LifecycleAdapters.TrifunctorHasLifecycleTag[R, T] =
// macro LifecycleTagMacro.fakeResourceTagMacroIntellijWorkaroundImpl[R]
//}

trait ZIOEnvLifecycleTagLowPriority1 {
implicit final def fakeResourceTagMacroIntellijWorkaround[R <: Lifecycle[Any, Any], T]: LifecycleAdapters.ZIOEnvLifecycleTag[R, T] = /*scalafmt*/
macro LifecycleTagMacro.fakeResourceTagMacroIntellijWorkaroundImpl[R]
Expand Down
Loading

0 comments on commit da711e1

Please sign in to comment.