Skip to content

Commit

Permalink
Policy: add special single-token policy
Browse files Browse the repository at this point in the history
  • Loading branch information
kitbellew committed Nov 27, 2024
1 parent 2ae3560 commit c035ada
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ class FormatOps(
implicit fileLine: FileLine,
): Policy = Policy ? (comma.right.is[T.Comment] && comma.noBreak) ||
delayedBreakPolicy(Policy.End < comma, exclude) {
Policy.onRight(comma, prefix = "NL->A[,]") { case Decision(`comma`, ss) =>
getOneArgPerLineSplitsAfterComma(comma.right, ss)
Policy.onlyFor(comma, prefix = "NL->A[,]") {
getOneArgPerLineSplitsAfterComma(comma.right, _)
}
}

Expand Down Expand Up @@ -292,10 +292,9 @@ class FormatOps(
getTemplateGroups(template).flatMap(iter)
}

def getBreakBeforeElsePolicy(beforeElse: FT): Policy = Policy.End <=
beforeElse ==> Policy.onRight(beforeElse, prefix = "ELSE") {
case d @ Decision(`beforeElse`, _) => d
.onlyNewlinesWithFallback(Split(Newline, 0))
def getBreakBeforeElsePolicy(beforeElse: FT): Policy = Policy
.onlyFor(beforeElse, prefix = "ELSE") {
Decision.onlyNewlinesWithFallback(_, Seq(Split(Newline, 0)))
}

def getBreakBeforeElsePolicy(term: Term.If): Policy = getElseToken(term)
Expand Down Expand Up @@ -1620,8 +1619,7 @@ class FormatOps(
val split = nlSplitFunc(0).forThisLine
Seq(if (rhsIsCommentedOut(nextFt)) split.withNoIndent else split)
}
val policy = Policy
.onRight(nextFt, "CBCMT") { case Decision(`nextFt`, _) => splits }
val policy = Policy.onlyFor(nextFt, "CBCMT")(_ => splits)
Seq(Split(Space, 0, policy = policy))
}

Expand Down Expand Up @@ -2731,10 +2729,8 @@ class FormatOps(

def noNLPolicy(): Policy = {
def close = next(ftBeforeClose)
if (scalaJsStyle)
Policy(Policy.End >= ftBeforeClose, prefix = "tuckSJS") {
case Decision(`ftBeforeClose`, ss) => Decision.noNewlineSplits(ss)
}
if (scalaJsStyle) Policy
.onlyFor(ftBeforeClose, prefix = "tuckSJS")(Decision.noNewlineSplits)
else style.newlines.source match {
case Newlines.keep if closeBreak => decideNewlinesOnlyBeforeClose(close)
case Newlines.fold
Expand Down Expand Up @@ -2877,10 +2873,9 @@ class FormatOps(
findLastApplyAndNextSelect(x.tree, cfg.encloseSelectChains)
Right(canStartSelectChain(x, nextSelect, expireTree))
case Newlines.keep =>
Left(Policy.onRight(afterDelims, "BP1L.NL") {
case Decision(`afterDelims`, ss) => Decision
.onlyNewlineSplits(ss)
.map(_.preActivateFor(SplitTag.SelectChainBinPackNL))
Left(Policy.onlyFor(afterDelims, "BP1L.NL") {
Decision.onlyNewlineSplits(_)
.map(_.preActivateFor(SplitTag.SelectChainBinPackNL))
})
case _ => Right(true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ object Policy {
)(f: Pf)(implicit fileLine: FileLine): Policy =
apply(End > exp, prefix, noDequeue, rank)(f)

def onlyFor(on: FT, prefix: String, noDequeue: Boolean = false, rank: Int = 0)(
f: Seq[Split] => Seq[Split],
)(implicit fileLine: FileLine): Policy = Policy.End <= on ==>
Policy.onRight(on, s"$prefix[${on.idx}]", noDequeue, rank) {
case Decision(`on`, ss) => f(ss)
}

abstract class Clause(implicit val fileLine: FileLine) extends Policy {
val endPolicy: End.WithPos
def prefix: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,11 +394,9 @@ class Router(formatOps: FormatOps) {
// copy logic from `( ...`, binpack=never, defining `slbSplit`
val slbParensPolicy = Policy ? (slbMod eq noSplitMod) || {
val beforeClose = prev(close)
Policy.End <= beforeClose ==>
Policy.onRight(beforeClose, "BracesToParens") {
case Decision(`beforeClose`, ss) => ss
.flatMap(s => if (s.isNL) None else Some(s.withMod(NoSplit)))
}
Policy.onlyFor(beforeClose, "BracesToParens") {
_.flatMap(s => if (s.isNL) None else Some(s.withMod(NoSplit)))
}
}
val exclude = slbParensExclude.getOrElse(TokenRanges.empty)
val slbPolicy =
Expand All @@ -411,15 +409,12 @@ class Router(formatOps: FormatOps) {
val pend = getSlbEndOnLeft(getLast(p))
def pendSlb(s: Split) = s
.withSingleLine(pend, noSyntaxNL = true, extend = true)
Policy.End <= close ==>
Policy.onRight(close, s"RB-ELSE[${pend.idx}]") {
case Decision(`close`, ss) =>
if (ss.exists(_.isNL)) ss
.map(s => if (s.isNL) s else pendSlb(s))
else ss.flatMap { s =>
Seq(pendSlb(s), s.withMod(Newline).withPenalty(1))
}
Policy.onlyFor(close, s"RB-ELSE[${pend.idx}]") { ss =>
if (ss.exists(_.isNL)) ss.map(s => if (s.isNL) s else pendSlb(s))
else ss.flatMap { s =>
Seq(pendSlb(s), s.withMod(Newline).withPenalty(1))
}
}
} else decideNewlinesOnlyAfterClose(close)
}
Split(slbMod, 0).withSingleLine(
Expand Down Expand Up @@ -476,16 +471,16 @@ class Router(formatOps: FormatOps) {
val (mod, policy) = singleLineSplitOpt match {
case Some(slbSplit) if singleLineSplit.isIgnored =>
val arrSplit = slbSplit.withMod(Space)
slbMod -> Policy.onRight(lambdaExpire, s"FNARR($arrSplit)") {
case Decision(`lambdaExpire`, ss) =>
var hadNoSplit = false
val nlSplits = ss.flatMap { s =>
// penalize NL one extra, for closing brace
if (s.isNL)
Some(s.andPolicy(nlPolicy).withPenalty(nlArrowPenalty))
else { hadNoSplit = true; None }
}
if (hadNoSplit) arrSplit +: nlSplits else nlSplits
val fnarrDesc = s"FNARR($nlArrowPenalty;$arrSplit)"
slbMod -> Policy.onlyFor(lambdaExpire, fnarrDesc) { ss =>
var hadNoSplit = false
val nlSplits = ss.flatMap { s =>
// penalize NL one extra, for closing brace
if (s.isNL)
Some(s.andPolicy(nlPolicy).withPenalty(nlArrowPenalty))
else { hadNoSplit = true; None }
}
if (hadNoSplit) arrSplit +: nlSplits else nlSplits
}
case _ => noSplitMod ->
(decideNewlinesOnlyAfterToken(lambdaExpire) ==> nlPolicy)
Expand Down Expand Up @@ -905,12 +900,11 @@ class Router(formatOps: FormatOps) {
)

val spacePolicy = SingleLineBlock(lambdaToken) ==> {
def before = Policy.End < close ==> Policy.onLeft(close, "NODANGLE") {
case Decision(`beforeClose`, _) =>
val bc = beforeClose.left
if (bc.is[T.Comment])
if (bc.text.startsWith("//")) Nil else Seq(Split(Space, 0))
else Seq(Split(Space(style.spaces.inParentheses), 0))
def before = Policy.onlyFor(beforeClose, "NODANGLE") { _ =>
val bc = beforeClose.left
if (bc.is[T.Comment])
if (bc.text.startsWith("//")) Nil else Seq(Split(Space, 0))
else Seq(Split(Space(style.spaces.inParentheses), 0))
}
Policy ? lambdaIsABlock ||
Policy.RelayOnSplit.by(Policy.End <= lambdaLeft.getOrElse(close))(
Expand Down Expand Up @@ -1770,24 +1764,23 @@ class Router(formatOps: FormatOps) {

def forcedBreakOnNextDotPolicy(implicit fileLine: FileLine) =
beforeNextDotOpt.map(decideNewlinesOnlyAfterToken(_))
def getClassicNonFirstBreakOnDot(
dot: FT,
)(implicit fileLine: FileLine): Policy = Policy.End <= dot ==>
Policy.onRight(dot, "NEXTSEL2NL") { case Decision(`dot`, s) =>
val filtered = s.flatMap { x =>
val y = x.activateFor(SplitTag.SelectChainSecondNL)
if (y.isActive) Some(y) else None
}
if (filtered.isEmpty) Seq.empty
else {
val minCost = math.max(0, filtered.map(_.costWithPenalty).min - 1)
filtered.map { x =>
val p = x.policy.filter(!_.isInstanceOf[PenalizeAllNewlines])
implicit val fileLine = x.fileLineStack.fileLineHead
x.copy(penalty = x.costWithPenalty - minCost, policy = p)
}
def getClassicNonFirstBreakOnDot(dot: FT)(implicit
fileLine: FileLine,
): Policy = Policy.onlyFor(dot, "NEXTSEL2NL") { s =>
val filtered = s.flatMap { x =>
val y = x.activateFor(SplitTag.SelectChainSecondNL)
if (y.isActive) Some(y) else None
}
if (filtered.isEmpty) Seq.empty
else {
val minCost = math.max(0, filtered.map(_.costWithPenalty).min - 1)
filtered.map { x =>
val p = x.policy.filter(!_.isInstanceOf[PenalizeAllNewlines])
implicit val fileLine = x.fileLineStack.fileLineHead
x.copy(penalty = x.costWithPenalty - minCost, policy = p)
}
}
}
def classicNonFirstBreakOnNextDot(implicit fileLine: FileLine): Policy =
beforeNextDotOpt.map(getClassicNonFirstBreakOnDot)

Expand Down Expand Up @@ -2326,13 +2319,12 @@ class Router(formatOps: FormatOps) {
)
val lmod = NewlineT(noIndent = rhsIsCommentedOut(postParen))
val lsplit = Seq(Split(lmod, 0).withIndents(lindents))
val rsplit = Seq(Split(Newline, 0))
Policy.onRight(postParen, prefix = "CASE[(]") {
case Decision(`postParen`, _) => lsplit
// fires only if there's a comment between lparentFt and postParentFt
case Decision(`lparen`, _) => Seq(Split(Space, 0))
} ==> Policy.afterRight(rparen, prefix = "CASE[)]") {
case Decision(`rparen`, _) => rsplit
} ==> Policy.onlyFor(rparen, prefix = "CASE[)]") { _ =>
Seq(Split(Newline, 0))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ object PolicyOps {
))
}

def penalizeOneNewline(on: FT, penalty: Int)(implicit
fileLine: FileLine,
): Policy = Policy.onlyFor(on, s"PNL+$penalty")(_.penalizeNL(penalty))

def penalizeNewlineByNesting(before: FT, after: FT)(implicit
fileLine: FileLine,
): Policy = Policy.End < before ==> Policy.beforeLeft(after, prefix = "PNL()") {
Expand Down Expand Up @@ -256,12 +260,10 @@ object PolicyOps {
val unindent = Indent(indent, rt, ExpiresOn.After)
val triggeredIndent = Indent.before(unindent, trigger)
val triggerUnindent = Policy
.onLeft(rt, prefix = "UNIND{") { case Decision(`lt`, s) =>
s.map(_.withIndent(triggeredIndent))
}
.onlyFor(lt, prefix = "UNIND{")(_.map(_.withIndent(triggeredIndent)))
val cancelUnindent = delayedBreakPolicy(Policy.End <= lt) {
Policy.onRight(lt, rank = 1, prefix = "UNIND}") { // use rank to apply after policy above
case Decision(`lt`, s) => s.map(_.switch(trigger, false))
Policy.onlyFor(lt, rank = 1, prefix = "UNIND}") { // use rank to apply after policy above
_.map(_.switch(trigger, false))
}
}
policy ==> triggerUnindent & cancelUnindent
Expand Down

0 comments on commit c035ada

Please sign in to comment.