From ae2c3b86a0218974980d5db7cd27fe0d91af13f7 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:17:42 -0800 Subject: [PATCH] FormatToken: alias, use everywhere as {FT} --- .../src/main/scala/org/scalafmt/Error.scala | 2 +- .../org/scalafmt/config/FormatEvent.scala | 2 +- .../scala/org/scalafmt/config/Newlines.scala | 5 +- .../scalafmt/internal/BestFirstSearch.scala | 36 +- .../org/scalafmt/internal/Decision.scala | 2 +- .../org/scalafmt/internal/FormatOps.scala | 826 +++++++++--------- .../org/scalafmt/internal/FormatToken.scala | 13 +- .../org/scalafmt/internal/FormatTokens.scala | 267 +++--- .../org/scalafmt/internal/FormatWriter.scala | 33 +- .../scala/org/scalafmt/internal/Indent.scala | 12 +- .../org/scalafmt/internal/Modification.scala | 9 +- .../internal/OptimizationEntities.scala | 7 +- .../scala/org/scalafmt/internal/Policy.scala | 64 +- .../org/scalafmt/internal/PolicySummary.scala | 2 +- .../scala/org/scalafmt/internal/Router.scala | 368 ++++---- .../scala/org/scalafmt/internal/State.scala | 20 +- .../org/scalafmt/internal/TokenRange.scala | 6 +- .../scala/org/scalafmt/internal/package.scala | 8 + .../rewrite/ConvertToNewScala3Syntax.scala | 4 +- .../rewrite/FormatTokensRewrite.scala | 56 +- .../scalafmt/rewrite/PreferCurlyFors.scala | 6 +- .../scalafmt/rewrite/RedundantBraces.scala | 322 ++++--- .../scalafmt/rewrite/RedundantParens.scala | 12 +- .../rewrite/RemoveEmptyDocstrings.scala | 4 +- .../rewrite/RemoveScala3OptionalBraces.scala | 80 +- .../rewrite/RewriteTrailingCommas.scala | 8 +- .../scala/org/scalafmt/util/LoggerOps.scala | 6 +- .../scala/org/scalafmt/util/PolicyOps.scala | 6 +- .../scala/org/scalafmt/util/StyleMap.scala | 4 +- .../scala/org/scalafmt/util/TokenOps.scala | 14 +- .../scala/org/scalafmt/util/TreeOps.scala | 47 +- 31 files changed, 1065 insertions(+), 1186 deletions(-) create mode 100644 scalafmt-core/shared/src/main/scala/org/scalafmt/internal/package.scala diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/Error.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/Error.scala index 50b66a3823..604473f195 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/Error.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/Error.scala @@ -85,7 +85,7 @@ object Error { ) extends Error( s"Search state exploded on '$tok', line $line: $why [see $cfgUrl#search-state-exploded]", ) { - def this(deepestState: State, ft: FormatToken, why: String)(implicit + def this(deepestState: State, ft: FT, why: String)(implicit formatWriter: FormatWriter, ) = this( deepestState, 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 59d143e3d2..a7f9d6d4ef 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 @@ -9,7 +9,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 VisitToken(formatToken: FT) extends FormatEvent case class Explored(n: Int, depth: Int, queueSize: Int) extends FormatEvent case class Enqueue(split: Split) extends FormatEvent case class CompleteFormat( diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala index cc6a16a30c..53503cc1e5 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala @@ -247,10 +247,9 @@ case class Newlines( @inline def keepBreak(hasBreak: => Boolean): Boolean = keep && hasBreak @inline - def keepBreak(newlines: Int): Boolean = - keepBreak(!FormatToken.noBreak(newlines)) + def keepBreak(newlines: Int): Boolean = keepBreak(!FT.noBreak(newlines)) @inline - def keepBreak(implicit ft: FormatToken): Boolean = keepBreak(ft.hasBreak) + def keepBreak(implicit ft: FT): Boolean = keepBreak(ft.hasBreak) val breakAfterInfix: AfterInfix = afterInfix.getOrElse { source match { 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 ea7e3a857e..7ae2a6f895 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 @@ -36,7 +36,7 @@ private class BestFirstSearch private (range: Set[Range])(implicit var stats = new StateStats(tokens, initStyle.runner) - private def getBlockCloseToRecurse(ft: FormatToken, stop: T)(implicit + private def getBlockCloseToRecurse(ft: FT, stop: T)(implicit style: ScalafmtConfig, ): Option[T] = getEndOfBlock(ft, parensToo = true).collect { case close if close.left != stop && { @@ -171,14 +171,14 @@ private class BestFirstSearch private (range: Set[Range])(implicit private def killOnFail( isKillOnFail: Boolean, - )(end: => FormatToken)(implicit nextState: State): State = { + )(end: => FT)(implicit nextState: State): State = { val kill = isKillOnFail || nextState.hasSlbUntil(end) if (kill) null else nextState } private def killOnFail( opt: OptimalToken, - end: => FormatToken = null, + end: => FT = null, nextNextState: State = null, )(implicit nextState: State): State = killOnFail(opt.killOnFail) { if ( @@ -222,8 +222,8 @@ private class BestFirstSearch private (range: Set[Range])(implicit } } - private def getActiveSplits(ft: FormatToken, state: State, maxCost: Int)( - implicit Q: StateQueue, + private def getActiveSplits(ft: FT, state: State, maxCost: Int)(implicit + Q: StateQueue, ): Seq[Split] = { stats.trackState(state) val useProvided = ft.meta.formatOff || !ft.inside(range) @@ -316,7 +316,7 @@ object BestFirstSearch { private def getNoOptZones(tokens: FormatTokens)(implicit styleMap: StyleMap) = { val result = mutable.Map.empty[T, Boolean] - var expire: FormatToken = null + var expire: FT = null @inline def addRange(t: T): Unit = expire = tokens.matching(t) @inline @@ -324,13 +324,13 @@ object BestFirstSearch { tokens.foreach { case ft if expire ne null => if (ft eq expire) expire = null else result.update(ft.left, true) - case FormatToken(t: T.LeftParen, _, m) if (m.leftOwner match { + case FT(t: T.LeftParen, _, m) if (m.leftOwner match { case lo: Term.ArgClause => !lo.parent.is[Term.ApplyInfix] && !styleMap.at(t).newlines.keep case _: Term.Apply => true // legacy: when enclosed in parens case _ => false }) => addRange(t) - case FormatToken(t: T.LeftBrace, _, m) => m.leftOwner match { + case FT(t: T.LeftBrace, _, m) => m.leftOwner match { // Type compounds can be inside defn.defs case lo: meta.Stat.Block if lo.parent.is[Type.Refine] => addRange(t) case _: Type.Refine => addRange(t) @@ -413,17 +413,15 @@ object BestFirstSearch { updateBestImpl(state) } - def checkExplored( - ft: FormatToken, - )(implicit formatWriter: FormatWriter): Unit = explode( - ft, - runner.getMaxStateVisits, - )(explored > _, x => s"exceeded `runner.maxStateVisits`=$x") - - def explode[A](ft: FormatToken, value: A)( - cond: A => Boolean, - msg: A => String, - )(implicit formatWriter: FormatWriter): Unit = if (cond(value)) { + def checkExplored(ft: FT)(implicit formatWriter: FormatWriter): Unit = + explode(ft, runner.getMaxStateVisits)( + explored > _, + x => s"exceeded `runner.maxStateVisits`=$x", + ) + + def explode[A](ft: FT, value: A)(cond: A => Boolean, msg: A => String)( + implicit formatWriter: FormatWriter, + ): Unit = if (cond(value)) { complete(deepestYet) throw new Error.SearchStateExploded(deepestYet, ft, msg(value)) } diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Decision.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Decision.scala index 89832ea373..7840d19ff1 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Decision.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Decision.scala @@ -4,7 +4,7 @@ package org.scalafmt.internal * * Used by [[Policy]] to enforce non-local formatting. */ -case class Decision(formatToken: FormatToken, splits: Seq[Split]) { +case class Decision(formatToken: FT, splits: Seq[Split]) { @inline def noNewlines: Seq[Split] = Decision.noNewlineSplits(splits) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala index b487336dbe..e18a1846d2 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala @@ -53,14 +53,11 @@ class FormatOps( def owners(token: T): Tree = ownersMap(hash(token)) @inline - final def findFirst(start: FormatToken, end: T)( - f: FormatToken => Boolean, - ): Option[FormatToken] = findFirst(start, end.end)(f) + final def findFirst(start: FT, end: T)(f: FT => Boolean): Option[FT] = + findFirst(start, end.end)(f) @tailrec - final def findFirst(start: FormatToken, end: Int)( - f: FormatToken => Boolean, - ): Option[FormatToken] = + final def findFirst(start: FT, end: Int)(f: FT => Boolean): Option[FT] = if (start.left.end >= end) None else if (f(start)) Some(start) else { @@ -68,14 +65,14 @@ class FormatOps( if (next_ == start) None else findFirst(next_, end)(f) } - def findFirstOnRight[A](start: FormatToken, end: T)(implicit + def findFirstOnRight[A](start: FT, end: T)(implicit classifier: Classifier[T, A], - ): Option[FormatToken] = findFirst(start, end.start)(x => classifier(x.right)) + ): Option[FT] = findFirst(start, end.start)(x => classifier(x.right)) @tailrec - final def getSlbEndOnLeft(start: FormatToken, end: Int = Int.MaxValue)( - implicit style: ScalafmtConfig, - ): FormatToken = { + final def getSlbEndOnLeft(start: FT, end: Int = Int.MaxValue)(implicit + style: ScalafmtConfig, + ): FT = { val nft = start.right match { case t if t.end >= end => start case _: T.EOF => start @@ -151,9 +148,8 @@ class FormatOps( else getSlbEndOnLeft(if (nft ne null) nft else next(start)) } - final def endOfSingleLineBlock(start: FormatToken)(implicit - style: ScalafmtConfig, - ): T = getSlbEndOnLeft(start).left + final def endOfSingleLineBlock(start: FT)(implicit style: ScalafmtConfig): T = + getSlbEndOnLeft(start).left /** js.native is very special in Scala.js. * @@ -166,37 +162,30 @@ class FormatOps( case _ => false }) - val StartsStatementRight = new FormatToken.ExtractFromMeta[Tree](meta => + val StartsStatementRight = new FT.ExtractFromMeta[Tree](meta => optimizationEntities.statementStarts.get(meta.idx + 1), ) - def parensTuple(ft: FormatToken): TokenRanges = matchingOpt(ft.left) + def parensTuple(ft: FT): TokenRanges = matchingOpt(ft.left) .fold(TokenRanges.empty)(other => TokenRanges(TokenRange(ft, other))) def parensTuple(tree: Tree): TokenRanges = parensTuple(getLast(tree)) - def insideBlock[A](start: FormatToken, end: T)(implicit + def insideBlock[A](start: FT, end: T)(implicit classifier: Classifier[T, A], ): TokenRanges = insideBlock(start, end, x => classifier(x.left)) - def insideBlock( - start: FormatToken, - end: T, - matches: FormatToken => Boolean, - ): TokenRanges = insideBlock { x => - if (matches(x)) matchingOpt(x.left) else None - }(start, end) + def insideBlock(start: FT, end: T, matches: FT => Boolean): TokenRanges = + insideBlock(x => if (matches(x)) matchingOpt(x.left) else None)(start, end) - def insideBracesBlock(start: FormatToken, end: T, parensToo: Boolean = false)( - implicit style: ScalafmtConfig, + def insideBracesBlock(start: FT, end: T, parensToo: Boolean = false)(implicit + style: ScalafmtConfig, ): TokenRanges = insideBlock(x => getEndOfBlock(x, parensToo))(start, end) - def insideBlock( - matches: FormatToken => Option[FormatToken], - )(start: FormatToken, end: T): TokenRanges = { + def insideBlock(matches: FT => Option[FT])(start: FT, end: T): TokenRanges = { var result = TokenRanges.empty @tailrec - def run(tok: FormatToken): Unit = if (tok.left.start < end.start) { + def run(tok: FT): Unit = if (tok.left.start < end.start) { val nextTokOpt = matches(tok).flatMap { closeFt => if (tok.left.start >= closeFt.left.end) None else { @@ -214,7 +203,7 @@ class FormatOps( // invoked on closing paren, part of ParamClause @tailrec - final def defnSiteLastToken(t: Tree): Option[FormatToken] = t match { + final def defnSiteLastToken(t: Tree): Option[FT] = t match { case _: Term.ParamClause | _: Type.FuncParamClause | _: Type.FunctionType | _: Member.ParamClauseGroup => t.parent match { case Some(p) => defnSiteLastToken(p) @@ -239,11 +228,11 @@ class FormatOps( def splitOneArgPerLineBeforeComma(owner: Tree): Policy.Pf = { // TODO(olafur) clear queue between arguments, they are independent. - case Decision(t @ FormatToken(_, _: T.Comma, _), splits) + case Decision(t @ FT(_, _: T.Comma, _), splits) if owner == t.meta.rightOwner && !next(t).right.is[T.Comment] => splits.map(x => if (x.mod ne NoSplit) x else x.withMod(Newline)) - case Decision(t @ FormatToken(_: T.Comma, right, _), splits) + case Decision(t @ FT(_: T.Comma, right, _), splits) if owner == t.meta.leftOwner && !right.is[T.LeftBrace] && // If comment is bound to comma, see unit/Comment. (!right.is[T.Comment] || t.hasBreak) => @@ -253,7 +242,7 @@ class FormatOps( def splitOneArgPerLineAfterComma(owner: Tree): Policy.Pf = { // Newline on every comma. - case Decision(t @ FormatToken(_: T.Comma, right, m), splits) + case Decision(t @ FT(_: T.Comma, right, m), splits) if owner == m.leftOwner && // TODO(olafur) what the right { decides to be single line? // If comment is bound to comma, see unit/Comment. @@ -269,7 +258,7 @@ class FormatOps( exclude: TokenRanges, )(comma: T)(implicit fileLine: FileLine): Policy = { val policy = Policy.after(comma, prefix = "NL->A[,]") { - case Decision(t @ FormatToken(`comma`, right, _), splits) + case Decision(t @ FT(`comma`, right, _), splits) if !right.is[T.Comment] || t.hasBreak => getOneArgPerLineSplitsAfterComma(right, splits) } @@ -280,28 +269,28 @@ class FormatOps( if (r.is[T.LeftBrace]) SplitTag.OneArgPerLine.activateOnly(s) else Decision.onlyNewlineSplits(s) - def templateCurly(obj: Template.Body): Option[FormatToken] = getHeadOpt(obj) + def templateCurly(obj: Template.Body): Option[FT] = getHeadOpt(obj) .map(x => if (x.meta.leftOwner eq obj) x else prevNonCommentBefore(x)) - def templateCurlyOrLastNonTrivial(tpl: Template): FormatToken = - templateCurly(tpl.body).getOrElse(getLastNonTrivial(tpl)) + def templateCurlyOrLastNonTrivial(tpl: Template): FT = templateCurly(tpl.body) + .getOrElse(getLastNonTrivial(tpl)) - def templateDerivesOrCurlyOrLastNonTrivial(template: Template)(implicit - ft: FormatToken, - ): FormatToken = findTemplateGroupOnRight(_.getExpireToken)(template) + def templateDerivesOrCurlyOrLastNonTrivial( + template: Template, + )(implicit ft: FT): FT = findTemplateGroupOnRight(_.getExpireToken)(template) .getOrElse(templateCurlyOrLastNonTrivial(template)) private def findTreeInGroup[A]( trees: Seq[Tree], func: TemplateSupertypeGroup => A, - )(expireFunc: Seq[Tree] => FormatToken)(implicit ft: FormatToken): Option[A] = - trees.find(_.pos.end >= ft.right.end).map { x => + )(expireFunc: Seq[Tree] => FT)(implicit ft: FT): Option[A] = trees + .find(_.pos.end >= ft.right.end).map { x => func(TemplateSupertypeGroup(x, trees, expireFunc)) } def findTemplateGroupOnRight[A]( func: TemplateSupertypeGroup => A, - )(template: Template)(implicit ft: FormatToken): Option[A] = { + )(template: Template)(implicit ft: FT): Option[A] = { @tailrec def iter(groups: Seq[Seq[Tree]]): Option[A] = if (isSeqSingle(groups)) @@ -318,9 +307,8 @@ class FormatOps( } def getBreakBeforeElsePolicy(els: T): Policy = Policy - .on(els, prefix = "ELSE") { - case d @ Decision(FormatToken(_, `els`, _), _) => d - .onlyNewlinesWithFallback(Split(Newline, 0)) + .on(els, prefix = "ELSE") { case d @ Decision(FT(_, `els`, _), _) => + d.onlyNewlinesWithFallback(Split(Newline, 0)) } def getBreakBeforeElsePolicy(term: Term.If): Policy = getElseToken(term) @@ -333,23 +321,22 @@ class FormatOps( private final def getElseToken( term: Term.If, - ): Option[(FormatToken, Option[T.KwElse])] = getHeadOpt(term.elsep) - .map { ftElsep => - val elsOpt = prevNonCommentBefore(ftElsep) match { - case ft @ FormatToken(els: T.KwElse, _, _) => - val ok = initStyle.newlines.alwaysBeforeElseAfterCurlyIf || ! { - val pft = prev(ft) - pft.leftOwner.is[Term.Block] && pft.left.is[T.RightBrace] && - !prevNonCommentSameLineBefore(pft).left.is[T.LeftBrace] && - matchingOpt(pft.left).exists { lb => - prev(lb).left.start < term.thenp.pos.start - } + ): Option[(FT, Option[T.KwElse])] = getHeadOpt(term.elsep).map { ftElsep => + val elsOpt = prevNonCommentBefore(ftElsep) match { + case ft @ FT(els: T.KwElse, _, _) => + val ok = initStyle.newlines.alwaysBeforeElseAfterCurlyIf || ! { + val pft = prev(ft) + pft.leftOwner.is[Term.Block] && pft.left.is[T.RightBrace] && + !prevNonCommentSameLineBefore(pft).left.is[T.LeftBrace] && + matchingOpt(pft.left).exists { lb => + prev(lb).left.start < term.thenp.pos.start } - if (ok) Some(els) else None - case _ => None - } - (ftElsep, elsOpt) + } + if (ok) Some(els) else None + case _ => None } + (ftElsep, elsOpt) + } @tailrec private final def getElseChain(term: Term.If, res: List[T]): List[T] = @@ -368,7 +355,7 @@ class FormatOps( def insideInfixSplit( app: Member.Infix, - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = { + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = { val op = app.op.value if (app.is[Type] && style.spaces.neverAroundInfixTypes.contains(op)) Seq(Split(NoSplit, 0)) @@ -442,7 +429,7 @@ class FormatOps( lhsApp: Member.Infix, afterInfix: Newlines.AfterInfix, newStmtMod: Option[Modification] = None, - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = { + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = { val fullInfixTreeOpt = findTreeWithParentSimple(lhsApp, false)(isInfixApp) val fullInfix = fullInfixTreeOpt.flatMap(asInfixApp).getOrElse(lhsApp) val app = findLeftInfix(fullInfix) @@ -452,7 +439,7 @@ class FormatOps( final def maybeGetInfixSplitsBeforeLhs(mod: => Option[Modification] = None)( nonInfixSplits: => Seq[Split], - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = { + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = { val tree = ft.meta.rightOwner val ai = style.breakAfterInfix(tree) val app = if (ai eq Newlines.AfterInfix.keep) None else asInfixApp(tree) @@ -461,12 +448,12 @@ class FormatOps( private[internal] object InfixSplits { - def apply(app: Member.Infix, ft: FormatToken)(implicit + def apply(app: Member.Infix, ft: FT)(implicit style: ScalafmtConfig, ): InfixSplits = apply(app, ft, findEnclosingInfix(app)) - def apply(app: Member.Infix, ft: FormatToken, fullInfix: Member.Infix)( - implicit style: ScalafmtConfig, + def apply(app: Member.Infix, ft: FT, fullInfix: Member.Infix)(implicit + style: ScalafmtConfig, ): InfixSplits = { val leftInfix = findLeftInfix(fullInfix) new InfixSplits(app, ft, fullInfix, leftInfix) @@ -500,16 +487,16 @@ class FormatOps( private[FormatOps] def findEnclosingInfix(app: Member.Infix): Member.Infix = findMaybeEnclosingInfix(app)._1 - def withNLIndent(split: Split)( - app: Member.Infix, - )(implicit ft: FormatToken, style: ScalafmtConfig): Split = + def withNLIndent( + split: Split, + )(app: Member.Infix)(implicit ft: FT, style: ScalafmtConfig): Split = withNLIndent(split, app, findEnclosingInfix(app)) def withNLIndent( split: Split, app: Member.Infix, fullInfix: => Member.Infix, - )(implicit ft: FormatToken, style: ScalafmtConfig): Split = { + )(implicit ft: FT, style: ScalafmtConfig): Split = { val noNL = !split.isNL && { val nextFt = nextNonCommentSameLine(ft) nextFt.eq(ft) || nextFt.noBreak @@ -521,7 +508,7 @@ class FormatOps( private[internal] class InfixSplits( app: Member.Infix, - ft: FormatToken, + ft: FT, fullInfix: Member.Infix, leftInfix: Member.Infix, )(implicit style: ScalafmtConfig) { @@ -630,7 +617,7 @@ class FormatOps( val (nlIndent, nlPolicy) = { def policy(triggers: T*)(implicit fileLine: FileLine) = Policy ? triggers.isEmpty || Policy.on(fullExpire, prefix = "INF") { - case Decision(t: FormatToken, s) + case Decision(t: FT, s) if isInfixOp(t.meta.leftOwner) || isInfixOp(t.meta.rightOwner) && !t.meta.rightOwner.parent.exists(style.formatInfix(_)) => @@ -663,7 +650,7 @@ class FormatOps( afterInfix: Newlines.AfterInfix, newStmtMod: Option[Modification] = None, spaceMod: Modification = Space, - )(implicit ft: FormatToken): Seq[Split] = { + )(implicit ft: FT): Seq[Split] = { val maxPrecedence = if (isAfterOp) infixSequenceMaxPrecedence(fullInfix) else 0 // 0 unused val closeOpt = matchingOpt(ft.right) @@ -697,7 +684,7 @@ class FormatOps( val breakMany = infixTooLong || afterInfix == Newlines.AfterInfix.many val rightAsInfix = asInfixApp(ft.meta.rightOwner) - def breakAfterComment(t: FormatToken) = { + def breakAfterComment(t: FT) = { val end = nextNonCommentSameLine(t) Policy ? end.right.isAny[T.LeftBrace, T.Comment] || { if (end eq t) decideNewlinesOnlyAfterToken(end.left) @@ -781,7 +768,7 @@ class FormatOps( } def getSingleLineInfixPolicy(end: T) = Policy.on(end, prefix = "INFSLB") { - case Decision(t: FormatToken, s) if isInfixOp(t.meta.leftOwner) => + case Decision(t: FT, s) if isInfixOp(t.meta.leftOwner) => SplitTag.InfixChainNoNL.activateOnly(s) } @@ -870,18 +857,17 @@ class FormatOps( case _ => getLastExceptParen(function).left -> ExpiresOn.After } - def mustForceConfigStyle(ft: FormatToken)(implicit + def mustForceConfigStyle(ft: FT)(implicit cfg: Newlines.ConfigStyleElement, ): Boolean = cfg.getForceIfOptimized && forceConfigStyle(ft.meta.idx) - def preserveConfigStyle( - ft: FormatToken, - breakBeforeClose: => Boolean, - )(implicit style: ScalafmtConfig, clauseSiteFlags: ClauseSiteFlags): Boolean = - preferConfigStyle && couldPreserveConfigStyle(ft, breakBeforeClose) + def preserveConfigStyle(ft: FT, breakBeforeClose: => Boolean)(implicit + style: ScalafmtConfig, + clauseSiteFlags: ClauseSiteFlags, + ): Boolean = preferConfigStyle && + couldPreserveConfigStyle(ft, breakBeforeClose) - def couldPreserveConfigStyle(ft: FormatToken, breakBeforeClose: => Boolean)( - implicit + def couldPreserveConfigStyle(ft: FT, breakBeforeClose: => Boolean)(implicit style: ScalafmtConfig, clauseSiteFlags: ClauseSiteFlags, ): Boolean = !style.newlines.sourceIgnored && { @@ -891,34 +877,34 @@ class FormatOps( } && breakBeforeClose /** Works for `using` as well */ - def opensConfigStyleImplicitParamList(formatToken: FormatToken)(implicit + def opensConfigStyleImplicitParamList(formatToken: FT)(implicit style: ScalafmtConfig, ): Boolean = soft.ImplicitOrUsing(formatToken.right) && style.newlines.notBeforeImplicitParamListModifier && hasImplicitParamList(formatToken.meta.rightOwner) - def isSingleIdentifierAnnotation(tok: FormatToken): Boolean = { + def isSingleIdentifierAnnotation(tok: FT): Boolean = { val toMatch = if (tok.right.is[T.RightParen]) // Hack to allow any annotations with arguments like @foo(1) tokens(matching(tok.right), -2) else tok toMatch match { - case FormatToken(T.At(), _: T.Ident, _) => true + case FT(T.At(), _: T.Ident, _) => true case _ => false } } def typeTemplateSplits(template: Template, indentIfSecond: Int)(implicit fileLine: FileLine, - ft: FormatToken, + ft: FT, style: ScalafmtConfig, ): Seq[Split] = { def getPolicy(expire: T) = expire match { case lb: T.LeftBrace if template.self.tokens.isEmpty => Policy.after(lb, "MLTMPL") { // Force template to be multiline. - case d @ Decision(ftd @ FormatToken(`lb`, right, _), _) + case d @ Decision(ftd @ FT(`lb`, right, _), _) if !right.is[T.RightBrace] && // corner case, body is {} !isAttachedCommentThenBreak(ftd) => d.onlyNewlinesWithoutFallback @@ -957,10 +943,10 @@ class FormatOps( ): Policy = Policy ? ((style.binPack.parentConstructors eq BinPack.ParentCtors.Always) || ownerSet.isEmpty) || Policy.after(lastToken, prefix = "WITH") { - case d @ Decision(t @ FormatToken(_, _: T.KwWith, _), _) + case d @ Decision(t @ FT(_, _: T.KwWith, _), _) if ownerSet.contains(t.meta.rightOwner) => d.onlyNewlinesWithoutFallback - case d @ Decision(t @ FormatToken(T.Comma(), _, _), _) + case d @ Decision(t @ FT(T.Comma(), _, _), _) if ownerSet.contains(t.meta.leftOwner) => d.onlyNewlinesWithoutFallback } @@ -969,14 +955,10 @@ class FormatOps( isFirstCtor: Boolean, owners: => Set[Tree], rhs: => Option[Tree], - lastFt: FormatToken, + lastFt: FT, indentLen: Int, extendsThenWith: => Boolean = false, - )(implicit - fileLine: FileLine, - ft: FormatToken, - style: ScalafmtConfig, - ): Seq[Split] = { + )(implicit fileLine: FileLine, ft: FT, style: ScalafmtConfig): Seq[Split] = { val lastToken = lastFt.left val nlMod = NewlineT(alt = Some(Space)) val indent = @@ -1031,7 +1013,7 @@ class FormatOps( if (callSite.isEnabled || defnSite.isEnabled) { val clearQueues = Set.newBuilder[Int] val forces = Set.newBuilder[Int] - def process(clause: Member.SyntaxValuesClause, ftOpen: FormatToken)( + def process(clause: Member.SyntaxValuesClause, ftOpen: FT)( cfg: ScalafmtOptimizer.ClauseElement, ): Unit = if (cfg.isEnabled) matchingOpt(ftOpen.left).foreach { close => val values = clause.values @@ -1044,7 +1026,7 @@ class FormatOps( } } tokens.foreach { - case ft @ FormatToken(_: T.LeftParen | _: T.LeftBracket, _, m) => + case ft @ FT(_: T.LeftParen | _: T.LeftBracket, _, m) => m.leftOwner match { case t: Member.ArgClause if !t.parent.is[Member.Infix] => process(t, ft)(callSite) @@ -1062,11 +1044,11 @@ class FormatOps( */ def verticalMultiline()(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = { val lpOwner = ft.meta.leftOwner - val FormatToken(open, r, _) = ft + val FT(open, r, _) = ft val close = matching(open).left val indentParam = Num(style.indent.getDefnSite(lpOwner)) val indentSep = Num((indentParam.n - 2).max(0)) @@ -1120,16 +1102,16 @@ class FormatOps( val paramGroupSplitter = Policy.on(lastParen, prefix = "VML") { // If this is a class, then don't dangle the last paren unless the line ends with a comment - case Decision(ftd @ FormatToken(_, `lastParen`, _), _) + case Decision(ftd @ FT(_, `lastParen`, _), _) if shouldNotDangle && !isLeftCommentThenBreak(ftd) => Seq(Split(NoSplit, 0)) // Indent separators `)(` and `](` by `indentSep` - case Decision(FormatToken(_, `close`, _), _) => + case Decision(FT(_, `close`, _), _) => Seq(Split(Newline, 0).withIndent(indentSep, close, ExpiresOn.After)) - case Decision(FormatToken(LeftParenOrBracket(), _, m), ss) + case Decision(FT(LeftParenOrBracket(), _, m), ss) if allParenOwners.contains(m.leftOwner) => ss.filter(!_.isActiveFor(SplitTag.VerticalMultilineSingleLine)) - case Decision(ftd @ FormatToken(soft.ImplicitOrUsing(), _, m), _) + case Decision(ftd @ FT(soft.ImplicitOrUsing(), _, m), _) if style.newlines.forceAfterImplicitParamListModifier && !isRightCommentThenBreak(ftd) && hasImplicitParamList(m.leftOwner) => Seq(Split(Newline, 0)) @@ -1164,7 +1146,7 @@ class FormatOps( if (isBracket) { val noSlbPolicy = Policy.on(lastParen, prefix = "VML!SLB") { - case Decision(FormatToken(LeftParenOrBracket(), _, m), ss) + case Decision(FT(LeftParenOrBracket(), _, m), ss) if allParenOwners.contains(m.leftOwner) => ss.filter(!_.isActiveFor(SplitTag.VerticalMultilineSingleLine)) } @@ -1214,10 +1196,10 @@ class FormatOps( // Returns leading comment, if there exists one, otherwise formatToken @inline - final def leadingComment(tree: Tree): FormatToken = + final def leadingComment(tree: Tree): FT = leadingComment(tokenJustBefore(tree)) @tailrec - final def leadingComment(ft: FormatToken): FormatToken = + final def leadingComment(ft: FT): FT = if (ft.hasBlankLine || !ft.left.is[T.Comment]) ft else { val pft = prevNonCommentSameLineBefore(ft) @@ -1226,11 +1208,11 @@ class FormatOps( // Returns trailing comment, if there exists one, otherwise formatToken @inline - final def trailingComment(ft: FormatToken, end: Int): FormatToken = { + final def trailingComment(ft: FT, end: Int): FT = { @inline - def isDone(x: FormatToken) = x.hasBlankLine || x.right.end >= end + def isDone(x: FT) = x.hasBlankLine || x.right.end >= end @tailrec - def iter(x: FormatToken): FormatToken = { + def iter(x: FT): FT = { val nft = nextNonCommentSameLineAfter(x) if (isDone(nft)) nft else if (!nft.right.is[T.Comment]) ft // original @@ -1252,7 +1234,7 @@ class FormatOps( } def getNoSplitAfterOpening( - ft: FormatToken, + ft: FT, commentNL: Modification, spaceOk: Boolean = true, )(implicit style: ScalafmtConfig): Modification = ft.right match { @@ -1264,7 +1246,7 @@ class FormatOps( } def getNoSplitBeforeClosing( - ft: FormatToken, + ft: FT, commentNL: Modification, spaceOk: Boolean = true, )(implicit style: ScalafmtConfig): Modification = ft.left match { @@ -1276,19 +1258,19 @@ class FormatOps( } // look for arrow before body, if any, else after params - def getFuncArrow(term: Term.FunctionTerm): Option[FormatToken] = tokens + def getFuncArrow(term: Term.FunctionTerm): Option[FT] = tokens .tokenBeforeOpt(term.body) .orElse(tokenAfterOpt(term.paramClause).map(getArrowAfter)) .orElse(findFirst(getHead(term), term.pos.end)(_.left.is[T.RightArrow])) // look for arrow before body, if any, else after cond/pat - def getCaseArrow(term: Case): FormatToken = tokenBeforeOpt(term.body) + def getCaseArrow(term: Case): FT = tokenBeforeOpt(term.body) .getOrElse(getArrowAfter(tokenAfter(term.cond.getOrElse(term.pat)))) // look for arrow before body, if any, else after cond/pat - def getCaseArrow(term: TypeCase): FormatToken = next(tokenAfter(term.pat)) + def getCaseArrow(term: TypeCase): FT = next(tokenAfter(term.pat)) - private def getArrowAfter(ft: FormatToken): FormatToken = { + private def getArrowAfter(ft: FT): FT = { val maybeArrow = next(ft) if (maybeArrow.left.is[T.RightArrow]) maybeArrow else nextAfterNonComment(maybeArrow) @@ -1409,7 +1391,7 @@ class FormatOps( } @tailrec - final def findXmlLastLineIndent(ft: FormatToken): Int = ft.left match { + final def findXmlLastLineIndent(ft: FT): Int = ft.left match { case _: T.Xml.Start => 0 case t: T.Xml.Part => TokenOps.getXmlLastLineIndent(t) match { case Some(x) => x @@ -1428,7 +1410,7 @@ class FormatOps( splits.map(_.withIndent(indent, end.left, ExpiresOn.After)) } else splits - def withIndentOnXmlSpliceStart(ft: FormatToken, splits: Seq[Split])(implicit + def withIndentOnXmlSpliceStart(ft: FT, splits: Seq[Split])(implicit style: ScalafmtConfig, ): Seq[Split] = ft.left match { case t: T.Xml.SpliceStart if style.xmlLiterals.assumeFormatted => @@ -1447,10 +1429,7 @@ class FormatOps( } @tailrec - private def getNestedOpens( - tree: Member.ArgClause, - res: List[FormatToken], - ): List[FormatToken] = { + private def getNestedOpens(tree: Member.ArgClause, res: List[FT]): List[FT] = { val args = tree.values if (args.isEmpty) res else { @@ -1463,7 +1442,7 @@ class FormatOps( } private def getNestedOpensPolicy( - opens: List[FormatToken], + opens: List[FT], policy: Policy, ): Policy = opens.foldLeft(policy) { case (res, x) => val endPos = nextNonComment(x).right match { @@ -1483,8 +1462,8 @@ class FormatOps( val opens = getNestedOpens(t.argClause, Nil) getFoldedPolicy(t.fun, getNestedOpensPolicy(opens, policy)) case t: Init => - val opens = t.argClauses.foldLeft(List.empty[FormatToken]) { - case (res, x) => getNestedOpens(x, res) + val opens = t.argClauses.foldLeft(List.empty[FT]) { case (res, x) => + getNestedOpens(x, res) } getNestedOpensPolicy(opens, policy) case t: Term.Select => getFoldedPolicy(t.qual, policy) @@ -1498,7 +1477,7 @@ class FormatOps( nlSplitFunc: Int => Split, isKeep: Boolean, spaceIndents: Seq[Indent] = Seq.empty, - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = { + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = { val btokens = body.tokens val blastFT = getLastNonTrivial(btokens, body) val blast = blastFT.left @@ -1608,7 +1587,7 @@ class FormatOps( nlSplitFunc: Int => Split, isKeep: Boolean, spaceIndents: Seq[Indent], - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = if (tokens.isEmpty(body)) Seq(Split(Space, 0)) else foldedNonEmptyNonComment(body, nlSplitFunc, isKeep, spaceIndents) @@ -1643,9 +1622,9 @@ class FormatOps( Seq(spaceSplit.withIndents(spaceIndents), nlSplitFunc(1).forThisLine) } - def checkComment(nlSplitFunc: Int => Split)( - splitsFunc: FormatToken => Seq[Split], - )(implicit ft: FormatToken): Seq[Split] = + def checkComment( + nlSplitFunc: Int => Split, + )(splitsFunc: FT => Seq[Split])(implicit ft: FT): Seq[Split] = if (!ft.right.is[T.Comment] && !ft.hasBlankLine) splitsFunc(ft) else if (ft.hasBreak) Seq(nlSplitFunc(0).forThisLine) else { @@ -1667,14 +1646,14 @@ class FormatOps( spaceIndents: Seq[Indent] = Seq.empty, )(nlSplitFunc: Int => Split)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = checkComment(nlSplitFunc) { _ => foldedNonComment(body, nlSplitFunc, isKeep, spaceIndents) } def slbOnly(body: Tree, spaceIndents: Seq[Indent] = Seq.empty)( nlSplitFunc: Int => Split, - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = checkComment(nlSplitFunc) { _ => unfoldedNonComment(body, nlSplitFunc, spaceIndents, true) } @@ -1683,7 +1662,7 @@ class FormatOps( classicNoBreakFunc: => Split, )(nlSplitFunc: Int => Split)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = checkComment(nlSplitFunc) { x => def getFolded(isKeep: Boolean) = foldedNonComment(body, nlSplitFunc, isKeep = isKeep, spaceIndents) @@ -1703,17 +1682,17 @@ class FormatOps( def getWithIndent( body: Tree, - endFt: => FormatToken, + endFt: => FT, spaceIndents: Seq[Indent] = Seq.empty, )(classicNoBreakFunc: => Split)(nlSplitFunc: Int => Split)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = get(body, spaceIndents)(classicNoBreakFunc)(x => withIndent(nlSplitFunc(x), body, endFt), ) - def withIndent(nlSplit: Split, endFt: FormatToken)(implicit - ft: FormatToken, + def withIndent(nlSplit: Split, endFt: FT)(implicit + ft: FT, style: ScalafmtConfig, ): Split = withNLPolicy(endFt) { val right = nextNonComment(ft).right @@ -1724,8 +1703,8 @@ class FormatOps( nlSplit.withIndent(Num(style.indent.main), expire.left, ExpiresOn.After) } - def withIndent(nlSplit: Split, body: Tree, endFt: => FormatToken)(implicit - ft: FormatToken, + def withIndent(nlSplit: Split, body: Tree, endFt: => FT)(implicit + ft: FT, style: ScalafmtConfig, ): Split = asInfixApp(body) .fold(withIndent(nlSplit, endFt))(InfixSplits.withNLIndent(nlSplit)) @@ -1741,10 +1720,10 @@ class FormatOps( } - def withNLPolicy(endFt: FormatToken)(nlSplit: Split): Split = nlSplit + def withNLPolicy(endFt: FT)(nlSplit: Split): Split = nlSplit .andPolicy(nextNonCommentSameLine(endFt) match { - case FormatToken(_, x: T.Keyword, _) => decideNewlinesOnlyBeforeToken(x) - case ft @ FormatToken(_, x: T.Semicolon, _) => + case FT(_, x: T.Keyword, _) => decideNewlinesOnlyBeforeToken(x) + case ft @ FT(_, x: T.Semicolon, _) => val semiFt = nextNonCommentSameLineAfter(ft) val semi = semiFt.left if (semiFt.noBreak || (semi eq x) && !semiFt.right.is[T.Comment]) @@ -1754,10 +1733,9 @@ class FormatOps( }) // Redundant () delims around case statements - def getClosingIfCaseBodyEnclosedAsBlock( - postArrowFt: FormatToken, - caseStat: CaseTree, - )(implicit beforeMultiline: Newlines.SourceHints): Option[FormatToken] = { + def getClosingIfCaseBodyEnclosedAsBlock(postArrowFt: FT, caseStat: CaseTree)( + implicit beforeMultiline: Newlines.SourceHints, + ): Option[FT] = { val body = caseStat.body val ok = body.eq(postArrowFt.meta.rightOwner) && (beforeMultiline.ignoreSourceSplit || postArrowFt.noBreak) @@ -1765,41 +1743,38 @@ class FormatOps( } // Redundant () delims around body - def getClosingIfBodyEnclosedAsBlock(body: Tree): Option[FormatToken] = - body match { - case _: Lit.Unit | _: Term.Tuple => None - case t: Term.ApplyInfix if { - val op = t.op.value - op == "->" || op == "→" - } => None - case _ => getClosingIfWithinParens(body).toOption - } + def getClosingIfBodyEnclosedAsBlock(body: Tree): Option[FT] = body match { + case _: Lit.Unit | _: Term.Tuple => None + case t: Term.ApplyInfix if { + val op = t.op.value + op == "->" || op == "→" + } => None + case _ => getClosingIfWithinParens(body).toOption + } def isBodyEnclosedAsBlock(body: Tree): Boolean = getClosingIfBodyEnclosedAsBlock(body).isDefined object GetSelectLike { - val OnRight = new FormatToken.ExtractFromMeta(m => - onRightOpt(m.rightOwner, tokens(m.idx)), - ) + val OnRight = + new FT.ExtractFromMeta(m => onRightOpt(m.rightOwner, tokens(m.idx))) private[FormatOps] def onRightOpt( ro: Tree, - ftOrNull: => FormatToken, + ftOrNull: => FT, ): Option[SelectLike] = ro match { case x: Term.Select => Some(SelectLike(x)) case x: Term.Match if dialect.allowMatchAsOperator => val ft = Option(ftOrNull).getOrElse(tokenAfter(x.expr)) if (!ft.right.is[T.Dot]) None else nextNonCommentAfter(ft) match { - case xft @ FormatToken(_, _: T.KwMatch, _) => - Some(SelectLike(x, next(xft))) + case xft @ FT(_, _: T.KwMatch, _) => Some(SelectLike(x, next(xft))) case _ => None } case _ => None } - def onRightOpt(ft: FormatToken): Option[SelectLike] = + def onRightOpt(ft: FT): Option[SelectLike] = onRightOpt(ft.meta.rightOwner, ft) def unapply(tree: Tree): Option[SelectLike] = onRightOpt(tree, null) @@ -1809,7 +1784,7 @@ class FormatOps( noNLMod: => Modification, tparam: Type.Param, bounds: Type.Param => Seq[Type], - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = { + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = { val boundOpt = bounds(tparam).find(_.pos.start > ft.right.end) val expireOpt = boundOpt.map(getLastNonTrivialToken) getSplitsForTypeBounds(noNLMod, tparam, expireOpt) @@ -1819,13 +1794,13 @@ class FormatOps( noNLMod: => Modification, typeOwner: Tree, boundEndOpt: Option[T], - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = { + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = { val typeEnd = getLastNonTrivialToken(typeOwner) val boundEnd = boundEndOpt.getOrElse(typeEnd) def indent = Indent(Num(style.indent.main), boundEnd, ExpiresOn.After) def unfoldPolicy = typeOwner match { case tparam: Type.Param => Policy.on(typeEnd, prefix = "VB") { - case Decision(t @ FormatToken(_, _: T.Colon | _: T.Viewbound, _), s) + case Decision(t @ FT(_, _: T.Colon | _: T.Viewbound, _), s) if t.meta.rightOwner eq tparam => Decision.onlyNewlineSplits(s) } case _ => NoPolicy @@ -1848,22 +1823,21 @@ class FormatOps( object OptionalBraces { private trait Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] } // Optional braces in templates after `:|with` // Optional braces after any token that can start indentation: // ) = => ?=> <- catch do else finally for // if match return then throw try while yield - def unapply(ftMeta: FormatToken.Meta)(implicit + def unapply(ftMeta: FT.Meta)(implicit style: ScalafmtConfig, ): Option[Seq[Split]] = get(tokens(ftMeta.idx)).flatMap(_.splits) def get( - ft: FormatToken, + ft: FT, )(implicit style: ScalafmtConfig): Option[OptionalBracesRegion] = if (!style.dialect.allowSignificantIndentation) None else Option(ft.left match { @@ -1886,15 +1860,14 @@ class FormatOps( _: T.KwYield => BlockImpl case _ => null }).flatMap { impl => - implicit val ift: FormatToken = ft + implicit val ift: FT = ft val nft = nextNonComment(ft) impl.create(nft).filter { ob => !nft.right.is[T.LeftBrace] || nft.meta.rightOwner.parent != ob.owner } } - def at(ft: FormatToken)(implicit style: ScalafmtConfig): Boolean = get(ft) - .nonEmpty + def at(ft: FT)(implicit style: ScalafmtConfig): Boolean = get(ft).nonEmpty private def getSplits( tree: Tree, @@ -1905,7 +1878,7 @@ class FormatOps( )(implicit fileLine: FileLine, style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = { val treeTokens = tree.tokens val end = getOnOrAfterLast(treeTokens, tree) @@ -1943,9 +1916,9 @@ class FormatOps( // https://dotty.epfl.ch/docs/reference/other-new-features/indentation.html#variant-indentation-marker- // TODO: amend for additional cases when the parser supports them private object ColonEolImpl extends Factory { - def create(nft: FormatToken)(implicit + def create(nft: FT)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[OptionalBracesRegion] = { val lo = ft.meta.leftOwner def createImpl(ownerOpt: => Option[Tree], okRightBrace: => Boolean) = @@ -1978,7 +1951,7 @@ class FormatOps( private def onArgClause(ac: Term.ArgClause, args: List[Tree])(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[OptionalBracesRegion] = { def funcSplit(arg: Term.FunctionTerm)(implicit fl: FileLine) = { val end = getLast(arg) @@ -2029,9 +2002,9 @@ class FormatOps( } private object WithImpl extends Factory { - def create(nft: FormatToken)(implicit + def create(nft: FT)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[OptionalBracesRegion] = { val lo = ft.meta.leftOwner def createImpl( @@ -2058,9 +2031,9 @@ class FormatOps( } private object BlockImpl extends Factory { - def create(nft: FormatToken)(implicit + def create(nft: FT)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[OptionalBracesRegion] = { val leftOwner = ft.meta.leftOwner findTreeWithParentSimple(nft.meta.rightOwner)(_ eq leftOwner) match { @@ -2072,9 +2045,9 @@ class FormatOps( } private object RightParenImpl extends Factory { - def create(nft: FormatToken)(implicit + def create(nft: FT)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[OptionalBracesRegion] = { def createImpl(ownerTree: => Tree, blockTree: => Tree)( splitsRef: => Option[Seq[Split]], @@ -2113,67 +2086,68 @@ class FormatOps( } private object RightArrowImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t: Case => // unsupported except for right brace, or when ends in comment - Some(new OptionalBracesRegion { - def owner = None - def splits = - if (getLastNotTrailingCommentOpt(t).forall(_.isRight)) None - else Some(Seq(Split(Newline2x(ft), 0))) - def rightBrace = blockLast(t.body) - }) - case t @ Tree.WithBody(b: Tree.CasesBlock) if nft.right.is[T.KwCase] => - Some(new OptionalBracesRegion { - def owner = Some(t) - def splits = Some(getSplits(b, forceNL = true)) - def rightBrace = treeLast(b) - }) - case _ => BlockImpl.create(nft) - } + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t: Case => // unsupported except for right brace, or when ends in comment + Some(new OptionalBracesRegion { + def owner = None + def splits = + if (getLastNotTrailingCommentOpt(t).forall(_.isRight)) None + else Some(Seq(Split(Newline2x(ft), 0))) + def rightBrace = blockLast(t.body) + }) + case t @ Tree.WithBody(b: Tree.CasesBlock) + if nft.right.is[T.KwCase] => + Some(new OptionalBracesRegion { + def owner = Some(t) + def splits = Some(getSplits(b, forceNL = true)) + def rightBrace = treeLast(b) + }) + case _ => BlockImpl.create(nft) + } } private object ForImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t @ Tree.WithEnums(x) if isSeqMulti(x) => - WithStats(nft, x.headOption, x.last, Some(t), nlOnly = false) - case _ => None - } + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t @ Tree.WithEnums(x) if isSeqMulti(x) => + WithStats(nft, x.headOption, x.last, Some(t), nlOnly = false) + case _ => None + } } private object WhileImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t: Term.While => t.expr match { - case b: Term.Block - if isMultiStatBlock(b) && - !matchingOpt(nft.right).exists(_.left.end >= b.pos.end) => - Some(new OptionalBracesRegion { - def owner = Some(t) - def splits = Some { - val dangle = style.danglingParentheses.ctrlSite - val forceNL = !nft.right.is[T.LeftParen] - getSplits(b, forceNL = forceNL, danglingKeyword = dangle) - } - def rightBrace = blockLast(b) - }) - case _ => None - } - case _ => None - } + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t: Term.While => t.expr match { + case b: Term.Block + if isMultiStatBlock(b) && + !matchingOpt(nft.right).exists(_.left.end >= b.pos.end) => + Some(new OptionalBracesRegion { + def owner = Some(t) + def splits = Some { + val dangle = style.danglingParentheses.ctrlSite + val forceNL = !nft.right.is[T.LeftParen] + getSplits(b, forceNL = forceNL, danglingKeyword = dangle) + } + def rightBrace = blockLast(b) + }) + case _ => None + } + case _ => None + } } private object DoImpl extends Factory { - def create(nft: FormatToken)(implicit + def create(nft: FT)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[OptionalBracesRegion] = { val lo = ft.meta.leftOwner def createImpl(body: Tree) = Some(new OptionalBracesRegion { @@ -2189,26 +2163,26 @@ class FormatOps( } private object EqualsImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t: Ctor.Secondary => - if (t.body.stats.isEmpty) None - else WithStats(nft, Some(t.body.init), t.body, t.parent) - case t @ Tree.WithBody(b) => (b match { - case x: Term.Block => getBlockWithNonSingleTermStat(x) - case x: Tree.CasesBlock => Some(x) - case _ => None - }).flatMap(x => WithStats(nft, x.stats.headOption, b, Some(t))) - case _ => BlockImpl.create(nft) - } + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t: Ctor.Secondary => + if (t.body.stats.isEmpty) None + else WithStats(nft, Some(t.body.init), t.body, t.parent) + case t @ Tree.WithBody(b) => (b match { + case x: Term.Block => getBlockWithNonSingleTermStat(x) + case x: Tree.CasesBlock => Some(x) + case _ => None + }).flatMap(x => WithStats(nft, x.stats.headOption, b, Some(t))) + case _ => BlockImpl.create(nft) + } } private object TryImpl extends Factory { - def create(nft: FormatToken)(implicit + def create(nft: FT)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[OptionalBracesRegion] = { val lo = ft.meta.leftOwner def createImpl(expr: Term, finallyp: Option[Term], usesOB: => Boolean) = @@ -2235,44 +2209,44 @@ class FormatOps( .catchp.headOption.exists(x => !tokenBefore(x).left.is[T.LeftBrace]) private object CatchImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t: Term.Try => t.catchClause match { - case Some(cb: Term.CasesBlock) => - val nlOnly = cb.cases match { - // to avoid next expression being interpreted as body - case head :: Nil => shouldBreakInOptionalBraces(ft, nft) || - t.finallyp.isEmpty && - (isEmptyTree(head.body) || getLastOpt(cb).exists { x => - val xend = nextNonCommentSameLine(x) - xend.right match { - case _: T.Comment => !xend.hasBlankLine - case _ => false - } - }) - case _ => true - } - Some(new OptionalBracesRegion { - def owner = Some(t) - def splits = Some(getSplits( - cb, - forceNL = nlOnly, - forceNLIfTrailingStandaloneComments = false, - )) - def rightBrace = treeLast(cb) - }) - case _ => None - } - case _ => None - } + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t: Term.Try => t.catchClause match { + case Some(cb: Term.CasesBlock) => + val nlOnly = cb.cases match { + // to avoid next expression being interpreted as body + case head :: Nil => shouldBreakInOptionalBraces(ft, nft) || + t.finallyp.isEmpty && + (isEmptyTree(head.body) || getLastOpt(cb).exists { x => + val xend = nextNonCommentSameLine(x) + xend.right match { + case _: T.Comment => !xend.hasBlankLine + case _ => false + } + }) + case _ => true + } + Some(new OptionalBracesRegion { + def owner = Some(t) + def splits = Some(getSplits( + cb, + forceNL = nlOnly, + forceNLIfTrailingStandaloneComments = false, + )) + def rightBrace = treeLast(cb) + }) + case _ => None + } + case _ => None + } } private object FinallyImpl extends Factory { - def create(nft: FormatToken)(implicit + def create(nft: FT)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[OptionalBracesRegion] = { val lo = ft.meta.leftOwner def createImpl(usingOB: => Boolean)(finallyExpr: Tree) = { @@ -2298,92 +2272,93 @@ class FormatOps( } private object MatchImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t @ Tree.WithCasesBlock(x) => - val ind = style.indent.matchSite - WithStats(nft, x.cases.headOption, t, Some(t), indentOpt = ind) - case _ => None - } + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t @ Tree.WithCasesBlock(x) => + val ind = style.indent.matchSite + WithStats(nft, x.cases.headOption, t, Some(t), indentOpt = ind) + case _ => None + } } private object ThenImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t: Term.If => Some(new OptionalBracesRegion { - def owner = Some(t) - def splits = Some(getSplitsForIf(nft, t)) - def rightBrace = blockLast(t.thenp) - }) - case _ => None - } + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t: Term.If => Some(new OptionalBracesRegion { + def owner = Some(t) + def splits = Some(getSplitsForIf(nft, t)) + def rightBrace = blockLast(t.thenp) + }) + case _ => None + } } private object IfImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t: Term.If => - val nr = nft.right - t.cond match { - case b: Term.Block if (matchingOpt(nr) match { - case Some(t) => t.left.end < b.pos.end - case None => isMultiStatBlock(b) - }) => - Some(new OptionalBracesRegion { - def owner = Some(t) - def splits = Some { - val dangle = style.danglingParentheses.ctrlSite - val forceNL = !nr.is[T.LeftParen] - getSplits(b, forceNL, dangle) - } - def rightBrace = blockLast(b) - }) - case _ => None - } - case _ => None - } + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t: Term.If => + val nr = nft.right + t.cond match { + case b: Term.Block if (matchingOpt(nr) match { + case Some(t) => t.left.end < b.pos.end + case None => isMultiStatBlock(b) + }) => + Some(new OptionalBracesRegion { + def owner = Some(t) + def splits = Some { + val dangle = style.danglingParentheses.ctrlSite + val forceNL = !nr.is[T.LeftParen] + getSplits(b, forceNL, dangle) + } + def rightBrace = blockLast(b) + }) + case _ => None + } + case _ => None + } } private object ElseImpl extends Factory { - def create(nft: FormatToken)(implicit - style: ScalafmtConfig, - ft: FormatToken, - ): Option[OptionalBracesRegion] = ft.meta.leftOwner match { - case t: Term.If => (getTreeSingleExpr(t.elsep) match { - case Some(x: Term.If) => - val forceNL = isJustBeforeTree(nft)(x) && ft.hasBreak && - ((ft ne nft) || style.newlines.keep) - if (forceNL) Some(true) else None - case Some(_: Tree.CasesBlock) => Some(true) - case Some(_) if !getLastNotTrailingCommentOpt(t).exists(_.isLeft) => - if (!isThenPWithOptionalBraces(t)) None - else Some(shouldBreakInOptionalBraces(ft, nft)) - case _ => Some(true) - }).map { forceNL => - new OptionalBracesRegion { - def owner = Some(t) - def splits = Some(getSplits(t.elsep, forceNL)) - def rightBrace = blockLast(t.elsep) + def create( + nft: FT, + )(implicit style: ScalafmtConfig, ft: FT): Option[OptionalBracesRegion] = + ft.meta.leftOwner match { + case t: Term.If => (getTreeSingleExpr(t.elsep) match { + case Some(x: Term.If) => + val forceNL = isJustBeforeTree(nft)(x) && ft.hasBreak && + ((ft ne nft) || style.newlines.keep) + if (forceNL) Some(true) else None + case Some(_: Tree.CasesBlock) => Some(true) + case Some(_) + if !getLastNotTrailingCommentOpt(t).exists(_.isLeft) => + if (!isThenPWithOptionalBraces(t)) None + else Some(shouldBreakInOptionalBraces(ft, nft)) + case _ => Some(true) + }).map { forceNL => + new OptionalBracesRegion { + def owner = Some(t) + def splits = Some(getSplits(t.elsep, forceNL)) + def rightBrace = blockLast(t.elsep) + } } - } - case _ => None - } + case _ => None + } } private def getSplitsMaybeBlock( - nft: FormatToken, + nft: FT, tree: Tree, danglingKeyword: Boolean = true, )(implicit fileLine: FileLine, style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = { val forceNL = !hasSingleTermStatIfBlock(tree) || shouldBreakInOptionalBraces(ft, nft) || tree.is[Tree.CasesBlock] @@ -2391,12 +2366,12 @@ class FormatOps( } private class WithStats private ( - nft: FormatToken, + nft: FT, body: Tree, val owner: Option[Tree], nlOnly: Boolean, indentOpt: Option[Int], - )(implicit fileLine: FileLine, style: ScalafmtConfig, ft: FormatToken) + )(implicit fileLine: FileLine, style: ScalafmtConfig, ft: FT) extends OptionalBracesRegion { def splits: Option[Seq[Split]] = { val forceNL = nlOnly || shouldBreakInOptionalBraces(ft, nft) @@ -2407,7 +2382,7 @@ class FormatOps( private object WithStats { def apply( - nft: FormatToken, + nft: FT, head: Option[Tree], body: => Tree, owner: => Option[Tree], @@ -2416,17 +2391,17 @@ class FormatOps( )(implicit fileLine: FileLine, style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Option[WithStats] = head.flatMap { head => if (!isJustBeforeTree(nft)(head)) None else Some(new WithStats(nft, body, owner, nlOnly, indentOpt)) } } - private def getSplitsForIf(nft: FormatToken, t: Term.If)(implicit + private def getSplitsForIf(nft: FT, t: Term.If)(implicit fileLine: FileLine, style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = { def nestedIf(x: Term.If) = { val forceNL = shouldBreakInOptionalBraces(ft, nft) || @@ -2465,8 +2440,8 @@ class FormatOps( }) } - private def shouldBreakInOptionalBraces(ft: FormatToken, nft: FormatToken)( - implicit style: ScalafmtConfig, + private def shouldBreakInOptionalBraces(ft: FT, nft: FT)(implicit + style: ScalafmtConfig, ): Boolean = style.newlines.source match { case Newlines.unfold => true case Newlines.fold => false @@ -2478,12 +2453,12 @@ class FormatOps( !isTreeSingleExpr(tree) && !tokenBefore(tree).left.is[T.LeftBrace] @inline - private def treeLast(tree: Tree): Option[FormatToken] = getLastOpt(tree) + private def treeLast(tree: Tree): Option[FT] = getLastOpt(tree) @inline - private def blockLast(tree: Tree): Option[FormatToken] = + private def blockLast(tree: Tree): Option[FT] = if (isTreeMultiStatBlock(tree)) treeLast(tree) else None @inline - private def blockLast(tree: Term.Block): Option[FormatToken] = + private def blockLast(tree: Term.Block): Option[FT] = if (isMultiStatBlock(tree)) treeLast(tree) else None def indentAndBreakBeforeCtrl[A](tree: Tree, split: Split)(implicit @@ -2518,10 +2493,10 @@ class FormatOps( type Result = Option[(Tree, Ranges)] private trait Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result + def getBlocks(ft: FT, nft: FT, all: Boolean): Result } - def getBlocks(ft: FormatToken, all: Boolean): Result = { + def getBlocks(ft: FT, all: Boolean): Result = { val nft = nextNonComment(ft) if (nft.right.is[T.LeftBrace]) None else { @@ -2552,7 +2527,7 @@ class FormatOps( if (all && t.nonEmpty) Seq(t.head -> t.last) else Nil private object BlockImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = { + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = { def ok(stat: Tree): Boolean = isJustBeforeTree(nft)(stat) val leftOwner = ft.meta.leftOwner findTreeWithParentSimple(nft.meta.rightOwner)(_ eq leftOwner) match { @@ -2564,7 +2539,7 @@ class FormatOps( } private object RightArrowImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case t: Term.FunctionTerm => val skip = t.parent.exists(TreeOps.isExprWithParentInBraces(t)) @@ -2574,7 +2549,7 @@ class FormatOps( } private object RightParenImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case x: Term.If if !nft.right.is[T.KwThen] => val hasElse = all && !ifWithoutElse(x) @@ -2592,7 +2567,7 @@ class FormatOps( } private object RightBraceImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case t: Term.EnumeratorsBlock if !nft.right.is[T.KwDo] && getLastOpt(t).contains(ft) => @@ -2605,7 +2580,7 @@ class FormatOps( } private object DoImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case t: Term.Do => Some((t.body, seq(all, t.expr))) case _ => None @@ -2613,7 +2588,7 @@ class FormatOps( } private object EqualsImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case t: Ctor.Secondary => Some((t, seq(all, t.body))) case t: Tree.WithBody => Some((t.body, Nil)) @@ -2622,7 +2597,7 @@ class FormatOps( } private object TryImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case t: Term.TryClause => Some((t.expr, seq(all, t.catchClause) ++ seq(all, t.finallyp))) @@ -2631,7 +2606,7 @@ class FormatOps( } private object CatchImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case t: Term.TryClause => t.catchClause.map { x => (x, seq(all, t.expr) ++ seq(all, t.finallyp)) @@ -2641,7 +2616,7 @@ class FormatOps( } private object FinallyImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case t: Term.TryClause => t.finallyp .map(x => (x, seq(all, t.expr) ++ seq(all, t.catchClause))) @@ -2650,7 +2625,7 @@ class FormatOps( } private object ElseImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case x: Term.If if !x.elsep.is[Term.If] => Some((x.elsep, seq(all, x.thenp) ++ seq(all, x.cond))) @@ -2659,7 +2634,7 @@ class FormatOps( } private object YieldImpl extends Factory { - def getBlocks(ft: FormatToken, nft: FormatToken, all: Boolean): Result = + def getBlocks(ft: FT, nft: FT, all: Boolean): Result = ft.meta.leftOwner match { case t: Term.ForYield => Some((t.body, seq(all, t.enumsBlock))) case _ => None @@ -2695,16 +2670,16 @@ class FormatOps( def getLastNonTrivialTokenOpt(tree: Tree): Option[T] = tokens .getLastNonTrivialOpt(tree).map(_.left) - def getEndOfBlock(ft: FormatToken, parensToo: => Boolean)(implicit + def getEndOfBlock(ft: FT, parensToo: => Boolean)(implicit style: ScalafmtConfig, - ): Option[FormatToken] = ft.left match { + ): Option[FT] = ft.left match { case x: T.LeftBrace => matchingOpt(x) case x: T.LeftParen => if (parensToo) matchingOpt(x) else None case _ => OptionalBraces.get(ft) .flatMap(_.rightBrace.map(x => nextNonCommentSameLine(x))) } - def isCloseDelimForTrailingCommasMultiple(ft: FormatToken): Boolean = + def isCloseDelimForTrailingCommasMultiple(ft: FT): Boolean = ft.meta.rightOwner match { case x: Importer => x.importees.lengthCompare(1) > 0 // take last arg when multiple @@ -2715,7 +2690,7 @@ class FormatOps( } } - def rightIsCloseDelimToAddTrailingComma(left: T, ft: => FormatToken)(implicit + def rightIsCloseDelimToAddTrailingComma(left: T, ft: => FT)(implicit style: ScalafmtConfig, ): Boolean = style.getTrailingCommas match { case TrailingCommas.keep => left.is[T.Comma] && @@ -2729,7 +2704,7 @@ class FormatOps( case _ => false } - def getMustDangleForTrailingCommas(getCloseFt: => FormatToken)(implicit + def getMustDangleForTrailingCommas(getCloseFt: => FT)(implicit style: ScalafmtConfig, ): Boolean = !style.rewrite.trailingCommas.allowFolding && { val closeFt = getCloseFt @@ -2742,19 +2717,13 @@ class FormatOps( beforeClose.exists(rightIsCloseDelimToAddTrailingComma(_, closeFt)) } - def getBinpackDefnSiteFlags( - ftAfterOpen: => FormatToken, - ftBeforeClose: FormatToken, - )(implicit + def getBinpackDefnSiteFlags(ftAfterOpen: => FT, ftBeforeClose: FT)(implicit style: ScalafmtConfig, clauseSiteFlags: ClauseSiteFlags, ): BinpackSiteFlags = getBinpackSiteFlags(ftAfterOpen, ftBeforeClose, literalArgList = false) - def getBinpackCallSiteFlags( - ftAfterOpen: FormatToken, - ftBeforeClose: FormatToken, - )(implicit + def getBinpackCallSiteFlags(ftAfterOpen: FT, ftBeforeClose: FT)(implicit style: ScalafmtConfig, clauseSiteFlags: ClauseSiteFlags, ): BinpackSiteFlags = { @@ -2762,11 +2731,8 @@ class FormatOps( getBinpackSiteFlags(ftAfterOpen, ftBeforeClose, literalArgList) } - def getBinpackSiteFlags( - defnSite: Boolean, - ftAfterOpen: FormatToken, - ftBeforeClose: FormatToken, - )(implicit + def getBinpackSiteFlags(defnSite: Boolean, ftAfterOpen: FT, ftBeforeClose: FT)( + implicit style: ScalafmtConfig, clauseSiteFlags: ClauseSiteFlags, ): BinpackSiteFlags = @@ -2774,8 +2740,8 @@ class FormatOps( else getBinpackCallSiteFlags(ftAfterOpen, ftBeforeClose) def getBinpackSiteFlags( - getFtAfterOpen: => FormatToken, - ftBeforeClose: FormatToken, + getFtAfterOpen: => FT, + ftBeforeClose: FT, literalArgList: Boolean, )(implicit style: ScalafmtConfig, @@ -2849,9 +2815,9 @@ class FormatOps( @tailrec final def scalaJsOptCloseOnRight( - ftBeforeClose: FormatToken, + ftBeforeClose: FT, bpFlags: BinpackSiteFlags, - ): FormatToken = + ): FT = if (bpFlags.scalaJsStyle) { val ftAfterClose = nextNonCommentAfter(ftBeforeClose) val continue = ftAfterClose != ftBeforeClose && @@ -2869,16 +2835,15 @@ class FormatOps( object BinPackOneline { - private def noRighDelim(xtok: T, xft: FormatToken): Option[FormatToken] = - xtok match { - case _: T.CloseDelim => None - case _: T.Comma => Some(null) // trailing comma, has NL - case _: T.Comment => if (xft.noBreak) None else Some(null) - case _ => Some(xft) - } + private def noRighDelim(xtok: T, xft: FT): Option[FT] = xtok match { + case _: T.CloseDelim => None + case _: T.Comma => Some(null) // trailing comma, has NL + case _: T.Comment => if (xft.noBreak) None else Some(null) + case _ => Some(xft) + } private def policyOnRightDelim( - ft: FormatToken, + ft: FT, exclude: TokenRanges, ): (Option[T], Policy) = { val beforeDelims = findTokenWith(ft, prev) { xft => @@ -2893,7 +2858,7 @@ class FormatOps( def closeBreakPolicy() = { @tailrec - def iter(currft: FormatToken): Option[Policy] = { + def iter(currft: FT): Option[Policy] = { val prevft = prevNonComment(currft) val tok = prevft.left val breakBeforeClose = matchingOpt(tok) match { @@ -2970,7 +2935,7 @@ class FormatOps( } def getPolicy(isCallSite: Boolean, exclude: TokenRanges)( - afterArg: FormatToken, + afterArg: FT, )(implicit fileLine: FileLine): (Option[T], Policy) = afterArg.right match { case c: T.Comma // check for trailing comma, which needs no breaks if !nextNonCommentAfter(afterArg).right.is[T.CloseDelim] => @@ -2986,10 +2951,10 @@ class FormatOps( def indentedPackage(pkg: Pkg): Boolean = indentedPackage(pkg.body) def insideBracesBlockIfBracesToParens( - rb: FormatToken, + rb: FT, mod: Modification, isWithinBraces: Boolean, - )(implicit style: ScalafmtConfig, ft: FormatToken): Option[TokenRanges] = { + )(implicit style: ScalafmtConfig, ft: FT): Option[TokenRanges] = { val ok = initStyle.rewrite.bracesToParensForOneLineApply && style.rewrite.trailingCommas.isOptional && (mod eq Space) && !(isWithinBraces && style.spaces.inParentheses) && @@ -3016,13 +2981,10 @@ class FormatOps( } else None } - def getBracesToParensMod( - rb: FormatToken, - mod: Modification, - isWithinBraces: Boolean, - )(implicit + def getBracesToParensMod(rb: FT, mod: Modification, isWithinBraces: Boolean)( + implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): (Modification, Option[TokenRanges]) = { val tr = insideBracesBlockIfBracesToParens(rb, mod, isWithinBraces) if ((tr eq null) || tr.isEmpty) (mod, tr) @@ -3032,21 +2994,21 @@ class FormatOps( } object FormatOps { - class SelectLike(val tree: Term, val qual: Term, val nameFt: FormatToken) { + class SelectLike(val tree: Term, val qual: Term, val nameFt: FT) { def nameToken: T = nameFt.left } object SelectLike { def apply(tree: Term.Select)(implicit ftoks: FormatTokens): SelectLike = new SelectLike(tree, tree.qual, ftoks.getHead(tree.name)) - def apply(tree: Term.Match, kw: FormatToken): SelectLike = + def apply(tree: Term.Match, kw: FT): SelectLike = new SelectLike(tree, tree.expr, kw) } case class TemplateSupertypeGroup( superType: Tree, superTypeGroup: Seq[Tree], - expireTokenFunc: Seq[Tree] => FormatToken, + expireTokenFunc: Seq[Tree] => FT, ) { def getExpireToken = expireTokenFunc(superTypeGroup) def isSecond = superTypeGroup.drop(1).headOption.contains(superType) @@ -3060,7 +3022,7 @@ object FormatOps { abstract class OptionalBracesRegion { def owner: Option[Tree] def splits: Option[Seq[Split]] - def rightBrace: Option[FormatToken] + def rightBrace: Option[FT] } def getOpenParenAlignIndents( @@ -3124,25 +3086,23 @@ object FormatOps { def alignOpenDelim(implicit clauseSiteFlags: ClauseSiteFlags): Boolean = clauseSiteFlags.alignOpenDelim - val ImplicitUsingOnLeft = new FormatToken.ExtractFromMeta(meta => - TreeOps.getImplicitParamList(meta.leftOwner), - ) + val ImplicitUsingOnLeft = + new FT.ExtractFromMeta(meta => TreeOps.getImplicitParamList(meta.leftOwner)) - val WithTemplateOnLeft = new FormatToken.ExtractFromMeta(_.leftOwner match { + val WithTemplateOnLeft = new FT.ExtractFromMeta(_.leftOwner match { case lo: Stat.WithTemplate => Some(lo.templ) case _ => None }) - val TemplateOnRight = new FormatToken.ExtractFromMeta(_.rightOwner match { + val TemplateOnRight = new FT.ExtractFromMeta(_.rightOwner match { case ro: Template => Some(ro) case _ => None }) - val EnumeratorAssignRhsOnLeft = - new FormatToken.ExtractFromMeta(_.leftOwner match { - case x: Enumerator.Assign => Some(x.rhs) - case _ => None - }) + val EnumeratorAssignRhsOnLeft = new FT.ExtractFromMeta(_.leftOwner match { + case x: Enumerator.Assign => Some(x.rhs) + case _ => None + }) @tailrec private def getBlockWithNonSingleTermStat(t: Term.Block): Option[Term.Block] = diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatToken.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatToken.scala index 9b8eb6b846..b601ad6b99 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatToken.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatToken.scala @@ -21,7 +21,7 @@ import scala.annotation.tailrec * @param meta * Extra information about the token */ -case class FormatToken(left: T, right: T, meta: FormatToken.Meta) { +case class FormatToken(left: T, right: T, meta: FT.Meta) { override def toString = { val ws = newlinesBetween match { @@ -51,11 +51,11 @@ case class FormatToken(left: T, right: T, meta: FormatToken.Meta) { else 0 } @inline - def noBreak: Boolean = FormatToken.noBreak(newlinesBetween) + def noBreak: Boolean = FT.noBreak(newlinesBetween) @inline def hasBreak: Boolean = !noBreak @inline - def hasBlankLine: Boolean = FormatToken.hasBlankLine(newlinesBetween) + def hasBlankLine: Boolean = FT.hasBlankLine(newlinesBetween) @inline def leftHasNewline = meta.left.hasNL @@ -74,8 +74,7 @@ case class FormatToken(left: T, right: T, meta: FormatToken.Meta) { */ override def hashCode(): Int = hash(left).## - private[scalafmt] def withIdx(idx: Int): FormatToken = - copy(meta = meta.copy(idx = idx)) + private[scalafmt] def withIdx(idx: Int): FT = copy(meta = meta.copy(idx = idx)) @inline def idx: Int = meta.idx @@ -147,8 +146,8 @@ object FormatToken { } } - class ExtractFromMeta[A](f: FormatToken.Meta => Option[A]) { - def unapply(meta: FormatToken.Meta): Option[A] = f(meta) + class ExtractFromMeta[A](f: FT.Meta => Option[A]) { + def unapply(meta: FT.Meta): Option[A] = f(meta) } val LeftOwner = new ExtractFromMeta(x => Some(x.leftOwner)) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatTokens.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatTokens.scala index fb96116cea..c93237ae84 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatTokens.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatTokens.scala @@ -12,10 +12,10 @@ import scala.annotation.tailrec import TokenOps._ -class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken]) - extends IndexedSeq[FormatToken] { +class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FT]) + extends IndexedSeq[FT] { - private def this(arr: Array[FormatToken]) = this { + private def this(arr: Array[FT]) = this { val result = new FormatTokens.TokenToIndexMapBuilder result.sizeHint(arr.length) arr.foreach(t => result.add(t.meta.idx)(t.left)) @@ -23,13 +23,13 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] result.result() }(arr) - private lazy val matchingParentheses: Map[TokenHash, FormatToken] = TreeOps + private lazy val matchingParentheses: Map[TokenHash, FT] = TreeOps .getMatchingParentheses(arr.view)(_.left) override def length: Int = arr.length - override def apply(idx: Int): FormatToken = arr(idx) + override def apply(idx: Int): FT = arr(idx) - private def getAt(tok: T, isBefore: Boolean)(idx: Int): FormatToken = + private def getAt(tok: T, isBefore: Boolean)(idx: Int): FT = if (idx >= arr.length) arr.last else { val ft = arr(idx) @@ -39,50 +39,50 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] else at(idx + 1) } - private def get(tok: T, isBefore: Boolean): FormatToken = + private def get(tok: T, isBefore: Boolean): FT = getAt(tok, isBefore)(leftTok2tok.getOrElse( FormatTokens.thash(tok), FormatTokens.throwNoToken(tok, "Missing token index"), )) - def at(off: Int): FormatToken = + def at(off: Int): FT = if (off < 0) arr.head else if (off < arr.length) arr(off) else arr.last // get token; if rewritten, the one before @inline - def before(tok: T): FormatToken = get(tok, true) + def before(tok: T): FT = get(tok, true) // get token; if rewritten, the one after @inline - def after(tok: T): FormatToken = get(tok, false) + def after(tok: T): FT = get(tok, false) @inline - def apply(tok: T): FormatToken = before(tok) + def apply(tok: T): FT = before(tok) /** If the token is missing: * - to go backward, start from the next token * - to go forward, start from the previous token This ensures that the * next token in the direction of search is counted. */ - def apply(tok: T, off: Int): FormatToken = + def apply(tok: T, off: Int): FT = apply(if (off < 0) after(tok) else before(tok), off) - def apply(ft: FormatToken, off: Int): FormatToken = at(ft.meta.idx + off) + def apply(ft: FT, off: Int): FT = at(ft.meta.idx + off) @inline - def hasNext(ft: FormatToken): Boolean = ft.meta.idx < (arr.length - 1) + def hasNext(ft: FT): Boolean = ft.meta.idx < (arr.length - 1) @inline - def hasPrev(ft: FormatToken): Boolean = ft.meta.idx > 0 + def hasPrev(ft: FT): Boolean = ft.meta.idx > 0 @inline - def prev(ft: FormatToken): FormatToken = apply(ft, -1) + def prev(ft: FT): FT = apply(ft, -1) @inline - def next(ft: FormatToken): FormatToken = apply(ft, 1) + def next(ft: FT): FT = apply(ft, 1) @inline - def matching(token: T): FormatToken = matchingParentheses.getOrElse( + def matching(token: T): FT = matchingParentheses.getOrElse( FormatTokens.thash(token), FormatTokens.throwNoToken(token, "Missing matching token index"), ) @inline - def matchingOpt(token: T): Option[FormatToken] = matchingParentheses + def matchingOpt(token: T): Option[FT] = matchingParentheses .get(FormatTokens.thash(token)) @inline def hasMatching(token: T): Boolean = matchingParentheses @@ -96,35 +96,31 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] def getHeadAndLastIfEnclosed( tokens: Tokens, tree: Tree, - ): Option[(FormatToken, Option[FormatToken])] = getHeadOpt(tokens, tree) - .map { head => - head -> matchingOpt(head.left).flatMap { other => - val last = getLastNonTrivial(tokens, tree) - if (last eq other) Some(last) else None - } + ): Option[(FT, Option[FT])] = getHeadOpt(tokens, tree).map { head => + head -> matchingOpt(head.left).flatMap { other => + val last = getLastNonTrivial(tokens, tree) + if (last eq other) Some(last) else None } - def getHeadAndLastIfEnclosed( - tree: Tree, - ): Option[(FormatToken, Option[FormatToken])] = + } + def getHeadAndLastIfEnclosed(tree: Tree): Option[(FT, Option[FT])] = getHeadAndLastIfEnclosed(tree.tokens, tree) - def getDelimsIfEnclosed( - tokens: Tokens, - tree: Tree, - ): Option[(FormatToken, FormatToken)] = getHeadAndLastIfEnclosed(tokens, tree) - .flatMap { case (head, lastOpt) => lastOpt.map(last => (head, last)) } - def getDelimsIfEnclosed(tree: Tree): Option[(FormatToken, FormatToken)] = + def getDelimsIfEnclosed(tokens: Tokens, tree: Tree): Option[(FT, FT)] = + getHeadAndLastIfEnclosed(tokens, tree).flatMap { case (head, lastOpt) => + lastOpt.map(last => (head, last)) + } + def getDelimsIfEnclosed(tree: Tree): Option[(FT, FT)] = getDelimsIfEnclosed(tree.tokens, tree) - def getHeadIfEnclosed(tokens: Tokens, tree: Tree): Option[FormatToken] = + def getHeadIfEnclosed(tokens: Tokens, tree: Tree): Option[FT] = getDelimsIfEnclosed(tokens, tree).map(_._1) - def getHeadIfEnclosed(tree: Tree): Option[FormatToken] = - getDelimsIfEnclosed(tree).map(_._1) + def getHeadIfEnclosed(tree: Tree): Option[FT] = getDelimsIfEnclosed(tree) + .map(_._1) - def getLastIfEnclosed(tokens: Tokens, tree: Tree): Option[FormatToken] = + def getLastIfEnclosed(tokens: Tokens, tree: Tree): Option[FT] = getDelimsIfEnclosed(tokens, tree).map(_._2) - def getLastIfEnclosed(tree: Tree): Option[FormatToken] = - getDelimsIfEnclosed(tree).map(_._2) + def getLastIfEnclosed(tree: Tree): Option[FT] = getDelimsIfEnclosed(tree) + .map(_._2) def isEnclosedInMatching(tokens: Tokens, tree: Tree): Boolean = getDelimsIfEnclosed(tokens, tree).isDefined @@ -132,7 +128,7 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] isEnclosedInMatching(tree.tokens, tree) @inline - def getBracesIfEnclosed(tree: Tree): Option[(FormatToken, FormatToken)] = + def getBracesIfEnclosed(tree: Tree): Option[(FT, FT)] = getDelimsIfEnclosed(tree).filter(_._1.left.is[T.LeftBrace]) @inline @@ -145,9 +141,7 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] def isEnclosedWithinParensOrBraces(tree: Tree): Boolean = getClosingIfWithinParens(tree) != Left(false) - def getClosingIfWithinParens( - last: FormatToken, - )(head: FormatToken): Either[Boolean, FormatToken] = { + def getClosingIfWithinParens(last: FT)(head: FT): Either[Boolean, FT] = { val innerMatched = areMatching(last.left)(head.left) if (innerMatched && last.left.is[T.RightParen]) Right(prev(last)) else { @@ -158,7 +152,7 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] } } - def getClosingIfWithinParens(tree: Tree): Either[Boolean, FormatToken] = { + def getClosingIfWithinParens(tree: Tree): Either[Boolean, FT] = { val tokens = tree.tokens getHeadOpt(tokens, tree) match { case Some(head) => @@ -167,70 +161,61 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] } } - def getLastExceptParen(tree: Tree): FormatToken = { + def getLastExceptParen(tree: Tree): FT = { val tokens = tree.tokens val last = getLastNonTrivial(tokens, tree) getClosingIfWithinParens(last)(getHead(tokens, tree)).getOrElse(last) } - final def findTokenWith[A](ft: FormatToken, iter: FormatToken => FormatToken)( - f: FormatToken => Option[A], - ): Either[FormatToken, A] = findTokenEx(ft)(xft => f(xft).toRight(iter(xft))) + final def findTokenWith[A](ft: FT, iter: FT => FT)( + f: FT => Option[A], + ): Either[FT, A] = findTokenEx(ft)(xft => f(xft).toRight(iter(xft))) @tailrec - final def findTokenEx[A](ft: FormatToken)( - f: FormatToken => Either[FormatToken, A], - ): Either[FormatToken, A] = f(ft) match { - case null => Left(ft) - case Left(nextFt) if nextFt ne ft => findTokenEx(nextFt)(f) - case x => x - } + final def findTokenEx[A](ft: FT)(f: FT => Either[FT, A]): Either[FT, A] = + f(ft) match { + case null => Left(ft) + case Left(nextFt) if nextFt ne ft => findTokenEx(nextFt)(f) + case x => x + } - final def findToken(ft: FormatToken, iter: FormatToken => FormatToken)( - f: FormatToken => Boolean, - ): FormatToken = findTokenWith(ft, iter)(Some(_).filter(f)).merge + final def findToken(ft: FT, iter: FT => FT)(f: FT => Boolean): FT = + findTokenWith(ft, iter)(Some(_).filter(f)).merge - final def nextNonCommentSameLine(curr: FormatToken): FormatToken = + final def nextNonCommentSameLine(curr: FT): FT = findToken(curr, next)(ft => ft.hasBreak || !ft.right.is[T.Comment]) - final def nextNonCommentSameLineAfter(curr: FormatToken): FormatToken = + final def nextNonCommentSameLineAfter(curr: FT): FT = nextNonCommentSameLine(next(curr)) - final def nextNonComment(curr: FormatToken): FormatToken = + final def nextNonComment(curr: FT): FT = findToken(curr, next)(!_.right.is[T.Comment]) - final def nextNonComment(curr: FormatToken.Meta): FormatToken = - nextNonComment(arr(curr.idx)) + final def nextNonComment(curr: FT.Meta): FT = nextNonComment(arr(curr.idx)) @inline - final def nextNonCommentAfter(curr: FormatToken): FormatToken = - nextNonComment(next(curr)) + final def nextNonCommentAfter(curr: FT): FT = nextNonComment(next(curr)) @inline - final def nextAfterNonComment(curr: FormatToken): FormatToken = - next(nextNonComment(curr)) + final def nextAfterNonComment(curr: FT): FT = next(nextNonComment(curr)) - final def prevNonCommentSameLine(curr: FormatToken): FormatToken = + final def prevNonCommentSameLine(curr: FT): FT = findToken(curr, prev)(ft => ft.hasBreak || !ft.left.is[T.Comment]) - final def prevNonComment(curr: FormatToken): FormatToken = + final def prevNonComment(curr: FT): FT = findToken(curr, prev)(!_.left.is[T.Comment]) @inline - final def prevNonCommentBefore(curr: FormatToken): FormatToken = - prevNonComment(prev(curr)) + final def prevNonCommentBefore(curr: FT): FT = prevNonComment(prev(curr)) @inline - final def prevBeforeNonComment(curr: FormatToken): FormatToken = - prev(prevNonComment(curr)) + final def prevBeforeNonComment(curr: FT): FT = prev(prevNonComment(curr)) @inline - final def prevNonCommentSameLineBefore(curr: FormatToken): FormatToken = + final def prevNonCommentSameLineBefore(curr: FT): FT = prevNonCommentSameLine(prev(curr)) - def prevNotTrailingComment( - curr: FormatToken, - ): Either[FormatToken, FormatToken] = curr.left match { + def prevNotTrailingComment(curr: FT): Either[FT, FT] = curr.left match { case _: T.Comment => val prev = prevNonCommentSameLineBefore(curr) if (prev.hasBreak) Left(curr) else Right(prev) @@ -238,40 +223,40 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] } @tailrec - final def getOnOrBeforeOwned(ft: FormatToken, tree: Tree): FormatToken = { + final def getOnOrBeforeOwned(ft: FT, tree: Tree): FT = { val prevFt = prevNonCommentBefore(ft) if (prevFt == ft || prevFt.meta.leftOwner != tree) ft else getOnOrBeforeOwned(prevFt, tree) } @tailrec - final def getOnOrAfterOwned(ft: FormatToken, tree: Tree): FormatToken = { + final def getOnOrAfterOwned(ft: FT, tree: Tree): FT = { val nextFt = nextAfterNonComment(ft) if (nextFt == ft || nextFt.meta.leftOwner != tree) ft else getOnOrAfterOwned(nextFt, tree) } @inline - private def getHeadImpl(tokens: Tokens): FormatToken = after(tokens.head) - def getHead(tokens: Tokens, tree: Tree): FormatToken = + private def getHeadImpl(tokens: Tokens): FT = after(tokens.head) + def getHead(tokens: Tokens, tree: Tree): FT = getOnOrBeforeOwned(getHeadImpl(tokens), tree) @inline - def getHead(tree: Tree): FormatToken = getHead(tree.tokens, tree) + def getHead(tree: Tree): FT = getHead(tree.tokens, tree) - def getHeadOpt(tokens: Tokens, tree: Tree): Option[FormatToken] = tokens - .headOption.map(x => getOnOrBeforeOwned(after(x), tree)) + def getHeadOpt(tokens: Tokens, tree: Tree): Option[FT] = tokens.headOption + .map(x => getOnOrBeforeOwned(after(x), tree)) @inline - def getHeadOpt(tree: Tree): Option[FormatToken] = getHeadOpt(tree.tokens, tree) + def getHeadOpt(tree: Tree): Option[FT] = getHeadOpt(tree.tokens, tree) @inline - private def getLastImpl(tokens: Tokens): FormatToken = + private def getLastImpl(tokens: Tokens): FT = apply(findLastVisibleToken(tokens)) - def getLast(tokens: Tokens, tree: Tree): FormatToken = + def getLast(tokens: Tokens, tree: Tree): FT = getOnOrAfterOwned(getLastImpl(tokens), tree) @inline - def getLast(tree: Tree): FormatToken = getLast(tree.tokens, tree) + def getLast(tree: Tree): FT = getLast(tree.tokens, tree) - def getOnOrAfterLast(tokens: Tokens, tree: Tree): FormatToken = { + def getOnOrAfterLast(tokens: Tokens, tree: Tree): FT = { val last = tokens.last val beforeLast = before(last) val res = getOnOrAfterOwned(beforeLast, tree) @@ -281,109 +266,103 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] } @inline - def getOnOrAfterLast(tree: Tree): FormatToken = - getOnOrAfterLast(tree.tokens, tree) + def getOnOrAfterLast(tree: Tree): FT = getOnOrAfterLast(tree.tokens, tree) - def getLastOpt(tokens: Tokens, tree: Tree): Option[FormatToken] = + def getLastOpt(tokens: Tokens, tree: Tree): Option[FT] = findLastVisibleTokenOpt(tokens).map(x => getOnOrAfterOwned(apply(x), tree)) @inline - def getLastOpt(tree: Tree): Option[FormatToken] = getLastOpt(tree.tokens, tree) + def getLastOpt(tree: Tree): Option[FT] = getLastOpt(tree.tokens, tree) - def getLastNonTrivial(tokens: Tokens, tree: Tree): FormatToken = + def getLastNonTrivial(tokens: Tokens, tree: Tree): FT = prevNonComment(getLast(tokens, tree)) - def getLastNonTrivial(tree: Tree): FormatToken = - getLastNonTrivial(tree.tokens, tree) + def getLastNonTrivial(tree: Tree): FT = getLastNonTrivial(tree.tokens, tree) - def getLastNonTrivialOpt(tokens: Tokens, tree: Tree): Option[FormatToken] = + def getLastNonTrivialOpt(tokens: Tokens, tree: Tree): Option[FT] = getLastOpt(tokens, tree).map(prevNonComment) - def getLastNonTrivialOpt(tree: Tree): Option[FormatToken] = + def getLastNonTrivialOpt(tree: Tree): Option[FT] = getLastNonTrivialOpt(tree.tokens, tree) - def getLastNotTrailingComment(tree: Tree): Either[FormatToken, FormatToken] = + def getLastNotTrailingComment(tree: Tree): Either[FT, FT] = prevNotTrailingComment(getLast(tree)) - def getLastNotTrailingCommentOpt( - tree: Tree, - ): Option[Either[FormatToken, FormatToken]] = getLastOpt(tree) - .map(prevNotTrailingComment) + def getLastNotTrailingCommentOpt(tree: Tree): Option[Either[FT, FT]] = + getLastOpt(tree).map(prevNotTrailingComment) /* the following methods return the first format token such that * its `right` is after the parameter and is not a comment */ @inline - def tokenAfter(ft: FormatToken): FormatToken = nextNonComment(ft) + def tokenAfter(ft: FT): FT = nextNonComment(ft) @inline - def tokenAfter(token: T): FormatToken = tokenAfter(before(token)) + def tokenAfter(token: T): FT = tokenAfter(before(token)) @inline - def tokenAfter(tree: Tree): FormatToken = tokenAfter(getLast(tree)) + def tokenAfter(tree: Tree): FT = tokenAfter(getLast(tree)) @inline - def tokenAfter(trees: Seq[Tree]): FormatToken = tokenAfter(trees.last) + def tokenAfter(trees: Seq[Tree]): FT = tokenAfter(trees.last) - def tokenAfterOpt(tree: Tree): Option[FormatToken] = getLastOpt(tree) + def tokenAfterOpt(tree: Tree): Option[FT] = getLastOpt(tree) .map(nextNonComment) - def tokenAfterOpt(trees: Seq[Tree]): Option[FormatToken] = trees.lastOption + def tokenAfterOpt(trees: Seq[Tree]): Option[FT] = trees.lastOption .flatMap(tokenAfterOpt) /* the following methods return the last format token such that * its `left` is before the parameter */ @inline - def justBefore(token: T): FormatToken = apply(token, -1) + def justBefore(token: T): FT = apply(token, -1) @inline - def tokenJustBefore(ft: FormatToken): FormatToken = prev(ft) + def tokenJustBefore(ft: FT): FT = prev(ft) @inline - def tokenJustBefore(tree: Tree): FormatToken = prev(getHead(tree)) + def tokenJustBefore(tree: Tree): FT = prev(getHead(tree)) - def tokenJustBeforeOpt(tree: Tree): Option[FormatToken] = getHeadOpt(tree) - .map(prev) - def tokenJustBeforeOpt(trees: Seq[Tree]): Option[FormatToken] = trees - .headOption.flatMap(tokenJustBeforeOpt) + def tokenJustBeforeOpt(tree: Tree): Option[FT] = getHeadOpt(tree).map(prev) + def tokenJustBeforeOpt(trees: Seq[Tree]): Option[FT] = trees.headOption + .flatMap(tokenJustBeforeOpt) def isTokenHeadOf(tok: => T, tree: Tree): Boolean = getHeadOpt(tree) match { case None => false case Some(x) => x.left eq tok } - def isJustBeforeTree(ft: FormatToken)(tree: Tree): Boolean = + def isJustBeforeTree(ft: FT)(tree: Tree): Boolean = isTokenHeadOf(ft.right, tree) /* the following methods return the last format token such that * its `left` is before the parameter and is not a comment */ @inline - def tokenOnOrBefore(token: T): FormatToken = prevNonComment(before(token)) + def tokenOnOrBefore(token: T): FT = prevNonComment(before(token)) @inline - def tokenBefore(ft: FormatToken): FormatToken = prevNonCommentBefore(ft) + def tokenBefore(ft: FT): FT = prevNonCommentBefore(ft) @inline - def tokenBefore(token: T): FormatToken = prevNonComment(justBefore(token)) + def tokenBefore(token: T): FT = prevNonComment(justBefore(token)) @inline - def tokenBefore(tree: Tree): FormatToken = - prevNonComment(tokenJustBefore(tree)) + def tokenBefore(tree: Tree): FT = prevNonComment(tokenJustBefore(tree)) @inline - def tokenBefore(trees: Seq[Tree]): FormatToken = tokenBefore(trees.head) + def tokenBefore(trees: Seq[Tree]): FT = tokenBefore(trees.head) - def tokenBeforeOpt(tree: Tree): Option[FormatToken] = tokenJustBeforeOpt(tree) + def tokenBeforeOpt(tree: Tree): Option[FT] = tokenJustBeforeOpt(tree) .map(prevNonComment) - def tokenBeforeOpt(trees: Seq[Tree]): Option[FormatToken] = trees.headOption + def tokenBeforeOpt(trees: Seq[Tree]): Option[FT] = trees.headOption .flatMap(tokenBeforeOpt) @inline - def isBreakAfterRight(ft: FormatToken): Boolean = next(ft).hasBreakOrEOF + def isBreakAfterRight(ft: FT): Boolean = next(ft).hasBreakOrEOF @inline - def hasBreakAfterRightBeforeNonComment(ft: FormatToken): Boolean = + def hasBreakAfterRightBeforeNonComment(ft: FT): Boolean = nextNonCommentSameLineAfter(ft).hasBreakOrEOF @inline - def hasBreakBeforeNonComment(ft: FormatToken): Boolean = ft.hasBreak || + def hasBreakBeforeNonComment(ft: FT): Boolean = ft.hasBreak || hasBreakAfterRightBeforeNonComment(ft) @inline - def isRightCommentThenBreak(ft: FormatToken): Boolean = ft.right - .is[T.Comment] && hasBreakAfterRightBeforeNonComment(ft) + def isRightCommentThenBreak(ft: FT): Boolean = ft.right.is[T.Comment] && + hasBreakAfterRightBeforeNonComment(ft) @inline - def isRightCommentWithBreak(ft: FormatToken): Boolean = ft.right - .is[T.Comment] && hasBreakBeforeNonComment(ft) + def isRightCommentWithBreak(ft: FT): Boolean = ft.right.is[T.Comment] && + hasBreakBeforeNonComment(ft) @inline - def isAttachedCommentThenBreak(ft: FormatToken): Boolean = ft.noBreak && + def isAttachedCommentThenBreak(ft: FT): Boolean = ft.noBreak && isRightCommentThenBreak(ft) def isEmpty(tree: Tree): Boolean = { @@ -406,17 +385,13 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken] result } - private def spanOrWidth(left: FormatToken, right: FormatToken)( - f: ((Int, Int)) => Int, - ): Int = { + private def spanOrWidth(left: FT, right: FT)(f: ((Int, Int)) => Int): Int = { val lastIdx = nonWhitespaceOffset.length - 1 val rightIdx = if (right.idx >= lastIdx) lastIdx else right.idx + 1 f(nonWhitespaceOffset(rightIdx)) - f(nonWhitespaceOffset(left.idx)) } - def width(left: FormatToken, right: FormatToken): Int = - spanOrWidth(left, right)(_._2) - def span(left: FormatToken, right: FormatToken): Int = - spanOrWidth(left, right)(_._1) + def width(left: FT, right: FT): Int = spanOrWidth(left, right)(_._2) + def span(left: FT, right: FT): Int = spanOrWidth(left, right)(_._1) def span(tokens: Tokens): Int = if (tokens.isEmpty) 0 else span(getHeadImpl(tokens), getLastImpl(tokens)) @inline @@ -435,22 +410,22 @@ object FormatTokens { style: ScalafmtConfig, ): (FormatTokens, StyleMap) = { var left: T = null - var lmeta: FormatToken.TokenMeta = null - val result = Array.newBuilder[FormatToken] + var lmeta: FT.TokenMeta = null + val result = Array.newBuilder[FT] var ftIdx = 0 var wsIdx = 0 var tokIdx = 0 var fmtWasOff = false val arr = tokens.toArray def process(right: T): Unit = { - val rmeta = FormatToken.TokenMeta(owner(right), right.text) + val rmeta = FT.TokenMeta(owner(right), right.text) if (left eq null) fmtWasOff = isFormatOff(right) else { val between = arr.slice(wsIdx, tokIdx) val fmtIsOff = fmtWasOff || isFormatOff(right) fmtWasOff = if (fmtWasOff) !isFormatOn(right) else fmtIsOff - val meta = FormatToken.Meta(between, ftIdx, fmtIsOff, lmeta, rmeta) - result += FormatToken(left, right, meta) + val meta = FT.Meta(between, ftIdx, fmtIsOff, lmeta, rmeta) + result += FT(left, right, meta) ftIdx += 1 } left = right diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatWriter.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatWriter.scala index 88863c4114..3394f126ee 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatWriter.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatWriter.scala @@ -111,12 +111,7 @@ class FormatWriter(formatOps: FormatOps) { } @tailrec - def iter( - cur: State, - lineId: Int, - gapId: Int, - prevEol: FormatToken, - ): Unit = { + def iter(cur: State, lineId: Int, gapId: Int, prevEol: FT): Unit = { val prev = cur.prev val idx = prev.depth val ft = toks(idx) @@ -484,12 +479,9 @@ class FormatWriter(formatOps: FormatOps) { def isClosedDelimWithNewline(expectedNewline: Boolean): Boolean = getClosedDelimWithNewline(expectedNewline).isDefined - def getClosedDelimWithNewline(whenNL: Boolean): Option[FormatToken] = { + def getClosedDelimWithNewline(whenNL: Boolean): Option[FT] = { @tailrec - def iter( - floc: FormatLocation, - hadNL: Boolean, - ): Option[FormatToken] = { + def iter(floc: FormatLocation, hadNL: Boolean): Option[FT] = { val isNL = floc.hasBreakAfter if (isNL && !whenNL) None else { @@ -1388,9 +1380,9 @@ class FormatWriter(formatOps: FormatOps) { def setIdxCheck(idx: => Int, cnt: Int, force: => Boolean) = if (cnt > 0) setIdx(idx, cnt) else if (cnt < 0 && force) setIdx(idx, 0) @inline - def setFt(ft: FormatToken) = setIdx(ft.meta.idx, 1) + def setFt(ft: FT) = setIdx(ft.meta.idx, 1) @inline - def setFtCheck(ft: FormatToken, cnt: Int, force: => Boolean) = + def setFtCheck(ft: FT, cnt: Int, force: => Boolean) = setIdxCheck(ft.meta.idx, cnt, force) def setTopStats(owner: Tree, notUnindentedPkg: Boolean)( stats: Seq[Tree], @@ -1565,7 +1557,7 @@ class FormatWriter(formatOps: FormatOps) { statHead: Tree, statLast: Tree, nest: Int, - ): Option[(Newlines.NumBlanks, FormatToken, FormatToken)] = { + ): Option[(Newlines.NumBlanks, FT, FT)] = { val head = tokenJustBefore(statHead) val last = getLast(statLast) val bLoc = locations(head.meta.idx + 1) @@ -1602,7 +1594,7 @@ object FormatWriter { private val NoLine = Int.MaxValue case class FormatLocation( - formatToken: FormatToken, + formatToken: FT, state: State, style: ScalafmtConfig, leftLineId: Int, // counts back from the end of the file @@ -1854,8 +1846,8 @@ object FormatWriter { if (useLeft) floc.state.prev.column else floc.state.column } - private def getAlignNonSlcOwner(ft: FormatToken, nextFloc: FormatLocation)( - implicit floc: FormatLocation, + private def getAlignNonSlcOwner(ft: FT, nextFloc: FormatLocation)(implicit + floc: FormatLocation, ): Option[Option[Tree]] = { def getNonSlcOwner = ft.meta.rightOwner match { case name: Term.Name => name.parent match { @@ -1950,11 +1942,8 @@ object FormatWriter { beg.leftBlankGapId - end.leftBlankGapId @inline - private def getLineDiff( - toks: Array[FormatLocation], - beg: FormatToken, - end: FormatToken, - ): Int = getLineDiff(toks(beg.meta.idx), toks(end.meta.idx)) + private def getLineDiff(toks: Array[FormatLocation], beg: FT, end: FT): Int = + getLineDiff(toks(beg.meta.idx), toks(end.meta.idx)) def isEmptyDocstring(text: String): Boolean = emptyDocstring.matcher(text) .matches() diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Indent.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Indent.scala index d987b7ef0a..8adc90c0c2 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Indent.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Indent.scala @@ -5,18 +5,17 @@ import scala.meta.tokens.{Token => T} import scala.annotation.tailrec sealed abstract class ExpiresOn { - def notExpiredBy(ft: FormatToken, expireEnd: Int): Boolean + def notExpiredBy(ft: FT, expireEnd: Int): Boolean } object ExpiresOn { case object After extends ExpiresOn { - def notExpiredBy(ft: FormatToken, expireEnd: Int): Boolean = - ft.right.start < expireEnd + def notExpiredBy(ft: FT, expireEnd: Int): Boolean = ft.right.start < + expireEnd } case object Before extends ExpiresOn { - def notExpiredBy(ft: FormatToken, expireEnd: Int): Boolean = ft.right.end < - expireEnd + def notExpiredBy(ft: FT, expireEnd: Int): Boolean = ft.right.end < expireEnd } @inline @@ -56,8 +55,7 @@ case class ActualIndent( reset: Boolean, ) { @inline - def notExpiredBy(ft: FormatToken): Boolean = expiresAt - .notExpiredBy(ft, expireEnd) + def notExpiredBy(ft: FT): Boolean = expiresAt.notExpiredBy(ft, expireEnd) } abstract class Indent { diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Modification.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Modification.scala index 560766f88c..b99d593543 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Modification.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Modification.scala @@ -9,7 +9,7 @@ sealed abstract class Modification { final def isBlankLine: Boolean = newlines > 1 } -case class Provided(ft: FormatToken) extends Modification { +case class Provided(ft: FT) extends Modification { override val newlines: Int = ft.newlinesBetween override lazy val length: Int = if (isNL) betweenText.indexOf('\n') else betweenText.length @@ -56,7 +56,7 @@ object Newline extends NewlineT { object Newline2x extends NewlineT(isDouble = true) { def apply(isDouble: Boolean): NewlineT = if (isDouble) this else Newline - def apply(ft: FormatToken): NewlineT = apply(ft.hasBlankLine) + def apply(ft: FT): NewlineT = apply(ft.hasBlankLine) } object NoIndentNewline extends NewlineT(noIndent = true) @@ -71,9 +71,8 @@ object Space extends Modification { def apply(flag: Boolean): Modification = if (flag) this else NoSplit def orNL(flag: Boolean): Modification = if (flag) this else Newline def orNL(nl: Int): Modification = - if (FormatToken.noBreak(nl)) this - else Newline2x(FormatToken.hasBlankLine(nl)) - def orNL(ft: FormatToken): Modification = orNL(ft.newlinesBetween) + if (FT.noBreak(nl)) this else Newline2x(FT.hasBlankLine(nl)) + def orNL(ft: FT): Modification = orNL(ft.newlinesBetween) } case class SpaceOrNoSplit(policy: Policy.End.WithPos) extends Modification { diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/OptimizationEntities.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/OptimizationEntities.scala index 0c36326e63..59443699cd 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/OptimizationEntities.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/OptimizationEntities.scala @@ -15,9 +15,8 @@ class OptimizationEntities( val statementStarts: Map[Int, Tree], ) { def argumentAt(idx: Int): Option[Tree] = argumentStarts.get(idx) - def argument(implicit ft: FormatToken): Option[Tree] = argumentAt(ft.meta.idx) - def optionalNL(implicit ft: FormatToken): Boolean = - optionalNewlines(ft.meta.idx) + def argument(implicit ft: FT): Option[Tree] = argumentAt(ft.meta.idx) + def optionalNL(implicit ft: FT): Boolean = optionalNewlines(ft.meta.idx) } object OptimizationEntities { @@ -86,7 +85,7 @@ object OptimizationEntities { case _ => } - private def addStmtFT(stmt: Tree)(ft: FormatToken): Unit = { + private def addStmtFT(stmt: Tree)(ft: FT): Unit = { val isComment = ft.left.is[T.Comment] val nft = if (isComment) ftoks.nextAfterNonComment(ft) else ft statements += nft.meta.idx -> stmt diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Policy.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Policy.scala index bdf69a975f..32e4bd7085 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Policy.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Policy.scala @@ -17,8 +17,8 @@ abstract class Policy { def filter(pred: Policy.Clause => Boolean): Policy def exists(pred: Policy.Clause => Boolean): Boolean - def appliesUntil(nextft: FormatToken)(pred: Policy.Clause => Boolean): Boolean - def unexpired(split: Split, nextft: FormatToken): Policy + def appliesUntil(nextft: FT)(pred: Policy.Clause => Boolean): Boolean + def unexpired(split: Split, nextft: FT): Policy def noDequeue: Boolean def switch(trigger: T, on: Boolean): Policy @@ -32,7 +32,7 @@ abstract class Policy { def ?(flag: Boolean): Policy = if (flag) this else Policy.NoPolicy @inline - final def unexpiredOpt(split: Split, nextft: FormatToken): Option[Policy] = + final def unexpiredOpt(split: Split, nextft: FT): Option[Policy] = Some(unexpired(split, nextft)).filter(_.nonEmpty) @inline @@ -66,8 +66,8 @@ object Policy { override def ?(flag: Boolean): Policy = this override def rank: Int = 0 - override def unexpired(split: Split, nextft: FormatToken): Policy = this - override def appliesUntil(nextft: FormatToken)( + override def unexpired(split: Split, nextft: FT): Policy = this + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = false override def filter(pred: Clause => Boolean): Policy = this @@ -123,7 +123,7 @@ object Policy { s"$prefixWithColon[$fileLine]$endPolicy${noDeqPrefix}d$suffixWithColon" } - override def unexpired(split: Split, nextft: FormatToken): Policy = + override def unexpired(split: Split, nextft: FT): Policy = if (endPolicy.notExpiredBy(nextft)) this else NoPolicy override def filter(pred: Clause => Boolean): Policy = @@ -133,7 +133,7 @@ object Policy { override def switch(trigger: T, on: Boolean): Policy = this - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = endPolicy.notExpiredBy(nextft) && pred(this) } @@ -148,7 +148,7 @@ object Policy { extends Clause abstract class WithConv extends Policy { - override def unexpired(split: Split, nextft: FormatToken): Policy = + override def unexpired(split: Split, nextft: FT): Policy = conv(_.unexpired(split, nextft)) override def filter(pred: Clause => Boolean): Policy = conv(_.filter(pred)) @@ -174,7 +174,7 @@ object Policy { if (np1.eq(p1) && np2.eq(p2)) this else np1 | np2 } - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = p1.appliesUntil(nextft)(pred) && p2.appliesUntil(nextft)(pred) @@ -202,7 +202,7 @@ object Policy { if (np1.eq(p1) && np2.eq(p2)) this else np1 & np2 } - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = p1.appliesUntil(nextft)(pred) || p2.appliesUntil(nextft)(pred) @@ -218,7 +218,7 @@ object Policy { val res = policy.switch(trigger, on) if (res eq policy) this else res } - override def unexpired(split: Split, nextft: FormatToken): Policy = + override def unexpired(split: Split, nextft: FT): Policy = if (!endPolicy.notExpiredBy(nextft)) NoPolicy else super.unexpired(split, nextft) override def noDequeue: Boolean = policy.noDequeue @@ -229,7 +229,7 @@ object Policy { if (filtered eq policy) this else filtered <== endPolicy } - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = endPolicy.notExpiredBy(nextft) && policy.appliesUntil(nextft)(pred) @@ -243,13 +243,13 @@ object Policy { override def filter(pred: Clause => Boolean): Policy = this override def exists(pred: Clause => Boolean): Boolean = policy.exists(pred) override def switch(trigger: T, on: Boolean): Policy = this - override def unexpired(split: Split, nextft: FormatToken): Policy = + override def unexpired(split: Split, nextft: FT): Policy = if (begPolicy.notExpiredBy(nextft)) this else policy.unexpired(split, nextft) override def noDequeue: Boolean = policy.noDequeue override def toString: String = s"$begPolicy ==> $policy" - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = false } @@ -268,7 +268,7 @@ object Policy { else new Relay(filtered, after) } - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = before.appliesUntil(nextft)(pred) && after.appliesUntil(nextft)(pred) @@ -279,14 +279,14 @@ object Policy { class RelayOnSplit( before: Policy, - trigger: (Split, FormatToken) => Boolean, + trigger: (Split, FT) => Boolean, triggerEnd: Policy.End.WithPos, after: Policy, )(implicit fileLine: FileLine) extends WithConv { override def f: Pf = before.f override def rank: Int = before.rank - override def unexpired(split: Split, nextft: FormatToken): Policy = + override def unexpired(split: Split, nextft: FT): Policy = if (trigger(split, nextft)) after.unexpired(split, nextft) else if (!triggerEnd.notExpiredBy(nextft)) NoPolicy else super.unexpired(split, nextft) @@ -300,7 +300,7 @@ object Policy { else new RelayOnSplit(filtered, trigger, triggerEnd, after) } - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = before.appliesUntil(nextft)(pred) && after.appliesUntil(nextft)(pred) @@ -311,14 +311,13 @@ object Policy { object RelayOnSplit { def by(triggerEnd: Policy.End.WithPos)( - trigger: (Split, FormatToken) => Boolean, + trigger: (Split, FT) => Boolean, )(before: Policy)(after: Policy)(implicit fileLine: FileLine): Policy = if (before.isEmpty) after else new RelayOnSplit(before, trigger, triggerEnd, after) - def apply( - trigger: (Split, FormatToken) => Boolean, - )(before: Policy)(after: Policy)(implicit fileLine: FileLine): Policy = - by(Policy.End.Never)(trigger)(before)(after) + def apply(trigger: (Split, FT) => Boolean)(before: Policy)(after: Policy)( + implicit fileLine: FileLine, + ): Policy = by(Policy.End.Never)(trigger)(before)(after) } class Switch(before: Policy, trigger: T, after: Policy)(implicit @@ -338,7 +337,7 @@ object Policy { if (filtered eq before) this else new Switch(filtered, trigger, after) } - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = before.appliesUntil(nextft)(pred) && after.appliesUntil(nextft)(pred) @@ -374,11 +373,11 @@ object Policy { if (switched eq policy) this else Proxy(switched, endPolicy)(factory) } - override def unexpired(split: Split, nextft: FormatToken): Policy = + override def unexpired(split: Split, nextft: FT): Policy = if (!endPolicy.notExpiredBy(nextft)) NoPolicy else Proxy(policy.unexpired(split, nextft), endPolicy)(factory) - override def appliesUntil(nextft: FormatToken)( + override def appliesUntil(nextft: FT)( pred: Policy.Clause => Boolean, ): Boolean = policy.appliesUntil(nextft)(pred) @@ -424,33 +423,30 @@ object Policy { def ==(token: T): End.WithPos = On(token) sealed trait WithPos { - def notExpiredBy(ft: FormatToken): Boolean + def notExpiredBy(ft: FT): Boolean def ==>(policy: Policy): Policy = if (policy.isEmpty) NoPolicy else new Policy.Delay(policy, this) } case object After extends End { def apply(token: T): WithPos = new End.WithPos { - def notExpiredBy(ft: FormatToken): Boolean = ft.left.start <= - token.start + def notExpiredBy(ft: FT): Boolean = ft.left.start <= token.start override def toString: String = s">${token.structure}" } } case object Before extends End { def apply(token: T): WithPos = new End.WithPos { - def notExpiredBy(ft: FormatToken): Boolean = ft.right.start < - token.start + def notExpiredBy(ft: FT): Boolean = ft.right.start < token.start override def toString: String = s"<${token.structure}" } } case object On extends End { def apply(token: T): WithPos = new End.WithPos { - def notExpiredBy(ft: FormatToken): Boolean = ft.right.start <= - token.start + def notExpiredBy(ft: FT): Boolean = ft.right.start <= token.start override def toString: String = s"@${token.structure}" } } case object Never extends WithPos { - override def notExpiredBy(ft: FormatToken): Boolean = true + override def notExpiredBy(ft: FT): Boolean = true } } diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/PolicySummary.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/PolicySummary.scala index 42e6ef5d65..d5e3787d60 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/PolicySummary.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/PolicySummary.scala @@ -10,7 +10,7 @@ class PolicySummary(val policies: Seq[Policy]) extends AnyVal { @inline def noDequeue = policies.exists(_.noDequeue) - def combine(split: Split, nextft: FormatToken): PolicySummary = + def combine(split: Split, nextft: FT): PolicySummary = if (nextft.right.is[T.EOF]) PolicySummary.empty else new PolicySummary( (split.policy +: policies).flatMap(_.unexpiredOpt(split, nextft)) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Router.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Router.scala index 9ed516b8e2..746a2f9064 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Router.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Router.scala @@ -52,29 +52,29 @@ class Router(formatOps: FormatOps) { import formatOps._ import tokens._ - private def getSplitsImpl(implicit ft: FormatToken): Seq[Split] = { + private def getSplitsImpl(implicit ft: FT): Seq[Split] = { implicit val style = styleMap.at(ft) val leftOwner = ft.meta.leftOwner val rightOwner = ft.meta.rightOwner val newlines = ft.newlinesBetween @inline - def noBreak(): Boolean = FormatToken.noBreak(newlines) + def noBreak(): Boolean = FT.noBreak(newlines) @inline def hasBreak(): Boolean = !noBreak() @inline - def hasBlankLine: Boolean = FormatToken.hasBlankLine(newlines) + def hasBlankLine: Boolean = FT.hasBlankLine(newlines) ft match { // between sources (EOF -> @ -> BOF) - case FormatToken(_: T.EOF, _, _) => + case FT(_: T.EOF, _, _) => Seq(Split(NoSplit.orNL(prev(ft).left.is[T.BOF]), 0)) - case FormatToken(_, _: T.BOF, _) => + case FT(_, _: T.BOF, _) => Seq(Split(NoSplit.orNL(next(ft).right.is[T.EOF]), 0)) // End files with trailing newline - case FormatToken(_, _: T.EOF, _) => Seq(Split(Newline, 0)) - case FormatToken(_: T.BOF, _, _) => Seq(Split(NoSplit, 0)) - case FormatToken(_: T.Shebang, _, _) => Seq(Split(Newline2x(ft), 0)) - case FormatToken(start: T.Interpolation.Start, _, m) => + case FT(_, _: T.EOF, _) => Seq(Split(Newline, 0)) + case FT(_: T.BOF, _, _) => Seq(Split(NoSplit, 0)) + case FT(_: T.Shebang, _, _) => Seq(Split(Newline2x(ft), 0)) + case FT(start: T.Interpolation.Start, _, m) => val end = matching(start).left val policy = { val penalty = BreakSingleLineInterpolatedString @@ -120,26 +120,25 @@ class Router(formatOps: FormatOps) { .getOrElse(Seq(Indent(style.indent.main, end, After))) Seq(split.withIndents(indents)) // Interpolation - case FormatToken( + case FT( _: T.Interpolation.Id | _: T.Interpolation.Part | _: T.Interpolation.Start | _: T.Interpolation.SpliceStart, _, _, ) => Seq(Split(NoSplit, 0)) - case FormatToken( + case FT( _, T.Interpolation.Part(_) | T.Interpolation.End() | T.Interpolation .SpliceEnd(), _, ) => Seq(Split(NoSplit, 0)) - case FormatToken(T.LeftBrace(), T.RightBrace(), _) => - Seq(Split(NoSplit, 0)) + case FT(T.LeftBrace(), T.RightBrace(), _) => Seq(Split(NoSplit, 0)) // Import - case FormatToken(_: T.Dot, _, _) + case FT(_: T.Dot, _, _) if existsParentOfType[ImportExportStat](rightOwner) => Seq(Split(NoSplit, 0)) // Import left brace - case FormatToken(open: T.LeftBrace, _, _) + case FT(open: T.LeftBrace, _, _) if existsParentOfType[ImportExportStat](leftOwner) => val closeFt = matching(open) val close = closeFt.left @@ -168,12 +167,12 @@ class Router(formatOps: FormatOps) { Split(Newline, 1, policy = newlinePolicy).notIf(newlinePolicy.isEmpty) .withIndent(style.indent.main, close, Before), ) - case FormatToken(_, _: T.RightBrace, _) + case FT(_, _: T.RightBrace, _) if existsParentOfType[ImportExportStat](rightOwner) => Seq(Split(Space(style.spaces.inImportCurlyBraces), 0)) // Interpolated string left brace - case FormatToken(open @ T.LeftBrace(), _, _) + case FT(open @ T.LeftBrace(), _, _) if prev(ft).left.is[T.Interpolation.SpliceStart] => val closeFt = matching(open) val close = closeFt.left @@ -223,12 +222,12 @@ class Router(formatOps: FormatOps) { Seq(spaceSplit.withSingleLine(slbEnd), newlineSplit(1)) } - case FormatToken(_, _: T.RightBrace, _) + case FT(_, _: T.RightBrace, _) if next(ft).right.is[T.Interpolation.SpliceEnd] => Seq(Split(Space(style.spaces.inInterpolatedStringCurlyBraces), 0)) // optional braces: block follows - case FormatToken( + case FT( _: T.Equals | _: T.Colon | _: T.KwWith | _: T.RightParen | _: T.KwReturn | _: T.ContextArrow | _: T.LeftArrow | _: T.RightArrow | _: T.KwMatch | _: T.KwThen | _: T.KwElse | @@ -238,7 +237,7 @@ class Router(formatOps: FormatOps) { OptionalBraces(splits), ) if dialect.allowSignificantIndentation => splits - case FormatToken(_: T.Equals, _, DefValAssignLeft(rhs)) => + case FT(_: T.Equals, _, DefValAssignLeft(rhs)) => maybeGetInfixSplitsBeforeLhs() { def endFt = getLast(rhs) getSplitsDefValEquals(rhs, endFt) { @@ -251,7 +250,7 @@ class Router(formatOps: FormatOps) { } // { ... } Blocks - case FormatToken(open: T.LeftBrace, right, _) => + case FT(open: T.LeftBrace, right, _) => val closeFT = matching(open) val close = closeFT.left val isSelfAnnotationNL = style.optIn.selfAnnotationNewline && @@ -270,7 +269,7 @@ class Router(formatOps: FormatOps) { ) // lambdaNLOnly: None for single line only - type LambdaInfo = (FormatToken, Int, Option[Boolean]) + type LambdaInfo = (FT, Int, Option[Boolean]) def getLambdaNone: LambdaInfo = (null, 0, None) @tailrec def getLambdaInfo(ts: List[Tree]): LambdaInfo = ts match { @@ -492,7 +491,7 @@ class Router(formatOps: FormatOps) { case Some(slbSplit) if singleLineSplit.isIgnored => val arrSplit = slbSplit.withMod(Space) slbMod -> Policy.after(lambdaExpire, s"FNARR($arrSplit)") { - case Decision(FormatToken(`lambdaExpire`, _, _), ss) => + case Decision(FT(`lambdaExpire`, _, _), ss) => var hadNoSplit = false val nlSplits = ss.flatMap { s => // penalize NL one extra, for closing brace @@ -516,8 +515,7 @@ class Router(formatOps: FormatOps) { case _ => splits } - case FormatToken(_: T.RightArrow | _: T.ContextArrow, r, _) - if (leftOwner match { + case FT(_: T.RightArrow | _: T.ContextArrow, r, _) if (leftOwner match { case t: Term.FunctionTerm => !r.is[T.Comment] && !tokens.isEmpty(t.body) && isBlockFunction(t) case _ => false @@ -547,8 +545,7 @@ class Router(formatOps: FormatOps) { ) } else Seq(spaceSplitBase) - case FormatToken(_: T.RightArrow | _: T.ContextArrow, right, _) - if (leftOwner match { + case FT(_: T.RightArrow | _: T.ContextArrow, right, _) if (leftOwner match { case _: Term.FunctionTerm | _: Term.PolyFunction => true case t: Self => t.ancestor(2).is[Term.NewAnonymous] case _ => false @@ -617,7 +614,7 @@ class Router(formatOps: FormatOps) { } // Case arrow - case FormatToken(_: T.RightArrow, rt, _) + case FT(_: T.RightArrow, rt, _) if leftOwner.is[CaseTree] && !rt.isAny[T.KwCatch, T.KwFinally] => val owner = leftOwner.asInstanceOf[CaseTree] val body = owner.body @@ -627,7 +624,7 @@ class Router(formatOps: FormatOps) { } val bodyIsEmpty = isEmptyTree(body) def baseSplit(implicit l: FileLine) = Split(Space, 0) - def nlSplit(ft: FormatToken)(cost: Int)(implicit l: FileLine) = + def nlSplit(ft: FT)(cost: Int)(implicit l: FileLine) = Split(Newline2x(ft), cost) CtrlBodySplits.checkComment(nlSplit(ft)) { nft => def withSlbSplit(implicit l: FileLine) = Seq( @@ -661,7 +658,7 @@ class Router(formatOps: FormatOps) { else getFolded(beforeMultiline eq Newlines.keep) } // New statement - case FormatToken(_: T.Semicolon, _, StartsStatementRight(stmt)) + case FT(_: T.Semicolon, _, StartsStatementRight(stmt)) if !stmt.is[Term.EndMarker] => val noSpace = !style.newlines.okSpaceForSource(newlines) || style.dialect.allowSignificantIndentation && @@ -676,15 +673,11 @@ class Router(formatOps: FormatOps) { Split(Newline2x(ft), 0), ) - case FormatToken( - _: T.RightParen, - _, - ParamClauseParentLeft(_: Defn.ExtensionGroup), - ) + case FT(_: T.RightParen, _, ParamClauseParentLeft(_: Defn.ExtensionGroup)) if !dialect.allowSignificantIndentation && !LeftParenOrBrace(nextNonComment(ft).right) => Seq(Split(Space, 0)) - case FormatToken(left, right, StartsStatementRight(_)) => + case FT(left, right, StartsStatementRight(_)) => val annoRight = right.is[T.At] val annoLeft = isSingleIdentifierAnnotation(prev(ft)) @@ -722,14 +715,13 @@ class Router(formatOps: FormatOps) { ) } - case FormatToken(_, _: T.RightBrace, _) => + case FT(_, _: T.RightBrace, _) => Seq(Split(if (ft.hasBlankLine) Newline2x else xmlSpace(rightOwner), 0)) - case FormatToken(_: T.KwPackage, _, _) if leftOwner.is[Pkg] => - Seq(Split(Space, 0)) + case FT(_: T.KwPackage, _, _) if leftOwner.is[Pkg] => Seq(Split(Space, 0)) // Opening [ with no leading space. // Opening ( with no leading space. - case FormatToken(left, open @ LeftParenOrBracket(), _) + case FT(left, open @ LeftParenOrBracket(), _) if noSpaceBeforeOpeningParen(rightOwner) && { val prevFt = prevNonComment(ft) prevFt.left match { @@ -870,7 +862,7 @@ class Router(formatOps: FormatOps) { beforeOpenParenSplits.getOrElse(Seq(baseNoSplit)) // Defn.{Object, Class, Trait, Enum} - case FormatToken( + case FT( _: T.KwObject | _: T.KwClass | _: T.KwTrait | _: T.KwEnum, _, WithTemplateOnLeft(template), @@ -879,7 +871,7 @@ class Router(formatOps: FormatOps) { (style.binPack.keepParentConstructors || template.pos.isEmpty) || { val expire = templateDerivesOrCurlyOrLastNonTrivial(template).left val forceNewlineBeforeExtends = Policy.before(expire, "NLPCTOR") { - case Decision(FormatToken(_, soft.ExtendsOrDerives(), m), s) + case Decision(FT(_, soft.ExtendsOrDerives(), m), s) if m.rightOwner eq template => s.filter(x => x.isNL && !x.isActiveFor(SplitTag.OnelineWithChain)) } @@ -888,13 +880,13 @@ class Router(formatOps: FormatOps) { Seq(Split(Space, 0).withPolicy(policy)) // DefDef - case FormatToken(_: T.KwDef, _: T.Ident, _) => Seq(Split(Space, 0)) + case FT(_: T.KwDef, _: T.Ident, _) => Seq(Split(Space, 0)) - case FormatToken(open @ LeftParenOrBracket(), _, _) + case FT(open @ LeftParenOrBracket(), _, _) if ft.meta.formatOff && leftOwner.isAny[Member.SyntaxValuesClause, Member.Tuple] => val close = matching(open).left - def splits(xft: FormatToken, policy: Policy)(implicit l: FileLine) = + def splits(xft: FT, policy: Policy)(implicit l: FileLine) = Seq(Split(Provided(xft), 0, policy = policy)) val policy = Policy.on(close, "(FMT:OFF)", rank = Int.MaxValue) { case Decision(xft, _) => splits(xft, NoPolicy) @@ -903,12 +895,12 @@ class Router(formatOps: FormatOps) { // Parameter opening for one parameter group. This format works // on the WHOLE defnSite (via policies) - case FormatToken(LeftParenOrBracket(), _, _) + case FT(LeftParenOrBracket(), _, _) if style.verticalMultiline.atDefnSite && isParamClauseSite(leftOwner) => verticalMultiline() // Term.Apply and friends - case FormatToken(lp: T.LeftParen, _, LambdaAtSingleArgCallSite(lambda)) => + case FT(lp: T.LeftParen, _, LambdaAtSingleArgCallSite(lambda)) => val closeFt = matching(lp) val close = closeFt.left val newlinePolicy = Policy ? style.danglingParentheses.callSite && @@ -923,7 +915,7 @@ class Router(formatOps: FormatOps) { def multilineSpaceSplit(implicit fileLine: FileLine): Split = { val lambdaLeft: Option[T] = matchingOpt(functionExpire(lambda)._1) match { - case Some(FormatToken(lb: T.LeftBrace, _, _)) => Some(lb) + case Some(FT(lb: T.LeftBrace, _, _)) => Some(lb) case _ => None } @@ -935,7 +927,7 @@ class Router(formatOps: FormatOps) { val spacePolicy = SingleLineBlock(lambdaToken) ==> { def before = Policy.End < close ==> Policy.on(close, "NODANGLE") { - case Decision(FormatToken(bc, `close`, _), _) => + case Decision(FT(bc, `close`, _), _) => if (bc.is[T.Comment]) if (bc.text.startsWith("//")) Nil else Seq(Split(Space, 0)) else Seq(Split(Space(style.spaces.inParentheses), 0)) @@ -965,11 +957,11 @@ class Router(formatOps: FormatOps) { ) } - case FormatToken(T.LeftParen(), T.RightParen(), _) => + case FT(T.LeftParen(), T.RightParen(), _) => val noNL = style.newlines.sourceIgnored || noBreak() Seq(Split(NoSplit.orNL(noNL), 0)) - case FormatToken(open @ LeftParenOrBracket(), right, _) if { + case FT(open @ LeftParenOrBracket(), right, _) if { if (isArgClauseSite(leftOwner)) style.binPack.callSiteFor(open) == BinPack.Site.Never else style.binPack.defnSiteFor(open) == BinPack.Site.Never && @@ -1042,8 +1034,7 @@ class Router(formatOps: FormatOps) { val optimalFtOpt = if (isBeforeOpenParen || !defnSite || isBracket) None else defnSiteLastToken(leftOwner) - val optimalFt: FormatToken = - getSlbEndOnLeft(optimalFtOpt.getOrElse(afterClose)) + val optimalFt: FT = getSlbEndOnLeft(optimalFtOpt.getOrElse(afterClose)) val optimal = optimalFt.left val wouldDangle = onlyConfigStyle || mustDangleForTrailingCommas || @@ -1232,7 +1223,7 @@ class Router(formatOps: FormatOps) { splitsNoNL ++ splitsNL ++ splitsForAssign.getOrElse(Seq.empty) - case FormatToken(open @ LeftParenOrBracket(), right, _) + case FT(open @ LeftParenOrBracket(), right, _) if style.binPack.defnSiteFor(open) != BinPack.Site.Never && isParamClauseSite(leftOwner) => val closeFt = matching(open) @@ -1276,7 +1267,7 @@ class Router(formatOps: FormatOps) { else { val opensPolicy = bracketPenalty.map { p => Policy.before(close, "PENBP[") { - case Decision(ftd @ FormatToken(o: T.LeftBracket, _, m), s) + case Decision(ftd @ FT(o: T.LeftBracket, _, m), s) if isParamClauseSite(m.leftOwner) && styleMap.at(o).binPack.bracketDefnSite .exists(_ != BinPack.Site.Never) => @@ -1318,7 +1309,7 @@ class Router(formatOps: FormatOps) { ) } - case FormatToken(open @ LeftParenOrBracket(), right, _) + case FT(open @ LeftParenOrBracket(), right, _) if style.binPack.callSiteFor(open) != BinPack.Site.Never && isArgClauseSite(leftOwner) => val closeFt = matching(open) @@ -1425,7 +1416,7 @@ class Router(formatOps: FormatOps) { Policy ? style.binPack.indentCallSiteOnce && { val trigger = getIndentTrigger(leftOwner) Policy.on(close, prefix = "IND1") { - case Decision(FormatToken(LeftParenOrBracket(), _, m), s) + case Decision(FT(LeftParenOrBracket(), _, m), s) if isArgClauseSite(m.leftOwner) => s.map(x => if (x.isNL) x else x.switch(trigger, false)) } @@ -1482,7 +1473,7 @@ class Router(formatOps: FormatOps) { Seq(noSplit, nlSplit) // Closing def site ): ReturnType - case FormatToken(left, _: T.Colon, ColonDeclTpeRight(returnType)) + case FT(left, _: T.Colon, ColonDeclTpeRight(returnType)) if style.newlines.sometimesBeforeColonInMethodReturnType || left.is[T.Comment] && hasBreak() => val expireFt = getLastNonTrivial(returnType) @@ -1521,7 +1512,7 @@ class Router(formatOps: FormatOps) { ) } } - case FormatToken(_: T.Colon, _, ColonDeclTpeLeft(returnType)) + case FT(_: T.Colon, _, ColonDeclTpeLeft(returnType)) if style.newlines.avoidInResultType => val expire = getLastNonTrivialToken(returnType) val policy = PenalizeAllNewlines(expire, Constants.ShouldBeNewline) @@ -1530,15 +1521,15 @@ class Router(formatOps: FormatOps) { .withOptimalToken(expire, killOnFail = false), ) - case FormatToken(T.LeftParen(), T.LeftBrace(), _) => Seq(Split(NoSplit, 0)) + case FT(T.LeftParen(), T.LeftBrace(), _) => Seq(Split(NoSplit, 0)) - case FormatToken(_, T.LeftBrace(), _) if isXmlBrace(rightOwner) => + case FT(_, T.LeftBrace(), _) if isXmlBrace(rightOwner) => withIndentOnXmlSpliceStart(ft, Seq(Split(NoSplit, 0))) - case FormatToken(T.RightBrace(), _, _) if isXmlBrace(leftOwner) => + case FT(T.RightBrace(), _, _) if isXmlBrace(leftOwner) => Seq(Split(NoSplit, 0)) // non-statement starting curly brace - case FormatToken(_: T.Comma, open: T.LeftBrace, _) + case FT(_: T.Comma, open: T.LeftBrace, _) if !style.poorMansTrailingCommasInConfigStyle && isArgClauseSite(leftOwner) => val close = matching(open).left @@ -1568,16 +1559,16 @@ class Router(formatOps: FormatOps) { else otherSplits.map(_.onlyFor(SplitTag.OneArgPerLine)) singleSplit +: oneArgPerLineSplits - case FormatToken( + case FT( _: T.MacroSplice | _: T.MacroQuote, _: T.LeftBrace | _: T.LeftBracket, _, ) => Seq(Split(NoSplit, 0)) - case FormatToken(_: T.KwMatch, _, _) if !leftOwner.is[Term.Name] => // exclude end marker + case FT(_: T.KwMatch, _, _) if !leftOwner.is[Term.Name] => // exclude end marker val indentLen = style.indent.matchSite.fold(0)(_ - style.indent.main) def expire = getLastNonTrivialToken(leftOwner) // should rbrace Seq(Split(Space, 0).withIndent(indentLen, expire, ExpiresOn.Before)) - case FormatToken(_, lb: T.LeftBrace, _) if ! { // partial initial expr + case FT(_, lb: T.LeftBrace, _) if ! { // partial initial expr @tailrec def startsInfix(ai: Term.ApplyInfix): Boolean = ai.parent match { case Some(_: Term.ArgClause) => false @@ -1598,10 +1589,10 @@ class Router(formatOps: FormatOps) { Seq(Split(mod, 0)) // Delim - case FormatToken(left, _: T.Comma, _) - if !left.is[T.Comment] || noBreak() => Seq(Split(NoSplit, 0)) + case FT(left, _: T.Comma, _) if !left.is[T.Comment] || noBreak() => + Seq(Split(NoSplit, 0)) // These are mostly filtered out/modified by policies. - case FormatToken(lc: T.Comma, _: T.Comment, m) => + case FT(lc: T.Comma, _: T.Comment, m) => val nextFt = next(ft) if (hasBlankLine) Seq(Split(Newline2x, 0)) else if (nextFt.hasBreak || m.right.hasNL) @@ -1616,7 +1607,7 @@ class Router(formatOps: FormatOps) { rightIsCloseDelimToAddTrailingComma(lc, nextNonComment(nextFt)) ) Seq(Split(Space, 0), Split(Newline, 1)) else Seq(Split(Newline, 0)) - case FormatToken(_: T.Comma, right, _) if !leftOwner.is[Template] => + case FT(_: T.Comma, right, _) if !leftOwner.is[Template] => def forBinPack(binPack: BinPack.Site, callSite: Boolean) = if (binPack eq BinPack.Site.Never) None else optimizationEntities.argument.map { nextArg => @@ -1629,7 +1620,7 @@ class Router(formatOps: FormatOps) { Some(afterNextArg) case _ => None } - def getEndOfResultType(cp: FormatToken) = + def getEndOfResultType(cp: FT) = if ( cp.right.is[T.Comma] || !style.newlines.avoidInResultType || style.newlines.sometimesBeforeColonInMethodReturnType @@ -1658,7 +1649,7 @@ class Router(formatOps: FormatOps) { (callSite && style.binPack.indentCallSiteOnce) && { val trigger = getIndentTrigger(leftOwner) Policy.on(lastTok, prefix = "IND1") { - case Decision(FormatToken(LeftParenOrBracket(), _, m), s) + case Decision(FT(LeftParenOrBracket(), _, m), s) if isArgClauseSite(m.leftOwner) => s.map(x => if (x.isNL) x else x.switch(trigger, true)) } @@ -1705,7 +1696,7 @@ class Router(formatOps: FormatOps) { .getOrElse(defaultSplits) } - case FormatToken(_, sc: T.Semicolon, _) => + case FT(_, sc: T.Semicolon, _) => val forceBreak = hasBreak() && { val ltoks = leftOwner.tokens val maxTokens = topSourceTree.tokens.length @@ -1717,7 +1708,7 @@ class Router(formatOps: FormatOps) { decideNewlinesOnlyAfterToken(nextNonCommentSameLineAfter(ft).left) Seq(Split(NoSplit, 0, policy = policy)) - case FormatToken(_: T.KwReturn, r, _) => + case FT(_: T.KwReturn, r, _) => val mod = if (hasBlankLine) Newline2x else leftOwner match { @@ -1732,7 +1723,7 @@ class Router(formatOps: FormatOps) { * Type Bounds */ - case FormatToken(_, _: T.Colon, _) if rightOwner.is[Type.Param] => + case FT(_, _: T.Colon, _) if rightOwner.is[Type.Param] => val tp = rightOwner.asInstanceOf[Type.Param] def noNLMod = Space(style.spaces.beforeContextBoundColon match { case Spaces.BeforeContextBound.Always => true @@ -1742,13 +1733,13 @@ class Router(formatOps: FormatOps) { case _ => false }) getSplitsForTypeBounds(noNLMod, tp, _.cbounds) - case FormatToken(_, _: T.Viewbound, _) if rightOwner.is[Type.Param] => + case FT(_, _: T.Viewbound, _) if rightOwner.is[Type.Param] => val tp = rightOwner.asInstanceOf[Type.Param] getSplitsForTypeBounds(Space, tp, _.vbounds) /* Type bounds in type definitions and declarations such as: * type `Tuple <: Alpha & Beta = Another` or `Tuple <: Alpha & Beta` */ - case FormatToken(_, bound @ (_: T.Subtype | _: T.Supertype), _) + case FT(_, bound @ (_: T.Subtype | _: T.Supertype), _) if rightOwner.is[Type.Bounds] && rightOwner.parent.isDefined => val tbounds = rightOwner.asInstanceOf[Type.Bounds] val boundOpt = bound match { @@ -1760,14 +1751,14 @@ class Router(formatOps: FormatOps) { val typeOwner = rightOwner.parent.get getSplitsForTypeBounds(Space, typeOwner, boundEnd) - case FormatToken(left, _: T.Colon, _) => + case FT(left, _: T.Colon, _) => val mod = left match { case ident: T.Ident => identModification(ident) case _ => NoSplit } Seq(Split(mod, 0)) - case FormatToken(_, _: T.Dot, _) + case FT(_, _: T.Dot, _) if !style.newlines.keep && rightOwner.is[Term.Select] && findTreeWithParent(rightOwner) { case _: Term.ArgClause => None @@ -1776,7 +1767,7 @@ class Router(formatOps: FormatOps) { case _ => Some(false) }.isDefined => Seq(Split(NoSplit, 0)) - case FormatToken(left, r: T.Dot, GetSelectLike.OnRight(thisSelect)) => + case FT(left, r: T.Dot, GetSelectLike.OnRight(thisSelect)) => val enclosed = style.encloseSelectChains val (expireTree, nextSelect) = findLastApplyAndNextSelect(rightOwner, enclosed) @@ -1804,16 +1795,15 @@ class Router(formatOps: FormatOps) { def forcedBreakOnNextDotPolicy = nextSelect.map { selectLike => val tree = selectLike.tree Policy.before(selectLike.nameToken, "NEXTSELFNL") { - case d @ Decision(FormatToken(_, _: T.Dot, m), _) - if m.rightOwner eq tree => d.onlyNewlinesWithoutFallback + case d @ Decision(FT(_, _: T.Dot, m), _) if m.rightOwner eq tree => + d.onlyNewlinesWithoutFallback } } def breakOnNextDot: Policy = nextSelect.map { selectLike => val tree = selectLike.tree Policy.before(selectLike.nameToken, "NEXTSEL2NL") { - case Decision(FormatToken(_, _: T.Dot, m), s) - if m.rightOwner eq tree => + case Decision(FT(_, _: T.Dot, m), s) if m.rightOwner eq tree => val filtered = s.flatMap { x => val y = x.activateFor(SplitTag.SelectChainSecondNL) if (y.isActive) Some(y) else None @@ -1966,7 +1956,7 @@ class Router(formatOps: FormatOps) { case t: Term.Block => t.parent.is[Member.ArgClause] case _ => false }) && { - implicit val ft: FormatToken = next(ftAfterRight) + implicit val ft: FT = next(ftAfterRight) val rb = matching(ftAfterRight.right) getBracesToParensMod(rb, Space, isWithinBraces = true)._1 ne Space @@ -1988,10 +1978,9 @@ class Router(formatOps: FormatOps) { val delayedBreakPolicyOpt = nextSelect.map { selectLike => val tree = selectLike.tree Policy.before(selectLike.nameToken, "NEXTSEL1NL") { - case Decision(FormatToken(_, _: T.Dot, m), s) - if m.rightOwner eq tree => + case Decision(FT(_, _: T.Dot, m), s) if m.rightOwner eq tree => SplitTag.SelectChainFirstNL.activateOnly(s) - case Decision(FormatToken(l, _: T.Comment, m), s) + case Decision(FT(l, _: T.Comment, m), s) if m.rightOwner.eq(tree) && !l.is[T.Comment] => SplitTag.SelectChainFirstNL.activateOnly(s) } @@ -2026,25 +2015,22 @@ class Router(formatOps: FormatOps) { else baseSplits ++ splits.map(_.onlyFor(SplitTag.SelectChainFirstNL)) // ApplyUnary - case FormatToken(T.Ident(_), T.Literal(), _) if leftOwner == rightOwner => + case FT(T.Ident(_), T.Literal(), _) if leftOwner == rightOwner => Seq(Split(NoSplit, 0)) - case FormatToken(op: T.Ident, right, _) if leftOwner.parent.exists { + case FT(op: T.Ident, right, _) if leftOwner.parent.exists { case unary: Term.ApplyUnary => unary.op.tokens.head == op case _ => false } => Seq(Split(Space(isSymbolicIdent(right)), 0)) // Annotations, see #183 for discussion on this. - case FormatToken(_, _: T.At, _) if rightOwner.is[Pat.Bind] => - Seq(Split(Space, 0)) - case FormatToken(_: T.At, _, _) if leftOwner.is[Pat.Bind] => - Seq(Split(Space, 0)) - case FormatToken(T.At(), _: T.Symbolic, _) => Seq(Split(NoSplit, 0)) - case FormatToken(T.At(), right @ T.Ident(_), _) => + case FT(_, _: T.At, _) if rightOwner.is[Pat.Bind] => Seq(Split(Space, 0)) + case FT(_: T.At, _, _) if leftOwner.is[Pat.Bind] => Seq(Split(Space, 0)) + case FT(T.At(), _: T.Symbolic, _) => Seq(Split(NoSplit, 0)) + case FT(T.At(), right @ T.Ident(_), _) => // Add space if right starts with a symbol Seq(Split(identModification(right), 0)) // Enum Case - case FormatToken(_, T.KwExtends(), _) - if rightOwner.isInstanceOf[Defn.EnumCase] => + case FT(_, T.KwExtends(), _) if rightOwner.isInstanceOf[Defn.EnumCase] => val enumCase = rightOwner.asInstanceOf[Defn.EnumCase] binPackParentConstructorSplits( true, @@ -2056,7 +2042,7 @@ class Router(formatOps: FormatOps) { ) // Template - case FormatToken(_, soft.ExtendsOrDerives(), TemplateOnRight(template)) => + case FT(_, soft.ExtendsOrDerives(), TemplateOnRight(template)) => def lastToken = templateDerivesOrCurlyOrLastNonTrivial(template) binPackParentConstructorSplits( @@ -2070,11 +2056,11 @@ class Router(formatOps: FormatOps) { ) // trait A extends B, C, D, E - case FormatToken(_: T.Comma, _, _) if leftOwner.is[Template] => + case FT(_: T.Comma, _, _) if leftOwner.is[Template] => val template = leftOwner.asInstanceOf[Template] typeTemplateSplits(template, style.indent.commaSiteRelativeToExtends) - case FormatToken(_, _: T.KwWith, _) => rightOwner match { + case FT(_, _: T.KwWith, _) => rightOwner match { // something like new A with B with C case template: Template if template.parent @@ -2111,7 +2097,7 @@ class Router(formatOps: FormatOps) { case _ => Seq(Split(Space, 0)) } // If/For/While/For with ( - case FormatToken(open: T.LeftParen, _, _) if (leftOwner match { + case FT(open: T.LeftParen, _, _) if (leftOwner match { case t: Term.EnumeratorsBlock => getHeadOpt(t).contains(ft) case _: Term.If | _: Term.While => !isTokenHeadOrBefore(open, leftOwner) @@ -2143,7 +2129,7 @@ class Router(formatOps: FormatOps) { baseNoSplit(Newline).withIndents(indents).withPolicy(penalizeNewlines), ) - case FormatToken(_: T.KwIf, right, _) if leftOwner.is[Term.If] => + case FT(_: T.KwIf, right, _) if leftOwner.is[Term.If] => val owner = leftOwner.asInstanceOf[Term.If] val expire = getLastToken(owner) val isKeep = style.newlines.keep @@ -2158,7 +2144,7 @@ class Router(formatOps: FormatOps) { val mlSplitOpt = OptionalBraces .indentAndBreakBeforeCtrl[T.KwThen](owner.cond, mlSplitBase) Seq(slb, mlSplitOpt.getOrElse(mlSplitBase)) - case FormatToken(_: T.KwWhile | _: T.KwFor, right, _) + case FT(_: T.KwWhile | _: T.KwFor, right, _) if leftOwner.isAny[Term.While, Term.ForClause] => // exclude end marker def spaceMod = Space(style.spaces.isSpaceAfterKeyword(right)) def splitBase(implicit fileLine: FileLine) = { @@ -2179,7 +2165,7 @@ class Router(formatOps: FormatOps) { case _ => None }).getOrElse(Split(spaceMod, 0)) Seq(split) - case FormatToken(close: T.RightParen, right, _) if (leftOwner match { + case FT(close: T.RightParen, right, _) if (leftOwner match { case t: Term.If => !nextNonComment(ft).right.is[T.KwThen] && !isTokenLastOrAfter(close, t) case t: Term.While => !nextNonComment(ft).right.is[T.KwDo] && @@ -2218,7 +2204,7 @@ class Router(formatOps: FormatOps) { ) }(nlSplitFunc) - case FormatToken(left, kw @ (_: T.KwElse | _: T.KwYield), _) => + case FT(left, kw @ (_: T.KwElse | _: T.KwYield), _) => if (left.is[T.RightBrace]) Seq(Split(Space, 0)) else Seq( if (style.newlines.okSpaceForSource(newlines)) { @@ -2231,7 +2217,7 @@ class Router(formatOps: FormatOps) { } else Split.ignored, Split(Newline, 1), ) - case FormatToken(_, _: T.KwThen | _: T.KwDo, _) => + case FT(_, _: T.KwThen | _: T.KwDo, _) => val okSpace = style.newlines.sourceIgnored || noBreak() Seq( Split(!okSpace, 0)(Space).withOptimalToken( @@ -2241,7 +2227,7 @@ class Router(formatOps: FormatOps) { Split(Newline, 1), ) // Last else branch - case FormatToken(_: T.KwElse, _, _) if (leftOwner match { + case FT(_: T.KwElse, _, _) if (leftOwner match { case t: Term.If => t.elsep match { case _: Term.If => false case b @ Term.Block((_: Term.If) :: Nil) => @@ -2262,19 +2248,19 @@ class Router(formatOps: FormatOps) { }(nlSplitFunc) // Type variance - case FormatToken(_: T.Ident, right @ (_: T.Ident | _: T.Underscore), _) + case FT(_: T.Ident, right @ (_: T.Ident | _: T.Underscore), _) if leftOwner.is[Mod.Variant] => Seq(Split(Space(isSymbolicIdent(right)), 0)) // Kind projector type lambda - case FormatToken(T.Ident("+" | "-"), T.Underscore(), _) - if rightOwner.is[Type] => Seq(Split(NoSplit, 0)) + case FT(T.Ident("+" | "-"), T.Underscore(), _) if rightOwner.is[Type] => + Seq(Split(NoSplit, 0)) // Var args - case FormatToken(_, T.Ident("*"), _) if rightOwner.is[Type.Repeated] => + case FT(_, T.Ident("*"), _) if rightOwner.is[Type.Repeated] => Seq(Split(NoSplit, 0)) - case FormatToken(open: T.LeftParen, right, _) => + case FT(open: T.LeftParen, right, _) => val closeFt = matching(open) val close = closeFt.left val beforeClose = prev(closeFt) @@ -2335,19 +2321,18 @@ class Router(formatOps: FormatOps) { } // Infix operator. - case FormatToken(_: T.Ident, _, FormatToken.LeftOwner(AsInfixOp(app))) => + case FT(_: T.Ident, _, FT.LeftOwner(AsInfixOp(app))) => insideInfixSplit(app) - case FormatToken(_, _: T.Ident, FormatToken.RightOwner(AsInfixOp(app))) => + case FT(_, _: T.Ident, FT.RightOwner(AsInfixOp(app))) => insideInfixSplit(app) // Case - case FormatToken(_: T.KwCase, _, _) - if leftOwner.is[Defn.RepeatedEnumCase] => + case FT(_: T.KwCase, _, _) if leftOwner.is[Defn.RepeatedEnumCase] => val indent = Indent(style.indent.main, leftOwner.tokens.last, ExpiresOn.After) Seq(Split(Space, 0).withIndent(indent)) - case FormatToken(_: T.KwCase, _, _) if leftOwner.is[CaseTree] => + case FT(_: T.KwCase, _, _) if leftOwner.is[CaseTree] => val owner = leftOwner.asInstanceOf[CaseTree] val arrowFt = leftOwner match { case c: Case => getCaseArrow(c) @@ -2416,7 +2401,7 @@ class Router(formatOps: FormatOps) { } Seq(Split(mod, 0, policy = policy)) - case FormatToken(_, cond: T.KwIf, _) if rightOwner.is[Case] => + case FT(_, cond: T.KwIf, _) if rightOwner.is[Case] => val arrow = getCaseArrow(rightOwner.asInstanceOf[Case]).left val noSplit = if (style.newlines.keepBreak(newlines)) Split.ignored @@ -2439,18 +2424,18 @@ class Router(formatOps: FormatOps) { Split(Newline, 1).withPolicy(penalizeNewlineByNesting(cond, arrow)), ) - case FormatToken(_: T.KwIf, _, _) if leftOwner.is[Case] => + case FT(_: T.KwIf, _, _) if leftOwner.is[Case] => val useNL = style.newlines.keepBreak(nextNonCommentSameLine(ft)) Seq(Split(Space.orNL(!useNL), 0)) // ForYield - case FormatToken( + case FT( _: T.LeftArrow | _: T.Equals, _, EnumeratorAssignRhsOnLeft(rhs), ) => getSplitsEnumerator(rhs) - case FormatToken(kw @ (_: T.KwTry | _: T.KwCatch | _: T.KwFinally), _, _) + case FT(kw @ (_: T.KwTry | _: T.KwCatch | _: T.KwFinally), _, _) if !leftOwner.is[Term.Name] => // exclude end marker val body = leftOwner match { case t: Term.TryClause => kw match { @@ -2468,7 +2453,7 @@ class Router(formatOps: FormatOps) { }(Split(Newline2x(ft), _).withIndent(indent)) // Term.ForYield - case FormatToken(T.KwYield(), _, _) if leftOwner.is[Term.ForYield] => + case FT(T.KwYield(), _, _) if leftOwner.is[Term.ForYield] => val lastToken = getLastToken(leftOwner.asInstanceOf[Term.ForYield].body) val indent = Indent(style.indent.main, lastToken, ExpiresOn.After) if (style.newlines.avoidAfterYield && !rightOwner.is[Term.If]) { @@ -2481,7 +2466,7 @@ class Router(formatOps: FormatOps) { ) // Term.For - case FormatToken(_: T.RightBrace, _, _) + case FT(_: T.RightBrace, _, _) if leftOwner.is[Term.EnumeratorsBlock] && leftOwner.parent.is[Term.For] && !nextNonComment(ft).right.is[T.KwDo] => @@ -2491,9 +2476,9 @@ class Router(formatOps: FormatOps) { CtrlBodySplits.get(body)(null)(nlSplit) // After comment - case FormatToken(_: T.Comment, _, _) => Seq(Split(getMod(ft), 0)) + case FT(_: T.Comment, _, _) => Seq(Split(getMod(ft), 0)) // Inline comment - case FormatToken(_, _: T.Comment, _) => + case FT(_, _: T.Comment, _) => val forceBlankLine = hasBreak() && blankLineBeforeDocstring(ft) val mod = if (forceBlankLine) Newline2x else getMod(ft) val nft = nextNonCommentAfter(ft) @@ -2502,11 +2487,11 @@ class Router(formatOps: FormatOps) { .withIndent(style.indent.main, nft.left, ExpiresOn.After) nft match { - case FormatToken(_, _: T.Dot, GetSelectLike.OnRight(t)) => + case FT(_, _: T.Dot, GetSelectLike.OnRight(t)) => if (findPrevSelect(t, style.encloseSelectChains).isEmpty) Seq(split) else Seq(baseSplit, split.onlyFor(SplitTag.SelectChainFirstNL)) case _ => prevBeforeNonComment(ft) match { - case FormatToken(_, _: T.Dot, GetSelectLike.OnRight(t)) => + case FT(_, _: T.Dot, GetSelectLike.OnRight(t)) => if (findPrevSelect(t, style.encloseSelectChains).isEmpty) Seq(split) else Seq(baseSplit, split.onlyFor(SplitTag.SelectChainFirstNL)) @@ -2514,7 +2499,7 @@ class Router(formatOps: FormatOps) { } } - case FormatToken(soft.ImplicitOrUsing(), _, ImplicitUsingOnLeft(params)) + case FT(soft.ImplicitOrUsing(), _, ImplicitUsingOnLeft(params)) if style.binPack.defnSite == BinPack.Site.Never && !style.verticalMultiline.atDefnSite => val spaceSplit = Split(Space, 0) @@ -2524,7 +2509,7 @@ class Router(formatOps: FormatOps) { ) Seq(spaceSplit, Split(Newline, if (spaceSplit.isActive) 1 else 0)) - case FormatToken(_, r, _) if optimizationEntities.optionalNL => + case FT(_, r, _) if optimizationEntities.optionalNL => @tailrec def noAnnoLeftFor(tree: Tree): Boolean = tree.parent match { case Some(_: Mod.Annot) => false @@ -2551,7 +2536,7 @@ class Router(formatOps: FormatOps) { } // Pattern alternatives - case FormatToken(T.Ident("|"), _, _) if leftOwner.is[Pat.Alternative] => + case FT(T.Ident("|"), _, _) if leftOwner.is[Pat.Alternative] => if (style.newlines.keep) Seq(Split(Space.orNL(noBreak()), 0)) else { val end = getLast(leftOwner.asInstanceOf[Pat.Alternative].rhs match { @@ -2567,32 +2552,32 @@ class Router(formatOps: FormatOps) { Split(Newline, 1), ) } - case FormatToken(_, T.Ident("|"), _) if rightOwner.is[Pat.Alternative] => + case FT(_, T.Ident("|"), _) if rightOwner.is[Pat.Alternative] => val noNL = !style.newlines.keepBreak(newlines) Seq(Split(Space.orNL(noNL), 0)) - case FormatToken(_, T.Ident("*"), _) + case FT(_, T.Ident("*"), _) if rightOwner.is[Pat.SeqWildcard] || rightOwner.is[Term.Repeated] || rightOwner.is[Pat.Repeated] => Seq(Split(NoSplit, 0)) - case FormatToken( + case FT( T.Ident(_) | T.Literal() | T.Interpolation.End() | T.Xml.End(), T.Ident(_) | T.Literal() | T.Xml.Start(), _, ) => Seq(Split(Space, 0)) // Case - case FormatToken(left, _: T.KwMatch, _) => + case FT(left, _: T.KwMatch, _) => // do not split `.match` val noSplit = left.is[T.Dot] && dialect.allowMatchAsOperator Seq(Split(Space(!noSplit), 0)) // Protected [] - case FormatToken(_, T.LeftBracket(), _) - if isModPrivateProtected(leftOwner) => Seq(Split(NoSplit, 0)) - case FormatToken(T.LeftBracket(), _, _) - if isModPrivateProtected(leftOwner) => Seq(Split(NoSplit, 0)) + case FT(_, T.LeftBracket(), _) if isModPrivateProtected(leftOwner) => + Seq(Split(NoSplit, 0)) + case FT(T.LeftBracket(), _, _) if isModPrivateProtected(leftOwner) => + Seq(Split(NoSplit, 0)) // Term.ForYield - case FormatToken(_, _: T.KwIf, _) if rightOwner.is[Enumerator.Guard] => + case FT(_, _: T.KwIf, _) if rightOwner.is[Enumerator.Guard] => /* this covers the first guard only; second and later consecutive guards * are considered to start a new statement and are handled early, in the * "if startsStatement" matches */ @@ -2608,47 +2593,47 @@ class Router(formatOps: FormatOps) { case _ => Seq(Split(Space, 0).onlyIf(noBreak()), Split(Newline, 1)) } // Interpolation - case FormatToken(_, _: T.Interpolation.Id, _) => Seq(Split(Space, 0)) + case FT(_, _: T.Interpolation.Id, _) => Seq(Split(Space, 0)) // Throw exception - case FormatToken(T.KwThrow(), _, _) => Seq(Split(Space, 0)) + case FT(T.KwThrow(), _, _) => Seq(Split(Space, 0)) // Singleton types - case FormatToken(_, T.KwType(), _) if rightOwner.is[Type.Singleton] => + case FT(_, T.KwType(), _) if rightOwner.is[Type.Singleton] => Seq(Split(NoSplit, 0)) // seq to var args foo(seq:_*) - case FormatToken(T.Colon(), T.Underscore(), _) + case FT(T.Colon(), T.Underscore(), _) if next(ft).meta.right.text == "*" => Seq(Split(Space, 0)) - case FormatToken(T.Underscore(), T.Ident("*"), _) - if prev(ft).left.is[T.Colon] => Seq(Split(NoSplit, 0)) + case FT(T.Underscore(), T.Ident("*"), _) if prev(ft).left.is[T.Colon] => + Seq(Split(NoSplit, 0)) // Xml - case FormatToken(_, _: T.Xml.Start, _) => Seq(Split(Space, 0)) - case FormatToken(open: T.Xml.Start, _, _) => + case FT(_, _: T.Xml.Start, _) => Seq(Split(Space, 0)) + case FT(open: T.Xml.Start, _, _) => val splits = Seq(Split(NoSplit, 0)) if (prev(ft).left.is[T.LeftBrace]) splits else withIndentOnXmlStart(open, splits) - case FormatToken(_: T.Xml.SpliceStart, _, _) + case FT(_: T.Xml.SpliceStart, _, _) if style.xmlLiterals.assumeFormatted => withIndentOnXmlSpliceStart(ft, Seq(Split(NoSplit, 0))) - case FormatToken(T.Xml.Part(_), _, _) => Seq(Split(NoSplit, 0)) - case FormatToken(_, T.Xml.Part(_), _) => Seq(Split(NoSplit, 0)) + case FT(T.Xml.Part(_), _, _) => Seq(Split(NoSplit, 0)) + case FT(_, T.Xml.Part(_), _) => Seq(Split(NoSplit, 0)) // Fallback - case FormatToken(_, T.Dot(), _) => Seq(Split(NoSplit, 0)) - case FormatToken(left, T.Hash(), _) => + case FT(_, T.Dot(), _) => Seq(Split(NoSplit, 0)) + case FT(left, T.Hash(), _) => Seq(Split(Space(endsWithSymbolIdent(left)), 0)) - case FormatToken(T.Hash(), ident: T.Ident, _) => + case FT(T.Hash(), ident: T.Ident, _) => Seq(Split(Space(isSymbolicIdent(ident)), 0)) - case FormatToken(T.Dot(), T.Ident(_) | T.KwThis() | T.KwSuper(), _) => + case FT(T.Dot(), T.Ident(_) | T.KwThis() | T.KwSuper(), _) => Seq(Split(NoSplit, 0)) - case FormatToken(_, T.RightBracket(), _) => Seq(Split(NoSplit, 0)) - case FormatToken(_, _: T.RightParen, _) => + case FT(_, T.RightBracket(), _) => Seq(Split(NoSplit, 0)) + case FT(_, _: T.RightParen, _) => val ok = !style.newlines.keepBreak(newlines) || style.binPack.siteFor(rightOwner) .fold(!rightOwner.is[Pat.Alternative])(_._1 eq BinPack.Site.Never) Seq(Split(if (ok) getNoSplitBeforeClosing(ft, Newline) else Newline, 0)) - case FormatToken(_: T.KwDo, _, _) if leftOwner.is[Term.Do] => + case FT(_: T.KwDo, _, _) if leftOwner.is[Term.Do] => val owner = leftOwner.asInstanceOf[Term.Do] val eft = getLast(owner.body) val end = eft.left @@ -2667,7 +2652,7 @@ class Router(formatOps: FormatOps) { .withIndents(indent) Seq(noSplit, nlSplit) - case FormatToken(left, _: T.KwWhile, _) if rightOwner.is[Term.Do] => + case FT(left, _: T.KwWhile, _) if rightOwner.is[Term.Do] => if (hasBlankLine) Seq(Split(Newline2x, 0)) else { val nlOnly = left.is[T.RightBrace] && @@ -2679,38 +2664,38 @@ class Router(formatOps: FormatOps) { Seq(noSplit, nlSplit) } - case FormatToken(left, _: T.KwCatch | _: T.KwFinally, _) + case FT(left, _: T.KwCatch | _: T.KwFinally, _) if style.newlines.alwaysBeforeElseAfterCurlyIf || !left.is[T.RightBrace] || leftOwner.ne(rightOwner) && !leftOwner.parent.contains(rightOwner) => Seq(Split(Newline2x(hasBlankLine), 0)) - case FormatToken(_, Reserved(), _) => Seq(Split(Space, 0)) - case FormatToken(Reserved(), _, _) => Seq(Split(Space, 0)) + case FT(_, Reserved(), _) => Seq(Split(Space, 0)) + case FT(Reserved(), _, _) => Seq(Split(Space, 0)) - case FormatToken(T.LeftBracket(), _, _) => Seq(Split(NoSplit, 0)) - case FormatToken(_, _: T.Symbolic, _) => Seq(Split(Space, 0)) - case FormatToken(T.Underscore(), T.Ident("*"), _) => Seq(Split(NoSplit, 0)) - case FormatToken(T.RightArrow(), _, _) if leftOwner.is[Type.ByName] => + case FT(T.LeftBracket(), _, _) => Seq(Split(NoSplit, 0)) + case FT(_, _: T.Symbolic, _) => Seq(Split(Space, 0)) + case FT(T.Underscore(), T.Ident("*"), _) => Seq(Split(NoSplit, 0)) + case FT(T.RightArrow(), _, _) if leftOwner.is[Type.ByName] => val mod = Space(style.spaces.inByNameTypes) Seq(Split(mod, 0)) - case FormatToken(_: T.Colon, _, _) - if style.spaces.notAfterColon(leftOwner) => Seq(Split(NoSplit, 0)) - case FormatToken(_: T.Symbolic, _, _) => Seq(Split(Space, 0)) + case FT(_: T.Colon, _, _) if style.spaces.notAfterColon(leftOwner) => + Seq(Split(NoSplit, 0)) + case FT(_: T.Symbolic, _, _) => Seq(Split(Space, 0)) case tok => logger.debug(s"MISSING CASE: $tok") Seq() // No solution available, partially format tree. } } - /** Assigns possible splits to a FormatToken. + /** Assigns possible splits to a FT. * - * The FormatToken can be considered as a node in a graph and the splits as - * edges. Given a format token (a node in the graph), Route determines which - * edges lead out from the format token. + * The FT can be considered as a node in a graph and the splits as edges. + * Given a format token (a node in the graph), Route determines which edges + * lead out from the format token. */ - def getSplits(ft: FormatToken): Seq[Split] = { + def getSplits(ft: FT): Seq[Split] = { val splits = getSplitsImpl(ft).filter(!_.isIgnored) require( splits.nonEmpty, @@ -2725,17 +2710,16 @@ class Router(formatOps: FormatOps) { if (filtered.nonEmpty) filtered else splits.map(_.withMod(Newline)) } ft match { - case FormatToken(_: T.BOF, _, _) => splits - case FormatToken(_, _: T.Comment, _) if rhsIsCommentedOutIfComment(ft) => + case FT(_: T.BOF, _, _) => splits + case FT(_, _: T.Comment, _) if rhsIsCommentedOutIfComment(ft) => splitsAsNewlines(splits.map(_.withNoIndent)) - case FormatToken(_: T.Comment, _, _) => + case FT(_: T.Comment, _, _) => if (ft.noBreak) splits else splitsAsNewlines(splits) - case FormatToken(_, _: T.Comment, _) - if hasBreakAfterRightBeforeNonComment(ft) => + case FT(_, _: T.Comment, _) if hasBreakAfterRightBeforeNonComment(ft) => if (ft.noBreak) splits.map(_.withMod(Space)) else splitsAsNewlines(splits) case ft if ft.meta.formatOff && ft.hasBreak => splitsAsNewlines(splits) - case FormatToken(_: T.Equals, r: T.KwMacro, _) + case FT(_: T.Equals, r: T.KwMacro, _) if dialect.allowSignificantIndentation => // scala3 compiler doesn't allow newline before `macro` splits.map { s => @@ -2750,11 +2734,9 @@ class Router(formatOps: FormatOps) { private def getSplitsDefValEquals( body: Tree, - endFt: => FormatToken, + endFt: => FT, spaceIndents: Seq[Indent] = Seq.empty, - )( - splits: => Seq[Split], - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = + )(splits: => Seq[Split])(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = if (ft.right.is[T.LeftBrace]) // The block will take care of indenting by 2 Seq(Split(Space, 0).withIndents(spaceIndents)) else if (isRightCommentWithBreak(ft)) @@ -2779,9 +2761,9 @@ class Router(formatOps: FormatOps) { } else splits - private def getSplitsDefEquals(body: Tree, endFt: FormatToken)(implicit + private def getSplitsDefEquals(body: Tree, endFt: FT)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = { val expire = endFt.left def baseSplit = Split(Space, 0) @@ -2805,16 +2787,16 @@ class Router(formatOps: FormatOps) { } } - private def getSplitsValEquals(body: Tree, endFt: => FormatToken)( + private def getSplitsValEquals(body: Tree, endFt: => FT)( classicSplits: => Seq[Split], - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = + )(implicit style: ScalafmtConfig, ft: FT): Seq[Split] = if (style.newlines.getBeforeMultiline eq Newlines.classic) classicSplits else CtrlBodySplits.getWithIndent(body, endFt)(null)(Split(Newline2x(ft), _)) - private def getSplitsValEqualsClassic( - rawBody: Tree, - endFt: FormatToken, - )(implicit style: ScalafmtConfig, ft: FormatToken): Seq[Split] = { + private def getSplitsValEqualsClassic(rawBody: Tree, endFt: FT)(implicit + style: ScalafmtConfig, + ft: FT, + ): Seq[Split] = { def wouldDangle = ft.meta.leftOwner.parent .exists(style.danglingParentheses.atSite(_, false)) @@ -2866,7 +2848,7 @@ class Router(formatOps: FormatOps) { private def getSplitsEnumerator(body: Tree)(implicit style: ScalafmtConfig, - ft: FormatToken, + ft: FT, ): Seq[Split] = maybeGetInfixSplitsBeforeLhs() { val endFt = getLastNonTrivial(body) val expire = endFt.left diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala index c0cf7c3417..d162efece2 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala @@ -36,7 +36,7 @@ final class State( @inline def mod: Modification = modExt.mod - def updatedWithSubsequentEOL(ft: FormatToken): Unit = { + def updatedWithSubsequentEOL(ft: FT): Unit = { column += pendingSpaces.count(_.notExpiredBy(ft)) val mod = split.mod val updatedMod = mod match { @@ -52,7 +52,7 @@ final class State( def costWithoutOverflowPenalty: Int = cost - appliedPenalty - def hasSlbUntil(ft: FormatToken): Boolean = policy + def hasSlbUntil(ft: FT): Boolean = policy .exists(_.appliesUntil(ft)(_.isInstanceOf[PolicyOps.SingleLineBlock])) def hasSlb(): Boolean = policy @@ -197,8 +197,8 @@ final class State( if (!State.allowSplitForLineStart(nextSplit, ft, isComment)) None else lineStartsStatement(isComment) val delay = startFtOpt.exists { - case FormatToken(_, t: T.Interpolation.Start, _) => tokens.matching(t) - .left ne ft.right + case FT(_, t: T.Interpolation.Start, _) => tokens.matching(t).left ne + ft.right case _ => true } // if delaying, estimate column if the split had been a newline @@ -241,7 +241,7 @@ final class State( private def getLineStartOwner(isComment: Boolean)(implicit style: ScalafmtConfig, tokens: FormatTokens, - ): Option[(FormatToken, Tree)] = { + ): Option[(FT, Tree)] = { val ft = tokens(depth) if (ft.meta.left.hasNL) None else if (!split.isNL) { @@ -271,7 +271,7 @@ final class State( private def lineStartsStatement(isComment: Boolean)(implicit style: ScalafmtConfig, tokens: FormatTokens, - ): Option[FormatToken] = getLineStartOwner(isComment) + ): Option[FT] = getLineStartOwner(isComment) .flatMap { case (lineFt, lineOwner) => val ft = tokens(depth) val ok = { @@ -292,7 +292,7 @@ final class State( val allowed = style.indent.relativeToLhsLastLine def treeEnd(x: Tree) = tokens.getLast(x).left.end - def indentEnd(ft: FormatToken, isNL: Boolean)(onComment: => Option[Int]) = { + def indentEnd(ft: FT, isNL: Boolean)(onComment: => Option[Int]) = { val leftOwner = ft.meta.leftOwner ft.left match { case _: T.KwMatch @@ -410,7 +410,7 @@ object State { if (pipe == '|') RegexCompat.stripMarginPatternWithLineContent else RegexCompat.compileStripMarginPatternWithLineContent(pipe) - def getColumns(tok: T, meta: FormatToken.TokenMeta, column: Int)( + def getColumns(tok: T, meta: FT.TokenMeta, column: Int)( stringMargin: Int => Int, )(interpPartMargin: Int => Int): (Int, Int) = { val syntax = meta.text @@ -442,7 +442,7 @@ object State { } } - def getColumns(ft: FormatToken, indent: Int, column: Int)(implicit + def getColumns(ft: FT, indent: Int, column: Int)(implicit style: ScalafmtConfig, ): (Int, Int) = getColumns(ft.right, ft.meta.right, column) { if (style.assumeStandardLibraryStripMargin) { @@ -515,7 +515,7 @@ object State { */ private def allowSplitForLineStart( split: Split, - ft: FormatToken, + ft: FT, isComment: Boolean, ): Boolean = { split.length == 0 || isComment || isInterpolation(ft.meta.rightOwner) || diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/TokenRange.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/TokenRange.scala index 447a07c44d..feb731d4f9 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/TokenRange.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/TokenRange.scala @@ -2,7 +2,7 @@ package org.scalafmt.internal import scala.meta.tokens.{Token => T} -class TokenRange private (val lt: FormatToken, val rt: FormatToken) { +class TokenRange private (val lt: FT, val rt: FT) { def validateAfter(other: TokenRange): Unit = require(lt.idx > other.rt.idx) @@ -37,10 +37,10 @@ class TokenRanges private (val ranges: Seq[TokenRange]) extends AnyVal { object TokenRange { - def apply(lt: FormatToken, rt: FormatToken): TokenRange = + def apply(lt: FT, rt: FT): TokenRange = if (lt.idx < rt.idx) new TokenRange(lt, rt) else new TokenRange(rt, lt) - def opt(lt: FormatToken, rt: FormatToken): Option[TokenRange] = + def opt(lt: FT, rt: FT): Option[TokenRange] = if (lt.idx < rt.idx) Some(new TokenRange(lt, rt)) else if (lt.idx > rt.idx) Some(new TokenRange(rt, lt)) else None diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/package.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/package.scala new file mode 100644 index 0000000000..58e8c4187b --- /dev/null +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/package.scala @@ -0,0 +1,8 @@ +package org.scalafmt + +package object internal { + + private[scalafmt] type FT = FormatToken + private[scalafmt] val FT = FormatToken + +} diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/ConvertToNewScala3Syntax.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/ConvertToNewScala3Syntax.scala index a6593550a9..05398721d1 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/ConvertToNewScala3Syntax.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/ConvertToNewScala3Syntax.scala @@ -28,7 +28,7 @@ private class ConvertToNewScala3Syntax(implicit val ftoks: FormatTokens) ConvertToNewScala3Syntax.enabled override def onToken(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[Replacement] = Option { @@ -117,7 +117,7 @@ private class ConvertToNewScala3Syntax(implicit val ftoks: FormatTokens) } override def onRight(left: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] = Option { diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/FormatTokensRewrite.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/FormatTokensRewrite.scala index b81563873d..a8d4150133 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/FormatTokensRewrite.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/FormatTokensRewrite.scala @@ -32,7 +32,7 @@ class FormatTokensRewrite( * - finally, reassign indices and copy left from previous token's right */ def rewrite: FormatTokens = { - val result = Array.newBuilder[FormatToken] + val result = Array.newBuilder[FT] result.sizeHint(arr.length) val tokenMap = new FormatTokens.TokenToIndexMapBuilder @@ -191,17 +191,14 @@ class FormatTokensRewrite( tokens.filter(_ != null) } - private def applyRules(implicit - ft: FormatToken, - session: Session, - ): Option[Int] = { + private def applyRules(implicit ft: FT, session: Session): Option[Int] = { implicit val style = styleMap.at(ft.right) session.applyRules(rules) } private def applyRule( rule: Rule, - )(implicit ft: FormatToken, session: Session): Option[Int] = { + )(implicit ft: FT, session: Session): Option[Int] = { implicit val style = styleMap.at(ft.right) session.applyRule(rule) } @@ -221,25 +218,25 @@ object FormatTokensRewrite { def enabled(implicit style: ScalafmtConfig): Boolean // act on or modify only ft.right; process standalone or open (left) delim def onToken(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[Replacement] // act on or modify only ft.right; process close (right) delim def onRight(left: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] protected final def removeToken(implicit - ft: FormatToken, + ft: FT, style: ScalafmtConfig, ): Replacement = removeToken(Nil) protected final def removeToken( claim: Iterable[Int] = Nil, - )(implicit ft: FormatToken, style: ScalafmtConfig): Replacement = + )(implicit ft: FT, style: ScalafmtConfig): Replacement = Replacement(this, ft, ReplacementType.Remove, style, claim) protected final def replaceToken( @@ -247,7 +244,7 @@ object FormatTokensRewrite { owner: Option[Tree] = None, claim: Iterable[Int] = Nil, rtype: ReplacementType = ReplacementType.Replace, - )(tok: T)(implicit ft: FormatToken, style: ScalafmtConfig): Replacement = { + )(tok: T)(implicit ft: FT, style: ScalafmtConfig): Replacement = { val mOld = ft.meta.right val mNew = mOld.copy(text = text, owner = owner.getOrElse(mOld.owner)) val ftNew = ft.copy(right = tok, meta = ft.meta.copy(right = mNew)) @@ -259,11 +256,11 @@ object FormatTokensRewrite { owner: Option[Tree] = None, claim: Iterable[Int] = Nil, rtype: ReplacementType = ReplacementType.Replace, - )(f: T => T)(implicit ft: FormatToken, style: ScalafmtConfig): Replacement = + )(f: T => T)(implicit ft: FT, style: ScalafmtConfig): Replacement = replaceToken(text, owner, claim, rtype)(f(ft.right)) protected final def replaceTokenIdent(text: String, t: T)(implicit - ft: FormatToken, + ft: FT, style: ScalafmtConfig, ): Replacement = replaceToken(text)( new T.Ident(t.input, t.dialect, t.start, t.start + text.length, text), @@ -308,11 +305,11 @@ object FormatTokensRewrite { } @inline - def claimedRule(implicit ft: FormatToken): Option[Replacement] = + def claimedRule(implicit ft: FT): Option[Replacement] = claimedRule(ft.meta.idx) @inline - def claimedRuleOnLeft(ft: FormatToken): Option[Replacement] = + def claimedRuleOnLeft(ft: FT): Option[Replacement] = claimedRule(ft.meta.idx - 1) @inline @@ -338,9 +335,8 @@ object FormatTokensRewrite { } @inline - private[rewrite] def claim(repl: Replacement)(implicit - ft: FormatToken, - ): Int = claim(ft.meta.idx, repl) + private[rewrite] def claim(repl: Replacement)(implicit ft: FT): Int = + claim(ft.meta.idx, repl) private def justClaim(ftIdx: Int)(repl: Replacement): Int = { val idx = tokens.length @@ -365,7 +361,7 @@ object FormatTokensRewrite { private[FormatTokensRewrite] def applyRule( attemptedRule: Rule, - )(implicit ft: FormatToken, style: ScalafmtConfig): Option[Int] = + )(implicit ft: FT, style: ScalafmtConfig): Option[Int] = if (attemptedRule.enabled) attemptedRule.onToken.map { repl => val idx = claim(repl) try idx @@ -375,7 +371,7 @@ object FormatTokensRewrite { private[FormatTokensRewrite] def applyRules( rules: Seq[Rule], - )(implicit ft: FormatToken, style: ScalafmtConfig): Option[Int] = { + )(implicit ft: FT, style: ScalafmtConfig): Option[Int] = { @tailrec def iter(remainingRules: Seq[Rule]): Option[Int] = remainingRules match { case r +: rs => applyRule(r) match { @@ -395,22 +391,22 @@ object FormatTokensRewrite { ruleOpt.map(_.asInstanceOf[A]).filter(_.enabled) } - private[rewrite] def isRemovedOnLeftOpt(x: FormatToken): Option[Boolean] = { + private[rewrite] def isRemovedOnLeftOpt(x: FT): Option[Boolean] = { val ftIdx = x.meta.idx - 1 claimedRule(ftIdx).filter(_.idx == ftIdx).map(_.isRemove) } - private[rewrite] def isRemovedOnLeft(x: FormatToken, ok: Boolean): Boolean = + private[rewrite] def isRemovedOnLeft(x: FT, ok: Boolean): Boolean = isRemovedOnLeftOpt(x).contains(ok) } private[rewrite] case class Replacement( rule: Rule, - ft: FormatToken, + ft: FT, how: ReplacementType, style: ScalafmtConfig, - // list of FormatToken indices, with the claimed token on the **right** + // list of FT indices, with the claimed token on the **right** claim: Iterable[Int] = Nil, ) { @inline @@ -419,14 +415,14 @@ object FormatTokensRewrite { def idx: Int = ft.meta.idx def onRight(hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] = if (rule.enabled) rule.onRight(this, hasFormatOff) else None def onRightAndClaim(hasFormatOff: Boolean, leftIdx: Int)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Unit = { @@ -444,16 +440,16 @@ object FormatTokensRewrite { object Replace extends ReplacementType { override def toString: String = "REPLACE" } - class RemoveAndResurrect(val ft: FormatToken) extends ReplacementType { + class RemoveAndResurrect(val ft: FT) extends ReplacementType { override def toString: String = s"REMOVE/RESURRECT(${ft.right.structure})" } } private def mergeWhitespaceLeftToRight( - lt: FormatToken.Meta, - rt: FormatToken.Meta, + lt: FT.Meta, + rt: FT.Meta, ): Option[Array[T]] = { - import FormatToken.isNL + import FT.isNL val rtBW = rt.between val rtNumNL = rt.newlinesBetween if (rtNumNL >= 2) None // right has a blank line, nothing to get from left diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/PreferCurlyFors.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/PreferCurlyFors.scala index 533bdc4ef0..bc9fcd659d 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/PreferCurlyFors.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/PreferCurlyFors.scala @@ -57,7 +57,7 @@ private class PreferCurlyFors(implicit val ftoks: FormatTokens) PreferCurlyFors.enabled override def onToken(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[Replacement] = Option { @@ -86,7 +86,7 @@ private class PreferCurlyFors(implicit val ftoks: FormatTokens) } override def onRight(left: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] = ft.right match { @@ -100,7 +100,7 @@ private class PreferCurlyFors(implicit val ftoks: FormatTokens) } private def hasNoLeadingInfix(t: Term.EnumeratorsBlock)(implicit - head: FormatToken, + head: FT, ): Boolean = findTokenWith(nextNonCommentAfter(head), next) { ft => ft.meta.rightOwner match { case ro: Name if (ro.parent match { diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RedundantBraces.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RedundantBraces.scala index 9f12e5b801..f593f052d3 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RedundantBraces.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RedundantBraces.scala @@ -62,8 +62,8 @@ object RedundantBraces extends Rewrite with FormatTokensRewrite.RuleFactory { case _ => false } - private[scalafmt] def canRewriteWithParensOnRightBrace(rb: FormatToken)( - implicit ftoks: FormatTokens, + private[scalafmt] def canRewriteWithParensOnRightBrace(rb: FT)(implicit + ftoks: FormatTokens, ): Boolean = !ftoks.prevNonCommentBefore(rb).left.is[T.Semicolon] && (rb.meta.leftOwner match { // look for "foo { bar }" case b: Term.Block => checkApply(b) && canRewriteBlockWithParens(b) && @@ -75,8 +75,8 @@ object RedundantBraces extends Rewrite with FormatTokensRewrite.RuleFactory { case _ => false }) - private[scalafmt] def isLeftParenReplacedWithBraceOnLeft(pft: FormatToken)( - implicit session: Session, + private[scalafmt] def isLeftParenReplacedWithBraceOnLeft(pft: FT)(implicit + session: Session, ): Boolean = session.claimedRuleOnLeft(pft).exists { x => (x.how eq ReplacementType.Replace) && x.ft.right.is[T.LeftBrace] } @@ -95,7 +95,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) RedundantBraces.enabled override def onToken(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[Replacement] = Option { @@ -107,7 +107,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) } override def onRight(left: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] = Option { @@ -118,16 +118,13 @@ class RedundantBraces(implicit val ftoks: FormatTokens) } } - private def onLeftParen(implicit - ft: FormatToken, - style: ScalafmtConfig, - ): Replacement = { + private def onLeftParen(implicit ft: FT, style: ScalafmtConfig): Replacement = { val rt = ft.right val rtOwner = ft.meta.rightOwner def lpFunction = okToReplaceFunctionInSingleArgApply(rtOwner).map { case (`rt`, f) => f.body match { case b: Term.Block => ftoks.getHead(b) match { - case FormatToken(_: T.LeftBrace, _, lbm) => + case FT(_: T.LeftBrace, _, lbm) => val lb = new T.LeftBrace(rt.input, rt.dialect, rt.start) replaceToken("{", claim = lbm.idx - 1 :: Nil)(lb) case _ => null @@ -143,7 +140,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) getOpeningParen(ta).map { lp => if (lp.ne(rt) || getBlockNestedPartialFunction(arg).isEmpty) null else ftoks.nextNonCommentAfter(ft) match { - case FormatToken(lt, _: T.LeftBrace, lbm) => + case FT(lt, _: T.LeftBrace, lbm) => if (lt eq rt) removeToken(claim = lbm.idx :: Nil) else { val lbo = Some(lbm.rightOwner) @@ -160,7 +157,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) } private def onRightParen(left: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): (Replacement, Replacement) = left.how match { @@ -173,7 +170,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) session.getClaimed(lb.meta.idx).foreach { case (leftIdx, _) => val repl = r.onLeftForArgClause(ac)(lb, left.style) if (null ne repl) { - implicit val ft: FormatToken = ftoks.prev(rb) + implicit val ft: FT = ftoks.prev(rb) repl.onRightAndClaim(hasFormatOff, leftIdx) } } @@ -209,11 +206,9 @@ class RedundantBraces(implicit val ftoks: FormatTokens) case _ => null } - private def getRightBraceBeforeRightParen(shouldBeRemoved: Boolean)(implicit - ft: FormatToken, - session: Session, - style: ScalafmtConfig, - ): Option[FormatToken] = { + private def getRightBraceBeforeRightParen( + shouldBeRemoved: Boolean, + )(implicit ft: FT, session: Session, style: ScalafmtConfig): Option[FT] = { val pft = ftoks.prevNonComment(ft) val ok = pft.left match { case _: T.Comma => // looks like trailing comma @@ -228,7 +223,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) } case _: T.RightBrace => @tailrec - def shouldNotBeRemoved(xft: FormatToken): Boolean = + def shouldNotBeRemoved(xft: FT): Boolean = !session.isRemovedOnLeft(xft, ok = true) || { val pxft = ftoks.prevNonCommentBefore(xft) pxft.left.is[T.RightBrace] && shouldNotBeRemoved(pxft) @@ -241,16 +236,14 @@ class RedundantBraces(implicit val ftoks: FormatTokens) } private def onLeftBrace(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Replacement = onLeftBrace(ft.meta.rightOwner) - private def onLeftBrace(owner: Tree)(implicit - ft: FormatToken, - session: Session, - style: ScalafmtConfig, - ): Replacement = { + private def onLeftBrace( + owner: Tree, + )(implicit ft: FT, session: Session, style: ScalafmtConfig): Replacement = { def handleInterpolation = if ( style.rewrite.redundantBraces.stringInterpolation && @@ -300,23 +293,22 @@ class RedundantBraces(implicit val ftoks: FormatTokens) } private def onRightBrace(left: Replacement)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): (Replacement, Replacement) = { @tailrec - def okComment(xft: FormatToken): Boolean = - ftoks.prevNotTrailingComment(xft) match { - case Right(x) => (x eq xft) || !session.isRemovedOnLeft(x, true) || { - val pft = ftoks.prev(x) - pft.noBreak && okComment(pft) - } - case _ => false - } + def okComment(xft: FT): Boolean = ftoks.prevNotTrailingComment(xft) match { + case Right(x) => (x eq xft) || !session.isRemovedOnLeft(x, true) || { + val pft = ftoks.prev(x) + pft.noBreak && okComment(pft) + } + case _ => false + } val ok = ft.meta.rightOwner match { case t: Term.Block => !braceSeparatesTwoXmlTokens && (ftoks.prevNonComment(ft) match { - case FormatToken(_: T.Semicolon, _, m) => + case FT(_: T.Semicolon, _, m) => val plo = m.leftOwner (plo eq t) || !plo.parent.contains(t) case _ => true @@ -332,7 +324,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) style: ScalafmtConfig, ): RedundantBracesSettings = style.rewrite.redundantBraces - private def processInterpolation(implicit ft: FormatToken): Boolean = { + private def processInterpolation(implicit ft: FT): Boolean = { def isIdentifierAtStart(value: String) = value.headOption .exists(x => Character.isLetterOrDigit(x) || x == '_') @@ -401,7 +393,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) } private def processBlock(b: Term.Block)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Boolean = b.stats.nonEmpty && b.tokens.headOption.contains(ft.right) && @@ -414,7 +406,7 @@ class RedundantBraces(implicit val ftoks: FormatTokens) private def checkValidInfixParent( p: Tree, - )(implicit ft: FormatToken, style: ScalafmtConfig): Boolean = p match { + )(implicit ft: FT, style: ScalafmtConfig): Boolean = p match { case _: Member.Infix => /* for infix, we will preserve the block unless the closing brace * follows a non-whitespace character on the same line as we don't @@ -434,63 +426,62 @@ class RedundantBraces(implicit val ftoks: FormatTokens) case _ => true } - private def okToRemoveBlock(b: Term.Block)(implicit - ft: FormatToken, - style: ScalafmtConfig, - session: Session, - ): Boolean = b.parent.exists { - case t: Term.ArgClause if isParentAnApply(t) => - // Example: as.map { _.toString } - // Leave this alone for now. - // In future there should be an option to surround such expressions with parens instead of braces - if (isSeqMulti(t.values)) okToRemoveBlockWithinApply(b) - else ftoks.getDelimsIfEnclosed(t).exists { case (ldelim, _) => - def isArgDelimRemoved = session.isRemovedOnLeft(ldelim, ok = true) - def hasExpressionWithBraces: Boolean = - // there's a nested expression with braces that will be kept - getSingleStatIfLineSpanOk(b).exists { - getBlockNestedPartialFunction(_).isDefined + private def okToRemoveBlock( + b: Term.Block, + )(implicit ft: FT, style: ScalafmtConfig, session: Session): Boolean = b + .parent.exists { + case t: Term.ArgClause if isParentAnApply(t) => + // Example: as.map { _.toString } + // Leave this alone for now. + // In future there should be an option to surround such expressions with parens instead of braces + if (isSeqMulti(t.values)) okToRemoveBlockWithinApply(b) + else ftoks.getDelimsIfEnclosed(t).exists { case (ldelim, _) => + def isArgDelimRemoved = session.isRemovedOnLeft(ldelim, ok = true) + def hasExpressionWithBraces: Boolean = + // there's a nested expression with braces that will be kept + getSingleStatIfLineSpanOk(b).exists { + getBlockNestedPartialFunction(_).isDefined + } + ldelim.left match { + case lb: T.LeftBrace => + // either arg clause has separate braces, or we guarantee braces + (ft.right ne lb) && !isArgDelimRemoved || hasExpressionWithBraces + case _: T.LeftParen => isLeftParenReplacedWithBraceOnLeft(ldelim) || + hasExpressionWithBraces + case _ => false } - ldelim.left match { - case lb: T.LeftBrace => - // either arg clause has separate braces, or we guarantee braces - (ft.right ne lb) && !isArgDelimRemoved || hasExpressionWithBraces - case _: T.LeftParen => isLeftParenReplacedWithBraceOnLeft(ldelim) || - hasExpressionWithBraces - case _ => false } - } - case d: Defn.Def => - def disqualifiedByUnit = !settings.includeUnitMethods && - d.decltpe.exists { - case Type.Name("Unit") => true - case _ => false - } - checkBlockAsBody(b, d.body, noParams = d.paramClauseGroups.isEmpty) && - !isProcedureSyntax(d) && !disqualifiedByUnit + case d: Defn.Def => + def disqualifiedByUnit = !settings.includeUnitMethods && + d.decltpe.exists { + case Type.Name("Unit") => true + case _ => false + } + checkBlockAsBody(b, d.body, noParams = d.paramClauseGroups.isEmpty) && + !isProcedureSyntax(d) && !disqualifiedByUnit - case d: Defn.Var => checkBlockAsBody(b, d.body, noParams = true) - case d: Defn.Val => checkBlockAsBody(b, d.rhs, noParams = true) - case d: Defn.Type => - checkBlockAsBody(b, d.body, noParams = d.tparamClause.isEmpty) - case d: Defn.Macro => - checkBlockAsBody(b, d.body, noParams = d.paramClauseGroups.isEmpty) - case d: Defn.GivenAlias => - checkBlockAsBody(b, d.body, noParams = d.paramClauseGroup.isEmpty) + case d: Defn.Var => checkBlockAsBody(b, d.body, noParams = true) + case d: Defn.Val => checkBlockAsBody(b, d.rhs, noParams = true) + case d: Defn.Type => + checkBlockAsBody(b, d.body, noParams = d.tparamClause.isEmpty) + case d: Defn.Macro => + checkBlockAsBody(b, d.body, noParams = d.paramClauseGroups.isEmpty) + case d: Defn.GivenAlias => + checkBlockAsBody(b, d.body, noParams = d.paramClauseGroup.isEmpty) - case p: Term.FunctionTerm if isFunctionWithBraces(p) => - okToRemoveAroundFunctionBody(b, okIfMultipleStats = true) + case p: Term.FunctionTerm if isFunctionWithBraces(p) => + okToRemoveAroundFunctionBody(b, okIfMultipleStats = true) - case _: Term.If => settings.ifElseExpressions && - shouldRemoveSingleStatBlock(b) + case _: Term.If => settings.ifElseExpressions && + shouldRemoveSingleStatBlock(b) - case Term.Block(List(`b`)) => true + case Term.Block(List(`b`)) => true - case _: Term.QuotedMacroExpr | _: Term.SplicedMacroExpr => false + case _: Term.QuotedMacroExpr | _: Term.SplicedMacroExpr => false - case _ => settings.generalExpressions && shouldRemoveSingleStatBlock(b) - } + case _ => settings.generalExpressions && shouldRemoveSingleStatBlock(b) + } private def checkBlockAsBody(b: Term.Block, rhs: Tree, noParams: => Boolean)( implicit style: ScalafmtConfig, @@ -532,87 +523,86 @@ class RedundantBraces(implicit val ftoks: FormatTokens) } /** Some blocks look redundant but aren't */ - private def shouldRemoveSingleStatBlock(b: Term.Block)(implicit - ft: FormatToken, - style: ScalafmtConfig, - session: Session, - ): Boolean = getSingleStatIfLineSpanOk(b).exists { stat => - @tailrec - def keepForParent(tree: Tree): Boolean = tree match { - case t: Term.ArgClause => t.parent match { - case Some(p) => keepForParent(p) - case _ => true - } - case _: Term.TryClause => - // "try (x).y" or "try { x }.y" isn't supported until scala 2.13 - // same is true with "try (a, b)" and "try ()" - // return true if rewrite is not OK - // inside exists, return true if rewrite is OK - !stat.tokens.headOption.exists { - case x: T.LeftParen => ftoks.matchingOpt(x) match { - case Some(y) if y.left ne stat.tokens.last => - session.rule[RedundantParens].exists { - _.onToken(ftoks(x, -1), session, style).exists(_.isRemove) - } - case Some(_) if !style.dialect.allowTryWithAnyExpr => - !stat.isAny[Term.Tuple, Lit.Unit] - case _ => true - } - case x: T.LeftBrace => ftoks.matchingOpt(x) match { - case Some(y) if y.left ne stat.tokens.last => - findFirstTreeBetween(stat, x, y.left).exists { - case z: Term.Block => okToRemoveBlock(z) - case _ => false - } - case _ => true - } - case _ => true - } + private def shouldRemoveSingleStatBlock( + b: Term.Block, + )(implicit ft: FT, style: ScalafmtConfig, session: Session): Boolean = + getSingleStatIfLineSpanOk(b).exists { stat => + @tailrec + def keepForParent(tree: Tree): Boolean = tree match { + case t: Term.ArgClause => t.parent match { + case Some(p) => keepForParent(p) + case _ => true + } + case _: Term.TryClause => + // "try (x).y" or "try { x }.y" isn't supported until scala 2.13 + // same is true with "try (a, b)" and "try ()" + // return true if rewrite is not OK + // inside exists, return true if rewrite is OK + !stat.tokens.headOption.exists { + case x: T.LeftParen => ftoks.matchingOpt(x) match { + case Some(y) if y.left ne stat.tokens.last => + session.rule[RedundantParens].exists { + _.onToken(ftoks(x, -1), session, style).exists(_.isRemove) + } + case Some(_) if !style.dialect.allowTryWithAnyExpr => + !stat.isAny[Term.Tuple, Lit.Unit] + case _ => true + } + case x: T.LeftBrace => ftoks.matchingOpt(x) match { + case Some(y) if y.left ne stat.tokens.last => + findFirstTreeBetween(stat, x, y.left).exists { + case z: Term.Block => okToRemoveBlock(z) + case _ => false + } + case _ => true + } + case _ => true + } - // can't do it for try until 2.13.3 - case _ if isPrefixExpr(stat) => false - - case parentIf: Term.If if stat.is[Term.If] => - // if (a) { if (b) c } else d - // ↑ cannot be replaced by ↓ - // if (a) if (b) c else d - // which would be equivalent to - // if (a) { if (b) c else d } - (parentIf.thenp eq b) && !ifWithoutElse(parentIf) && - existsIfWithoutElse(stat.asInstanceOf[Term.If]) - - case p: Term.ApplyInfix => stat match { - case t: Term.ApplyInfix => - val useRight = hasSingleElement(p.argClause, b) - SyntacticGroupOps.groupNeedsParenthesis( - TreeSyntacticGroup(p), - TreeSyntacticGroup(t), - if (useRight) Side.Right else Side.Left, - ) - case _ => true // don't allow other non-infix - } + // can't do it for try until 2.13.3 + case _ if isPrefixExpr(stat) => false + + case parentIf: Term.If if stat.is[Term.If] => + // if (a) { if (b) c } else d + // ↑ cannot be replaced by ↓ + // if (a) if (b) c else d + // which would be equivalent to + // if (a) { if (b) c else d } + (parentIf.thenp eq b) && !ifWithoutElse(parentIf) && + existsIfWithoutElse(stat.asInstanceOf[Term.If]) + + case p: Term.ApplyInfix => stat match { + case t: Term.ApplyInfix => + val useRight = hasSingleElement(p.argClause, b) + SyntacticGroupOps.groupNeedsParenthesis( + TreeSyntacticGroup(p), + TreeSyntacticGroup(t), + if (useRight) Side.Right else Side.Left, + ) + case _ => true // don't allow other non-infix + } - case p: Term.Match => p.expr eq b - case p: Type.Match => p.tpe eq b + case p: Term.Match => p.expr eq b + case p: Type.Match => p.tpe eq b - case p: Term.ForClause if p.body eq b => - @tailrec - def iter(t: Tree): Boolean = t match { - case _: Term.Do => true - case Term.Block(x :: Nil) => iter(x) - case _ => false - } - iter(stat) + case p: Term.ForClause if p.body eq b => + @tailrec + def iter(t: Tree): Boolean = t match { + case _: Term.Do => true + case Term.Block(x :: Nil) => iter(x) + case _ => false + } + iter(stat) - case parent => SyntacticGroupOps.groupNeedsParenthesis( - TreeSyntacticGroup(parent), - TreeSyntacticGroup(stat), - Side.Left, - ) - } + case parent => SyntacticGroupOps.groupNeedsParenthesis( + TreeSyntacticGroup(parent), + TreeSyntacticGroup(stat), + Side.Left, + ) + } - innerOk(b)(stat) && !b.parent.exists(keepForParent) - } + innerOk(b)(stat) && !b.parent.exists(keepForParent) + } @inline private def okToRemoveAroundFunctionBody(b: Term, s: Seq[Tree])(implicit @@ -654,11 +644,11 @@ class RedundantBraces(implicit val ftoks: FormatTokens) ftoks(t.name.tokens.head, -1).left.is[T.Dot] } - private def braceSeparatesTwoXmlTokens(implicit ft: FormatToken): Boolean = ft - .left.is[T.Xml.End] && ftoks.next(ft).right.is[T.Xml.Start] + private def braceSeparatesTwoXmlTokens(implicit ft: FT): Boolean = ft.left + .is[T.Xml.End] && ftoks.next(ft).right.is[T.Xml.Start] private def elseAfterRightBraceThenpOnLeft(implicit - ft: FormatToken, + ft: FT, ftoks: FormatTokens, session: Session, ): Boolean = ftoks.nextNonCommentAfter(ft).right.is[T.KwElse] && { diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RedundantParens.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RedundantParens.scala index 7e4f6d1a92..d54cc807cd 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RedundantParens.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RedundantParens.scala @@ -71,7 +71,7 @@ class RedundantParens(implicit val ftoks: FormatTokens) RedundantParens.enabled override def onToken(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[Replacement] = ft.right match { @@ -82,7 +82,7 @@ class RedundantParens(implicit val ftoks: FormatTokens) } override def onRight(left: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] = @@ -214,15 +214,15 @@ class RedundantParens(implicit val ftoks: FormatTokens) case _ => true } - private def findEnclosed(implicit ft: FormatToken): Option[Enclosed] = { + private def findEnclosed(implicit ft: FT): Option[Enclosed] = { // counts consecutive parent pairs starting with the given one as the innermost // the parens could belong to tree they are enclosing, or its parent @tailrec - def iter(lt: FormatToken, rt: FormatToken, cnt: Int): Option[Enclosed] = + def iter(lt: FT, rt: FT, cnt: Int): Option[Enclosed] = (ftoks.prevNonComment(lt), ftoks.nextNonComment(rt)) match { case ( - prev @ FormatToken(_: T.LeftParen, _, _), - next @ FormatToken(_, _: T.RightParen, _), + prev @ FT(_: T.LeftParen, _, _), + next @ FT(_, _: T.RightParen, _), ) => iter(ftoks.prev(prev), ftoks.next(next), cnt + 1) case _ => TreeOps .findEnclosedBetweenParens(lt.right, rt.left, ft.meta.rightOwner) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RemoveEmptyDocstrings.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RemoveEmptyDocstrings.scala index ea842a532d..4b02749192 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RemoveEmptyDocstrings.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RemoveEmptyDocstrings.scala @@ -18,7 +18,7 @@ object RemoveEmptyDocstrings this override def onToken(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[Replacement] = { @@ -28,7 +28,7 @@ object RemoveEmptyDocstrings } override def onRight(lt: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] = None diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RemoveScala3OptionalBraces.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RemoveScala3OptionalBraces.scala index 9164cdcbe3..ea9638f8e8 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RemoveScala3OptionalBraces.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RemoveScala3OptionalBraces.scala @@ -36,7 +36,7 @@ private class RemoveScala3OptionalBraces(implicit val ftoks: FormatTokens) RemoveScala3OptionalBraces.enabled override def onToken(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[Replacement] = Option { @@ -79,7 +79,7 @@ private class RemoveScala3OptionalBraces(implicit val ftoks: FormatTokens) } override def onRight(left: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] = { @@ -118,15 +118,14 @@ private class RemoveScala3OptionalBraces(implicit val ftoks: FormatTokens) } } - private def onLeftForBlock(tree: Term.Block)(implicit - ft: FormatToken, - session: Session, - style: ScalafmtConfig, - ): Replacement = onLeftForBlock(tree, ftoks.prevNonComment(ft)) + private def onLeftForBlock( + tree: Term.Block, + )(implicit ft: FT, session: Session, style: ScalafmtConfig): Replacement = + onLeftForBlock(tree, ftoks.prevNonComment(ft)) @tailrec - private def onLeftForBlock(tree: Term.Block, pft: FormatToken)(implicit - ft: FormatToken, + private def onLeftForBlock(tree: Term.Block, pft: FT)(implicit + ft: FT, session: Session, style: ScalafmtConfig, ): Replacement = tree.parent.orNull match { @@ -182,7 +181,7 @@ private class RemoveScala3OptionalBraces(implicit val ftoks: FormatTokens) private def shouldRewriteArgClauseWithLeftParen[A <: Rule]( lp: T, - )(implicit ft: FormatToken, session: Session, tag: ClassTag[A]) = { + )(implicit ft: FT, session: Session, tag: ClassTag[A]) = { val prevFt = ftoks.prevNonComment(ft) prevFt.left.eq(lp) && session.claimedRule(prevFt.meta.idx - 1) .exists(x => tag.runtimeClass.isInstance(x.rule)) @@ -190,7 +189,7 @@ private class RemoveScala3OptionalBraces(implicit val ftoks: FormatTokens) private[rewrite] def onLeftForArgClause( tree: Term.ArgClause, - )(implicit ft: FormatToken, style: ScalafmtConfig): Replacement = { + )(implicit ft: FT, style: ScalafmtConfig): Replacement = { def okLeftDelim = ft.right.is[T.LeftBrace] || style.rewrite.scala3.removeOptionalBraces.fewerBracesParensToo && (style.dialect.allowInfixOperatorAfterNL || style.newlines.formatInfix) @@ -210,11 +209,9 @@ private class RemoveScala3OptionalBraces(implicit val ftoks: FormatTokens) } } - private def shouldRewriteColonOnRight(left: Replacement)(implicit - ft: FormatToken, - session: Session, - style: ScalafmtConfig, - ): Boolean = { + private def shouldRewriteColonOnRight( + left: Replacement, + )(implicit ft: FT, session: Session, style: ScalafmtConfig): Boolean = { val lft = left.ft lft.meta.rightOwner match { case t: Term.ArgClause => shouldRewriteArgClauseColonOnRight(t, lft) @@ -229,33 +226,30 @@ private class RemoveScala3OptionalBraces(implicit val ftoks: FormatTokens) private def shouldRewriteArgClauseColonOnRight( ac: Term.ArgClause, - lft: FormatToken, - )(implicit - ft: FormatToken, - session: Session, - style: ScalafmtConfig, - ): Boolean = ac.values match { - case arg :: Nil => - val begIdx = math.max(ftoks.getHead(arg).meta.idx - 1, lft.meta.idx + 1) - val endIdx = math.min(ftoks.getLast(arg).meta.idx, ft.meta.idx) - var span = 0 - val rob = style.rewrite.scala3.removeOptionalBraces - val maxStats = rob.fewerBracesMaxSpan - (begIdx until endIdx).foreach { idx => - val tokOpt = session.claimedRule(idx) match { - case Some(x) if x.ft.meta.idx == idx => - if (x.how == ReplacementType.Remove) None else Some(x.ft.right) - case _ => - val tok = ftoks(idx).right - if (tok.is[T.Whitespace]) None else Some(tok) - } - tokOpt.foreach { tok => - span += tok.end - tok.start - if (span > maxStats) return false // RETURNING!!! + lft: FT, + )(implicit ft: FT, session: Session, style: ScalafmtConfig): Boolean = + ac.values match { + case arg :: Nil => + val begIdx = math.max(ftoks.getHead(arg).meta.idx - 1, lft.meta.idx + 1) + val endIdx = math.min(ftoks.getLast(arg).meta.idx, ft.meta.idx) + var span = 0 + val rob = style.rewrite.scala3.removeOptionalBraces + val maxStats = rob.fewerBracesMaxSpan + (begIdx until endIdx).foreach { idx => + val tokOpt = session.claimedRule(idx) match { + case Some(x) if x.ft.meta.idx == idx => + if (x.how == ReplacementType.Remove) None else Some(x.ft.right) + case _ => + val tok = ftoks(idx).right + if (tok.is[T.Whitespace]) None else Some(tok) + } + tokOpt.foreach { tok => + span += tok.end - tok.start + if (span > maxStats) return false // RETURNING!!! + } } - } - span >= rob.fewerBracesMinSpan - case _ => false - } + span >= rob.fewerBracesMinSpan + case _ => false + } } diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RewriteTrailingCommas.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RewriteTrailingCommas.scala index dc307c837f..b457900dc2 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RewriteTrailingCommas.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/RewriteTrailingCommas.scala @@ -19,7 +19,7 @@ object RewriteTrailingCommas extends FormatTokensRewrite.RuleFactory { new RewriteTrailingCommas private[rewrite] def checkIfPrevious(implicit - ft: FormatToken, + ft: FT, session: Session, ftoks: FormatTokens, ): Boolean = ft.right match { @@ -46,13 +46,13 @@ private class RewriteTrailingCommas(implicit val ftoks: FormatTokens) RewriteTrailingCommas.enabled override def onToken(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[Replacement] = if (shouldRemove(ft)) Some(removeToken) else None private[rewrite] def shouldRemove( - ft: FormatToken, + ft: FT, )(implicit session: Session): Boolean = ft.right.is[T.Comma] && { val nft = ftoks.nextNonCommentAfter(ft) def delimOwner = nft.meta.rightOwner @@ -77,7 +77,7 @@ private class RewriteTrailingCommas(implicit val ftoks: FormatTokens) } override def onRight(lt: Replacement, hasFormatOff: Boolean)(implicit - ft: FormatToken, + ft: FT, session: Session, style: ScalafmtConfig, ): Option[(Replacement, Replacement)] = None diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/LoggerOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/LoggerOps.scala index 8e735f9296..a28eb3686a 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/LoggerOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/LoggerOps.scala @@ -49,13 +49,13 @@ object LoggerOps { } def log(split: Split): String = s"$split" - def log(formatToken: FormatToken): String = + def log(formatToken: FT): String = s"""|${log(formatToken.left)} |${log(formatToken.between: _*)} |${log(formatToken.right)}""".stripMargin - def log2(formatToken: FormatToken): String = formatToken.toString - def log2(formatToken: Option[FormatToken]): String = formatToken.fold("")(log2) + def log2(formatToken: FT): String = formatToken.toString + def log2(formatToken: Option[FT]): String = formatToken.fold("")(log2) def escape(raw: String): String = raw diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/PolicyOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/PolicyOps.scala index 9f7f7af9f0..a616ff3bc5 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/PolicyOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/PolicyOps.scala @@ -47,13 +47,13 @@ object PolicyOps { def penalizeNewlineByNesting(from: T, to: T)(implicit fileLine: FileLine, - ): Policy = Policy.End < from ==> Policy.before(to, prefix = "PNL()") { - case Decision(FormatToken(l, _, m), s) => + ): Policy = Policy.End < from ==> + Policy.before(to, prefix = "PNL()") { case Decision(FT(l, _, m), s) => val nonBoolPenalty = if (TokenOps.isBoolOperator(l)) 0 else 5 val penalty = TreeOps.nestedSelect(m.leftOwner) + TreeOps.nestedApplies(m.rightOwner) + nonBoolPenalty s.map(x => if (x.isNL) x.withPenalty(penalty) else x) - } + } /** Forces all splits up to including expire to be on a single line. * @param okSLC diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/StyleMap.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/StyleMap.scala index 3308df7100..f51b92255e 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/StyleMap.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/StyleMap.scala @@ -118,7 +118,7 @@ class StyleMap(tokens: FormatTokens, val init: ScalafmtConfig) { } def opensLiteralArgumentList( - ft: FormatToken, + ft: FT, )(implicit style: ScalafmtConfig): Boolean = (ft.meta.leftOwner match { case Member.Tuple(v) => Some(v) case Member.SyntaxValuesClause(v) => Some(v) @@ -138,7 +138,7 @@ class StyleMap(tokens: FormatTokens, val init: ScalafmtConfig) { } @inline - def at(token: FormatToken): ScalafmtConfig = at(token.left) + def at(token: FT): ScalafmtConfig = at(token.left) @inline def forall(f: ScalafmtConfig => Boolean): Boolean = styles.forall(f) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TokenOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TokenOps.scala index 431327a597..bd9eba591c 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TokenOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TokenOps.scala @@ -41,7 +41,7 @@ object TokenOps { def isDocstring(text: String): Boolean = text.length > 4 && text.startsWith("/**") // excludes /**/ - def blankLineBeforeDocstring(ft: FormatToken)(implicit + def blankLineBeforeDocstring(ft: FT)(implicit style: ScalafmtConfig, ): Boolean = style.forceNewlineBeforeDocstring && isDocstring(ft.meta.right.text) && @@ -61,19 +61,19 @@ object TokenOps { .getOrElse(tokens.last) @inline - def withNoIndent(ft: FormatToken): Boolean = ft.between.lastOption.is[AtEOL] + def withNoIndent(ft: FT): Boolean = ft.between.lastOption.is[AtEOL] @inline - def rhsIsCommentedOut(ft: FormatToken): Boolean = ft.right.is[Comment] && + def rhsIsCommentedOut(ft: FT): Boolean = ft.right.is[Comment] && rhsIsCommentedOutIfComment(ft) @inline - def rhsIsCommentedOutIfComment(ft: FormatToken): Boolean = withNoIndent(ft) && + def rhsIsCommentedOutIfComment(ft: FT): Boolean = withNoIndent(ft) && isSingleLineIfComment(ft.right) @inline - def isLeftCommentThenBreak(ft: FormatToken): Boolean = ft.left - .is[T.Comment] && ft.hasBreak + def isLeftCommentThenBreak(ft: FT): Boolean = ft.left.is[Comment] && + ft.hasBreak def isSingleLineIfComment(c: T): Boolean = { val off = c.start @@ -93,7 +93,7 @@ object TokenOps { } @inline - def getMod(ft: FormatToken): Modification = Space.orNL(ft.newlinesBetween) + def getMod(ft: FT): Modification = Space.orNL(ft.newlinesBetween) val formatOnCode = Set( "@formatter:on", // IntelliJ diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TreeOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TreeOps.scala index 6147455cfd..b2dbfbb2d2 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TreeOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TreeOps.scala @@ -35,29 +35,29 @@ object TreeOps { } object SingleArgInBraces { - def unapply(tree: Tree)(implicit - ftoks: FormatTokens, - ): Option[(FormatToken, Term, FormatToken)] = tree match { + def unapply( + tree: Tree, + )(implicit ftoks: FormatTokens): Option[(FT, Term, FT)] = tree match { case t: Term.ArgClause => unapply(t) case _ => None } def unapply(tree: Term.ArgClause)(implicit ftoks: FormatTokens, - ): Option[(FormatToken, Term, FormatToken)] = getBraces(tree, tree.values) + ): Option[(FT, Term, FT)] = getBraces(tree, tree.values) @inline private def getBraces[A](tree: Tree, values: List[A])(implicit ftoks: FormatTokens, - ): Option[(FormatToken, A, FormatToken)] = values match { + ): Option[(FT, A, FT)] = values match { case arg :: Nil => ftoks.getBracesIfEnclosed(tree).map { case (b, e) => (b, arg, e) } case _ => None } - def orBlock(tree: Tree)(implicit - ftoks: FormatTokens, - ): Option[(FormatToken, Stat, FormatToken)] = tree match { + def orBlock( + tree: Tree, + )(implicit ftoks: FormatTokens): Option[(FT, Stat, FT)] = tree match { case t: Term.ArgClause => unapply(t) case t: Term.Block => getBraces(t, t.stats) case _ => None @@ -66,7 +66,7 @@ object TreeOps { object OrBlock { def unapply(tree: Tree)(implicit ftoks: FormatTokens, - ): Option[(FormatToken, Stat, FormatToken)] = orBlock(tree) + ): Option[(FT, Stat, FT)] = orBlock(tree) } } @@ -244,10 +244,9 @@ object TreeOps { case _ => None } - val ColonDeclTpeLeft = - new FormatToken.ExtractFromMeta(x => colonDeclType(x.leftOwner)) + val ColonDeclTpeLeft = new FT.ExtractFromMeta(x => colonDeclType(x.leftOwner)) val ColonDeclTpeRight = - new FormatToken.ExtractFromMeta(x => colonDeclType(x.rightOwner)) + new FT.ExtractFromMeta(x => colonDeclType(x.rightOwner)) def isParamClauseSite(tree: Tree): Boolean = tree match { case _: Type.ParamClause => !tree.parent.is[Type.Lambda] @@ -306,7 +305,7 @@ object TreeOps { case _ => false } - val DefValAssignLeft = new FormatToken.ExtractFromMeta(_.leftOwner match { + val DefValAssignLeft = new FT.ExtractFromMeta(_.leftOwner match { case _: Enumerator => None // it's WithBody case t: Ctor.Secondary => Some(t.body.init) case t: Tree.WithBody => Some(t.body) @@ -678,7 +677,7 @@ object TreeOps { } // Redundant {} block around case statements - def isCaseBodyABlock(ft: FormatToken, caseStat: CaseTree): Boolean = ft.right + def isCaseBodyABlock(ft: FT, caseStat: CaseTree): Boolean = ft.right .is[T.LeftBrace] && (caseStat.body eq ft.meta.rightOwner) def getTemplateGroups(template: Template): Option[Seq[List[Tree]]] = { @@ -697,7 +696,7 @@ object TreeOps { // try to add them in the TrainingCommas.always branch. def rightIsCloseDelimForTrailingComma( left: T, - ft: FormatToken, + ft: FT, whenNL: Boolean = true, ): Boolean = { def owner = ft.meta.rightOwner @@ -860,17 +859,15 @@ object TreeOps { (initStyle, ownersMap.result()) } - val ParamClauseParentLeft = - new FormatToken.ExtractFromMeta(_.leftOwner match { - case ParamClauseParent(p) => Some(p) - case _ => None - }) + val ParamClauseParentLeft = new FT.ExtractFromMeta(_.leftOwner match { + case ParamClauseParent(p) => Some(p) + case _ => None + }) - val LambdaAtSingleArgCallSite = - new FormatToken.ExtractFromMeta(_.leftOwner match { - case Term.ArgClause((fun: Term.FunctionTerm) :: Nil, _) => Some(fun) - case _ => None - }) + val LambdaAtSingleArgCallSite = new FT.ExtractFromMeta(_.leftOwner match { + case Term.ArgClause((fun: Term.FunctionTerm) :: Nil, _) => Some(fun) + case _ => None + }) def isFewerBraces( tree: Term.Apply,