diff --git a/shared/src/main/scala-2/com/eed3si9n/expecty/Recorder.scala b/shared/src/main/scala-2/com/eed3si9n/expecty/Recorder.scala index db7826d..5e2babc 100644 --- a/shared/src/main/scala-2/com/eed3si9n/expecty/Recorder.scala +++ b/shared/src/main/scala-2/com/eed3si9n/expecty/Recorder.scala @@ -15,8 +15,8 @@ package com.eed3si9n.expecty import language.experimental.macros -abstract class Recorder { - def listener: RecorderListener[Boolean] - def apply(recording: Boolean): Unit = macro RecorderMacro1.apply - def apply(recording: Boolean, message: => String): Unit = macro RecorderMacro.apply +abstract class Recorder[R, A] { + def listener: RecorderListener[R, A] + def apply(recording: R): A = macro RecorderMacro1.apply[R, A] + def apply(recording: R, message: => String): A = macro RecorderMacro.apply[R, A] } diff --git a/shared/src/main/scala-2/com/eed3si9n/expecty/RecorderMacro.scala b/shared/src/main/scala-2/com/eed3si9n/expecty/RecorderMacro.scala index 8a5aac7..85811e0 100644 --- a/shared/src/main/scala-2/com/eed3si9n/expecty/RecorderMacro.scala +++ b/shared/src/main/scala-2/com/eed3si9n/expecty/RecorderMacro.scala @@ -19,23 +19,23 @@ import scala.util.Properties class RecorderMacro[C <: Context](val context: C) { import context.universe._ - def apply(recording: context.Tree, message: context.Tree): Expr[Unit] = { - context.Expr(Block(declareRuntime :: + def apply[R: context.WeakTypeTag, A: context.WeakTypeTag](recording: context.Tree, message: context.Tree): Expr[A] = { + context.Expr(Block(declareRuntime[R, A] :: recordMessage(message) :: recordExpressions(recording), completeRecording)) } - private[this] def declareRuntime: Tree = { - val runtimeClass = context.mirror.staticClass(classOf[RecorderRuntime].getName) + private[this] def declareRuntime[R: context.WeakTypeTag, A : context.WeakTypeTag] : Tree = { + val runtimeClass = context.mirror.staticClass(classOf[RecorderRuntime[_, _]].getName()) ValDef( Modifiers(), termName(context)("$com_eed3si9n_expecty_recorderRuntime"), - TypeTree(runtimeClass.toType), + TypeTree(weakTypeOf[RecorderRuntime[R, A]]), Apply( Select( New(Ident(runtimeClass)), - termName(context)("")), + termNames.CONSTRUCTOR), List( Select( context.prefix.tree, @@ -67,6 +67,7 @@ class RecorderMacro[C <: Context](val context: C) { termName(context)("completeRecording")), List()) + private[this] def resetValues: Tree = Apply( Select( @@ -142,13 +143,13 @@ Instrumented AST: ${showRaw(instrumented)}") } object RecorderMacro1 { - def apply(context: Context)(recording: context.Tree): context.Expr[Unit] = { - new RecorderMacro[context.type](context).apply(recording, context.literal("").tree) + def apply[R: context.WeakTypeTag, A: context.WeakTypeTag](context: Context)(recording: context.Tree): context.Expr[A] = { + new RecorderMacro[context.type](context).apply[R, A](recording, context.literal("").tree) } } object RecorderMacro { - def apply(context: Context)(recording: context.Tree, message: context.Tree): context.Expr[Unit] = { - new RecorderMacro[context.type](context).apply(recording, message) + def apply[R: context.WeakTypeTag, A : context.WeakTypeTag](context: Context)(recording: context.Tree, message: context.Tree): context.Expr[A] = { + new RecorderMacro[context.type](context).apply[R, A](recording, message) } } diff --git a/shared/src/main/scala-3/com/eed3si9n/expecty/Recorder.scala b/shared/src/main/scala-3/com/eed3si9n/expecty/Recorder.scala index 9143718..173ac28 100644 --- a/shared/src/main/scala-3/com/eed3si9n/expecty/Recorder.scala +++ b/shared/src/main/scala-3/com/eed3si9n/expecty/Recorder.scala @@ -15,10 +15,10 @@ package com.eed3si9n.expecty import language.experimental.macros -abstract class Recorder { - def listener: RecorderListener[Boolean] - inline def apply(recording: Boolean): Unit = +abstract class Recorder[R, A] { + def listener: RecorderListener[R, A] + inline def apply(recording: R): A = ${ RecorderMacro.apply('recording, 'listener) } - inline def apply(recording: Boolean, message: => String): Unit = + inline def apply(recording: R, message: => String): A = ${ RecorderMacro.apply('recording, 'message, 'listener) } } diff --git a/shared/src/main/scala-3/com/eed3si9n/expecty/RecorderMacro.scala b/shared/src/main/scala-3/com/eed3si9n/expecty/RecorderMacro.scala index 870bc96..ce3d183 100644 --- a/shared/src/main/scala-3/com/eed3si9n/expecty/RecorderMacro.scala +++ b/shared/src/main/scala-3/com/eed3si9n/expecty/RecorderMacro.scala @@ -19,16 +19,16 @@ import scala.tasty._ object RecorderMacro { implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader) - def apply( - recording: Expr[Boolean], - listener: Expr[RecorderListener[Boolean]]) given (qctx: QuoteContext): Expr[Unit] = { + def apply[R: Type, A: Type]( + recording: Expr[R], + listener: Expr[RecorderListener[R, A]]) given (qctx: QuoteContext): Expr[A] = { apply(recording, '{""}, listener) } - def apply( - recording: Expr[Boolean], + def apply[R: Type, A: Type]( + recording: Expr[R], message: Expr[String], - listener: Expr[RecorderListener[Boolean]]) given (qctx: QuoteContext): Expr[Unit] = { + listener: Expr[RecorderListener[R, A]]) given (qctx: QuoteContext): Expr[A] = { import qctx.tasty._ val termArg: Term = recording.unseal.underlyingArgument @@ -38,10 +38,10 @@ object RecorderMacro { } '{ - val recorderRuntime: RecorderRuntime = new RecorderRuntime($listener) + val recorderRuntime: RecorderRuntime[R, A] = new RecorderRuntime($listener) recorderRuntime.recordMessage($message) ${ - val runtimeSym = '[RecorderRuntime].unseal.symbol match { + val runtimeSym = '[RecorderRuntime[_, _]].unseal.symbol match { case IsClassDefSymbol(sym) => sym } val recordExpressionSel: Term = { @@ -151,9 +151,8 @@ object RecorderMacro { Block( recordExpressions(termArg), '{ recorderRuntime.completeRecording() }.unseal - ).seal + ).seal.cast[A] } - () } } } diff --git a/shared/src/main/scala/com/eed3si9n/expecty/Expecty.scala b/shared/src/main/scala/com/eed3si9n/expecty/Expecty.scala index 5cbc589..1536ae5 100644 --- a/shared/src/main/scala/com/eed3si9n/expecty/Expecty.scala +++ b/shared/src/main/scala/com/eed3si9n/expecty/Expecty.scala @@ -14,13 +14,13 @@ package com.eed3si9n.expecty -class Expecty extends Recorder { +class Expecty extends Recorder[Boolean, Unit] { val failEarly: Boolean = true val showTypes: Boolean = false // val printAsts: Boolean = false // val printExprs: Boolean = false - class ExpectyListener extends RecorderListener[Boolean] { + class ExpectyListener extends RecorderListener[Boolean, Unit] { override def expressionRecorded( recordedExpr: RecordedExpression[Boolean], recordedMessage: Function0[String]): Unit = { lazy val rendering: String = new ExpressionRenderer(showTypes).render(recordedExpr) @@ -35,6 +35,9 @@ class Expecty extends Recorder { throw new AssertionError(header + "\n\n" + rendering) } } + + override def recordingCompleted( + recording: Recording[Boolean], recordedMessage: Function0[String]) = {} } override lazy val listener = new ExpectyListener diff --git a/shared/src/main/scala/com/eed3si9n/expecty/RecorderListener.scala b/shared/src/main/scala/com/eed3si9n/expecty/RecorderListener.scala index 81c2635..05f3076 100644 --- a/shared/src/main/scala/com/eed3si9n/expecty/RecorderListener.scala +++ b/shared/src/main/scala/com/eed3si9n/expecty/RecorderListener.scala @@ -13,8 +13,8 @@ */ package com.eed3si9n.expecty -trait RecorderListener[T] { +trait RecorderListener[T, A] { def valueRecorded(recordedValue: RecordedValue): Unit = {} def expressionRecorded(recordedExpr: RecordedExpression[T], recordedMessage: Function0[String]): Unit = {} - def recordingCompleted(recording: Recording[T], recordedMessage: Function0[String]): Unit = {} + def recordingCompleted(recording: Recording[T], recordedMessage: Function0[String]): A } diff --git a/shared/src/main/scala/com/eed3si9n/expecty/RecorderRuntime.scala b/shared/src/main/scala/com/eed3si9n/expecty/RecorderRuntime.scala index c47e160..898ebda 100644 --- a/shared/src/main/scala/com/eed3si9n/expecty/RecorderRuntime.scala +++ b/shared/src/main/scala/com/eed3si9n/expecty/RecorderRuntime.scala @@ -14,9 +14,9 @@ package com.eed3si9n.expecty // one instance per recording -class RecorderRuntime(listener: RecorderListener[Boolean]) { +class RecorderRuntime[R, A](listener: RecorderListener[R, A]) { protected var recordedValues: List[RecordedValue] = _ - protected var recordedExprs: List[RecordedExpression[Boolean]] = List.empty + protected var recordedExprs: List[RecordedExpression[R]] = List.empty protected var recordedMessage: Function0[String] = () => "" def resetValues(): Unit = { @@ -34,13 +34,13 @@ class RecorderRuntime(listener: RecorderListener[Boolean]) { recordedMessage = () => message } - def recordExpression(text: String, ast: String, value: Boolean): Unit = { + def recordExpression(text: String, ast: String, value: R): Unit = { val recordedExpr = RecordedExpression(text, ast, value, recordedValues) listener.expressionRecorded(recordedExpr, recordedMessage) recordedExprs = recordedExpr :: recordedExprs } - def completeRecording(): Unit = { + def completeRecording(): A = { val lastRecorded = recordedExprs.head val recording = Recording(lastRecorded.value, recordedExprs) listener.recordingCompleted(recording, recordedMessage)