From deab513d1376cf66061b7bda840ee6403cb56f56 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:33:15 -0700 Subject: [PATCH] Debug: capture and log routes (splits) --- .../org/scalafmt/config/FormatEvent.scala | 1 + .../scalafmt/internal/BestFirstSearch.scala | 1 + .../src/test/scala/org/scalafmt/Debug.scala | 29 ++++++++++++++----- .../scala/org/scalafmt/util/HasTests.scala | 4 +-- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/FormatEvent.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/FormatEvent.scala index d6665c814..51b0f4a31 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/FormatEvent.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/FormatEvent.scala @@ -12,6 +12,7 @@ sealed abstract class FormatEvent object FormatEvent { case class CreateFormatOps(formatOps: FormatOps) extends FormatEvent + case class Routes(routes: IndexedSeq[Seq[Split]]) extends FormatEvent case class VisitToken(formatToken: FormatToken) extends FormatEvent case class Explored(n: Int, depth: Int, queueSize: Int) extends FormatEvent case class Enqueue(split: Split) extends FormatEvent diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/BestFirstSearch.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/BestFirstSearch.scala index 6f1683504..b589b28ca 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/BestFirstSearch.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/BestFirstSearch.scala @@ -320,6 +320,7 @@ private class BestFirstSearch private (range: Set[Range])(implicit style.runner.event(FormatEvent.CompleteFormat(explored, state, visits, best)) def getBestPath: SearchResult = { + initStyle.runner.event(FormatEvent.Routes(routes)) val state = { def run = shortestPath(State.start, topSourceTree.tokens.last) val state = run diff --git a/scalafmt-tests/shared/src/test/scala/org/scalafmt/Debug.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/Debug.scala index 015db9751..4a0dcdb03 100644 --- a/scalafmt-tests/shared/src/test/scala/org/scalafmt/Debug.scala +++ b/scalafmt-tests/shared/src/test/scala/org/scalafmt/Debug.scala @@ -1,6 +1,6 @@ package org.scalafmt -import org.scalafmt.config.FormatEvent.CompleteFormat +import org.scalafmt.config.FormatEvent._ import org.scalafmt.internal.FormatOps import org.scalafmt.internal.FormatWriter import org.scalafmt.internal.Split @@ -20,6 +20,7 @@ class Debug(val verbose: Boolean) { val enqueuedSplits = mutable.Set.empty[Split] var formatOps: FormatOps = _ + var routes: IndexedSeq[Seq[Split]] = _ var completedEvent: Option[CompleteFormat] = None var locations: FormatWriter#FormatLocations = _ val startTime = System.nanoTime() @@ -52,7 +53,7 @@ class Debug(val verbose: Boolean) { LoggerOps.logger.debug(sb.toString()) } - completedEvent.foreach(x => Debug.printCompletedEvent(x, formatOps)) + completedEvent.foreach(x => Debug.printCompletedEvent(x, routes, formatOps)) } } @@ -63,10 +64,13 @@ object Debug { def printCompletedEvent( completedEvent: CompleteFormat, + routes: IndexedSeq[Seq[Split]], formatOps: FormatOps, ): Unit = { val toks = if (null == formatOps) null else formatOps.tokens.arr if (null != toks) { + import LoggerOps._ + if (null != completedEvent.visits) { val sb = new StringBuilder() sb.append("Visited ").append(completedEvent.totalExplored).append(":") @@ -75,17 +79,26 @@ object Debug { .append(toks(idx)) } sb.append("\n") - LoggerOps.logger.debug(sb.toString()) + logger.debug(sb.toString()) } if (null != completedEvent.best) { val sb = new StringBuilder() sb.append("Best splits:") completedEvent.best.values.toSeq.sortBy(_.depth).take(5).foreach { - state => sb.append("\n\t").append(LoggerOps.log(state)) + state => sb.append("\n\t").append(log(state)) } sb.append("\n") - LoggerOps.logger.debug(sb.toString()) + logger.debug(sb.toString()) + } + + if (null ne routes) { + var tokidx = 0 + while (tokidx < toks.length) { + logger.debug(s"FT: ${log2(toks(tokidx))}") + routes(tokidx).foreach(s => logger.debug(s"> S: ${log(s)}")) + tokidx += 1 + } } val stack = new mutable.ListBuffer[String] @@ -95,7 +108,7 @@ object Debug { val prev = state.prev val idx = prev.depth val tok = toks(idx).left - val clean = "%-15s".format(LoggerOps.cleanup(tok).slice(0, 15)) + val clean = "%-15s".format(cleanup(tok).slice(0, 15)) stack.prepend( s"[$idx] ${posWidth.format(tok.end)}: $clean" + s" ${state.split} ${prev.indentation} ${prev.column} [${state.cost}]", @@ -105,8 +118,8 @@ object Debug { val finalState = completedEvent.finalState if (null != finalState) { if (finalState ne State.start) iter(finalState) - stack.foreach(LoggerOps.logger.debug) - LoggerOps.logger.debug(s"Total cost: ${finalState.cost}") + stack.foreach(logger.debug) + logger.debug(s"Total cost: ${finalState.cost}") } } } diff --git a/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/HasTests.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/HasTests.scala index 2ce23a591..f67c9e114 100644 --- a/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/HasTests.scala +++ b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/HasTests.scala @@ -30,8 +30,8 @@ trait HasTests extends FormatAssertions { maxStateVisits = 150000, eventCallback = { case CreateFormatOps(ops) => dg.formatOps = ops - case explored: Explored if explored.n % 10000 == 0 => - logger.elem(explored) + case Routes(routes) => dg.routes = routes + case explored: Explored if explored.n % 10000 == 0 => logger.elem(explored) case Enqueue(split) => dg.enqueued(split) case evt: CompleteFormat => dg.completed(evt) case x: Written => dg.locations = x.formatLocations