diff --git a/build.sbt b/build.sbt index 79df936c..2e02061b 100644 --- a/build.sbt +++ b/build.sbt @@ -223,14 +223,13 @@ lazy val `scalafix-tests` = project .settings( scalaVersion := scalafixScala212, libraryDependencies += "ch.epfl.scala" % "scalafix-testkit" % scalafixVersion % Test cross CrossVersion.full, - buildInfoPackage := "fix", + buildInfoPackage := "build", buildInfoKeys := Seq[BuildInfoKey]( "inputSourceroot" -> sourceDirectory.in(`scalafix-input`, Compile).value, "outputSourceroot" -> (baseDirectory in ThisBuild).value / "scalafix/output/src/main", "output212Sourceroot" -> output212.value, "output212PlusSourceroot" -> output212Plus.value, "output213Sourceroot" -> output213.value, - "output212PlusSourceroot" -> output212Plus.value, "output213FailureSourceroot" -> sourceDirectory.in(`scalafix-output213-failure`, Compile).value, "inputClassdirectory" -> classDirectory.in(`scalafix-input`, Compile).value ), diff --git a/scalafix/input/src/main/scala/fix/CompanionSrc.scala b/scalafix/input/src/main/scala/fix/CompanionSrc.scala new file mode 100644 index 00000000..d4d5eb04 --- /dev/null +++ b/scalafix/input/src/main/scala/fix/CompanionSrc.scala @@ -0,0 +1,42 @@ +/* +rule = "scala:fix.CrossCompat" + */ +package fix + +import scala.collection.immutable +import scala.collection.mutable + +object CompanionSrc { + + (null: collection.IndexedSeq[Int]).companion + (null: collection.Iterable[Int]).companion + (null: collection.Seq[Int]).companion + (null: collection.Traversable[Int]).companion + + (null: immutable.HashSet[Int]).companion + (null: immutable.IndexedSeq[Int]).companion + (null: immutable.Iterable[Int]).companion + (null: immutable.LinearSeq[Int]).companion + (null: immutable.List[Int]).companion + (null: immutable.ListSet[Int]).companion + (null: immutable.Queue[Int]).companion + (null: immutable.Seq[Int]).companion + (null: immutable.Set[Int]).companion + (null: immutable.Stream[Int]).companion + (null: immutable.Traversable[Int]).companion + (null: immutable.Vector[Int]).companion + + (null: mutable.ArrayBuffer[Int]).companion + (null: mutable.ArraySeq[Int]).companion + (null: mutable.ArrayStack[Int]).companion + (null: mutable.Buffer[Int]).companion + (null: mutable.HashSet[Int]).companion + (null: mutable.IndexedSeq[Int]).companion + (null: mutable.Iterable[Int]).companion + (null: mutable.LinearSeq[Int]).companion + (null: mutable.LinkedHashSet[Int]).companion + (null: mutable.Queue[Int]).companion + (null: mutable.Seq[Int]).companion + (null: mutable.Set[Int]).companion + (null: mutable.Traversable[Int]).companion +} diff --git a/scalafix/input/src/main/scala/fix/CompanionSrc212.scala b/scalafix/input/src/main/scala/fix/CompanionSrc212.scala index d5d667c5..34251872 100644 --- a/scalafix/input/src/main/scala/fix/CompanionSrc212.scala +++ b/scalafix/input/src/main/scala/fix/CompanionSrc212.scala @@ -7,41 +7,10 @@ import scala.collection.{immutable => i, mutable => m} import scala.{collection => c} object CompanionSrc212 { - - (null: c.IndexedSeq[Int]).companion - (null: c.Iterable[Int]).companion - (null: c.Seq[Int]).companion - (null: c.Traversable[Int]).companion - - (null: i.HashSet[Int]).companion - (null: i.IndexedSeq[Int]).companion - (null: i.Iterable[Int]).companion - (null: i.LinearSeq[Int]).companion - (null: i.List[Int]).companion - (null: i.ListSet[Int]).companion - (null: i.Queue[Int]).companion - (null: i.Seq[Int]).companion - (null: i.Set[Int]).companion (null: i.Stack[Int]).companion - (null: i.Stream[Int]).companion - (null: i.Traversable[Int]).companion - (null: i.Vector[Int]).companion - - (null: m.ArrayBuffer[Int]).companion - (null: m.ArraySeq[Int]).companion - (null: m.ArrayStack[Int]).companion - (null: m.Buffer[Int]).companion (null: m.DoubleLinkedList[Int]).companion - (null: m.HashSet[Int]).companion - (null: m.IndexedSeq[Int]).companion - (null: m.Iterable[Int]).companion - (null: m.LinearSeq[Int]).companion - (null: m.LinkedHashSet[Int]).companion (null: m.LinkedList[Int]).companion (null: m.MutableList[Int]).companion - (null: m.Queue[Int]).companion (null: m.ResizableArray[Int]).companion - (null: m.Seq[Int]).companion - (null: m.Set[Int]).companion - (null: m.Traversable[Int]).companion } + diff --git a/scalafix/input/src/main/scala/fix/ReplaceToSrc.scala b/scalafix/input/src/main/scala/fix/ReplaceToSrc.scala new file mode 100644 index 00000000..7ed93852 --- /dev/null +++ b/scalafix/input/src/main/scala/fix/ReplaceToSrc.scala @@ -0,0 +1,17 @@ +/* +rule = "scala:fix.CrossCompat" + */ +package fix + +object ReplaceToSrc { + List(1).to[Set] + Set(1).to[List] + + def m1(xs: Set[Int]): List[Int] = + xs.to + + List[Int]() // unrelated matching brackets + + def m2(xs: List[Int]): Iterable[Int] = + xs.to +} diff --git a/scalafix/input/src/main/scala/fix/TraversableSrc.scala b/scalafix/input/src/main/scala/fix/TraversableSrc.scala index 791fb1a3..727ccaa8 100644 --- a/scalafix/input/src/main/scala/fix/TraversableSrc.scala +++ b/scalafix/input/src/main/scala/fix/TraversableSrc.scala @@ -3,16 +3,15 @@ rule = "scala:fix.CrossCompat" */ package fix -object TraversableSrc { - def foo(xs: Traversable[(Int, String)], ys: List[Int]): Unit = { - xs.to[List] - xs.to[Set] - xs.toIterator - ys.iterator - } +import scala.collection.immutable +import scala.collection.mutable - def m1(xs: TraversableOnce[Int]): List[Int] = - xs.to +trait TraversableSrc { + val to: TraversableOnce[Int] + val cto: collection.TraversableOnce[Int] - List[Int]() // unrelated matching brackets + val t: Traversable[Int] + val ct: collection.Traversable[Int] + val it: immutable.Traversable[Int] + val mt: mutable.Traversable[Int] } diff --git a/scalafix/output/src/main/scala/fix/CompanionSrc.scala b/scalafix/output/src/main/scala/fix/CompanionSrc.scala new file mode 100644 index 00000000..05aabf71 --- /dev/null +++ b/scalafix/output/src/main/scala/fix/CompanionSrc.scala @@ -0,0 +1,43 @@ + + + +package fix + +import scala.collection.immutable +import scala.collection.mutable +import scala.collection.compat._ + +object CompanionSrc { + + (null: collection.IndexedSeq[Int]).iterableFactory + (null: collection.Iterable[Int]).iterableFactory + (null: collection.Seq[Int]).iterableFactory + (null: collection.Iterable[Int]).iterableFactory + + (null: immutable.HashSet[Int]).iterableFactory + (null: immutable.IndexedSeq[Int]).iterableFactory + (null: immutable.Iterable[Int]).iterableFactory + (null: immutable.LinearSeq[Int]).iterableFactory + (null: immutable.List[Int]).iterableFactory + (null: immutable.ListSet[Int]).iterableFactory + (null: immutable.Queue[Int]).iterableFactory + (null: immutable.Seq[Int]).iterableFactory + (null: immutable.Set[Int]).iterableFactory + (null: immutable.Stream[Int]).iterableFactory + (null: immutable.Iterable[Int]).iterableFactory + (null: immutable.Vector[Int]).iterableFactory + + (null: mutable.ArrayBuffer[Int]).iterableFactory + (null: mutable.ArraySeq[Int]).iterableFactory + (null: mutable.ArrayStack[Int]).iterableFactory + (null: mutable.Buffer[Int]).iterableFactory + (null: mutable.HashSet[Int]).iterableFactory + (null: mutable.IndexedSeq[Int]).iterableFactory + (null: mutable.Iterable[Int]).iterableFactory + (null: mutable.LinearSeq[Int]).iterableFactory + (null: mutable.LinkedHashSet[Int]).iterableFactory + (null: mutable.Queue[Int]).iterableFactory + (null: mutable.Seq[Int]).iterableFactory + (null: mutable.Set[Int]).iterableFactory + (null: mutable.Iterable[Int]).iterableFactory +} diff --git a/scalafix/output/src/main/scala/fix/ReplaceToSrc.scala b/scalafix/output/src/main/scala/fix/ReplaceToSrc.scala new file mode 100644 index 00000000..f7d0eb06 --- /dev/null +++ b/scalafix/output/src/main/scala/fix/ReplaceToSrc.scala @@ -0,0 +1,18 @@ + + + +package fix + +import scala.collection.compat._ +object ReplaceToSrc { + List(1).to(Set) + Set(1).to(List) + + def m1(xs: Set[Int]): List[Int] = + xs.to(scala.collection.immutable.List) + + List[Int]() // unrelated matching brackets + + def m2(xs: List[Int]): Iterable[Int] = + xs.to(scala.collection.immutable.IndexedSeq) +} diff --git a/scalafix/output/src/main/scala/fix/TraversableSrc.scala b/scalafix/output/src/main/scala/fix/TraversableSrc.scala index 30429bb0..879ea9c7 100644 --- a/scalafix/output/src/main/scala/fix/TraversableSrc.scala +++ b/scalafix/output/src/main/scala/fix/TraversableSrc.scala @@ -3,17 +3,16 @@ package fix +import scala.collection.immutable +import scala.collection.mutable import scala.collection.compat._ -object TraversableSrc { - def foo(xs: Iterable[(Int, String)], ys: List[Int]): Unit = { - xs.to(List) - xs.to(Set) - xs.iterator - ys.iterator - } - def m1(xs: IterableOnce[Int]): List[Int] = - xs.to(scala.collection.immutable.List) +trait TraversableSrc { + val to: IterableOnce[Int] + val cto: IterableOnce[Int] - List[Int]() // unrelated matching brackets + val t: Iterable[Int] + val ct: collection.Iterable[Int] + val it: immutable.Iterable[Int] + val mt: mutable.Iterable[Int] } diff --git a/scalafix/output212/src/main/scala/fix/CompanionSrc212.scala b/scalafix/output212/src/main/scala/fix/CompanionSrc212.scala index 446cb5cf..4bae8dd0 100644 --- a/scalafix/output212/src/main/scala/fix/CompanionSrc212.scala +++ b/scalafix/output212/src/main/scala/fix/CompanionSrc212.scala @@ -8,41 +8,9 @@ import scala.{collection => c} import scala.collection.compat._ object CompanionSrc212 { - - (null: c.IndexedSeq[Int]).iterableFactory - (null: c.Iterable[Int]).iterableFactory - (null: c.Seq[Int]).iterableFactory - (null: collection.Iterable[Int]).iterableFactory - - (null: i.HashSet[Int]).iterableFactory - (null: i.IndexedSeq[Int]).iterableFactory - (null: i.Iterable[Int]).iterableFactory - (null: i.LinearSeq[Int]).iterableFactory - (null: i.List[Int]).iterableFactory - (null: i.ListSet[Int]).iterableFactory - (null: i.Queue[Int]).iterableFactory - (null: i.Seq[Int]).iterableFactory - (null: i.Set[Int]).iterableFactory (null: i.Stack[Int]).iterableFactory - (null: i.Stream[Int]).iterableFactory - (null: i.Traversable[Int]).iterableFactory - (null: i.Vector[Int]).iterableFactory - - (null: m.ArrayBuffer[Int]).iterableFactory - (null: m.ArraySeq[Int]).iterableFactory - (null: m.ArrayStack[Int]).iterableFactory - (null: m.Buffer[Int]).iterableFactory (null: m.DoubleLinkedList[Int]).iterableFactory - (null: m.HashSet[Int]).iterableFactory - (null: m.IndexedSeq[Int]).iterableFactory - (null: m.Iterable[Int]).iterableFactory - (null: m.LinearSeq[Int]).iterableFactory - (null: m.LinkedHashSet[Int]).iterableFactory (null: m.LinkedList[Int]).iterableFactory (null: m.MutableList[Int]).iterableFactory - (null: m.Queue[Int]).iterableFactory (null: m.ResizableArray[Int]).iterableFactory - (null: m.Seq[Int]).iterableFactory - (null: m.Set[Int]).iterableFactory - (null: m.Traversable[Int]).iterableFactory } diff --git a/scalafix/rules/src/main/scala/fix/Stable212Base.scala b/scalafix/rules/src/main/scala/fix/Stable212Base.scala index 515f9140..577d0fc6 100644 --- a/scalafix/rules/src/main/scala/fix/Stable212Base.scala +++ b/scalafix/rules/src/main/scala/fix/Stable212Base.scala @@ -31,7 +31,7 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule => val foldLeftSymbol = foldSymbol(isLeft = true) val foldRightSymbol = foldSymbol(isLeft = false) - val iterator = normalized("_root_.scala.collection.TraversableLike.toIterator.") + val toTpe = normalized( "_root_.scala.collection.TraversableLike.to.", "_root_.scala.collection.TraversableOnce.to.", @@ -73,10 +73,9 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule => "_root_.scala.collection.immutable.TreeSet#until(Ljava/lang/Object;)Lscala/collection/immutable/TreeSet;." ) - val traversable = exact( - "_root_.scala.collection.Traversable#", + val `TraversableLike.toIterator` = normalized("_root_.scala.collection.TraversableLike.toIterator.") + val traversableOnce = exact( "_root_.scala.collection.TraversableOnce#", - "_root_.scala.package.Traversable#", "_root_.scala.package.TraversableOnce#" ) @@ -99,28 +98,42 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule => sameElements + compatImport } - def replaceSymbols0(ctx: RuleCtx): Patch = { + def replaceTraversable(ctx: RuleCtx): Patch = { + + val traversableIterator = + ctx.tree.collect { + case `TraversableLike.toIterator`(t: Name) => + ctx.replaceTree(t, "iterator") + }.asPatch + val traversableToIterable = ctx.replaceSymbols( - "scala.Traversable" -> "scala.Iterable", - "scala.collection.Traversable" -> "scala.collection.Iterable", - "scala.TraversableOnce" -> "scala.IterableOnce", - "scala.collection.TraversableOnce" -> "scala.collection.IterableOnce" + "scala.Traversable" -> "scala.Iterable", + "scala.collection.Traversable" -> "scala.collection.Iterable", + "scala.collection.immutable.Traversable" -> "scala.collection.immutable.Iterable", + "scala.collection.mutable.Traversable" -> "scala.collection.mutable.Iterable", ) - import scala.meta.contrib._ - val hasTraversable = - ctx.tree.exists { - case traversable(_) => true - case _ => false + val traversableOnceToIterableOnce = + ctx.tree.collect { + case Type.Apply(sel @ Type.Select(chain, traversableOnce(n: Name)), _) => + val dot = chain.tokens.toList.reverse.drop(1) + + ctx.removeTokens(chain.tokens) + + ctx.removeTokens(dot) + + ctx.replaceTree(sel, "IterableOnce") - } + case Type.Apply(traversableOnce(n: Name), _) => + ctx.replaceTree(n, "IterableOnce") + + + }.asPatch val compatImport = - if (hasTraversable) addCompatImport(ctx) + if (traversableOnceToIterableOnce.nonEmpty || traversableIterator.nonEmpty) addCompatImport(ctx) else Patch.empty - traversableToIterable + compatImport + traversableOnceToIterableOnce + traversableToIterable + traversableIterator + compatImport } def replaceSymbolicFold(ctx: RuleCtx): Patch = { @@ -251,14 +264,8 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule => } } - def replaceToList(ctx: RuleCtx): Patch = { - val replaceToIterator = - ctx.tree.collect { - case iterator(t: Name) => - ctx.replaceTree(t, "iterator") - }.asPatch - - val replaceTo = + def replaceTo(ctx: RuleCtx): Patch = { + val patch = ctx.tree.collect { case Term.ApplyType(Term.Select(_, t @ toTpe(n: Name)), _) if !handledTo.contains(n) => trailingBrackets(n, ctx).map { case (open, close) => @@ -286,10 +293,10 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule => }.asPatch val compatImport = - if (replaceTo.nonEmpty) addCompatImport(ctx) + if (patch.nonEmpty) addCompatImport(ctx) else Patch.empty - compatImport + replaceToIterator + replaceTo + compatImport + patch } def replaceFuture(ctx: RuleCtx): Patch = { @@ -566,9 +573,9 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule => } override def fix(ctx: RuleCtx): Patch = { - replaceSymbols0(ctx) + + replaceTraversable(ctx) + replaceCanBuildFrom(ctx) + - replaceToList(ctx) + + replaceTo(ctx) + replaceCopyToBuffer(ctx) + replaceSymbolicFold(ctx) + replaceSetMapPlus2(ctx) + diff --git a/scalafix/tests/src/test/scala/fix/ScalafixTests.scala b/scalafix/tests/src/test/scala/fix/ScalafixTests.scala index b3f04f15..7c709fd7 100644 --- a/scalafix/tests/src/test/scala/fix/ScalafixTests.scala +++ b/scalafix/tests/src/test/scala/fix/ScalafixTests.scala @@ -6,14 +6,14 @@ import scalafix._ class ScalafixTests extends SemanticRuleSuite( - SemanticdbIndex.load(Classpath(AbsolutePath(BuildInfo.inputClassdirectory))), - AbsolutePath(BuildInfo.inputSourceroot), + SemanticdbIndex.load(Classpath(AbsolutePath(build.BuildInfo.inputClassdirectory))), + AbsolutePath(build.BuildInfo.inputSourceroot), Seq( - AbsolutePath(BuildInfo.outputSourceroot), - AbsolutePath(BuildInfo.output212Sourceroot), - AbsolutePath(BuildInfo.output213Sourceroot), - AbsolutePath(BuildInfo.output212PlusSourceroot), - AbsolutePath(BuildInfo.output213FailureSourceroot) + AbsolutePath(build.BuildInfo.outputSourceroot), + AbsolutePath(build.BuildInfo.output212Sourceroot), + AbsolutePath(build.BuildInfo.output213Sourceroot), + AbsolutePath(build.BuildInfo.output212PlusSourceroot), + AbsolutePath(build.BuildInfo.output213FailureSourceroot) ) ) {