Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1122 from japgolly/topic/redundant-braces
Remove redundant braces from if-else and case expressions
- Loading branch information
Showing
14 changed files
with
672 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC3") | ||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.2") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Side.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.scalafmt.internal | ||
|
||
sealed abstract class Side { | ||
def isLeft: Boolean = this == Side.Left | ||
} | ||
|
||
object Side { | ||
case object Right extends Side | ||
case object Left extends Side | ||
} |
71 changes: 71 additions & 0 deletions
71
scalafmt-core/shared/src/main/scala/org/scalafmt/internal/SyntacticGroup.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package org.scalafmt.internal | ||
|
||
import scala.meta.Tree | ||
|
||
sealed trait SyntacticGroup { | ||
def categories: List[String] | ||
def precedence: Double | ||
} | ||
|
||
object SyntacticGroup { | ||
sealed trait Type extends SyntacticGroup { | ||
def categories = List("Type") | ||
} | ||
object Type { | ||
case object ParamTyp extends Type { def precedence = 0 } | ||
case object Typ extends Type { def precedence = 1 } | ||
case object AnyInfixTyp extends Type { def precedence = 1.5 } | ||
case class InfixTyp(operator: String) extends Type { def precedence = 2 } | ||
case object RefineTyp extends Type { def precedence = 3 } | ||
case object WithTyp extends Type { def precedence = 3.5 } | ||
case object AnnotTyp extends Type { def precedence = 4 } | ||
case object SimpleTyp extends Type { def precedence = 6 } | ||
} | ||
sealed trait Term extends SyntacticGroup { | ||
def categories = List("Term") | ||
} | ||
object Term { | ||
case object Expr extends Term { def precedence = 0 } | ||
case object Expr1 extends Term { def precedence = 1 } | ||
case object Ascription extends Term { def precedence = 2 } | ||
case object PostfixExpr extends Term { def precedence = 2 } | ||
case class InfixExpr(operator: String) extends Term { def precedence = 3 } | ||
case class PrefixExpr(operator: String) extends Term { def precedence = 4 } | ||
object PrefixArg { | ||
def apply(tree: Tree): PrefixArg = | ||
PrefixArg(tree, TreeSyntacticGroup(tree)) | ||
} | ||
case class PrefixArg(tree: Tree, innerGroup: SyntacticGroup) extends Term { | ||
def precedence = innerGroup.precedence | ||
} | ||
case object SimpleExpr extends Term { def precedence = 5 } | ||
case object SimpleExpr1 extends Term { def precedence = 6 } | ||
} | ||
sealed trait Pat extends SyntacticGroup { | ||
def categories = List("Pat") | ||
} | ||
object Pat { | ||
case object Pattern extends Pat { def precedence = 0 } | ||
case object Pattern1 extends Pat { def precedence = 1 } | ||
case object Pattern2 extends Pat { def precedence = 2 } | ||
case object AnyPattern3 extends Pat { def precedence = 2.5 } | ||
case class Pattern3(operator: String) extends Pat { def precedence = 3 } | ||
case object SimplePattern extends Pat { def precedence = 6 } | ||
} | ||
case object Literal extends Term with Pat { | ||
override def categories = List("Term", "Pat"); def precedence = 6 | ||
} | ||
require( | ||
Literal.precedence == Term.SimpleExpr1.precedence && | ||
Literal.precedence == Pat.SimplePattern.precedence | ||
) | ||
case object Path extends Type with Term with Pat { | ||
override def categories = List("Type", "Term", "Pat"); | ||
def precedence = 6 | ||
} | ||
require( | ||
Path.precedence == Type.SimpleTyp.precedence && | ||
Path.precedence == Term.SimpleExpr1.precedence && | ||
Path.precedence == Pat.SimplePattern.precedence | ||
) | ||
} |
101 changes: 101 additions & 0 deletions
101
scalafmt-core/shared/src/main/scala/org/scalafmt/internal/SyntacticGroupOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package org.scalafmt.internal | ||
|
||
import scala.meta.{Term, Tree, Lit} | ||
import org.scalafmt.internal.{SyntacticGroup => g} | ||
import scala.meta.internal.ast.Helpers._ | ||
|
||
object SyntacticGroupOps { | ||
|
||
def operatorNeedsParenthesis( | ||
outerOperator: String, | ||
innerOperator: String, | ||
customAssociativity: Boolean, | ||
customPrecedence: Boolean, | ||
side: Side, | ||
forceRight: Boolean = false | ||
): Boolean = { | ||
|
||
// The associativity of an operator is determined by the operator's last character. | ||
// Operators ending in a colon ‘:’ are right-associative. All | ||
// other operators are left-associative. | ||
// https://www.scala-lang.org/files/archive/spec/2.13/06-expressions.html#infix-operations | ||
def isLeftAssociative(name: String): Boolean = | ||
if (customAssociativity) name.last != ':' else true | ||
|
||
def precedence(name: String): Int = | ||
if (customPrecedence) Term.Name(name).precedence else 0 | ||
|
||
val outerOperatorIsLeftAssociative = isLeftAssociative(outerOperator) | ||
val innerOperatorIsLeftAssociative = isLeftAssociative(innerOperator) | ||
|
||
if (outerOperatorIsLeftAssociative ^ innerOperatorIsLeftAssociative) true | ||
else { | ||
val isLeft = outerOperatorIsLeftAssociative | ||
val isRight = !outerOperatorIsLeftAssociative | ||
|
||
val outerOperatorPrecedence = precedence(outerOperator) | ||
val innerOperatorPrecedence = precedence(innerOperator) | ||
|
||
if (outerOperatorPrecedence < innerOperatorPrecedence) { | ||
isRight | ||
} else if (outerOperatorPrecedence == innerOperatorPrecedence) { | ||
isLeft ^ side.isLeft | ||
} else { | ||
isLeft || forceRight | ||
} | ||
} | ||
} | ||
|
||
def startsWithNumericLiteral(tree: Tree): Boolean = { | ||
tree match { | ||
case _: Lit.Int | _: Lit.Long | _: Lit.Double | _: Lit.Float | | ||
_: Lit.Byte | _: Lit.Short => | ||
true | ||
case Term.Select(tree0, _) => startsWithNumericLiteral(tree0) | ||
case _ => false | ||
} | ||
} | ||
|
||
def groupNeedsParenthesis( | ||
outerGroup: SyntacticGroup, | ||
innerGroup: SyntacticGroup, | ||
side: Side | ||
): Boolean = (outerGroup, innerGroup) match { | ||
case (g.Term.InfixExpr(outerOperator), g.Term.InfixExpr(innerOperator)) => | ||
operatorNeedsParenthesis( | ||
outerOperator, | ||
innerOperator, | ||
customAssociativity = true, | ||
customPrecedence = true, | ||
side, | ||
forceRight = true | ||
) | ||
case (g.Type.InfixTyp(outerOperator), g.Type.InfixTyp(innerOperator)) => | ||
operatorNeedsParenthesis( | ||
outerOperator, | ||
innerOperator, | ||
customAssociativity = true, | ||
customPrecedence = false, | ||
side | ||
) | ||
case (g.Pat.Pattern3(outerOperator), g.Pat.Pattern3(innerOperator)) => | ||
operatorNeedsParenthesis( | ||
outerOperator, | ||
innerOperator, | ||
customAssociativity = true, | ||
customPrecedence = true, | ||
side | ||
) | ||
|
||
case (_: g.Term.PrefixExpr, g.Term.PrefixArg(_, _: g.Term.PrefixExpr)) => | ||
true | ||
|
||
case (g.Term.PrefixExpr("-"), g.Term.PrefixArg(Term.Select(tree, _), _)) | ||
if startsWithNumericLiteral(tree) => | ||
true | ||
|
||
case _ => | ||
outerGroup.precedence > innerGroup.precedence | ||
} | ||
|
||
} |
81 changes: 81 additions & 0 deletions
81
scalafmt-core/shared/src/main/scala/org/scalafmt/internal/TreeSyntacticGroup.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package org.scalafmt.internal | ||
|
||
import scala.meta.Lit | ||
import scala.meta.Pat | ||
import scala.meta.Term | ||
import scala.meta.Tree | ||
import scala.meta.Type | ||
import org.scalafmt.internal.{SyntacticGroup => g} | ||
|
||
object TreeSyntacticGroup { | ||
def apply(tree: Tree): SyntacticGroup = tree match { | ||
case _: Lit => g.Literal | ||
// Term | ||
case _: Term.Name => g.Path | ||
case _: Term.Select => g.Path | ||
case _: Term.Interpolate => g.Term.SimpleExpr1 | ||
case _: Term.Xml => g.Term.SimpleExpr1 | ||
case _: Term.Apply => g.Term.SimpleExpr1 | ||
case _: Term.ApplyType => g.Term.SimpleExpr1 | ||
case t: Term.ApplyInfix => g.Term.InfixExpr(t.op.value) | ||
case t: Term.ApplyUnary => g.Term.PrefixExpr(t.op.value) | ||
case _: Term.Assign => g.Term.Expr1 | ||
case _: Term.Return => g.Term.Expr1 | ||
case _: Term.Throw => g.Term.Expr1 | ||
case _: Term.Ascribe => g.Term.Expr1 | ||
case _: Term.Annotate => g.Term.Expr1 | ||
case _: Term.Block => g.Term.SimpleExpr1 | ||
case _: Term.Tuple => g.Term.SimpleExpr1 // ???, breaks a op ((b, c)) | ||
// case _: Term.Tuple => g.Term.Expr1 // ??? Was SimpleExpr1, which is buggy for `a op ((b, c)) | ||
case _: Term.If => g.Term.Expr1 | ||
case _: Term.Match => g.Term.Expr1 | ||
case _: Term.TryWithCases => g.Term.Expr1 | ||
case _: Term.TryWithTerm => g.Term.Expr1 | ||
case _: Term.Function => g.Term.Expr | ||
case _: Term.PartialFunction => g.Term.SimpleExpr | ||
case _: Term.While => g.Term.Expr1 | ||
case _: Term.Do => g.Term.Expr1 | ||
case _: Term.For => g.Term.Expr1 | ||
case _: Term.ForYield => g.Term.Expr1 | ||
case _: Term.New => g.Term.SimpleExpr | ||
case _: Term.Placeholder => g.Term.SimpleExpr1 | ||
case _: Term.Eta => g.Term.SimpleExpr | ||
case _: Term.Arg.Repeated => g.Term.PostfixExpr | ||
case _: Term.Param => g.Path // ??? | ||
// Type | ||
case _: Type.Name => g.Path | ||
case _: Type.Select => g.Type.SimpleTyp | ||
case _: Type.Project => g.Type.SimpleTyp | ||
case _: Type.Singleton => g.Type.SimpleTyp | ||
case _: Type.Apply => g.Type.SimpleTyp | ||
case t: Type.ApplyInfix => g.Type.InfixTyp(t.op.value) | ||
case _: Type.Function => g.Type.Typ | ||
case _: Type.Tuple => g.Type.SimpleTyp | ||
case _: Type.With => g.Type.WithTyp | ||
case _: Type.And => g.Type.InfixTyp("&") | ||
case _: Type.Or => g.Type.InfixTyp("|") | ||
case _: Type.Refine => g.Type.RefineTyp | ||
case _: Type.Existential => g.Type.Typ | ||
case _: Type.Annotate => g.Type.AnnotTyp | ||
case _: Type.Placeholder => g.Type.SimpleTyp | ||
case _: Type.Bounds => g.Path // ??? | ||
case _: Type.Arg.Repeated => g.Type.ParamTyp | ||
case _: Type.Arg.ByName => g.Type.ParamTyp | ||
case _: Pat.Var.Type => g.Type.ParamTyp | ||
case _: Type.Param => g.Path // ??? | ||
// Pat | ||
case _: Pat.Var => g.Pat.SimplePattern | ||
case _: Pat.Wildcard => g.Pat.SimplePattern | ||
case _: Pat.Bind => g.Pat.Pattern2 | ||
case _: Pat.Alternative => g.Pat.Pattern | ||
case _: Pat.Tuple => g.Pat.SimplePattern | ||
case _: Pat.Extract => g.Pat.SimplePattern | ||
case t: Pat.ExtractInfix => g.Pat.Pattern3(t.op.value) | ||
case _: Pat.Interpolate => g.Pat.SimplePattern | ||
case _: Pat.Xml => g.Pat.SimplePattern | ||
case _: Pat.Typed => g.Pat.Pattern1 | ||
|
||
// Misc | ||
case _ => g.Path | ||
} | ||
} |
Oops, something went wrong.