forked from scalameta/scalafmt
/
RemoveScala3OptionalBraces.scala
142 lines (127 loc) · 4.94 KB
/
RemoveScala3OptionalBraces.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package org.scalafmt.rewrite
import scala.meta._
import scala.meta.tokens.Token
import org.scalafmt.config.ScalafmtConfig
import org.scalafmt.internal.FormatToken
import org.scalafmt.internal.FormatTokens
import org.scalafmt.util.TreeOps
object RemoveScala3OptionalBraces extends FormatTokensRewrite.RuleFactory {
override def enabled(implicit style: ScalafmtConfig): Boolean =
style.dialect.allowSignificantIndentation &&
style.rewrite.scala3.removeOptionalBraces.enabled
override def create(implicit ftoks: FormatTokens): FormatTokensRewrite.Rule =
new RemoveScala3OptionalBraces
override def priority: Int = 1
}
private class RemoveScala3OptionalBraces(implicit val ftoks: FormatTokens)
extends FormatTokensRewrite.Rule {
import FormatTokensRewrite._
private def allowOldSyntax(implicit style: ScalafmtConfig): Boolean =
ConvertToNewScala3Syntax.enabled ||
style.rewrite.scala3.removeOptionalBraces.oldSyntaxToo
override def enabled(implicit style: ScalafmtConfig): Boolean =
RemoveScala3OptionalBraces.enabled
override def onToken(implicit
ft: FormatToken,
session: Session,
style: ScalafmtConfig
): Option[Replacement] = Option {
ft.right match {
case x: Token.LeftBrace // skip empty brace pairs
if !ftoks.nextNonComment(ftoks.next(ft)).right.is[Token.RightBrace] =>
ft.meta.rightOwner match {
case t: Term.Block if t.stats.nonEmpty => onLeftForBlock(t)
case t: Template if t.stats.nonEmpty || t.self.tokens.nonEmpty =>
if (t.parent.exists(_.is[Defn.Given])) removeToken
else
replaceToken(":")(new Token.Colon(x.input, x.dialect, x.start))
case _: Term.For if allowOldSyntax || {
val rbFt = ftoks(ftoks.matching(ft.right))
ftoks.nextNonComment(rbFt).right.is[Token.KwDo]
} =>
removeToken
case _: Term.ForYield => removeToken
case _: Term.Match => removeToken
case _: Type.Match => removeToken
case _: Term.Try => removeToken
case _: Ctor.Secondary
if ftoks.prevNonComment(ft).left.is[Token.Equals] =>
removeToken
case _ => null
}
case _ => null
}
}
override def onRight(left: Replacement, hasFormatOff: Boolean)(implicit
ft: FormatToken,
session: Session,
style: ScalafmtConfig
): Option[(Replacement, Replacement)] = {
val nextFt = ftoks.nextNonComment(ftoks.next(ft))
val notOkToRewrite = hasFormatOff || // can't force significant indentation
(nextFt.meta.rightOwner match {
case t: Term.Name =>
t.parent.exists {
case p: Term.Select => p.name eq t // select without `.`
case p: Term.ApplyInfix if p.op eq t =>
!style.dialect.allowInfixOperatorAfterNL ||
!t.tokens.head.isSymbolicInfixOperator
case _ => false
}
case _ => false
})
ft.right match {
case _ if notOkToRewrite => None
case x: Token.RightBrace =>
val replacement = ft.meta.rightOwner match {
case _: Term.For if allowOldSyntax && !nextFt.right.is[Token.KwDo] =>
replaceToken("do")(new Token.KwDo(x.input, x.dialect, x.start))
case _ => removeToken
}
Some((left, replacement))
case _ => None
}
}
private def onLeftForBlock(
tree: Term.Block
)(implicit ft: FormatToken, style: ScalafmtConfig): Replacement =
tree.parent.fold(null: Replacement) {
case t: Term.If =>
val ok = ftoks.prevNonComment(ft).left match {
case _: Token.KwIf => true
case _: Token.KwThen => true
case _: Token.KwElse =>
!TreeOps.isTreeMultiStatBlock(t.elsep) ||
ftoks.tokenAfter(t.cond).right.is[Token.KwThen]
case _: Token.RightParen => allowOldSyntax
case _ => false
}
if (ok) removeToken else null
case _: Term.While =>
val ok = ftoks.prevNonComment(ft).left match {
case _: Token.KwDo => true
case _: Token.RightParen => allowOldSyntax
case _ => false
}
if (ok) removeToken else null
case _: Term.For =>
val ok = ftoks.prevNonComment(ft).left match {
case _: Token.KwDo => true
case _: Token.RightParen | _: Token.RightBrace => allowOldSyntax
case _ => false
}
if (ok) removeToken else null
case _: Term.ForYield => removeToken
case _: Term.Try => removeToken
case _: Term.Throw => removeToken
case _: Term.Return => removeToken
case _: Defn.ExtensionGroup => removeToken
case _: Term.FunctionTerm => removeToken
case t: Defn.Def =>
if (tree ne t.body) null
else if (ftoks.prevNonComment(ft).left.is[Token.Equals]) removeToken
else null
case p: Tree.WithBody => if (p.body eq tree) removeToken else null
case _ => null
}
}