From 089be16b0bb5ac3250d6101a14204f2750bc22d5 Mon Sep 17 00:00:00 2001 From: Nikita Gazarov Date: Sat, 25 Nov 2023 02:19:44 +0100 Subject: [PATCH] API: Shorten default displayName-s, use pretty default names for var signals and eventbus streams --- .../com/raquo/airstream/core/Named.scala | 2 +- .../raquo/airstream/eventbus/EventBus.scala | 2 +- .../airstream/eventbus/EventBusStream.scala | 6 ++- .../raquo/airstream/eventbus/WriteBus.scala | 17 +++++--- .../raquo/airstream/state/DerivedVar.scala | 7 +++- .../airstream/state/DerivedVarSignal.scala | 5 ++- .../com/raquo/airstream/state/SourceVar.scala | 5 ++- .../scala/com/raquo/airstream/state/Var.scala | 2 +- .../com/raquo/airstream/state/VarSignal.scala | 5 ++- .../scala/com/raquo/airstream/DebugSpec.scala | 42 +++++++++++++++++++ 10 files changed, 79 insertions(+), 14 deletions(-) diff --git a/src/main/scala/com/raquo/airstream/core/Named.scala b/src/main/scala/com/raquo/airstream/core/Named.scala index d311ab79..769088f4 100644 --- a/src/main/scala/com/raquo/airstream/core/Named.scala +++ b/src/main/scala/com/raquo/airstream/core/Named.scala @@ -16,7 +16,7 @@ trait Named { protected[this] var maybeDisplayName: js.UndefOr[String] = js.undefined /** This is the method that subclasses override to preserve the user's ability to set custom display names. */ - protected def defaultDisplayName: String = super.toString + protected def defaultDisplayName: String = s"${getClass.getSimpleName}@${hashCode()}" /** Override [[defaultDisplayName]] instead of this, if you need to. */ final override def toString: String = displayName diff --git a/src/main/scala/com/raquo/airstream/eventbus/EventBus.scala b/src/main/scala/com/raquo/airstream/eventbus/EventBus.scala index c66ef342..b993ec49 100644 --- a/src/main/scala/com/raquo/airstream/eventbus/EventBus.scala +++ b/src/main/scala/com/raquo/airstream/eventbus/EventBus.scala @@ -13,7 +13,7 @@ import scala.util.Try */ class EventBus[A] extends EventSource[A] with Sink[A] with Named { - val writer: WriteBus[A] = new WriteBus[A] + val writer: WriteBus[A] = new WriteBus[A](parentDisplayName = displayName) val events: EventStream[A] = writer.stream diff --git a/src/main/scala/com/raquo/airstream/eventbus/EventBusStream.scala b/src/main/scala/com/raquo/airstream/eventbus/EventBusStream.scala index 49434144..65976a07 100644 --- a/src/main/scala/com/raquo/airstream/eventbus/EventBusStream.scala +++ b/src/main/scala/com/raquo/airstream/eventbus/EventBusStream.scala @@ -4,7 +4,9 @@ import com.raquo.airstream.common.InternalNextErrorObserver import com.raquo.airstream.core.{EventStream, Protected, Transaction, WritableStream} import com.raquo.ew.JsArray -class EventBusStream[A] private[eventbus] () extends WritableStream[A] with InternalNextErrorObserver[A] { +class EventBusStream[A] private[eventbus] ( + parentDisplayName: => String +) extends WritableStream[A] with InternalNextErrorObserver[A] { private val sourceStreams: JsArray[EventStream[A]] = JsArray() @@ -72,4 +74,6 @@ class EventBusStream[A] private[eventbus] () extends WritableStream[A] with Inte sourceStreams.forEach(_.removeInternalObserver(observer = this)) super.onStop() } + + override protected def defaultDisplayName: String = parentDisplayName + ".events" } diff --git a/src/main/scala/com/raquo/airstream/eventbus/WriteBus.scala b/src/main/scala/com/raquo/airstream/eventbus/WriteBus.scala index 757629c5..9e7f62fe 100644 --- a/src/main/scala/com/raquo/airstream/eventbus/WriteBus.scala +++ b/src/main/scala/com/raquo/airstream/eventbus/WriteBus.scala @@ -6,12 +6,15 @@ import com.raquo.airstream.util.hasDuplicateTupleKeys import scala.util.Try -class WriteBus[A] extends Observer[A] { +class WriteBus[A]( + parentDisplayName: => String, + displayNameSuffix: String = ".writer" +) extends Observer[A] { /** Hidden here because the public interface of WriteBus is all about writing * rather than reading, but exposed in [[EventBus]] */ - private[eventbus] val stream: EventBusStream[A] = new EventBusStream() + private[eventbus] val stream: EventBusStream[A] = new EventBusStream(displayName) /** Note: this source will be removed when the `owner` you provide says so. * To remove this source manually, call .kill() on the resulting Subscription. @@ -24,19 +27,21 @@ class WriteBus[A] extends Observer[A] { } def contracomposeWriter[B](operator: EventStream[B] => EventStream[A])(implicit owner: Owner): WriteBus[B] = { - val mapBus = new WriteBus[B] + val mapBus = new WriteBus[B](displayName, ".contracomposeWriter") addSource(mapBus.stream.compose(operator))(owner) mapBus } /** Behaves similar to `contramap`, but gives you a WriteBus, not just an Observer */ def contramapWriter[B](project: B => A)(implicit owner: Owner): WriteBus[B] = { - contracomposeWriter[B](_.map(project))(owner) + val mapBus = new WriteBus[B](displayName, ".contramapWriter") + addSource(mapBus.stream.map(project))(owner) + mapBus } /** Behaves similar to `filter`, but gives you a WriteBus, not just an Observer */ def filterWriter(passes: A => Boolean)(implicit owner: Owner): WriteBus[A] = { - val filterBus = new WriteBus[A] + val filterBus = new WriteBus[A](displayName, ".filterWriter") addSource(filterBus.stream.filter(passes))(owner) filterBus } @@ -80,6 +85,8 @@ class WriteBus[A] extends Observer[A] { onNextWithSharedTransaction(_, sharedTransaction) ) } + + override protected def defaultDisplayName: String = parentDisplayName + displayNameSuffix } object WriteBus { diff --git a/src/main/scala/com/raquo/airstream/state/DerivedVar.scala b/src/main/scala/com/raquo/airstream/state/DerivedVar.scala index 25a2b15f..097a3cc2 100644 --- a/src/main/scala/com/raquo/airstream/state/DerivedVar.scala +++ b/src/main/scala/com/raquo/airstream/state/DerivedVar.scala @@ -17,12 +17,13 @@ class DerivedVar[A, B]( parent: Var[A], zoomIn: A => B, zoomOut: (A, B) => A, - owner: Owner + owner: Owner, + displayNameSuffix: String ) extends Var[B] { override private[state] def underlyingVar: SourceVar[_] = parent.underlyingVar - private[this] val _varSignal = new DerivedVarSignal(parent, zoomIn, owner) + private[this] val _varSignal = new DerivedVarSignal(parent, zoomIn, owner, displayName) // #Note this getCurrentValue implementation is different from SourceVar // - SourceVar's getCurrentValue looks at an internal currentValue variable @@ -54,4 +55,6 @@ class DerivedVar[A, B]( } override val signal: StrictSignal[B] = _varSignal + + override protected def defaultDisplayName: String = parent.displayName + displayNameSuffix } diff --git a/src/main/scala/com/raquo/airstream/state/DerivedVarSignal.scala b/src/main/scala/com/raquo/airstream/state/DerivedVarSignal.scala index 766f33ed..fe253a12 100644 --- a/src/main/scala/com/raquo/airstream/state/DerivedVarSignal.scala +++ b/src/main/scala/com/raquo/airstream/state/DerivedVarSignal.scala @@ -7,7 +7,8 @@ import com.raquo.airstream.ownership.{Owner, Subscription} class DerivedVarSignal[A, B]( parent: Var[A], zoomIn: A => B, - owner: Owner + owner: Owner, + parentDisplayName: => String ) extends MapSignal[A, B]( parent.signal, project = zoomIn, @@ -18,4 +19,6 @@ class DerivedVarSignal[A, B]( override protected[state] def isStarted: Boolean = super.isStarted override protected[this] val subscription: Subscription = this.addObserver(Observer.empty)(owner) + + override protected def defaultDisplayName: String = parentDisplayName + ".signal" } diff --git a/src/main/scala/com/raquo/airstream/state/SourceVar.scala b/src/main/scala/com/raquo/airstream/state/SourceVar.scala index 68dc465a..becd7837 100644 --- a/src/main/scala/com/raquo/airstream/state/SourceVar.scala +++ b/src/main/scala/com/raquo/airstream/state/SourceVar.scala @@ -13,7 +13,10 @@ class SourceVar[A] private[state](initial: Try[A]) extends Var[A] { private[this] var currentValue: Try[A] = initial /** VarSignal is a private type, do not expose it */ - private[this] val _varSignal = new VarSignal[A](initial = currentValue) + private[this] val _varSignal = new VarSignal[A]( + initial = currentValue, + parentDisplayName = displayName + ) override private[state] def underlyingVar: SourceVar[_] = this diff --git a/src/main/scala/com/raquo/airstream/state/Var.scala b/src/main/scala/com/raquo/airstream/state/Var.scala index dbb116d7..aa7e96e4 100644 --- a/src/main/scala/com/raquo/airstream/state/Var.scala +++ b/src/main/scala/com/raquo/airstream/state/Var.scala @@ -84,7 +84,7 @@ trait Var[A] extends SignalSource[A] with Sink[A] with Named { } def zoom[B](in: A => B)(out: (A, B) => A)(implicit owner: Owner): Var[B] = { - new DerivedVar[A, B](this, in, out, owner) + new DerivedVar[A, B](this, in, out, owner, displayNameSuffix = ".zoom") } def setTry(tryValue: Try[A]): Unit = writer.onTry(tryValue) diff --git a/src/main/scala/com/raquo/airstream/state/VarSignal.scala b/src/main/scala/com/raquo/airstream/state/VarSignal.scala index a9f92b59..8786f69e 100644 --- a/src/main/scala/com/raquo/airstream/state/VarSignal.scala +++ b/src/main/scala/com/raquo/airstream/state/VarSignal.scala @@ -12,7 +12,8 @@ import scala.util.Try * (see StrictSignal). */ private[state] class VarSignal[A] private[state]( - initial: Try[A] + initial: Try[A], + parentDisplayName: => String ) extends WritableSignal[A] with StrictSignal[A] { /** SourceVar does not directly depend on other observables, so it breaks the graph. */ @@ -31,4 +32,6 @@ private[state] class VarSignal[A] private[state]( override protected def currentValueFromParent(): Try[A] = tryNow() // noop override protected def onWillStart(): Unit = () // noop + + override protected def defaultDisplayName: String = parentDisplayName + ".signal" } diff --git a/src/test/scala/com/raquo/airstream/DebugSpec.scala b/src/test/scala/com/raquo/airstream/DebugSpec.scala index 847314de..08b53a7c 100644 --- a/src/test/scala/com/raquo/airstream/DebugSpec.scala +++ b/src/test/scala/com/raquo/airstream/DebugSpec.scala @@ -833,4 +833,46 @@ class DebugSpec extends UnitSpec with BeforeAndAfter { calculations.clear() } + + it("EventBus.events and Var.signal display names") { + + val bus = new EventBus[Int] + + assert(bus.displayName.startsWith("EventBus@")) + assertEquals(bus.events.displayName, bus.displayName + ".writer.events") + + // -- + + bus.setDisplayName("bus") + + assertEquals(bus.writer.displayName, "bus.writer") + assertEquals(bus.events.displayName, "bus.writer.events") + assertEquals(bus.writer.contramapWriter(identity[Int]).displayName, "bus.writer.contramapWriter") + + // -- + + val _var = Var(1) + val _derived = _var.zoom(x => x)((acc, x) => x) + + assert(_var.displayName.startsWith("SourceVar@")) + assertEquals(_var.signal.displayName, _var.displayName + ".signal") + assertEquals(_derived.displayName, _var.displayName + ".zoom") + assertEquals(_derived.signal.displayName, _derived.displayName + ".signal") + + // -- + + _var.setDisplayName("var") + + assertEquals(_var.displayName, "var") + assertEquals(_var.signal.displayName, "var.signal") + assertEquals(_derived.displayName, _var.displayName + ".zoom") + assertEquals(_derived.signal.displayName, _derived.displayName + ".signal") + + // -- + + _derived.setDisplayName("zoomed") + + assertEquals(_derived.displayName, "zoomed") + assertEquals(_derived.signal.displayName, _derived.displayName + ".signal") + } }