diff --git a/parsley-debug/shared/src/main/scala/parsley/debugger/frontend/ConsolePrettyPrinter.scala b/parsley-debug/shared/src/main/scala/parsley/debugger/frontend/ConsolePrettyPrinter.scala index 5cb424281..42a0aeb43 100644 --- a/parsley-debug/shared/src/main/scala/parsley/debugger/frontend/ConsolePrettyPrinter.scala +++ b/parsley-debug/shared/src/main/scala/parsley/debugger/frontend/ConsolePrettyPrinter.scala @@ -9,7 +9,7 @@ import parsley.debugger.DebugTree import parsley.debugger.frontend.internal.consolepretty.* private [frontend] sealed class ConsolePrettyPrinterImpl private[frontend] (ioF: String => Unit) extends ReusableFrontend { - override protected def processImpl(input: => String, tree: => DebugTree): Unit = { + override private [debugger] def process(input: => String, tree: => DebugTree): Unit = { ioF(s"${tree.parserName}'s parse tree for input:\n\n$input\n\n") ioF(tree.pretty + "\n") } diff --git a/parsley-debug/shared/src/main/scala/parsley/debugger/frontend/DebugFrontend.scala b/parsley-debug/shared/src/main/scala/parsley/debugger/frontend/DebugFrontend.scala index b9d07edff..385ed254c 100644 --- a/parsley-debug/shared/src/main/scala/parsley/debugger/frontend/DebugFrontend.scala +++ b/parsley-debug/shared/src/main/scala/parsley/debugger/frontend/DebugFrontend.scala @@ -26,37 +26,12 @@ import parsley.debugger.internal.XIllegalStateException * @since 4.5.0 */ sealed trait DebugFrontend { - // Is this frontend stateful (and should only be able to run once)? - protected [frontend] val reusable: Boolean - - // Tracks if this frontend has run already. - private var hasRun: Boolean = false - - // This function localises the use of synchronized down to this expression only. - @inline private def hasBeenRun: Boolean = this.synchronized { - (reusable && hasRun) || { hasRun = true; false } - } - /** Process a debug tree using whatever the frontend is doing to present the tree in some way. * * @param input The full input of the parse. * @param tree Debug tree to process. */ - final def process(input: => String, tree: => DebugTree): Unit = { - if (hasBeenRun) { - // XXX: There isn't really another way to enforce not running a stateful frontend more than once that isn't just "do nothing". - // Especially since doing nothing turns that action into a silent error, which is generally less preferable to "loud" - // errors. Failing fast may be better for some frontends. - throw new XIllegalStateException("Stateful frontend has already been run.").except // scalastyle:ignore throw - } else { - processImpl(input, tree) - } - } - - /** The actual method that does the processing of the tree. - * Override this to process a tree in a custom way. - */ - protected def processImpl(input: => String, tree: => DebugTree): Unit + private [debugger] def process(input: =>String, tree: => DebugTree): Unit } /** Signifies that the frontend inheriting from this can be used multiple times. @@ -64,9 +39,7 @@ sealed trait DebugFrontend { * @see [[DebugFrontend]] * @since 4.5.0 */ -trait ReusableFrontend extends DebugFrontend { - override protected [frontend] final val reusable: Boolean = false -} +trait ReusableFrontend extends DebugFrontend /** Signifies that the frontend inheriting from this can only be run once. * @@ -74,5 +47,18 @@ trait ReusableFrontend extends DebugFrontend { * @since 4.5.0 */ trait SingleUseFrontend extends DebugFrontend { - override protected [frontend] final val reusable: Boolean = true + private var hasBeenRun = false + final override private[debugger] def process(input: => String, tree: => DebugTree): Unit = { + if (hasBeenRun) { + // XXX: There isn't really another way to enforce not running a stateful frontend more than once that isn't just "do nothing". + // Especially since doing nothing turns that action into a silent error, which is generally less preferable to "loud" + // errors. Failing fast may be better for some frontends. + throw new XIllegalStateException("Stateful frontend has already been run.").except // scalastyle:ignore throw + } else { + processImpl(input, tree) + hasBeenRun = true + } + } + /** The implementation of the process method above */ + private[debugger] def processImpl(input: => String, tree: => DebugTree): Unit } diff --git a/parsley-debug/shared/src/test/scala/parsley/debugger/frontend/ReuseSpec.scala b/parsley-debug/shared/src/test/scala/parsley/debugger/frontend/ReuseSpec.scala index fadf74a88..f9bf56066 100644 --- a/parsley-debug/shared/src/test/scala/parsley/debugger/frontend/ReuseSpec.scala +++ b/parsley-debug/shared/src/test/scala/parsley/debugger/frontend/ReuseSpec.scala @@ -16,11 +16,11 @@ class ReuseSpec extends ParsleyTest { it should "throw when run multiple times, only if the frontend is marked as single-use" in { // Dummy values. val reusable: ReusableFrontend = new ReusableFrontend { - override protected def processImpl(input: => String, tree: => DebugTree): Unit = () + override private [debugger] def process(input: => String, tree: => DebugTree): Unit = () } val singleUse: SingleUseFrontend = new SingleUseFrontend { - override protected def processImpl(input: => String, tree: => DebugTree): Unit = () + override private [debugger] def processImpl(input: => String, tree: => DebugTree): Unit = () } val tree: DebugTree = new DebugTree {