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

Router: implement align.beforeOpenParenXxxSite #3052

Merged
merged 3 commits into from
Jan 13, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,19 @@ object a {
}
```

### `align.beforeOpenParenXxxSite`

Aligns parameter groups (not parameters within a group) if using
[`newlines.beforeOpenParenXxxSite`](#newlinesbeforeopenparenxxxsite).
Requires [`align.closeParenSite`](#aligncloseparensite).

> Since v3.3.2.

```scala mdoc:defaults
align.beforeOpenParenCallSite
align.beforeOpenParenDefnSite
```

### `align.stripMargin`

See [assumeStandardLibraryStripMargin](#assumestandardlibrarystripmargin).
Expand Down Expand Up @@ -2068,6 +2081,9 @@ Additional nuances:
- if the corresponding `align.openParenXxxSite` is true, multi-line parameters
will start on the same line as the opening parenthesis and align; otherwise,
formatting will use a newline and an appropriate continuation indent.
- if the corresponding [`align.beforeOpenParenXxxSite`](#alignbeforeopenparenxxxsite)
is true, when the first parameter group starts without a line break, subsequent
parameter groups will be aligned to it.

```scala mdoc:defaults
newlines.beforeOpenParenDefnSite
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ case class Align(
private val openBracketDefnSite: Option[Boolean] = None,
openParenDefnSite: Boolean = false,
private[config] val openParenTupleSite: Option[Boolean] = None,
beforeOpenParenDefnSite: Boolean = false,
beforeOpenParenCallSite: Boolean = false,
tokens: Seq[AlignToken] = Seq(AlignToken.caseArrow),
arrowEnumeratorGenerator: Boolean = false,
tokenCategory: Map[String, String] = Map(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,8 @@ object ScalafmtConfig {
addIf(rewrite.insertBraces.minLines != 0 && rewrite.scala3.removeOptionalBraces == RemoveOptionalBraces.oldSyntaxToo)
if (rewrite.insertBraces.minLines != 0 && rewrite.rules.contains(RedundantBraces))
addIf(rewrite.insertBraces.minLines < rewrite.redundantBraces.maxBreaks)
addIf(align.beforeOpenParenDefnSite && !align.closeParenSite)
addIf(align.beforeOpenParenCallSite && !align.closeParenSite)
}
// scalafmt: {}
if (allErrors.isEmpty) Configured.ok(cfg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1600,7 +1600,7 @@ class FormatOps(

private def getOpenNLByTree(
fun: Tree,
argsOrArgss: Either[Seq[Tree], Seq[Seq[Tree]]],
argsOrArgss: CallArgs,
penalty: Int
): Seq[Policy] = {
val argss = argsOrArgss match {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.scalafmt.internal

import org.scalafmt.Error.UnexpectedTree
import org.scalafmt.config.BinPack
import org.scalafmt.config.{Align, BinPack}
import org.scalafmt.config.{ImportSelectors, Newlines, ScalafmtConfig, Spaces}
import org.scalafmt.internal.ExpiresOn.{After, Before}
import org.scalafmt.internal.Length.{Num, StateColumn}
Expand Down Expand Up @@ -622,11 +622,17 @@ class Router(formatOps: FormatOps) {
val beforeDefRhs = defRhs.flatMap(tokens.tokenJustBeforeOpt)
def getSplitsBeforeOpenParen(
src: Newlines.SourceHints,
indentLen: Int
) = {
indentLen: Int,
shouldAlignBefore: Align => Boolean
)(getArgsOpt: => Option[Seq[Tree]]) = {
val close = matching(open)
val indent = Indent(indentLen, close, ExpiresOn.After)
src match {
val isAlignFirstParen = shouldAlignBefore(style.align) &&
!prevNonComment(ft).left.is[T.RightParen]
def noSplitSplit(implicit fileLine: FileLine) =
if (isAlignFirstParen) Split(NoSplit, 0)
else Split(NoSplit, 0).withSingleLine(close)
val splits = src match {
case Newlines.unfold =>
val slbEnd =
if (defn) beforeDefRhs.fold(getLastToken(rightOwner))(_.left)
Expand Down Expand Up @@ -657,7 +663,7 @@ class Router(formatOps: FormatOps) {
Seq(Split(Newline, 0).withIndent(indent))
else
Seq(
Split(NoSplit, 0).withSingleLine(close),
noSplitSplit,
Split(Newline, 1).withIndent(indent)
)
case _ =>
Expand All @@ -672,12 +678,22 @@ class Router(formatOps: FormatOps) {
}
}
Seq(
Split(NoSplit, 0).withSingleLine(close),
noSplitSplit,
Split(Newline, 1)
.withIndent(indent)
.withPolicyOpt(nlColonPolicy)
)
}
val argsOpt = if (isAlignFirstParen) getArgsOpt else None
argsOpt.map(x => tokens.tokenAfter(x).right).fold(splits) { x =>
val noSplitIndents = Seq(
Indent(StateColumn, x, ExpiresOn.Before),
Indent(-indentLen, x, ExpiresOn.Before)
)
splits.map { s =>
if (s.isNL) s else s.withIndents(noSplitIndents)
}
}
}
val beforeOpenParenSplits =
if (!open.is[T.LeftParen]) None
Expand All @@ -692,12 +708,31 @@ class Router(formatOps: FormatOps) {
style.indent.extraBeforeOpenParenDefnSite +
(if (ob) style.indent.getSignificant else style.indent.main)
}
getSplitsBeforeOpenParen(x, indent)
getSplitsBeforeOpenParen(x, indent, _.beforeOpenParenDefnSite) {
rightOwner match {
case SplitDefnIntoParts(_, _, _, args) => Some(args.last)
case _ => None
}
}
}
else if (style.dialect.allowSignificantIndentation)
style.newlines.getBeforeOpenParenCallSite.map(
getSplitsBeforeOpenParen(_, style.indent.getSignificant)
)
style.newlines.getBeforeOpenParenCallSite.map { x =>
val indent = style.indent.getSignificant
@tailrec
def findLastCallArgs(tree: Tree, ca: CallArgs): CallArgs =
tree match {
case SplitCallIntoParts(_, pca) =>
tree.parent match {
case Some(p) => findLastCallArgs(p, pca)
case _ => pca
}
case _ => ca
}
getSplitsBeforeOpenParen(x, indent, _.beforeOpenParenCallSite) {
Option(findLastCallArgs(rightOwner, null))
.map(_.fold(identity, _.last))
}
}
else None
beforeOpenParenSplits.getOrElse(Seq(Split(modification, 0)))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ object TreeOps {
case _ => false
}

type CallParts = (Tree, Either[Seq[Tree], Seq[Seq[Tree]]])
type CallArgs = Either[Seq[Tree], Seq[Seq[Tree]]]
type CallParts = (Tree, CallArgs)
val splitCallIntoParts: PartialFunction[Tree, CallParts] = {
case t: Term.Apply => (t.fun, Left(t.args))
case t: Term.Super => (t, Left(Seq(t.superp)))
Expand Down
31 changes: 31 additions & 0 deletions scalafmt-tests/src/test/resources/newlines/source_classic.stat
Original file line number Diff line number Diff line change
Expand Up @@ -5679,3 +5679,34 @@ object a {
}
else doSomethingOtherwise()
}
<<< align.beforeOpenParenDefnSite
maxColumn = 100
align.closeParenSite = true
align.beforeOpenParenDefnSite = true
newlines.beforeOpenParenDefnSite = source
===
def allMatching(versionString: String)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {

}
>>>
def allMatching(versionString: String)
(partialFunctions: PartialFunction[options.Common, List[String]]*)
: List[String] = {}
<<< align.beforeOpenParenDefnSite + align.openParenDefnSite
maxColumn = 85
danglingParentheses.defnSite = false
align.closeParenSite = true
align.openParenDefnSite = true
align.beforeOpenParenDefnSite = true
newlines.beforeOpenParenDefnSite = source
===
def allMatching(versionString: String, partialFunctions: PartialFunction[options.Common, List[String]]*)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {

}
>>>
def allMatching(versionString: String,
partialFunctions: PartialFunction[options.Common, List[String]]*)
(partialFunctions: PartialFunction[options.Common, List[String]]*)
: List[String] = {}
31 changes: 31 additions & 0 deletions scalafmt-tests/src/test/resources/newlines/source_fold.stat
Original file line number Diff line number Diff line change
Expand Up @@ -5438,3 +5438,34 @@ object a {
}
else doSomethingOtherwise()
}
<<< align.beforeOpenParenDefnSite
maxColumn = 100
align.closeParenSite = true
align.beforeOpenParenDefnSite = true
newlines.beforeOpenParenDefnSite = source
===
def allMatching(versionString: String)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {

}
>>>
def allMatching(versionString: String)
(partialFunctions: PartialFunction[options.Common, List[String]]*)
: List[String] = {}
<<< align.beforeOpenParenDefnSite + align.openParenDefnSite
maxColumn = 85
danglingParentheses.defnSite = false
align.closeParenSite = true
align.openParenDefnSite = true
align.beforeOpenParenDefnSite = true
newlines.beforeOpenParenDefnSite = source
===
def allMatching(versionString: String, partialFunctions: PartialFunction[options.Common, List[String]]*)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {

}
>>>
def allMatching(versionString: String,
partialFunctions: PartialFunction[options.Common, List[String]]*)
(partialFunctions: PartialFunction[options.Common, List[String]]*)
: List[String] = {}
30 changes: 30 additions & 0 deletions scalafmt-tests/src/test/resources/newlines/source_keep.stat
Original file line number Diff line number Diff line change
Expand Up @@ -5698,3 +5698,33 @@ object a {
}
else doSomethingOtherwise()
}
<<< align.beforeOpenParenDefnSite
maxColumn = 100
align.closeParenSite = true
align.beforeOpenParenDefnSite = true
newlines.beforeOpenParenDefnSite = source
===
def allMatching(versionString: String)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {

}
>>>
def allMatching(versionString: String)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {}
<<< align.beforeOpenParenDefnSite + align.openParenDefnSite
maxColumn = 85
danglingParentheses.defnSite = false
align.closeParenSite = true
align.openParenDefnSite = true
align.beforeOpenParenDefnSite = true
newlines.beforeOpenParenDefnSite = source
===
def allMatching(versionString: String, partialFunctions: PartialFunction[options.Common, List[String]]*)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {

}
>>>
def allMatching(versionString: String,
partialFunctions: PartialFunction[options.Common, List[String]]*)
(partialFunctions: PartialFunction[options.Common, List[String]]*)
: List[String] = {}
33 changes: 33 additions & 0 deletions scalafmt-tests/src/test/resources/newlines/source_unfold.stat
Original file line number Diff line number Diff line change
Expand Up @@ -5949,3 +5949,36 @@ object a {
else
doSomethingOtherwise()
}
<<< align.beforeOpenParenDefnSite
maxColumn = 100
align.closeParenSite = true
align.beforeOpenParenDefnSite = true
newlines.beforeOpenParenDefnSite = source
===
def allMatching(versionString: String)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {

}
>>>
def allMatching
(versionString: String)
(partialFunctions: PartialFunction[options.Common, List[String]]*)
: List[String] = {}
<<< align.beforeOpenParenDefnSite + align.openParenDefnSite
maxColumn = 85
danglingParentheses.defnSite = false
align.closeParenSite = true
align.openParenDefnSite = true
align.beforeOpenParenDefnSite = true
newlines.beforeOpenParenDefnSite = source
===
def allMatching(versionString: String, partialFunctions: PartialFunction[options.Common, List[String]]*)
(partialFunctions: PartialFunction[options.Common, List[String]]*): List[String] = {

}
>>>
def allMatching
(versionString: String,
partialFunctions: PartialFunction[options.Common, List[String]]*)
(partialFunctions: PartialFunction[options.Common, List[String]]*)
: List[String] = {}
24 changes: 24 additions & 0 deletions scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat
Original file line number Diff line number Diff line change
Expand Up @@ -3288,3 +3288,27 @@ object a:
do matrix(x)(0) += matrix(x - 1)(0)
while x < range
do matrix(x)(0) += matrix(x - 1)(0)
<<< align.beforeOpenParenCallSite
maxColumn = 30
align.closeParenSite = true
align.beforeOpenParenCallSite = true
newlines.beforeOpenParenCallSite = source
===
allMatching(versionString)
(partialFunctions)
>>>
allMatching(versionString)
(partialFunctions)
<<< align.beforeOpenParenCallSite + align.openParenCallSite
maxColumn = 30
align.closeParenSite = true
align.openParenCallSite = true
align.beforeOpenParenCallSite = true
newlines.beforeOpenParenCallSite = source
===
allMatching(versionString, partialFunctions)
(partialFunctions)
>>>
allMatching(versionString,
partialFunctions
)(partialFunctions)
24 changes: 24 additions & 0 deletions scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat
Original file line number Diff line number Diff line change
Expand Up @@ -3131,3 +3131,27 @@ object a:
matrix(x)(0) += matrix(x - 1)(0)
while x < range do
matrix(x)(0) += matrix(x - 1)(0)
<<< align.beforeOpenParenCallSite
maxColumn = 30
align.closeParenSite = true
align.beforeOpenParenCallSite = true
newlines.beforeOpenParenCallSite = source
===
allMatching(versionString)
(partialFunctions)
>>>
allMatching(versionString)
(partialFunctions)
<<< align.beforeOpenParenCallSite + align.openParenCallSite
maxColumn = 30
align.closeParenSite = true
align.openParenCallSite = true
align.beforeOpenParenCallSite = true
newlines.beforeOpenParenCallSite = source
===
allMatching(versionString, partialFunctions)
(partialFunctions)
>>>
allMatching(versionString,
partialFunctions
)(partialFunctions)
25 changes: 25 additions & 0 deletions scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat
Original file line number Diff line number Diff line change
Expand Up @@ -3276,3 +3276,28 @@ object a:
x < range
do
matrix(x)(0) += matrix(x - 1)(0)
<<< align.beforeOpenParenCallSite
maxColumn = 30
align.closeParenSite = true
align.beforeOpenParenCallSite = true
newlines.beforeOpenParenCallSite = source
===
allMatching(versionString)
(partialFunctions)
>>>
allMatching(versionString)
(partialFunctions)
<<< align.beforeOpenParenCallSite + align.openParenCallSite
maxColumn = 30
align.closeParenSite = true
align.openParenCallSite = true
align.beforeOpenParenCallSite = true
newlines.beforeOpenParenCallSite = source
===
allMatching(versionString, partialFunctions)
(partialFunctions)
>>>
allMatching(versionString,
partialFunctions
)
(partialFunctions)