diff --git a/src/main/scala-3/com/raquo/airstream/core/ObservableMacroImplicits.scala b/src/main/scala-3/com/raquo/airstream/core/ObservableMacroImplicits.scala index 3b4308c..6914422 100644 --- a/src/main/scala-3/com/raquo/airstream/core/ObservableMacroImplicits.scala +++ b/src/main/scala-3/com/raquo/airstream/core/ObservableMacroImplicits.scala @@ -1,7 +1,7 @@ package com.raquo.airstream.core import com.raquo.airstream.core.{Observable, BaseObservable, Signal} -import com.raquo.airstream.split.{DuplicateKeysConfig, SplitMatchOneObservable, SplitMatchSeqObservable} +import com.raquo.airstream.split.* trait ObservableMacroImplicits { @@ -10,6 +10,37 @@ trait ObservableMacroImplicits { SplitMatchOneObservable.build(observable)()() } + extension [Self[+_] <: Observable[_], I, O]( + inline matchSplitObservable: SplitMatchOneObservable[Self, I, O] + ) { + inline def handleCase[A, B, O1 >: O](inline casePf: PartialFunction[A, B])(inline handleFn: (B, Signal[B]) => O1): SplitMatchOneObservable[Self, I, O1] = + SplitMatchOneMacros.deglateHandleCase(matchSplitObservable, casePf, handleFn) + + inline def handleType[T]: SplitMatchOneTypeObservable[Self, I, O, T] = + SplitMatchOneMacros.deglateHandleType(matchSplitObservable) + + inline def handleValue[V](inline v: V)(using inline valueOf: ValueOf[V]): SplitMatchOneValueObservable[Self, I, O, V] = + SplitMatchOneMacros.deglateHandleValue(matchSplitObservable, v) + } + + extension [Self[+_] <: Observable[_], I, O, T](inline matchTypeObserver: SplitMatchOneTypeObservable[Self, I, O, T]) { + inline def apply[O1 >: O](inline handleFn: (T, Signal[T]) => O1): SplitMatchOneObservable[Self, I, O1] = + SplitMatchOneMacros.deglateHandleTypeApply(matchTypeObserver, handleFn) + } + + extension [Self[+_] <: Observable[_], I, O, V](inline matchValueObservable: SplitMatchOneValueObservable[Self, I, O, V]) { + inline def apply[O1 >: O](inline handle: => O1): SplitMatchOneObservable[Self, I, O1] = + SplitMatchOneMacros.deglateHandleValueApply(matchValueObservable, (_, _) => handle) + } + + extension [I, O](inline matchSplitObservable: SplitMatchOneObservable[Signal, I, O]) { + inline def toSignal: Signal[O] = SplitMatchOneMacros.deglateToSignal(matchSplitObservable) + } + + extension [I, O](inline matchSplitObservable: SplitMatchOneObservable[EventStream, I, O]) { + inline def toStream: EventStream[O] = SplitMatchOneMacros.deglateToStream(matchSplitObservable) + } + extension [Self[+_] <: Observable[_], I, K, CC[_]](inline observable: BaseObservable[Self, CC[I]]) { inline def splitMatchSeq( inline keyFn: Function1[I, K], @@ -19,4 +50,31 @@ trait ObservableMacroImplicits { SplitMatchSeqObservable.build(keyFn, distinctCompose, duplicateKeysConfig, observable)()() } } + + extension [Self[+_] <: Observable[_], I, K, O, CC[_]]( + inline matchSplitObservable: SplitMatchSeqObservable[Self, I, K, O, CC] + ) { + inline def handleCase[A, B, O1 >: O](inline casePf: PartialFunction[A, B])(inline handleFn: (B, Signal[B]) => O1): SplitMatchSeqObservable[Self, I, K, O1, CC] = + SplitMatchSeqMacros.deglateHandleCase(matchSplitObservable, casePf, handleFn) + + inline def handleType[T]: SplitMatchSeqTypeObservable[Self, I, K, O, CC, T] = + SplitMatchSeqMacros.deglateHandleType(matchSplitObservable) + + inline def handleValue[V](inline v: V)(using inline valueOf: ValueOf[V]): SplitMatchSeqValueObservable[Self, I, K, O, CC, V] = + SplitMatchSeqMacros.deglateHandleValue(matchSplitObservable, v) + + inline def toSignal: Signal[CC[O]] = + SplitMatchSeqMacros.deglateToSignal(matchSplitObservable) + } + + extension [Self[+_] <: Observable[_], I, K, O, CC[_], T](inline matchTypeObserver: SplitMatchSeqTypeObservable[Self, I, K, O, CC, T]) { + inline def apply[O1 >: O](inline handleFn: (T, Signal[T]) => O1): SplitMatchSeqObservable[Self, I, K, O1, CC] = + SplitMatchSeqMacros.deglateHandleTypeApply(matchTypeObserver, handleFn) + } + + extension [Self[+_] <: Observable[_], I, K, O, CC[_], V](inline matchValueObservable: SplitMatchSeqValueObservable[Self, I, K, O, CC, V]) { + + inline def apply[O1 >: O](inline handle: => O1): SplitMatchSeqObservable[Self, I, K, O1, CC] = + SplitMatchSeqMacros.deglateHandleValueApply(matchValueObservable, (_, _) => handle) + } } diff --git a/src/main/scala-3/com/raquo/airstream/split/SplitMatchOneMacros.scala b/src/main/scala-3/com/raquo/airstream/split/SplitMatchOneMacros.scala index 85621bd..baad9ad 100644 --- a/src/main/scala-3/com/raquo/airstream/split/SplitMatchOneMacros.scala +++ b/src/main/scala-3/com/raquo/airstream/split/SplitMatchOneMacros.scala @@ -52,46 +52,53 @@ import scala.reflect.TypeTest */ object SplitMatchOneMacros { - extension [Self[+_] <: Observable[_], I, O]( - inline matchSplitObservable: SplitMatchOneObservable[Self, I, O] - ) { - inline def handleCase[A, B, O1 >: O](inline casePf: PartialFunction[A, B])(inline handleFn: (B, Signal[B]) => O1) = ${ - handleCaseImpl('{ matchSplitObservable }, '{ casePf }, '{ handleFn }) - } - - inline def handleType[T]: SplitMatchOneTypeObservable[Self, I, O, T] = ${ - handleTypeImpl[Self, I, O, T]('{ matchSplitObservable }) - } + private[airstream] inline def deglateHandleCase[Self[+_] <: Observable[_], I, O, A, B, O1 >: O]( + inline matchSplitObservable: SplitMatchOneObservable[Self, I, O], + inline casePf: PartialFunction[A, B], + inline handleFn: (B, Signal[B]) => O1 + ) = ${ + handleCaseImpl('{ matchSplitObservable }, '{ casePf }, '{ handleFn }) + } - inline def handleValue[V](inline v: V)(using inline valueOf: ValueOf[V]): SplitMatchOneValueObservable[Self, I, O, V] = ${ - handleValueImpl[Self, I, O, V]('{ matchSplitObservable }, '{ v }) - } + private[airstream] inline def deglateHandleType[Self[+_] <: Observable[_], I, O, T]( + inline matchSplitObservable: SplitMatchOneObservable[Self, I, O] + ) = ${ + handleTypeImpl[Self, I, O, T]('{ matchSplitObservable }) } - extension [Self[+_] <: Observable[_], I, O, T](inline matchTypeObserver: SplitMatchOneTypeObservable[Self, I, O, T]) { - inline def apply[O1 >: O](inline handleFn: (T, Signal[T]) => O1): SplitMatchOneObservable[Self, I, O1] = ${ - handleTypeApplyImpl('{ matchTypeObserver }, '{ handleFn }) - } + private[airstream] inline def deglateHandleValue[Self[+_] <: Observable[_], I, O, V]( + inline matchSplitObservable: SplitMatchOneObservable[Self, I, O], + inline v: V + )( + using inline valueOf: ValueOf[V] + ) = ${ + handleValueImpl[Self, I, O, V]('{ matchSplitObservable }, '{ v }) } - extension [Self[+_] <: Observable[_], I, O, V](inline matchValueObservable: SplitMatchOneValueObservable[Self, I, O, V]) { - inline private def delegate[O1 >: O](inline handleFn: (V, Signal[V]) => O1) = ${ - handleValueApplyImpl('{ matchValueObservable }, '{ handleFn }) - } + private[airstream] inline def deglateHandleTypeApply[Self[+_] <: Observable[_], I, O, T, O1 >: O]( + inline matchTypeObserver: SplitMatchOneTypeObservable[Self, I, O, T], + inline handleFn: (T, Signal[T]) => O1 + ) = ${ + handleTypeApplyImpl('{ matchTypeObserver }, '{ handleFn }) + } - inline def apply[O1 >: O](inline handle: => O1): SplitMatchOneObservable[Self, I, O1] = delegate { (_, _) => handle } + private[airstream] inline def deglateHandleValueApply[Self[+_] <: Observable[_], I, O, V, O1 >: O]( + inline matchValueObservable: SplitMatchOneValueObservable[Self, I, O, V], + inline handleFn: (V, Signal[V]) => O1 + ) = ${ + handleValueApplyImpl('{ matchValueObservable }, '{ handleFn }) } - extension [I, O](inline matchSplitObservable: SplitMatchOneObservable[Signal, I, O]) { - inline def toSignal: Signal[O] = ${ - observableImpl('{ matchSplitObservable }) - } + private[airstream] inline def deglateToSignal[I, O]( + inline matchSplitObservable: SplitMatchOneObservable[Signal, I, O] + ) = ${ + observableImpl('{ matchSplitObservable }) } - extension [I, O](inline matchSplitObservable: SplitMatchOneObservable[EventStream, I, O]) { - inline def toStream: EventStream[O] = ${ - observableImpl('{ matchSplitObservable }) - } + private[airstream] inline def deglateToStream[I, O]( + inline matchSplitObservable: SplitMatchOneObservable[EventStream, I, O] + ) = ${ + observableImpl('{ matchSplitObservable }) } private def handleCaseImpl[Self[+_] <: Observable[_]: Type, I: Type, O: Type, O1 >: O: Type, A: Type, B: Type]( diff --git a/src/main/scala-3/com/raquo/airstream/split/SplitMatchSeqMacros.scala b/src/main/scala-3/com/raquo/airstream/split/SplitMatchSeqMacros.scala index 1780502..f6a3f20 100644 --- a/src/main/scala-3/com/raquo/airstream/split/SplitMatchSeqMacros.scala +++ b/src/main/scala-3/com/raquo/airstream/split/SplitMatchSeqMacros.scala @@ -14,38 +14,47 @@ import com.raquo.airstream.split.MacrosUtilities.{CaseAny, HandlerAny, MatchType object SplitMatchSeqMacros { - extension [Self[+_] <: Observable[_], I, K, O, CC[_]]( - inline matchSplitObservable: SplitMatchSeqObservable[Self, I, K, O, CC] - ) { - inline def handleCase[A, B, O1 >: O](inline casePf: PartialFunction[A, B])(inline handleFn: (B, Signal[B]) => O1) = ${ - handleCaseImpl('{ matchSplitObservable }, '{ casePf }, '{ handleFn }) - } - - inline def handleType[T]: SplitMatchSeqTypeObservable[Self, I, K, O, CC, T] = ${ - handleTypeImpl('{ matchSplitObservable }) - } - - inline def handleValue[V](inline v: V)(using inline valueOf: ValueOf[V]): SplitMatchSeqValueObservable[Self, I, K, O, CC, V] = ${ - handleValueImpl('{ matchSplitObservable }, '{ v }) - } + private[airstream] inline def deglateHandleCase[Self[+_] <: Observable[_], I, K, O, CC[_], A, B, O1 >: O]( + inline matchSplitObservable: SplitMatchSeqObservable[Self, I, K, O, CC], + inline casePf: PartialFunction[A, B], + inline handleFn: (B, Signal[B]) => O1 + ) = ${ + handleCaseImpl('{ matchSplitObservable }, '{ casePf }, '{ handleFn }) + } - inline def toSignal: Signal[CC[O]] = ${ observableImpl('{ matchSplitObservable }) } + private[airstream] inline def deglateHandleType[Self[+_] <: Observable[_], I, K, O, CC[_], T]( + inline matchSplitObservable: SplitMatchSeqObservable[Self, I, K, O, CC] + ) = ${ + handleTypeImpl[Self, I, K, O, CC, T]('{ matchSplitObservable }) } - extension [Self[+_] <: Observable[_], I, K, O, CC[_], T](inline matchTypeObserver: SplitMatchSeqTypeObservable[Self, I, K, O, CC, T]) { - inline def apply[O1 >: O](inline handleFn: (T, Signal[T]) => O1): SplitMatchSeqObservable[Self, I, K, O1, CC] = ${ - handleTypeApplyImpl('{ matchTypeObserver }, '{ handleFn }) - } + private[airstream] inline def deglateHandleValue[Self[+_] <: Observable[_], I, K, O, CC[_], V]( + inline matchSplitObservable: SplitMatchSeqObservable[Self, I, K, O, CC], + inline v: V + )( + using inline valueOf: ValueOf[V] + ) = ${ + handleValueImpl('{ matchSplitObservable }, '{ v }) } - extension [Self[+_] <: Observable[_], I, K, O, CC[_], V](inline matchValueObservable: SplitMatchSeqValueObservable[Self, I, K, O, CC, V]) { - inline private def delegate[O1 >: O](inline handleFn: (V, Signal[V]) => O1) = ${ - handleValueApplyImpl('{ matchValueObservable }, '{ handleFn }) - } + private[airstream] inline def deglateHandleTypeApply[Self[+_] <: Observable[_], I, K, O, CC[_], T, O1 >: O]( + inline matchTypeObserver: SplitMatchSeqTypeObservable[Self, I, K, O, CC, T], + inline handleFn: (T, Signal[T]) => O1 + ) = ${ + handleTypeApplyImpl('{ matchTypeObserver }, '{ handleFn }) + } - inline def apply[O1 >: O](inline handle: => O1): SplitMatchSeqObservable[Self, I, K, O1, CC] = delegate { (_, _) => handle } + private[airstream] inline def deglateHandleValueApply[Self[+_] <: Observable[_], I, K, O, CC[_], V, O1 >: O]( + inline matchValueObservable: SplitMatchSeqValueObservable[Self, I, K, O, CC, V], + inline handleFn: (V, Signal[V]) => O1 + ) = ${ + handleValueApplyImpl('{ matchValueObservable }, '{ handleFn }) } + private[airstream] inline def deglateToSignal[Self[+_] <: Observable[_], I, K, O, CC[_]]( + inline matchSplitObservable: SplitMatchSeqObservable[Self, I, K, O, CC] + ) = ${ observableImpl('{ matchSplitObservable }) } + private def handleCaseImpl[Self[+_] <: Observable[_]: Type, I: Type, K: Type, O: Type, O1 >: O: Type, CC[_]: Type, A: Type, B: Type]( matchSplitObservableExpr: Expr[SplitMatchSeqObservable[Self, I, K, O, CC]], casePfExpr: Expr[PartialFunction[A, B]], diff --git a/src/test/scala-3/com/raquo/airstream/split/SplitMatchOneSpec.scala b/src/test/scala-3/com/raquo/airstream/split/SplitMatchOneSpec.scala index 85a7463..a6f481b 100644 --- a/src/test/scala-3/com/raquo/airstream/split/SplitMatchOneSpec.scala +++ b/src/test/scala-3/com/raquo/airstream/split/SplitMatchOneSpec.scala @@ -4,7 +4,6 @@ import com.raquo.airstream.UnitSpec import com.raquo.airstream.eventbus.EventBus import com.raquo.airstream.fixtures.{Effect, TestableOwner} import com.raquo.airstream.state.Var -import com.raquo.airstream.split.SplitMatchOneMacros.* import scala.collection.{immutable, mutable} import scala.scalajs.js diff --git a/src/test/scala-3/com/raquo/airstream/split/SplitMatchSeqSpec.scala b/src/test/scala-3/com/raquo/airstream/split/SplitMatchSeqSpec.scala index 76a48ff..476975a 100644 --- a/src/test/scala-3/com/raquo/airstream/split/SplitMatchSeqSpec.scala +++ b/src/test/scala-3/com/raquo/airstream/split/SplitMatchSeqSpec.scala @@ -6,7 +6,6 @@ import com.raquo.airstream.eventbus.EventBus import com.raquo.airstream.fixtures.{Effect, TestableOwner} import com.raquo.airstream.ownership.{DynamicOwner, DynamicSubscription, ManualOwner, Subscription} import com.raquo.airstream.split.DuplicateKeysConfig -import com.raquo.airstream.split.SplitMatchSeqMacros.* import com.raquo.airstream.state.Var import com.raquo.ew.{JsArray, JsVector} import org.scalatest.{Assertion, BeforeAndAfter}