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 610a730
Showing 1 changed file with 54 additions and 60 deletions.
114 changes: 54 additions & 60 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,25 +11,16 @@ 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 t.matchesNormalized(target) =>
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)
implicit class TreeOps(t: Tree) {
def matchesNormalized(s: Symbol)(implicit index: SemanticdbIndex): Boolean =
t.matches(SymbolMatcher.normalized(s))
}

}
Expand All @@ -38,34 +30,35 @@ import Utils._
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 +90,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 +113,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 +133,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 +153,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 +170,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 +190,8 @@ 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 = Symbol("_root_.cats.data.EitherTFunctions.left.")
private[this] val rightSymbol = Symbol("_root_.cats.data.EitherTFunctions.right.")

private[this] def removeWithLeadingComma(ctx: RuleCtx, t: Tree): Patch =
(for {
Expand All @@ -212,10 +206,10 @@ 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) =>
if name.matchesNormalized(leftSymbol) =>
ctx.replaceTree(name, "leftT") + removeWithLeadingComma(ctx, a)
case Term.ApplyType(Term.Select(_, name), Seq(f, a, b))
if name.isSymbol(rightSymbol) =>
if name.matchesNormalized(rightSymbol) =>
ctx.replaceTree(name, "pure") + removeWithLeadingComma(ctx, b)
}.asPatch
}
Expand All @@ -241,13 +235,13 @@ 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 610a730

Please sign in to comment.