Repository: 7mind/izumi
Pull request #964 (2020-03-18 22:37:20)

Add LogBIO3, add LogStageZIO.log ZIO environment forwarder, fix BIOFunctor attachments


Patch:
diff --git a/fundamentals/fundamentals-bio/src/main/scala/izumi/functional/bio/BIOFunctor3.scala b/fundamentals/fundamentals-bio/src/main/scala/izumi/functional/bio/BIOFunctor3.scala
index 433ce9dfa..cb0a613b8 100644
--- a/fundamentals/fundamentals-bio/src/main/scala/izumi/functional/bio/BIOFunctor3.scala
+++ b/fundamentals/fundamentals-bio/src/main/scala/izumi/functional/bio/BIOFunctor3.scala
@@ -21,7 +21,7 @@ private[bio] sealed trait BIOFunctorInstances
 object BIOFunctorInstances extends BIOFunctorInstancesLowPriority1 {
   @inline implicit final def BIOConvertFromBIOMonadAsk[FR[-_, +_, +_]](implicit BIOMonadAsk: NotPredefined.Of[BIOMonadAsk[FR]]): BIOMonad3[FR] with S1 = S1(BIOMonadAsk.InnerF)
 
-  @inline implicit final def AttachBIOAsk[FR[-_, +_, +_]](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOAsk: BIOAsk[FR]): BIOAsk.type = BIOAsk
+  @inline implicit final def AttachBIOLocal[FR[-_, +_, +_], R](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOLocal: BIOLocal[FR]): BIOLocal.type = BIOLocal
   @inline implicit final def AttachBIOPrimitives3[FR[-_, +_, +_]](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOPrimitives: BIOPrimitives3[FR]): BIOPrimitives.type = BIOPrimitives
   @inline implicit final def AttachBIOFork3[FR[-_, +_, +_]](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOFork: BIOFork3[FR]): BIOFork.type = BIOFork
   @inline implicit final def AttachBlockingIO3[FR[-_, +_, +_]](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BlockingIO: BlockingIO3[FR]): BlockingIO.type = BlockingIO
@@ -34,12 +34,15 @@ object BIOFunctorInstances extends BIOFunctorInstancesLowPriority1 {
 
 sealed trait BIOFunctorInstancesLowPriority1 extends BIOFunctorInstancesLowPriority2 {
   @inline implicit final def BIOConvertFromBIOAsk[FR[-_, +_, +_]](implicit BIOAsk: NotPredefined.Of[BIOAsk[FR]]): BIOApplicative3[FR] with S2 = S2(BIOAsk.InnerF)
+
 }
 
 sealed trait BIOFunctorInstancesLowPriority2 extends BIOFunctorInstancesLowPriority3 {
   @inline implicit final def BIOConvertFromBIOProfunctor[FR[-_, +_, +_]](implicit BIOProfunctor: NotPredefined.Of[BIOProfunctor[FR]]): BIOFunctor3[FR] with S3 = S3(BIOProfunctor.InnerF)
 
-  @inline implicit final def AttachBIOProfunctor[FR[-_, +_, +_]](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOProfunctor: BIOProfunctor[FR]): BIOProfunctor.type = BIOProfunctor
+  @inline implicit final def AttachBIOArrowChoice[FR[-_, +_, +_]](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOArrowChoice: BIOArrowChoice[FR]): BIOArrowChoice.type = BIOArrowChoice
+  @inline implicit final def AttachBIOArrow[FR[-_, +_, +_]](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOArrow: BIOArrow[FR]): BIOArrow.type = BIOArrow
+  @inline implicit final def AttachBIOMonadAsk[FR[-_, +_, +_], R](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOMonadAsk: BIOMonadAsk[FR]): BIOMonadAsk.type = BIOMonadAsk
 }
 
 sealed trait BIOFunctorInstancesLowPriority3 {
@@ -47,6 +50,9 @@ sealed trait BIOFunctorInstancesLowPriority3 {
   @inline implicit final def BIOZIO: Predefined.Of[BIOAsync3[ZIO]] = Predefined(BIOAsyncZio)
 //  @inline implicit final def BIOZIOR[R]: BIOAsync[ZIO[R, +?, +?]] = convert3To2(BIOAsyncZio)
 
+  @inline implicit final def AttachBIOProfunctor[FR[-_, +_, +_]](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOProfunctor: BIOProfunctor[FR]): BIOProfunctor.type = BIOProfunctor
+  @inline implicit final def AttachBIOAsk[FR[-_, +_, +_], R](@deprecated("unused", "") self: BIOFunctor3[FR])(implicit BIOAsk: BIOAsk[FR]): BIOAsk.type = BIOAsk
+
   @inline implicit final def BIOConvert3To2[C[_[-_, +_, +_]], FR[-_, +_, +_], R0](
     implicit BIOFunctor3: C[FR] with BIOFunctor3[FR] {
       type Divergence = Nondivergent
diff --git a/fundamentals/fundamentals-bio/src/main/scala/izumi/functional/bio/syntax/BIO3Syntax.scala b/fundamentals/fundamentals-bio/src/main/scala/izumi/functional/bio/syntax/BIO3Syntax.scala
index 4d030b066..51c64afe4 100644
--- a/fundamentals/fundamentals-bio/src/main/scala/izumi/functional/bio/syntax/BIO3Syntax.scala
+++ b/fundamentals/fundamentals-bio/src/main/scala/izumi/functional/bio/syntax/BIO3Syntax.scala
@@ -210,6 +210,9 @@ object BIO3Syntax {
     @inline implicit final def BIOArrowChoice[FR[-_, +_, +_]: BIOArrowChoice, R, E, A](self: FR[R, E, A]): BIO3Syntax.BIOArrowChoiceOps[FR, R, E, A] = new BIO3Syntax.BIOArrowChoiceOps[FR, R, E, A](self)
     @inline implicit final def BIOArrowChoice[FR[-_, +_, +_]: BIOFunctor3, R, E, A](self: FR[R, E, A]): BIO3Syntax.BIOFunctor3Ops[FR, R, E, A] = new BIO3Syntax.BIOFunctor3Ops[FR, R, E, A](self)
     @inline final def BIOArrowChoice[FR[-_, +_, +_]: BIOArrowChoice]: BIOArrowChoice[FR] = implicitly
+
+    @inline implicit final def BIOMonadAsk[FR[-_, +_, +_]: BIOMonad3, R, E, A](self: FR[R, E, A]): BIO3Syntax.BIOMonad3Ops[FR, R, E, A] = new BIO3Syntax.BIOMonad3Ops[FR, R, E, A](self)
+    @inline final def BIOMonadAsk[FR[-_, +_, +_]: BIOAsk]: BIOAsk[FR] = implicitly
   }
   trait BIO3ImplicitPuns2 extends BIO3ImplicitPuns3 {
     @inline implicit final def BIO3[FR[-_, +_, +_]: BIO3, R, E, A](self: FR[R, E, A]): BIO3Syntax.BIO3Ops[FR, R, E, A] = new BIO3Syntax.BIO3Ops[FR, R, E, A](self)
@@ -234,7 +237,6 @@ object BIO3Syntax {
     @inline implicit final def BIOProfunctor[FR[-_, +_, +_]: BIOProfunctor, R, E, A](self: FR[R, E, A]): BIO3Syntax.BIOProfunctorOps[FR, R, E, A] = new BIO3Syntax.BIOProfunctorOps[FR, R, E, A](self)
     @inline implicit final def BIOProfunctor[FR[-_, +_, +_]: BIOFunctor3, R, E, A](self: FR[R, E, A]): BIO3Syntax.BIOFunctor3Ops[FR, R, E, A] = new BIO3Syntax.BIOFunctor3Ops[FR, R, E, A](self)
     @inline final def BIOProfunctor[FR[-_, +_, +_]: BIOProfunctor]: BIOProfunctor[FR] = implicitly
-
   }
   trait BIO3ImplicitPuns4 extends BIO3ImplicitPuns5 {
     @inline implicit final def BIOBracket3[FR[-_, +_, +_]: BIOBracket3, R, E, A](self: FR[R, E, A]): BIO3Syntax.BIOBracket3Ops[FR, R, E, A] = new BIO3Syntax.BIOBracket3Ops[FR, R, E, A](self)
diff --git a/logstage/logstage-core/src/main/scala/logstage/LogBIO.scala b/logstage/logstage-core/src/main/scala/logstage/LogBIO.scala
deleted file mode 100644
index 7988aa1ff..000000000
--- a/logstage/logstage-core/src/main/scala/logstage/LogBIO.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package logstage
-
-import izumi.functional.bio.SyncSafe2
-import izumi.logstage.api.logger.AbstractLogger
-
-object LogBIO {
-  def apply[F[_, _]: LogBIO]: LogBIO[F] = implicitly
-
-  def fromLogger[F[_, _]: SyncSafe2](logger: AbstractLogger): LogBIO[F] = {
-    LogIO.fromLogger(logger)
-  }
-}
-
-
diff --git a/logstage/logstage-core/src/main/scala/logstage/LogBIO3EnvInstance.scala b/logstage/logstage-core/src/main/scala/logstage/LogBIO3EnvInstance.scala
new file mode 100644
index 000000000..48f7d2aec
--- /dev/null
+++ b/logstage/logstage-core/src/main/scala/logstage/LogBIO3EnvInstance.scala
@@ -0,0 +1,26 @@
+package logstage
+
+import izumi.functional.bio.BIOMonadAsk
+import izumi.fundamentals.platform.language.CodePositionMaterializer
+import izumi.logstage.api.Log.CustomContext
+import zio.Has
+
+class LogBIO3EnvInstance[F[-_, +_, +_]](get: Has[LogBIO3[F]] => LogBIO3[F])(implicit F: BIOMonadAsk[F]) extends LogBIO[F[Has[LogBIO3[F]], ?, ?]] {
+  override def log(entry: Log.Entry): F[Has[LogBIO3[F]], Nothing, Unit] =
+    F.access(get(_).log(entry))
+  override def log(logLevel: Level)(messageThunk: => Log.Message)(implicit pos: CodePositionMaterializer): F[Has[LogBIO3[F]], Nothing, Unit] =
+    F.access(get(_).log(logLevel)(messageThunk))
+  override def unsafeLog(entry: Log.Entry): F[Has[LogBIO3[F]], Nothing, Unit] =
+    F.access(get(_).log(entry))
+  override def acceptable(loggerId: Log.LoggerId, logLevel: Level): F[Has[LogBIO3[F]], Nothing, Boolean] =
+    F.access(get(_).acceptable(loggerId, logLevel))
+  override def acceptable(logLevel: Level)(implicit pos: CodePositionMaterializer): F[Has[LogBIO3[F]], Nothing, Boolean] =
+    F.access(get(_).acceptable(logLevel))
+  override def createEntry(logLevel: Level, message: Log.Message)(implicit pos: CodePositionMaterializer): F[Has[LogBIO3[F]], Nothing, Log.Entry] =
+    F.access(get(_).createEntry(logLevel, message))
+  override def createContext(logLevel: Level, customContext: CustomContext)(implicit pos: CodePositionMaterializer): F[Has[LogBIO3[F]], Nothing, Log.Context] =
+    F.access(get(_).createContext(logLevel, customContext))
+  override def withCustomContext(context: CustomContext): LogBIO[F[Has[LogBIO3[F]], ?, ?]] = {
+    new LogBIO3EnvInstance[F](get(_).withCustomContext(context))
+  }
+}
diff --git a/logstage/logstage-core/src/main/scala/logstage/LogCreateBIO.scala b/logstage/logstage-core/src/main/scala/logstage/LogCreateBIO.scala
deleted file mode 100644
index cea1cb421..000000000
--- a/logstage/logstage-core/src/main/scala/logstage/LogCreateBIO.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package logstage
-
-object LogCreateBIO {
-  def apply[F[_, _]: LogCreateBIO]: LogCreateBIO[F] = implicitly
-}
diff --git a/logstage/logstage-core/src/main/scala/logstage/LogstageZIO.scala b/logstage/logstage-core/src/main/scala/logstage/LogstageZIO.scala
index b35bc298b..7b0f2907d 100644
--- a/logstage/logstage-core/src/main/scala/logstage/LogstageZIO.scala
+++ b/logstage/logstage-core/src/main/scala/logstage/LogstageZIO.scala
@@ -5,13 +5,16 @@ import izumi.functional.mono.SyncSafe
 import izumi.logstage.api.Log.CustomContext
 import izumi.logstage.api.logger.AbstractLogger
 import logstage.LogstageCats.WrappedLogIO
-import zio.{IO, ZIO}
+import zio.{Has, IO, ZIO}
 
 object LogstageZIO {
 
+  /** Lets you carry LogBIO capability in environment */
+  object log extends LogBIO3EnvInstance[ZIO](_.get) with LogBIO[ZIO[Has[LogBIO[IO]], ?, ?]]
+
   def withFiberId(logger: AbstractLogger): LogBIO[IO] = {
     new WrappedLogIO[IO[Nothing, ?]](logger)(SyncSafe2[IO]) {
-      override def withCustomContext(context: CustomContext): LogIO[IO[Nothing, ?]] = {
+      override def withCustomContext(context: CustomContext): LogBIO[IO] = {
         withFiberId(logger.withCustomContext(context))
       }
 
@@ -24,7 +27,7 @@ object LogstageZIO {
     }
   }
 
-  def withDynamicContext[R](logger: AbstractLogger)(dynamic: ZIO[R, Nothing, CustomContext]): LogIO[ZIO[R, Nothing, ?]] = {
+  def withDynamicContext[R](logger: AbstractLogger)(dynamic: ZIO[R, Nothing, CustomContext]): LogBIO[ZIO[R, ?, ?]] = {
     new WrappedLogIO[ZIO[R, Nothing, ?]](logger)(SyncSafe[ZIO[R, Nothing, ?]]) {
       override def withCustomContext(context: CustomContext): LogIO[ZIO[R, Nothing, ?]] = {
         withDynamicContext(logger.withCustomContext(context))(dynamic)
diff --git a/logstage/logstage-core/src/main/scala/logstage/UnsafeLogBIO.scala b/logstage/logstage-core/src/main/scala/logstage/UnsafeLogBIO.scala
deleted file mode 100644
index 8ad9bc754..000000000
--- a/logstage/logstage-core/src/main/scala/logstage/UnsafeLogBIO.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package logstage
-
-import izumi.functional.bio.SyncSafe2
-import izumi.logstage.api.logger.AbstractLogger
-
-object UnsafeLogBIO {
-  def apply[F[_, _]: UnsafeLogBIO]: UnsafeLogBIO[F] = implicitly
-
-  def fromLogger[F[_, _]: SyncSafe2](logger: AbstractLogger): UnsafeLogBIO[F] = {
-    UnsafeLogIO.fromLogger(logger)
-  }
-}
diff --git a/logstage/logstage-core/src/main/scala/logstage/package.scala b/logstage/logstage-core/src/main/scala/logstage/package.scala
index 4d9915600..ca0c35376 100644
--- a/logstage/logstage-core/src/main/scala/logstage/package.scala
+++ b/logstage/logstage-core/src/main/scala/logstage/package.scala
@@ -1,3 +1,5 @@
+import izumi.functional.bio.{BIOMonadAsk, SyncSafe2, SyncSafe3}
+import izumi.logstage.api.logger.AbstractLogger
 import izumi.logstage.{api, sink}
 import logstage.strict.LogIOStrict
 
@@ -34,8 +36,53 @@ package object logstage extends LogStage {
   override final val Crit: api.Log.Level.Crit.type = api.Log.Level.Crit
 
   type LogBIO[F[_, _]] = LogIO[F[Nothing, ?]]
+  object LogBIO {
+    def apply[F[_, _]: LogBIO]: LogBIO[F] = implicitly
+
+    def fromLogger[F[_, _]: SyncSafe2](logger: AbstractLogger): LogBIO[F] = {
+      LogIO.fromLogger(logger)
+    }
+  }
   type LogBIOStrict[F[_, _]] = LogIOStrict[F[Nothing, ?]]
 
   type LogCreateBIO[F[_, _]] = LogCreateIO[F[Nothing, ?]]
+  object LogCreateBIO {
+    def apply[F[_, _]: LogCreateBIO]: LogCreateBIO[F] = implicitly
+  }
+
   type UnsafeLogBIO[F[_, _]] = UnsafeLogIO[F[Nothing, ?]]
+  object UnsafeLogBIO {
+    def apply[F[_, _]: UnsafeLogBIO]: UnsafeLogBIO[F] = implicitly
+
+    def fromLogger[F[_, _]: SyncSafe2](logger: AbstractLogger): UnsafeLogBIO[F] = {
+      UnsafeLogIO.fromLogger(logger)
+    }
+  }
+
+  type LogBIO3[F[_, _, _]] = LogIO[F[Any, Nothing, ?]]
+  object LogBIO3 {
+    def apply[F[_, _, _]: LogBIO3]: LogBIO3[F] = implicitly
+
+    def fromLogger[F[_, _, _]: SyncSafe3](logger: AbstractLogger): LogBIO3[F] = {
+      LogIO.fromLogger(logger)
+    }
+
+    /** Lets you carry LogBIO capability in environment */
+    def log[F[-_, +_, +_]: BIOMonadAsk: zio.TaggedF3] = new LogBIO3EnvInstance[F](_.get)
+  }
+  type LogBIOStrict3[F[_, _, _]] = LogIOStrict[F[Any, Nothing, ?]]
+
+  type LogCreateBIO3[F[_, _, _]] = LogCreateIO[F[Any, Nothing, ?]]
+  object LogCreateBIO3 {
+    def apply[F[_, _, _]: LogCreateBIO3]: LogCreateBIO3[F] = implicitly
+  }
+
+  type UnsafeLogBIO3[F[_, _, _]] = UnsafeLogIO[F[Any, Nothing, ?]]
+  object UnsafeLogBIO3 {
+    def apply[F[_, _, _]: UnsafeLogBIO3]: UnsafeLogBIO3[F] = implicitly
+
+    def fromLogger[F[_, _, _]: SyncSafe3](logger: AbstractLogger): UnsafeLogBIO3[F] = {
+      UnsafeLogIO.fromLogger(logger)
+    }
+  }
 }


Test patch:
diff --git a/fundamentals/fundamentals-bio/src/test/scala/izumi/fundamentals/bio/test/BIOSyntaxTest.scala b/fundamentals/fundamentals-bio/src/test/scala/izumi/fundamentals/bio/test/BIOSyntaxTest.scala
index b58acd3e4..a0712c905 100644
--- a/fundamentals/fundamentals-bio/src/test/scala/izumi/fundamentals/bio/test/BIOSyntaxTest.scala
+++ b/fundamentals/fundamentals-bio/src/test/scala/izumi/fundamentals/bio/test/BIOSyntaxTest.scala
@@ -104,6 +104,12 @@ class BIOSyntaxTest extends AnyWordSpec {
           true
       }
     }
+    def onlyMonadAskAccess[FR[-_, +_, +_]: BIOMonadAsk]: FR[Int, Nothing, Unit] = {
+      F.unit <* F.access {
+        _: Int =>
+          F.unit
+      }
+    }
     def onlyAsk[FR[-_, +_, +_]: BIOAsk]: FR[Int, Nothing, Unit] = {
       F.askWith {
         _: Int =>
@@ -140,6 +146,7 @@ class BIOSyntaxTest extends AnyWordSpec {
     lazy val _ = (
       x[zio.ZIO],
       onlyMonadAsk[zio.ZIO],
+      onlyMonadAskAccess[zio.ZIO],
       onlyAsk[zio.ZIO],
       y[zio.ZIO],
       arrowAsk[zio.ZIO],