Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Policy: add special single-token policy #4604

Merged
merged 1 commit into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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