Skip to content

Commit

Permalink
RedundantParens: implement infixSide parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
kitbellew committed May 18, 2022
1 parent 6691bc0 commit 6b81790
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import scala.annotation.tailrec
import scala.meta._
import scala.meta.tokens.Token

import org.scalafmt.config.ScalafmtConfig
import org.scalafmt.config.{RedundantParensSettings, ScalafmtConfig}
import org.scalafmt.internal.{FormatToken, FormatTokens}
import org.scalafmt.internal.{Side, SyntacticGroupOps, TreeSyntacticGroup}
import org.scalafmt.util.{InfixApp, TreeOps}
Expand All @@ -25,6 +25,11 @@ object RedundantParens extends Rewrite with FormatTokensRewrite.RuleFactory {
SyntacticGroupOps.groupNeedsParenthesis(sgOuter, sgInner, side)
}

private val precedenceVeryHigh = InfixApp.getPrecedence("+")
private val precedenceHigh = InfixApp.getPrecedence("=")
private val precedenceMedium = InfixApp.getPrecedence("<")
private val precedenceLowest = InfixApp.getPrecedence("foo")

}

class RedundantParens(ftoks: FormatTokens) extends FormatTokensRewrite.Rule {
Expand Down Expand Up @@ -98,6 +103,25 @@ class RedundantParens(ftoks: FormatTokens) extends FormatTokensRewrite.Rule {
case p: Term.If =>
style.dialect.allowSignificantIndentation && p.cond == t &&
ftoks.tokenBefore(p.thenp).left.is[Token.KwThen]
case InfixApp(pia) if !infixNeedsParens(pia, t) =>
t match {
case InfixApp(tia) =>
style.rewrite.redundantParens.infixSide.exists {
case RedundantParensSettings.InfixSide.many =>
tia.op.value == pia.op.value ||
tia.precedence <= precedenceHigh ||
tia.precedence < precedenceLowest &&
pia.precedence >= precedenceLowest
case RedundantParensSettings.InfixSide.some =>
tia.precedence <= precedenceVeryHigh ||
tia.precedence <= precedenceMedium &&
pia.precedence >= precedenceLowest
case _ => true
}
case _: Lit | _: Name | _: Term.Interpolate => true
case _: Term.PartialFunction => true
case _ => style.rewrite.redundantParens.infixSide.isDefined
}
case p =>
t match {
case _: Lit | _: Name | _: Term.Interpolate => true
Expand All @@ -106,11 +130,7 @@ class RedundantParens(ftoks: FormatTokens) extends FormatTokensRewrite.Rule {
!p.is[Term.ApplyInfix] ||
ftoks.tokenAfter(t.expr).right.is[Token.Dot] &&
ftoks.tokenBefore(t.cases).left.is[Token.LeftBrace]
case _ =>
p match {
case InfixApp(pia) => !infixNeedsParens(pia, t)
case _ => false
}
case _ => false
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ case class InfixApp(lhs: Tree, op: Name, rhs: Seq[Tree], all: Tree) {
def isAssignment: Boolean = InfixApp.isAssignment(op.value)

@inline
lazy val precedence: Int =
InfixApp.infixOpPrecedence.getOrElse(op.value.head, 0)
lazy val precedence: Int = InfixApp.getPrecedence(op.value)

}

Expand Down Expand Up @@ -64,6 +63,9 @@ object InfixApp {
// Operators ending in a colon `:' are right-associative. All other operators are left-associative.
@inline def isLeftAssoc(op: String): Boolean = op.last != ':'

@inline def getPrecedence(op: String): Int =
infixOpPrecedence.getOrElse(op.head, 0)

}

object WithChain {
Expand Down
2 changes: 1 addition & 1 deletion scalafmt-tests/src/test/resources/rewrite/AvoidInfix.stat
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ object a {
}
>>>
object a {
(a(b("c")).over(d) / (e + 1)).as(f)
((a(b("c")).over(d)) / (e + 1)).as(f)
}
<<< exclude "cross" for sbt
foo("bar" % "baz" % "qux" cross CrossVersion.full)
Expand Down
34 changes: 17 additions & 17 deletions scalafmt-tests/src/test/resources/rewrite/RedundantParens.stat
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ object a {
}
>>>
object a {
private val foo = (bar == baz
|| bar == baz
private val foo = ((bar == baz
|| bar == baz)
|| bar == baz)
}
<<< #1953
Expand Down Expand Up @@ -896,10 +896,10 @@ object a {
}
>>>
object a {
foo * new bar
foo * new bar(baz).qux
new foo * bar
new foo(bar).baz * qux
foo * (new bar)
foo * (new bar(baz).qux)
(new foo) * bar
(new foo(bar).baz) * qux
}
<<< infix with anonymous function
object a {
Expand All @@ -908,8 +908,8 @@ object a {
}
>>>
object a {
foo map _.foo[A]
foo map new foo(_).bar
foo map (_.foo[A])
foo map (new foo(_).bar)
}
<<< infix with anonymous function, infixSide = some
rewrite.redundantParens.infixSide = some
Expand Down Expand Up @@ -957,9 +957,9 @@ object a {
foo & 0 // literal
foo & bar // identifier
// some+
foo & bar.baz // non-infix
foo & bar + baz // very high precedence infix
foo or bar < baz // non-symbolic outer op, medium precedence infix
foo & (bar.baz) // non-infix
foo & (bar + baz) // very high precedence infix
foo or (bar < baz) // non-symbolic outer op, medium precedence infix
}
<<< infix expressions with infixSide = some
rewrite.redundantParens.infixSide = some
Expand All @@ -983,11 +983,11 @@ object a {
foo & bar + baz // very high precedence infix
foo or bar < baz // non-symbolic outer op, medium precedence infix
// many+
foo || bar == baz // high precedence infix
foo or bar || baz // non-symbolic outer op; low precedence infix
foo |: bar |: baz // identical op: non-symbolic; right infix, right assoc
foo :| bar :| baz // identical op: symbolic; left infix, left assoc
foo or bar or baz // identical op: non-symbolic; left infix, left assoc
foo || (bar == baz) // high precedence infix
foo or (bar || baz) // non-symbolic outer op; low precedence infix
foo |: (bar |: baz) // identical op: non-symbolic; right infix, right assoc
(foo :| bar) :| baz // identical op: symbolic; left infix, left assoc
(foo or bar) or baz // identical op: non-symbolic; left infix, left assoc
}
<<< infix expressions with infixSide = many
rewrite.redundantParens.infixSide = many
Expand All @@ -1011,7 +1011,7 @@ object a {
foo :| bar :| baz // identical op: symbolic; left infix, left assoc
foo or bar or baz // identical op: non-symbolic; left infix, left assoc
// all
foo || bar && baz // low precedence infix
foo || (bar && baz) // low precedence infix
}
<<< infix expressions with infixSide = all
rewrite.redundantParens.infixSide = all
Expand Down

0 comments on commit 6b81790

Please sign in to comment.