Skip to content
New issue

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

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

Already on GitHub? # to your account

ConvertToNewScala3Syntax: use the new granular parameter #3735

Merged
merged 2 commits into from
Dec 28, 2023
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
13 changes: 12 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -3605,18 +3605,29 @@ This section describes rules which are applied if the appropriate dialect (e.g.,

### `rewrite.scala3.convertToNewSyntax`

If this flag is enabled, the following new syntax will be applied:
If this flag is enabled, the following new syntax will be applied (also,
**since 3.8.0**, if an appropriate flag under `rewrite.scala.newSyntax` is not
set to `false`, see below):

- [control syntax](https://dotty.epfl.ch/docs/reference/other-new-features/control-syntax.html)
- if dialect sets `allowSignificantIndentation`
(any scala3 dialect) and `...newSyntax.control` is set
- `if (...)` to `if ... then`
- `while (...)` to `while ... do`
- `for (...)` to `for ... do` (or `for (...) yield` to `for ... yield`)
- [vararg splices](https://dotty.epfl.ch/docs/reference/changed-features/vararg-splices.html)
- vararg `: _*` or `@ _*` to `*` if dialect sets `allowPostfixStarVarargSplices`
(any scala3, or scala2xxSource3) and `...newSyntax.deprecated` is set
- [imports](https://dotty.epfl.ch/docs/reference/changed-features/imports.html)
- import wildcard `_` to `*` if dialect sets `allowStarWildcardImport`
(any scala3, or scala2xxSource3) and `...newSyntax.deprecated` is set
- import rename `=>` to `as` if dialect sets `allowAsForImportRename`
(any scala3, or scala2xxSource3) and `...newSyntax.deprecated` is set
- [wildcards](https://docs.scala-lang.org/scala3/reference/changed-features/wildcards.html)
- type wildcard `_` to `?` if dialect sets `allowQuestionMarkAsTypeWildcard`
(scala212 and later) and `...newSyntax.deprecated` is set
- anonymous type param `*` to `_` if dialect sets `allowUnderscoreAsTypePlaceholder`
(scala3Future only) and `...newSyntax.deprecated` is set

NB: You could control these rules individually by
[overriding dialect properties](#runnerdialectoverride).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import metaconfig._

case class RewriteScala3Settings(
convertToNewSyntax: Boolean = false,
newSyntax: ConvertToNewSyntax = ConvertToNewSyntax.default,
removeOptionalBraces: RemoveOptionalBraces = RemoveOptionalBraces.no,
countEndMarkerLines: RewriteScala3Settings.EndMarkerLines =
RewriteScala3Settings.EndMarkerLines.all,
Expand All @@ -24,7 +25,10 @@ object RewriteScala3Settings {
implicit val decodec: ConfDecoderEx[RewriteScala3Settings] = Presets
.mapDecoder(generic.deriveDecoderEx(default).noTypos, "rewrite.scala3") {
case Conf.Bool(true) =>
new RewriteScala3Settings(true, RemoveOptionalBraces.yes)
new RewriteScala3Settings(
convertToNewSyntax = true,
removeOptionalBraces = RemoveOptionalBraces.yes
)
case Conf.Bool(false) => default
}

Expand Down Expand Up @@ -56,4 +60,24 @@ object RewriteScala3Settings {

}

case class ConvertToNewSyntax(
// https://dotty.epfl.ch/docs/reference/other-new-features/control-syntax.html
control: Boolean = true,
// https://dotty.epfl.ch/docs/reference/changed-features/vararg-splices.html
// https://dotty.epfl.ch/docs/reference/changed-features/imports.html
// https://dotty.epfl.ch/docs/reference/changed-features/wildcards.html
deprecated: Boolean = true
)

private object ConvertToNewSyntax {

val default = new ConvertToNewSyntax

implicit val surface: generic.Surface[ConvertToNewSyntax] =
generic.deriveSurface
implicit val codec: ConfCodecEx[ConvertToNewSyntax] =
generic.deriveCodecEx(default).noTypos

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 +32,41 @@ private class ConvertToNewScala3Syntax(ftoks: FormatTokens)
ft: FormatToken,
style: ScalafmtConfig
): Option[Replacement] = Option {
val flag = style.rewrite.scala3.newSyntax
def left = ftoks.prevNonComment(ft).left
ft.right match {

case _: Token.LeftParen if dialect.allowSignificantIndentation =>
case _: Token.LeftParen
if flag.control && dialect.allowSignificantIndentation =>
ft.meta.rightOwner match {
case _: Term.If if ftoks.prevNonComment(ft).left.is[Token.KwIf] =>
case _: Term.If if left.is[Token.KwIf] =>
removeToken
case _: Term.While
if ftoks.prevNonComment(ft).left.is[Token.KwWhile] =>
case _: Term.While if left.is[Token.KwWhile] =>
removeToken
case _: Term.For if ftoks.prevNonComment(ft).left.is[Token.KwFor] =>
case _: Term.For if left.is[Token.KwFor] =>
removeToken
case _: Term.ForYield
if ftoks.prevNonComment(ft).left.is[Token.KwFor] =>
case _: Term.ForYield if left.is[Token.KwFor] =>
removeToken
case _ => null
}

case _: Token.Colon if dialect.allowPostfixStarVarargSplices =>
case _: Token.Colon
if flag.deprecated && dialect.allowPostfixStarVarargSplices =>
ft.meta.rightOwner match {
case t: Term.Repeated if isSimpleRepeated(t) =>
removeToken // trick: to get "*", just remove ":" and "_"
case _ => null
}

case _: Token.At if dialect.allowPostfixStarVarargSplices =>
case _: Token.At
if flag.deprecated && dialect.allowPostfixStarVarargSplices =>
ft.meta.rightOwner match {
case Pat.Bind(_, _: Pat.SeqWildcard) =>
removeToken // trick: to get "*", just remove "@" and "_"
case _ => null
}

case _: Token.Underscore =>
case _: Token.Underscore if flag.deprecated =>
ft.meta.rightOwner match {
case _: Importee.Wildcard if dialect.allowStarWildcardImport =>
replaceTokenIdent("*", ft.right)
Expand All @@ -81,14 +84,15 @@ private class ConvertToNewScala3Syntax(ftoks: FormatTokens)
case _ => null
}

case _: Token.RightArrow if dialect.allowAsForImportRename =>
case _: Token.RightArrow
if flag.deprecated && dialect.allowAsForImportRename =>
ft.meta.rightOwner match {
case _: Importee.Rename | _: Importee.Unimport =>
replaceTokenIdent("as", ft.right)
case _ => null
}

case Token.Ident("*") =>
case Token.Ident("*") if flag.deprecated =>
ft.meta.rightOwner match {
case _: Type.AnonymousParam
if dialect.allowUnderscoreAsTypePlaceholder =>
Expand All @@ -106,18 +110,19 @@ private class ConvertToNewScala3Syntax(ftoks: FormatTokens)
ft: FormatToken,
style: ScalafmtConfig
): Option[(Replacement, Replacement)] = Option {
def nextRight = ftoks.nextNonComment(ftoks.next(ft)).right
ft.right match {

case x: Token.RightParen if left.how eq ReplacementType.Remove =>
ft.meta.rightOwner match {
case _: Term.If =>
if (!ftoks.nextNonComment(ftoks.next(ft)).right.is[Token.KwThen])
if (!nextRight.is[Token.KwThen])
replaceToken("then")(
new Token.KwThen(x.input, x.dialect, x.start)
)
else removeToken
case _: Term.While | _: Term.For =>
if (!ftoks.nextNonComment(ftoks.next(ft)).right.is[Token.KwDo])
if (!nextRight.is[Token.KwDo])
replaceToken("do")(new Token.KwDo(x.input, x.dialect, x.start))
else removeToken
case _ => null
Expand Down
38 changes: 33 additions & 5 deletions scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat
Original file line number Diff line number Diff line change
Expand Up @@ -1206,8 +1206,8 @@ rewrite.scala3.removeOptionalBraces = yes
===
object a {
val a = {
if (a) { // scalafmt: { rewrite.scala3.convertToNewSyntax = false }
if (aa) { // scalafmt: { rewrite.scala3.convertToNewSyntax = true }
if (a) { // scalafmt: { rewrite.scala3.newSyntax.control = false }
if (aa) { // scalafmt: { rewrite.scala3.newSyntax.control = true }
aaa
} // c1
} else {
Expand All @@ -1234,10 +1234,10 @@ object a {
>>>
object a:
val a =
if a then // scalafmt: { rewrite.scala3.convertToNewSyntax = false }
if (aa) { // scalafmt: { rewrite.scala3.convertToNewSyntax = true }
if a then // scalafmt: { rewrite.scala3.newSyntax.control = false }
if (aa) // scalafmt: { rewrite.scala3.newSyntax.control = true }
aaa
} // c1
// c1
else b
val a =
if a then // scalafmt: { rewrite.scala3.convertToNewSyntax = false }
Expand Down Expand Up @@ -1270,11 +1270,25 @@ object a {
foo
}
}
// scalafmt: { rewrite.scala3.newSyntax.control = false }
while (a > 0) {
while (a > 0) do {
foo
}
}
// scalafmt: { rewrite.scala3.newSyntax.control = true }
for (a <- b) {
for (a <- b) do {
foo
}
}
// scalafmt: { rewrite.scala3.newSyntax.control = false }
for (a <- b) do {
for (a <- b) {
foo
}
}
// scalafmt: { rewrite.scala3.newSyntax.control = true }
for {a <- b} {
for {a <- b} do {
foo
Expand All @@ -1285,8 +1299,18 @@ object a {
object a:
for (a <- b) yield for a <- b yield foo
while a > 0 do while a > 0 do foo
// scalafmt: { rewrite.scala3.newSyntax.control = false }
while (a > 0)
while a > 0 do foo
// scalafmt: { rewrite.scala3.newSyntax.control = true }
for a <- b do for a <- b do foo
// scalafmt: { rewrite.scala3.newSyntax.control = false }
for (a <- b) do
for (a <- b)
foo
// scalafmt: { rewrite.scala3.newSyntax.control = true }
for a <- b do for a <- b do foo
end a
<<< rewrite to new syntax with for-do, multiple
runner.parser = source
rewrite.scala3.insertEndMarkerMinLines = 6
Expand Down Expand Up @@ -1381,13 +1405,17 @@ object a:
import scala.{annotation => ann}
import java as j
import Predef.{augmentString => _}
// scalafmt: { rewrite.scala3.newSyntax.deprecated = false }
import Predef.{augmentString => _}
>>>
object a:
import A.{min as minimum, `*` as multiply}
import Predef.{augmentString as _, *}
import scala.{annotation as ann}
import java as j
import Predef.{augmentString as _}
// scalafmt: { rewrite.scala3.newSyntax.deprecated = false }
import Predef.{augmentString => _}
<<< rewrite to new syntax, imports, scala2-source3
rewrite.scala3.convertToNewSyntax = true
rewrite.scala3.removeOptionalBraces = yes
Expand Down
35 changes: 30 additions & 5 deletions scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat
Original file line number Diff line number Diff line change
Expand Up @@ -1133,8 +1133,8 @@ rewrite.scala3.removeOptionalBraces = yes
===
object a {
val a = {
if (a) { // scalafmt: { rewrite.scala3.convertToNewSyntax = false }
if (aa) { // scalafmt: { rewrite.scala3.convertToNewSyntax = true }
if (a) { // scalafmt: { rewrite.scala3.newSyntax.control = false }
if (aa) { // scalafmt: { rewrite.scala3.newSyntax.control = true }
aaa
} // c1
} else {
Expand All @@ -1161,10 +1161,10 @@ object a {
>>>
object a:
val a =
if a then // scalafmt: { rewrite.scala3.convertToNewSyntax = false }
if (aa) { // scalafmt: { rewrite.scala3.convertToNewSyntax = true }
if a then // scalafmt: { rewrite.scala3.newSyntax.control = false }
if (aa) // scalafmt: { rewrite.scala3.newSyntax.control = true }
aaa
} // c1
// c1
else b
val a =
if a then // scalafmt: { rewrite.scala3.convertToNewSyntax = false }
Expand Down Expand Up @@ -1197,11 +1197,25 @@ object a {
foo
}
}
// scalafmt: { rewrite.scala3.newSyntax.control = false }
while (a > 0) {
while (a > 0) do {
foo
}
}
// scalafmt: { rewrite.scala3.newSyntax.control = true }
for (a <- b) {
for (a <- b) do {
foo
}
}
// scalafmt: { rewrite.scala3.newSyntax.control = false }
for (a <- b) do {
for (a <- b) {
foo
}
}
// scalafmt: { rewrite.scala3.newSyntax.control = true }
for {a <- b} {
for {a <- b} do {
foo
Expand All @@ -1212,8 +1226,15 @@ object a {
object a:
for (a <- b) yield for a <- b yield foo
while a > 0 do while a > 0 do foo
// scalafmt: { rewrite.scala3.newSyntax.control = false }
while (a > 0) while a > 0 do foo
// scalafmt: { rewrite.scala3.newSyntax.control = true }
for a <- b do for a <- b do foo
// scalafmt: { rewrite.scala3.newSyntax.control = false }
for (a <- b) do for (a <- b) foo
// scalafmt: { rewrite.scala3.newSyntax.control = true }
for a <- b do for a <- b do foo
end a
<<< rewrite to new syntax with for-do, multiple
runner.parser = source
rewrite.scala3.insertEndMarkerMinLines = 6
Expand Down Expand Up @@ -1308,13 +1329,17 @@ object a:
import scala.{annotation => ann}
import java as j
import Predef.{augmentString => _}
// scalafmt: { rewrite.scala3.newSyntax.deprecated = false }
import Predef.{augmentString => _}
>>>
object a:
import A.{min as minimum, `*` as multiply}
import Predef.{augmentString as _, *}
import scala.{annotation as ann}
import java as j
import Predef.{augmentString as _}
// scalafmt: { rewrite.scala3.newSyntax.deprecated = false }
import Predef.{augmentString => _}
<<< rewrite to new syntax, imports, scala2-source3
rewrite.scala3.convertToNewSyntax = true
rewrite.scala3.removeOptionalBraces = yes
Expand Down
Loading
Loading