Skip to content

Commit

Permalink
Use Symbol and SymbolMatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
gabro committed Sep 10, 2017
1 parent 81c18da commit 963e71c
Showing 1 changed file with 60 additions and 64 deletions.
124 changes: 60 additions & 64 deletions scalafix/rules/src/main/scala/fix/Cats_v1_0_0.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fix
package v1_0_0

import scalafix._
import scalafix.util.SymbolMatcher
import scalafix.syntax._
import scala.meta._

Expand All @@ -10,62 +11,53 @@ object Utils {
private[fix] def rename(
ctx: RuleCtx,
t: Term.Name,
renames: Map[String, String])(implicit index: SemanticdbIndex): Patch = {
renames: Map[Symbol, String])(implicit index: SemanticdbIndex): Patch = {
renames.collect {
case (target, rename) if t.isSymbol(target) =>
case (target, rename) if SymbolMatcher.normalized(target).matches(t) =>
ctx.replaceTree(t, rename)
}.asPatch
}

implicit class TermNameOps(t: Name) {
def isSymbol(s: String)(implicit index: SemanticdbIndex): Boolean =
t.symbol.exists(_.normalized.syntax == s)

def isOneOfSymbols(symbols: Set[String])(
implicit index: SemanticdbIndex): Boolean =
t.symbol.exists(s => symbols.contains(s.normalized.syntax))
}

implicit class OptionTermNameOps(t: Option[Name]) {
def isSymbol(s: String)(implicit index: SemanticdbIndex): Boolean =
t.flatMap(_.symbol).exists(_.normalized.syntax == s)
}

}
import Utils._

// ref: https://github.com/typelevel/cats/pull/1745
case class RemoveCartesianBuilder(index: SemanticdbIndex)
extends SemanticRule(index, "RemoveCartesianBuilder") {

private[this] val cartesianBuilders =
(1 to 22)
.map(arity =>
s"_root_.cats.syntax.CartesianBuilder.CartesianBuilder$arity.`|@|`.")
.toSet +
"_root_.cats.syntax.CartesianOps.`|@|`."

private[this] val partialApplies = Set(
s"_root_.cats.syntax.CartesianOps.`*>`.",
s"_root_.cats.syntax.CartesianOps.`<*`."
private[this] val cartesianBuilders = SymbolMatcher.normalized(
Symbol("_root_.cats.syntax.CartesianOps.`|@|`.") ::
(1 to 22).toList.map(arity =>
Symbol(
s"_root_.cats.syntax.CartesianBuilder.CartesianBuilder$arity.`|@|`.")): _*)

private[this] val partialApplies = SymbolMatcher.normalized(
Symbol(s"_root_.cats.syntax.CartesianOps.`*>`."),
Symbol(s"_root_.cats.syntax.CartesianOps.`<*`.")
)

private[this] val renames: Map[String, String] =
private[this] val renames: Map[Symbol, String] =
(1 to 22)
.map { arity =>
Seq(
s"_root_.cats.syntax.CartesianBuilder.CartesianBuilder$arity.map." -> "mapN",
s"_root_.cats.syntax.CartesianBuilder.CartesianBuilder$arity.imap." -> "imapN",
s"_root_.cats.syntax.CartesianBuilder.CartesianBuilder$arity.contramap." -> "contramapN"
Symbol(
s"_root_.cats.syntax.CartesianBuilder.CartesianBuilder$arity.map.") -> "mapN",
Symbol(
s"_root_.cats.syntax.CartesianBuilder.CartesianBuilder$arity.imap.") -> "imapN",
Symbol(
s"_root_.cats.syntax.CartesianBuilder.CartesianBuilder$arity.contramap.") -> "contramapN"
)
}
.flatten
.toMap

private[this] val cartesianOps =
SymbolMatcher.normalized(renames.keys.toSeq: _*)

// Hackish way to work around duplicate fixes due to recursion
val alreadyFixedOps = collection.mutable.Set.empty[Term.Name]
private[this] def replaceOpWithComma(ctx: RuleCtx, op: Term.Name): Patch =
if (op.isOneOfSymbols(cartesianBuilders) && !alreadyFixedOps.contains(op)) {
if (op.matches(cartesianBuilders) && !alreadyFixedOps.contains(op)) {
alreadyFixedOps += op
// remove the space before |@|
ctx.removeToken(ctx.tokenList.prev(op.tokens.head)) +
Expand Down Expand Up @@ -97,14 +89,14 @@ case class RemoveCartesianBuilder(index: SemanticdbIndex)

override def fix(ctx: RuleCtx): Patch = {
ctx.tree.collect {
case t: Term.ApplyInfix if t.op.isOneOfSymbols(cartesianBuilders) =>
case t: Term.ApplyInfix if t.op.matches(cartesianBuilders) =>
removeCartesianBuilderOp(ctx, t)
case t: Term.ApplyInfix if t.op.isOneOfSymbols(renames.keys.toSet) =>
case t: Term.ApplyInfix if t.op.matches(cartesianOps) =>
wrapInParensIfNeeded(ctx, t.lhs)
case t: Term.Name => rename(ctx, t, renames)
case t @ q"import cats.syntax.cartesian._" =>
val usesPartialApplies = ctx.tree.collect {
case t: Term.Name if t.isOneOfSymbols(partialApplies) => ()
case partialApplies(t: Term.Name) => ()
}.length > 0
if (usesPartialApplies) {
ctx.addRight(t.tokens.last, "\n import cats.syntax.apply._")
Expand All @@ -120,14 +112,14 @@ case class RemoveUnapply(index: SemanticdbIndex)
extends SemanticRule(index, "RemoveUnapply") {

private[this] val renames = Map(
"_root_.cats.Traverse.Ops.traverseU." -> "traverse",
"_root_.cats.Foldable.Ops.traverseU_." -> "traverse_",
"_root_.cats.Foldable.traverseU_." -> "traverse_",
"_root_.cats.Traverse.Ops.sequenceU." -> "sequence",
"_root_.cats.Foldable.Ops.sequenceU_." -> "sequence_",
"_root_.cats.Foldable.sequenceU_." -> "sequence_",
"_root_.cats.data.Func.appFuncU." -> "appFunc",
"_root_.cats.free.FreeT.liftTU." -> "liftT"
Symbol("_root_.cats.Traverse.Ops.traverseU.") -> "traverse",
Symbol("_root_.cats.Foldable.Ops.traverseU_.") -> "traverse_",
Symbol("_root_.cats.Foldable.traverseU_.") -> "traverse_",
Symbol("_root_.cats.Traverse.Ops.sequenceU.") -> "sequence",
Symbol("_root_.cats.Foldable.Ops.sequenceU_.") -> "sequence_",
Symbol("_root_.cats.Foldable.sequenceU_.") -> "sequence_",
Symbol("_root_.cats.data.Func.appFuncU.") -> "appFunc",
Symbol("_root_.cats.free.FreeT.liftTU.") -> "liftT"
)

private[this] def importeeName(importee: Importee): Option[Name] =
Expand All @@ -140,11 +132,12 @@ case class RemoveUnapply(index: SemanticdbIndex)
private[this] def removeImportee(
ctx: RuleCtx,
importee: Importee,
fixes: Map[String, String]): Patch =
fixes.collect {
case (target, _) if importeeName(importee).isSymbol(target) =>
ctx.removeImportee(importee)
fixes: Map[Symbol, String]): Patch = {
val importsToRemove = SymbolMatcher.normalized(fixes.keys.toSeq: _*)
importeeName(importee).collect {
case importsToRemove(n) => ctx.removeImportee(importee)
}.asPatch
}

override def fix(ctx: RuleCtx): Patch = {
ctx.tree.collect {
Expand All @@ -159,8 +152,8 @@ case class RenameFreeSuspend(index: SemanticdbIndex)
extends SemanticRule(index, "RenameFreeSuspend") {

private[this] val renames = Map(
"_root_.cats.free.Free.suspend." -> "defer",
"_root_.cats.free.TrampolineFunctions.suspend." -> "defer"
Symbol("_root_.cats.free.Free.suspend.") -> "defer",
Symbol("_root_.cats.free.TrampolineFunctions.suspend.") -> "defer"
)

override def fix(ctx: RuleCtx): Patch = {
Expand All @@ -176,12 +169,12 @@ case class RenameReducibleMethods(index: SemanticdbIndex)
extends SemanticRule(index, "RenameReducibleMethods") {

private[this] val renames = Map(
"_root_.cats.Reducible.traverse1_." -> "nonEmptyTraverse_",
"_root_.cats.Reducible.Ops.traverse1_." -> "nonEmptyTraverse_",
"_root_.cats.Reducible.intercalate1." -> "nonEmptyIntercalate",
"_root_.cats.Reducible.Ops.intercalate1." -> "nonEmptyIntercalate",
"_root_.cats.Reducible.sequence1_." -> "nonEmptySequence_",
"_root_.cats.Reducible.Ops.sequence1_." -> "nonEmptySequence_"
Symbol("_root_.cats.Reducible.traverse1_.") -> "nonEmptyTraverse_",
Symbol("_root_.cats.Reducible.Ops.traverse1_.") -> "nonEmptyTraverse_",
Symbol("_root_.cats.Reducible.intercalate1.") -> "nonEmptyIntercalate",
Symbol("_root_.cats.Reducible.Ops.intercalate1.") -> "nonEmptyIntercalate",
Symbol("_root_.cats.Reducible.sequence1_.") -> "nonEmptySequence_",
Symbol("_root_.cats.Reducible.Ops.sequence1_.") -> "nonEmptySequence_"
)

override def fix(ctx: RuleCtx): Patch = {
Expand All @@ -196,8 +189,12 @@ case class RenameReducibleMethods(index: SemanticdbIndex)
case class SimplifyEitherTLift(index: SemanticdbIndex)
extends SemanticRule(index, "SimplifyEitherTLift") {

private[this] val leftSymbol = "_root_.cats.data.EitherTFunctions.left."
private[this] val rightSymbol = "_root_.cats.data.EitherTFunctions.right."
private[this] val leftSymbol = SymbolMatcher.normalized(
Symbol("_root_.cats.data.EitherTFunctions.left.")
)
private[this] val rightSymbol = SymbolMatcher.normalized(
Symbol("_root_.cats.data.EitherTFunctions.right.")
)

private[this] def removeWithLeadingComma(ctx: RuleCtx, t: Tree): Patch =
(for {
Expand All @@ -211,11 +208,9 @@ case class SimplifyEitherTLift(index: SemanticdbIndex)

override def fix(ctx: RuleCtx): Patch = {
ctx.tree.collect {
case Term.ApplyType(Term.Select(_, name), Seq(f, a, b))
if name.isSymbol(leftSymbol) =>
case Term.ApplyType(Term.Select(_, leftSymbol(name)), Seq(f, a, b)) =>
ctx.replaceTree(name, "leftT") + removeWithLeadingComma(ctx, a)
case Term.ApplyType(Term.Select(_, name), Seq(f, a, b))
if name.isSymbol(rightSymbol) =>
case Term.ApplyType(Term.Select(_, rightSymbol(name)), Seq(f, a, b)) =>
ctx.replaceTree(name, "pure") + removeWithLeadingComma(ctx, b)
}.asPatch
}
Expand All @@ -241,13 +236,14 @@ case class RenameInjectProdAndCoproduct(index: SemanticdbIndex)
case class RenameTupleApplySyntax(index: SemanticdbIndex)
extends SemanticRule(index, "RenameTupleApplySyntax") {

private[this] val renames: Map[String, String] =
private[this] val renames: Map[Symbol, String] =
(1 to 22)
.map { arity =>
Seq(
s"_root_.cats.syntax.Tuple${arity}CartesianOps.map$arity." -> "mapN",
s"_root_.cats.syntax.Tuple${arity}CartesianOps.contramap$arity." -> "contramapN",
s"_root_.cats.syntax.Tuple${arity}CartesianOps.imap$arity." -> "imapN"
Symbol(s"_root_.cats.syntax.Tuple${arity}CartesianOps.map$arity.") -> "mapN",
Symbol(
s"_root_.cats.syntax.Tuple${arity}CartesianOps.contramap$arity.") -> "contramapN",
Symbol(s"_root_.cats.syntax.Tuple${arity}CartesianOps.imap$arity.") -> "imapN"
)
}
.flatten
Expand Down

0 comments on commit 963e71c

Please sign in to comment.