Skip to content

Commit

Permalink
Merge pull request #2 from ThoughtWorksInc/exception-handling
Browse files Browse the repository at this point in the history
 Support new exception handling in Dsl.scala 1.4
  • Loading branch information
Atry authored Jun 23, 2019
2 parents 8b7680f + b5d7e0e commit 1864cb7
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 9 deletions.
14 changes: 7 additions & 7 deletions domains-cats/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ libraryDependencies += "org.typelevel" %%% "cats-core" % "2.0.0-M4"

libraryDependencies += "org.scalatest" %%% "scalatest" % "3.0.8" % Test

libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-catch" % "1.3.2"
libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-catch" % "1.4.0"

libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-monadic" % "1.3.2"
libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-monadic" % "1.4.0"

libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-return" % "1.3.2"
libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-return" % "1.4.0"

libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-shift" % "1.3.2" % Optional
libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-shift" % "1.4.0" % Optional

libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-yield" % "1.3.2" % Optional
libraryDependencies += "com.thoughtworks.dsl" %%% "keywords-yield" % "1.4.0" % Optional

addCompilerPlugin("com.thoughtworks.dsl" %% "compilerplugins-bangnotation" % "1.3.2")
addCompilerPlugin("com.thoughtworks.dsl" %% "compilerplugins-bangnotation" % "1.4.0")

addCompilerPlugin("com.thoughtworks.dsl" %% "compilerplugins-reseteverywhere" % "1.3.2")
addCompilerPlugin("com.thoughtworks.dsl" %% "compilerplugins-reseteverywhere" % "1.4.0")

scalacOptions ++= {
import Ordering.Implicits._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package domains

import _root_.cats.{Applicative, FlatMap}
import com.thoughtworks.dsl.Dsl
import com.thoughtworks.dsl.Dsl.!!
import com.thoughtworks.dsl.Dsl.{!!, TryCatch, TryFinally}
import _root_.cats.MonadError
import com.thoughtworks.Extractor._
import com.thoughtworks.dsl.keywords.Catch.CatchDsl
Expand All @@ -12,6 +12,7 @@ import com.thoughtworks.dsl.keywords.{Monadic, Return}
import scala.language.higherKinds
import scala.language.implicitConversions
import scala.util.control.Exception.Catcher
import scala.util.control.NonFatal

/** Contains interpreters to enable [[Dsl.Keyword#unary_$bang !-notation]]
* for [[keywords.Monadic]] and other keywords
Expand Down Expand Up @@ -112,8 +113,54 @@ object cats {
(keyword: Return[A], handler: Nothing => F[B]) =>
applicative.pure(restReturnDsl.cpsApply(keyword, identity))
}
@inline private def catchNativeException[F[_], A](continuation: F[A] !! A)(
implicit monadThrowable: MonadThrowable[F]): F[A] = {
try {
continuation(monadThrowable.pure(_))
} catch {
case NonFatal(e) =>
monadThrowable.raiseError(e)
}
}

implicit def catsTryFinally[F[_], A, B](
implicit monadError: MonadThrowable[F]): TryFinally[A, F[B], F[A], F[Unit]] = {
(block: F[A] !! A, finalizer: F[Unit] !! Unit, outerSuccessHandler: A => F[B]) =>
@inline
def injectFinalizer[A](f: Unit => F[A]): F[A] = {
monadError.flatMap(catchNativeException(finalizer))(f)
}

monadError.flatMap(monadError.handleErrorWith(catchNativeException(block)) { e: Throwable =>
injectFinalizer { _: Unit =>
monadError.raiseError(e)
}
}) { a =>
injectFinalizer { _: Unit =>
outerSuccessHandler(a)
}
}
}

implicit def catsTryCatch[F[_], A, B](implicit monadError: MonadThrowable[F]): TryCatch[A, F[B], F[A]] = {
(block: F[A] !! A, catcher: Catcher[F[A] !! A], outerSuccessHandler: A => F[B]) =>
def errorHandler(e: Throwable): F[A] = {
(try {
catcher.lift(e)
} catch {
case NonFatal(extractorException) =>
return monadError.raiseError(extractorException)
}) match {
case None =>
monadError.raiseError(e)
case Some(recovered) =>
catchNativeException(recovered)
}
}
monadError.flatMap(monadError.handleErrorWith(catchNativeException(block))(errorHandler))(outerSuccessHandler)
}

implicit def catsCatchDsl[F[_], A, B](implicit monadError: MonadThrowable[F]): CatchDsl[F[A], F[B], A] = {
private[dsl] def catsCatchDsl[F[_], A, B](implicit monadError: MonadThrowable[F]): CatchDsl[F[A], F[B], A] = {
(block: F[A] !! A, catcher: Catcher[F[A] !! A], handler: A => F[B]) =>
val fa = monadError.flatMap(monadError.pure(block))(_(monadError.pure))
val protectedFa = monadError.handleErrorWith(fa) {
Expand Down

0 comments on commit 1864cb7

Please sign in to comment.