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

AvoidInfix: process scala3 match operator, too #4567

Merged
merged 2 commits into from
Nov 20, 2024
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
4 changes: 4 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -3025,6 +3025,9 @@ The rule takes the following parameters under `rewrite.avoidInfix`:
be excluded
- (since 3.8.4) `excludePostfix`, unless set to `true` explicitly, will also
apply the rule to `Term.Select` trees specified without a dot
- (since 3.8.4) `excludeMatch`, if set to `false` explicitly and if the dialect
enables `allowMatchAsOperator` (such as Scala 3), will also apply the rule to
`Term.Match` trees specified without a dot

```scala mdoc:scalafmt
rewrite.rules = [AvoidInfix]
Expand Down Expand Up @@ -5142,6 +5145,7 @@ object A {

This option will enforce a break before each parent. As usual, the break is only
actually introduced if indented position on the next line is less than the current.
Added in 3.8.4.

```scala mdoc:scalafmt
binPack.parentConstructors = ForceBreak
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ case class AvoidInfixSettings(
private val excludeScalaTest: Option[Boolean] = None,
excludePlaceholderArg: Option[Boolean] = None,
excludePostfix: Boolean = false,
excludeMatch: Boolean = true,
) {
// if the user completely redefined (rather than appended), we don't touch
@inline
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ object AvoidInfix extends RewriteFactory {
class AvoidInfix(implicit ctx: RewriteCtx) extends RewriteSession {

private val cfg = ctx.style.rewrite.avoidInfix
private val allowMatchAsOperator = dialect.allowMatchAsOperator

// In a perfect world, we could just use
// Tree.transform {
Expand All @@ -30,18 +31,32 @@ class AvoidInfix(implicit ctx: RewriteCtx) extends RewriteSession {
// we will do these dangerous rewritings by hand.

override def rewrite(tree: Tree): Unit = tree match {
case x: Term.ApplyInfix => rewriteImpl(x.lhs, x.op, x.arg, x.targClause)
case x: Term.ApplyInfix =>
rewriteImpl(x.lhs, Right(x.op), x.arg, x.targClause)
case x: Term.Select if !cfg.excludePostfix && noDot(x.name.tokens.head) =>
rewriteImpl(x.qual, x.name)
rewriteImpl(x.qual, Right(x.name))
case x: Term.Match => noDotMatch(x)
.foreach(op => rewriteImpl(x.expr, Left(op), null))
case _ =>
}

private def noDot(opToken: T): Boolean =
!ctx.tokenTraverser.prevNonTrivialToken(opToken).forall(_.is[T.Dot])

private def noDotMatch(t: Term.Match): Either[Boolean, T] =
if (allowMatchAsOperator && t.mods.isEmpty)
ctx.tokenTraverser.prevNonTrivialToken(t.casesBlock.tokens.head) match {
case Some(kw) =>
if (!noDot(kw)) Left(true)
else if (cfg.excludeMatch) Left(false)
else Right(kw)
case _ => Left(false)
}
else Left(false)

private def rewriteImpl(
lhs: Term,
op: Name,
op: Either[T, Name],
rhs: Tree = null,
targs: Member.SyntaxValuesClause = null,
): Unit = {
Expand All @@ -52,19 +67,24 @@ class AvoidInfix(implicit ctx: RewriteCtx) extends RewriteSession {
val lhsIsOK = lhsIsWrapped ||
(lhs match {
case t: Term.ApplyInfix => checkMatchingInfix(t.lhs, t.op.value, t.arg)
case t: Term.Match => noDotMatch(t) match {
case Left(ok) => ok
case Right(kw) => checkMatchingInfix(t.expr, kw.text, t.casesBlock)
}
case _ => false
})

if (!checkMatchingInfix(lhs, op.value, rhs, Some(lhsIsOK))) return
if (!checkMatchingInfix(lhs, op.fold(_.text, _.value), rhs, Some(lhsIsOK)))
return
if (!ctx.dialect.allowTryWithAnyExpr)
if (beforeLhsHead.exists(_.is[T.KwTry])) return

val builder = Seq.newBuilder[TokenPatch]

val (opHead, opLast) = ends(op)
val (opHead, opLast) = op.fold((_, null), ends)
builder += TokenPatch.AddLeft(opHead, ".", keepTok = true)

if (rhs ne null) {
if ((rhs ne null) && (opLast ne null)) {
def moveOpenDelim(prev: T, open: T): Unit = {
// move delimiter (before comment or newline)
builder += TokenPatch.AddRight(prev, open.text, keepTok = true)
Expand Down Expand Up @@ -94,7 +114,8 @@ class AvoidInfix(implicit ctx: RewriteCtx) extends RewriteSession {
case _: Term.ApplyInfix | _: Term.Match => !lhsIsOK
// foo _ compose bar => (foo _).compose(bar)
// new Foo compose bar => (new Foo).compose(bar)
case _: Term.Eta | _: Term.New => true
case _: Term.Eta | _: Term.New | _: Term.Annotate => true
case t: Term.Select if rhs eq null => !noDot(t.name.tokens.head)
case _ => false
})
if (shouldWrapLhs) {
Expand Down Expand Up @@ -124,6 +145,15 @@ class AvoidInfix(implicit ctx: RewriteCtx) extends RewriteSession {
case None => isWrapped(lhs) ||
checkMatchingInfix(lhs.lhs, lhs.op.value, lhs.arg)
}
case lhs: Term.Match if hasPlaceholder(lhs, includeArg = true) =>
lhsIsOK match {
case Some(x) => x
case None if isWrapped(lhs) => true
case None => noDotMatch(lhs) match {
case Left(ok) => ok
case Right(op) => checkMatchingInfix(lhs.expr, op.text, null)
}
}
case _ => true
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7564,8 +7564,9 @@ object Build:
}
}.evaluated
)
<<< AvoidInfix with match
<<< AvoidInfix with match, excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = true
===
object a {
a b c match
Expand All @@ -7576,8 +7577,23 @@ object a {
a.b(c) match
case _ =>
}
<<< AvoidInfix with match within applyinfix
<<< AvoidInfix with match, !excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = false
===
object a {
a b c match
case _ =>
}
>>>
object a {
a.b(c)
.match
case _ =>
}
<<< AvoidInfix with match within applyinfix, excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = true
===
object a {
a b c match {
Expand All @@ -7590,8 +7606,39 @@ object a {
case _ =>
}).d(e)
}
<<< AvoidInfix with match, with dot
<<< AvoidInfix with match within applyinfix, !excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = false
===
object a {
a b c match {
case _ =>
} d e
}
>>>
object a {
a.b(c)
.match { case _ =>
}
.d(e)
}
<<< AvoidInfix with match, with dot, excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = true
===
object a {
(a.b(c)).match
case _ =>
}
>>>
object a {
(a.b(c))
.match
case _ =>
}
<<< AvoidInfix with match, with dot, !excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = false
===
object a {
(a.b(c)).match
Expand All @@ -7603,6 +7650,32 @@ object a {
.match
case _ =>
}
<<< AvoidInfix with match, with annotation, excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = true
===
object a {
a(b): @c match
case _ =>
}
>>>
object a {
a(b): @c match
case _ =>
}
<<< AvoidInfix with match, with annotation, !excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = false
===
object a {
a(b): @c match
case _ =>
}
>>>
object a {
(a(b): @c).match
case _ =>
}
<<< match with dot, trailing case comment
object a:
b.c.match
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7275,8 +7275,9 @@ object Build:
config: GenerationConfig => config.remove[SiteRoot]
}
}.evaluated)
<<< AvoidInfix with match
<<< AvoidInfix with match, excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = true
===
object a {
a b c match
Expand All @@ -7287,8 +7288,22 @@ object a {
a.b(c) match
case _ =>
}
<<< AvoidInfix with match within applyinfix
<<< AvoidInfix with match, !excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = false
===
object a {
a b c match
case _ =>
}
>>>
object a {
a.b(c).match
case _ =>
}
<<< AvoidInfix with match within applyinfix, excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = true
===
object a {
a b c match {
Expand All @@ -7299,8 +7314,22 @@ object a {
object a {
(a.b(c) match { case _ => }).d(e)
}
<<< AvoidInfix with match, with dot
<<< AvoidInfix with match within applyinfix, !excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = false
===
object a {
a b c match {
case _ =>
} d e
}
>>>
object a {
a.b(c).match { case _ => }.d(e)
}
<<< AvoidInfix with match, with dot, excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = true
===
object a {
(a.b(c)).match
Expand All @@ -7311,6 +7340,45 @@ object a {
(a.b(c)).match
case _ =>
}
<<< AvoidInfix with match, with dot, !excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = false
===
object a {
(a.b(c)).match
case _ =>
}
>>>
object a {
(a.b(c)).match
case _ =>
}
<<< AvoidInfix with match, with annotation, excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = true
===
object a {
a(b): @c match
case _ =>
}
>>>
object a {
a(b): @c match
case _ =>
}
<<< AvoidInfix with match, with annotation, !excludeMatch
rewrite.rules = [AvoidInfix]
rewrite.avoidInfix.excludeMatch = false
===
object a {
a(b): @c match
case _ =>
}
>>>
object a {
(a(b): @c).match
case _ =>
}
<<< match with dot, trailing case comment
object a:
b.c.match
Expand Down
Loading