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 f28320ae69..85bced1ad0 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 @@ -45,10 +45,9 @@ private class BestFirstSearch private ( val noOptimizations = noOptimizationZones(tree) var explored = 0 var deepestYet = State.start - var statementCount = 0 val best = mutable.Map.empty[Int, State] - var pathologicalEscapes = 0 val visits = new Array[Int](tokens.length) + var keepSlowStates = !pruneSlowStates type StateHash = Long @@ -60,17 +59,11 @@ private class BestFirstSearch private ( /** * Returns true if it's OK to skip over state. */ - def shouldEnterState(curr: State): Boolean = { - val splitToken = tokens(curr.depth) - val insideOptimizationZone = - curr.policy.noDequeue || isInsideNoOptZone(splitToken) - def hasBestSolution = !pruneSlowStates || insideOptimizationZone || { + def shouldEnterState(curr: State): Boolean = + keepSlowStates || curr.policy.noDequeue || + isInsideNoOptZone(tokens(curr.depth)) || // TODO(olafur) document why/how this optimization works. - val result = !best.get(curr.depth).exists(_.alwaysBetter(curr)) - result - } - hasBestSolution - } + !best.get(curr.depth).exists(_.alwaysBetter(curr)) def shouldRecurseOnBlock( ft: FormatToken, @@ -208,7 +201,7 @@ private class BestFirstSearch private ( var optimalNotFound = true actualSplit.foreach { split => val nextState = curr.next(style, split, splitToken) - if (depth == 0 && split.modification.isNewline && + if (!keepSlowStates && depth == 0 && split.modification.isNewline && !best.contains(curr.depth)) { best.update(curr.depth, nextState) } @@ -254,7 +247,16 @@ private class BestFirstSearch private ( } def getBestPath: SearchResult = { - val state = shortestPath(State.start, tree.tokens.last) + val state = { + def run = shortestPath(State.start, tree.tokens.last) + val state = run + if (null != state) state + else { + best.clear() + keepSlowStates = true + run + } + } if (null != state) { runner.event(CompleteFormat(explored, state)) SearchResult(state, reachedEOF = true) diff --git a/scalafmt-tests/src/test/resources/align/DefaultWithAlign.stat b/scalafmt-tests/src/test/resources/align/DefaultWithAlign.stat index 05532a69e2..09e2c3441d 100644 --- a/scalafmt-tests/src/test/resources/align/DefaultWithAlign.stat +++ b/scalafmt-tests/src/test/resources/align/DefaultWithAlign.stat @@ -483,3 +483,73 @@ object x { // comment println("foo") // comment } +<<< #1720 original, two SL comments +type iovec = CStruct2[Ptr[Byte], // iov_base + CSize] // iov_len +>>> +type iovec = CStruct2[ + Ptr[Byte], // iov_base + CSize +] // iov_len +<<< #1720 with val +val iovec = CStruct2[Ptr[Byte], // iov_base + CSize](a) // iov_len +>>> +val iovec = CStruct2[ + Ptr[Byte], // iov_base + CSize +](a) // iov_len +<<< #1720 no align +align = none +=== +type iovec = CStruct2[Ptr[Byte], // iov_base + CSize] // iov_len +>>> +type iovec = CStruct2[ + Ptr[Byte], // iov_base + CSize +] // iov_len +<<< #1720 second SL comment +type iovec = CStruct2[Ptr[Byte], + CSize] // iov_len +>>> +type iovec = CStruct2[Ptr[Byte], CSize] // iov_len +<<< #1720 first SL comment +type iovec = CStruct2[Ptr[Byte], // iov_base + CSize] +>>> +type iovec = CStruct2[ + Ptr[Byte], // iov_base + CSize +] +<<< #1720 nested multi-arg type with two SL comments +type iovec = CStruct2[Ptr[Byte, // iov_base + CSize]] // iov_len +>>> +type iovec = CStruct2[Ptr[ + Byte, // iov_base + CSize +]] // iov_len +<<< #1720 one arg with SL comment +type iovec = CStruct2[Ptr[Byte] // iov_base + ] +>>> +type iovec = CStruct2[ + Ptr[Byte] // iov_base +] +<<< #1720 first inline comment +type iovec = CStruct2[Ptr[Byte], /* iov_base */ + CSize] +>>> +type iovec = CStruct2[ + Ptr[Byte], /* iov_base */ + CSize +] +<<< #1720 first inline comment with apply +val iovec = CStruct2(Ptr(Byte), /* iov_base */ + CSize) +>>> +val iovec = CStruct2( + Ptr(Byte), /* iov_base */ + CSize +)