5252/** A {@code Level} inside a {@link Doc}. */
5353public final class Level extends Doc {
5454 /**
55- * How many branches we are allowed to take (i.e how many times we can consider breaking vs not breaking the current
56- * level) before we stop branching and always break, which is the google-java-format default behaviour.
55+ * The depth of nested levels in the current level tree from which we explore both breaking vs not breaking the current level.
5756 */
58- private static final int MAX_BRANCHING_COEFFICIENT = 20 ;
57+ private static final int LAST_LEVELS_TO_EXPLORE = 7 ;
5958
6059 private static final Collector <Level , ?, Optional <Level >> GET_LAST_COLLECTOR = Collectors .reducing ((u , v ) -> v );
6160
@@ -64,6 +63,10 @@ public final class Level extends Doc {
6463 @ SuppressWarnings ("Immutable" ) // Effectively immutable
6564 private final ImmutableSupplier <SplitsBreaks > memoizedSplitsBreaks =
6665 Suppliers .memoize (() -> splitByBreaks (docs ))::get ;
66+
67+ @ SuppressWarnings ("Immutable" ) // Effectively immutable
68+ private final ImmutableSupplier <Integer > memoizedMaxDepth = Suppliers .memoize (() -> computeMaxDepth (docs ))::get ;
69+
6770 /** The immutable characteristics of this level determined before the level contents are available. */
6871 private final OpenOp openOp ;
6972
@@ -130,7 +133,7 @@ public State computeBreaks(CommentsHelper commentsHelper, int maxWidth, State st
130133 * into account the level's {@link #getColumnLimitBeforeLastBreak()}.
131134 *
132135 * @return the width after fitting it onto one line, if it was possible. This is guaranteed to be less than
133- * {@code maxWidth}
136+ * {@code maxWidth}
134137 */
135138 private Optional <Integer > tryToFitOnOneLine (int maxWidth , State state , Iterable <Doc > docs ) {
136139 int column = state .column ();
@@ -189,16 +192,15 @@ public State breakThisLevel() {
189192
190193 @ Override
191194 public State preferBreakingLastInnerLevel (boolean _keepIndentWhenInlined ) {
192- // Try both breaking and not breaking. Choose the better one based on LOC, preferring
193- // breaks if the outcome is the same.
194- State state = this .state .withNewBranch ();
195-
196- Obs .Exploration broken = breakNormally (state );
197-
198- if (state .branchingCoefficient () < MAX_BRANCHING_COEFFICIENT ) {
195+ int maxDepth = getMaxDepth ();
196+ // Explore both breaking and not breaking if we're in the last LAST_LEVELS_TO_EXPLORE levels. Choose the
197+ // better one based on LOC, preferring breaks if the outcome is the same.
198+ if (maxDepth <= LAST_LEVELS_TO_EXPLORE ) {
199+ State state = this .state .withNewBranch ();
200+ Obs .Exploration broken = breakNormally (state );
199201 State state1 = state .withNoIndent ();
200202 Optional <Obs .Exploration > lastLevelBroken = levelNode .maybeExplore (
201- "tryBreakLastLevel" ,
203+ "tryBreakLastLevel" + maxDepth ,
202204 state1 ,
203205 explorationNode -> tryBreakLastLevel (commentsHelper , maxWidth , state1 , explorationNode , true ));
204206
@@ -208,8 +210,20 @@ public State preferBreakingLastInnerLevel(boolean _keepIndentWhenInlined) {
208210 return lastLevelBroken .get ().markAccepted ();
209211 }
210212 }
213+ return broken .markAccepted ();
214+ } else {
215+ State state1 = state .withNoIndent ();
216+ Optional <Obs .Exploration > lastLevelBroken = levelNode .maybeExplore (
217+ "tryBreakLastLevel only" + maxDepth ,
218+ state1 ,
219+ explorationNode -> tryBreakLastLevel (commentsHelper , maxWidth , state1 , explorationNode , true ));
220+
221+ if (lastLevelBroken .isPresent ()) {
222+ return lastLevelBroken .get ().markAccepted ();
223+ }
224+ // falling back to breaking normally
211225 }
212- return broken .markAccepted ();
226+ return breakNormally ( state ) .markAccepted ();
213227 }
214228
215229 @ Override
@@ -242,7 +256,7 @@ public State inlineSuffix() {
242256 private Exploration breakNormally (State state , LevelNode levelNode , CommentsHelper commentsHelper , int maxWidth ) {
243257 State stateForBroken = state .withIndentIncrementedBy (getPlusIndent ());
244258 return levelNode .explore (
245- "breaking normally" ,
259+ "breaking normally " + getMaxDepth () ,
246260 stateForBroken ,
247261 explorationNode -> computeBroken (commentsHelper , maxWidth , stateForBroken , explorationNode ));
248262 }
@@ -258,7 +272,7 @@ private Exploration breakNormally(State state, LevelNode levelNode, CommentsHelp
258272 * </ul>
259273 *
260274 * @param brokenState is expected to be the state resulting from {@link Level#breakNormally}, but is passed in
261- * for efficiency reasons
275+ * for efficiency reasons
262276 */
263277 private Optional <State > handle_breakOnlyIfInnerLevelsThenFitOnOneLine (
264278 CommentsHelper commentsHelper ,
@@ -736,6 +750,44 @@ public String representation(State state) {
736750 return new LevelDelimitedFlatValueDocVisitor (state ).visit (this );
737751 }
738752
753+ /**
754+ * Get the approximation of the maximum depth of nested levels in this level tree (memoized).
755+ */
756+ private int getMaxDepth () {
757+ return memoizedMaxDepth .get ();
758+ }
759+
760+ /**
761+ * Calculate an approximation of the maximum depth of nested levels in this level tree, counting method call nesting.
762+ * This counts levels that represent method invocations (including lambdas and other callable constructs),
763+ * which provides a better measure of structural complexity than counting all levels.
764+ * This computation is expensive, so it's memoized via {@link #getMaxDepth()}.
765+ */
766+ private int computeMaxDepth (Iterable <Doc > docs ) {
767+ int maxChildDepth = 0 ;
768+ for (Doc doc : docs ) {
769+ if (doc instanceof Level ) {
770+ Level childLevel = (Level ) doc ;
771+ maxChildDepth = Math .max (maxChildDepth , childLevel .getMaxDepth ());
772+ }
773+ }
774+
775+ // Count this level if it represents a method call or similar construct
776+ // A level is considered a "method call level" if it has breaks (can span multiple lines)
777+ // and is not just a simple wrapper. We use the presence of breaks as a proxy for
778+ // meaningful structural nesting.
779+ boolean hasBreaks = false ;
780+ for (Doc doc : docs ) {
781+ if (doc instanceof Break ) {
782+ hasBreaks = true ;
783+ break ;
784+ }
785+ }
786+
787+ // Only count levels that have breaks (i.e., can actually be formatted across multiple lines)
788+ return hasBreaks ? 1 + maxChildDepth : maxChildDepth ;
789+ }
790+
739791 /**
740792 * Get the width of a sequence of {@link Doc}s.
741793 *
@@ -774,6 +826,7 @@ public String toString() {
774826 interface SplitsBreaks {
775827 /** Groups of {@link Doc}s that are children of the current {@link Level}, separated by {@link Break}s. */
776828 ImmutableList <ImmutableList <Doc >> splits ();
829+
777830 /** {@link Break}s between {@link Doc}s in the current {@link Level}. */
778831 ImmutableList <Break > breaks ();
779832 }
0 commit comments