From 15b166e46703f342152cf33b333f7b7423256822 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Fri, 19 Jan 2018 11:53:14 +0100 Subject: [PATCH 1/2] Create two distinct scalafix rules targeting 2.12 and 2.13 --- README.md | 26 +++-- build.sbt | 12 ++- .../scala/fix/Collectionstrawman_v0.scala | 0 .../Collectionstrawman_v0_Traversable.scala | 0 .../Collectionstrawman_v0_TupleNZipped.scala | 0 .../src/main/scala/fix/ConvertersTest.scala | 0 .../input/src/main/scala/fix/ListTest.scala | 0 .../scala/fix/Collectionstrawman_v0.scala | 0 .../Collectionstrawman_v0_Traversable.scala | 0 .../Collectionstrawman_v0_TupleNZipped.scala | 0 .../src/main/scala/fix/ConvertersTest.scala | 0 .../output/src/main/scala/fix/ListTest.scala | 0 .../scala/fix/Collectionstrawman_v0.scala | 0 .../scala/fix/Collectionstrawman_Tests.scala | 0 .../fix/Collectionstrawman_v0_Stream.scala | 13 +++ .../Collectionstrawman_v0_Traversable.scala | 13 +++ .../Collectionstrawman_v0_TupleNZipped.scala | 36 +++++++ .../fix/Collectionstrawman_v0_Stream.scala | 10 ++ .../Collectionstrawman_v0_Traversable.scala | 10 ++ .../Collectionstrawman_v0_TupleNZipped.scala | 33 +++++++ .../scala/fix/Collectionstrawman_v0.scala | 94 +++++++++++++++++++ .../scala/fix/Collectionstrawman_Tests.scala | 18 ++++ scalafix/build.sbt | 44 ++++++++- scalafix/project/plugins.sbt | 4 +- 24 files changed, 298 insertions(+), 15 deletions(-) rename scalafix/{ => 2.12}/input/src/main/scala/fix/Collectionstrawman_v0.scala (100%) rename scalafix/{ => 2.12}/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala (100%) rename scalafix/{ => 2.12}/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala (100%) rename scalafix/{ => 2.12}/input/src/main/scala/fix/ConvertersTest.scala (100%) rename scalafix/{ => 2.12}/input/src/main/scala/fix/ListTest.scala (100%) rename scalafix/{ => 2.12}/output/src/main/scala/fix/Collectionstrawman_v0.scala (100%) rename scalafix/{ => 2.12}/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala (100%) rename scalafix/{ => 2.12}/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala (100%) rename scalafix/{ => 2.12}/output/src/main/scala/fix/ConvertersTest.scala (100%) rename scalafix/{ => 2.12}/output/src/main/scala/fix/ListTest.scala (100%) rename scalafix/{ => 2.12}/rules/src/main/scala/fix/Collectionstrawman_v0.scala (100%) rename scalafix/{ => 2.12}/tests/src/test/scala/fix/Collectionstrawman_Tests.scala (100%) create mode 100644 scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_Stream.scala create mode 100644 scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala create mode 100644 scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala create mode 100644 scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_Stream.scala create mode 100644 scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala create mode 100644 scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala create mode 100644 scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala create mode 100644 scalafix/2.13/tests/src/test/scala/fix/Collectionstrawman_Tests.scala diff --git a/README.md b/README.md index 92ef5f84fb..ef7c7396b0 100644 --- a/README.md +++ b/README.md @@ -58,20 +58,34 @@ To use it, add the [scalafix](https://scalacenter.github.io/scalafix/) sbt plugi to your build, as explained in [its documentation](https://scalacenter.github.io/scalafix/#Installation). -Then run the following sbt task on your project: +Two situations are supported: (1) migrating a 2.12 code base to a 2.12 code base that +uses the collection strawman as a library (instead of the standard collections), and +(2) migrating a 2.12 code base to 2.13 code base. + +The migration tool is not exhaustive and we will continue to improve +it over time. If you encounter a use case that’s not supported, please +report it as described in the +[contributing documentation](CONTRIBUTING.md#migration-tool). + +#### Migrating a 2.12 code base to a 2.12 code base that uses the collection strawman as a library + +Run the following sbt task on your project: ~~~ -> scalafix github:scala/collection-strawman/v0 +> scalafix https://github.com/scala/collection-strawman/raw/master/scalafix/2.12/rules/src/main/scala/fix/Collectionstrawman_v0.scala ~~~ In essence, the migration tool changes the imports in your source code so that the strawman definitions are imported. It also rewrites expressions that use an API that is different in the strawman. -The migration tool is not exhaustive and we will continue to improve -it over time. If you encounter a use case that’s not supported, please -report it as described in the -[contributing documentation](CONTRIBUTING.md#migration-tool). +#### Migrating a 2.12 code base to 2.13 code base + +Run the following sbt task on your project: + +~~~ +> scalafix https://github.com/scala/collection-strawman/raw/master/scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala +~~~ ### Additional Operations diff --git a/build.sbt b/build.sbt index effe9b22d9..bc035dc6c8 100644 --- a/build.sbt +++ b/build.sbt @@ -5,11 +5,15 @@ import org.scalajs.sbtplugin.cross.CrossProject val dotty = settingKey[String]("dotty version") dotty in ThisBuild := "0.6.0-bin-20171212-9de3905-NIGHTLY" +val collectionsScalaVersionSettings = Seq( + scalaVersion := "2.13.0-M2", + crossScalaVersions := scalaVersion.value :: "2.12.4" :: dotty.value :: Nil +) + val commonSettings = Seq( organization := "ch.epfl.scala", version := "0.9.0-SNAPSHOT", - scalaVersion := "2.13.0-M2", - crossScalaVersions := scalaVersion.value :: "2.12.4" :: dotty.value :: Nil, + scalaVersion := "2.12.4", scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked", "-language:higherKinds"/*, "-opt:l:classpath"*/), scalacOptions ++= { if (!isDotty.value) @@ -74,6 +78,7 @@ def crossProj(id: String, base: File) = val collections = crossProj("collections", file("collections")) .settings( + collectionsScalaVersionSettings, name := "collection-strawman", scalacOptions += "-Yno-imports" ) @@ -85,6 +90,7 @@ val `collections-contrib` = crossProj("collections-contrib", file("collections-contrib")) .dependsOn(collections) .settings( + collectionsScalaVersionSettings, name := "collections-contrib" ) @@ -112,6 +118,7 @@ val junit = project.in(file("test") / "junit") .dependsOn(collectionsJVM) .settings(commonSettings ++ disablePublishing) .settings( + collectionsScalaVersionSettings, fork in Test := true, javaOptions in Test += "-Xss1M", libraryDependencies ++= Seq( @@ -129,6 +136,7 @@ val scalacheck = project.in(file("test") / "scalacheck") // Dotty 0.3.0-RC1 crashes when trying to compile this project .settings(disableDotty) .settings( + collectionsScalaVersionSettings, fork in Test := true, javaOptions in Test += "-Xss1M", libraryDependencies ++= Seq( diff --git a/scalafix/input/src/main/scala/fix/Collectionstrawman_v0.scala b/scalafix/2.12/input/src/main/scala/fix/Collectionstrawman_v0.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/Collectionstrawman_v0.scala rename to scalafix/2.12/input/src/main/scala/fix/Collectionstrawman_v0.scala diff --git a/scalafix/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala b/scalafix/2.12/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala rename to scalafix/2.12/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala diff --git a/scalafix/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala b/scalafix/2.12/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala rename to scalafix/2.12/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala diff --git a/scalafix/input/src/main/scala/fix/ConvertersTest.scala b/scalafix/2.12/input/src/main/scala/fix/ConvertersTest.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/ConvertersTest.scala rename to scalafix/2.12/input/src/main/scala/fix/ConvertersTest.scala diff --git a/scalafix/input/src/main/scala/fix/ListTest.scala b/scalafix/2.12/input/src/main/scala/fix/ListTest.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/ListTest.scala rename to scalafix/2.12/input/src/main/scala/fix/ListTest.scala diff --git a/scalafix/output/src/main/scala/fix/Collectionstrawman_v0.scala b/scalafix/2.12/output/src/main/scala/fix/Collectionstrawman_v0.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/Collectionstrawman_v0.scala rename to scalafix/2.12/output/src/main/scala/fix/Collectionstrawman_v0.scala diff --git a/scalafix/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala b/scalafix/2.12/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala rename to scalafix/2.12/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala diff --git a/scalafix/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala b/scalafix/2.12/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala rename to scalafix/2.12/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala diff --git a/scalafix/output/src/main/scala/fix/ConvertersTest.scala b/scalafix/2.12/output/src/main/scala/fix/ConvertersTest.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/ConvertersTest.scala rename to scalafix/2.12/output/src/main/scala/fix/ConvertersTest.scala diff --git a/scalafix/output/src/main/scala/fix/ListTest.scala b/scalafix/2.12/output/src/main/scala/fix/ListTest.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/ListTest.scala rename to scalafix/2.12/output/src/main/scala/fix/ListTest.scala diff --git a/scalafix/rules/src/main/scala/fix/Collectionstrawman_v0.scala b/scalafix/2.12/rules/src/main/scala/fix/Collectionstrawman_v0.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/Collectionstrawman_v0.scala rename to scalafix/2.12/rules/src/main/scala/fix/Collectionstrawman_v0.scala diff --git a/scalafix/tests/src/test/scala/fix/Collectionstrawman_Tests.scala b/scalafix/2.12/tests/src/test/scala/fix/Collectionstrawman_Tests.scala similarity index 100% rename from scalafix/tests/src/test/scala/fix/Collectionstrawman_Tests.scala rename to scalafix/2.12/tests/src/test/scala/fix/Collectionstrawman_Tests.scala diff --git a/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_Stream.scala b/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_Stream.scala new file mode 100644 index 0000000000..5d9d809d48 --- /dev/null +++ b/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_Stream.scala @@ -0,0 +1,13 @@ +/* +rule = "scala:fix.Collectionstrawman_v0" + */ +package fix + +object Collectionstrawman_v0_Stream { + Stream(1, 2, 3) + 1 #:: 2 #:: 3 #:: Stream.Empty + val isEmpty: Stream[_] => Boolean = { + case Stream.Empty => true + case x #:: xs => false + } +} diff --git a/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala b/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala new file mode 100644 index 0000000000..604a3c2bee --- /dev/null +++ b/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala @@ -0,0 +1,13 @@ +/* +rule = "scala:fix.Collectionstrawman_v0" + */ +package fix + +object Collectionstrawman_v0_Traversable { + def foo(xs: Traversable[(Int, String)], ys: List[Int]): Unit = { + xs.to[List] + xs.to[Set] + xs.toIterator + ys.iterator + } +} diff --git a/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala b/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala new file mode 100644 index 0000000000..6130a0123e --- /dev/null +++ b/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala @@ -0,0 +1,36 @@ +/* +rule = "scala:fix.Collectionstrawman_v0" + */ +package fix + +import scala.language.postfixOps +object Collectionstrawman_v0_Tuple2Zipped { + def zipped(xs: List[Int], ys: List[Int]): Unit = { + (xs, ys).zipped + (xs,ys).zipped + ((xs, ys) zipped) + (((xs) , (ys)).zipped) + (xs, // foo + ys).zipped + /* a */(/* b */ xs /* c */, /* d */ ys /* e */)/* f */./* g */zipped/* h */ + (coll(1), coll(2)).zipped + (List(1, 2, 3), Stream.from(1)).zipped + } + def coll(x: Int): List[Int] = ??? +} + +object Collectionstrawman_v0_Tuple3Zipped { + def zipped(xs: List[Int], ys: List[Int], zs: List[Int]): Unit = { + (xs, ys, zs).zipped + (xs,ys,zs).zipped + ((xs, ys, zs) zipped) + (((xs) , (ys) , (zs)).zipped) + (xs, // foo + ys, // bar + zs).zipped + /* a */(/* b */ xs /* c */, /* d */ ys /* e */, /* f */ zs /* g */)/* h */./* i */zipped/* j */ + (coll(1), coll(2), coll(3)).zipped + (List(1, 2, 3), Set(1, 2, 3), Stream.from(1)).zipped + } + def coll(x: Int): List[Int] = ??? +} \ No newline at end of file diff --git a/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_Stream.scala b/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_Stream.scala new file mode 100644 index 0000000000..88ff29fe76 --- /dev/null +++ b/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_Stream.scala @@ -0,0 +1,10 @@ +package fix + +object Collectionstrawman_v0_Stream { + LazyList(1, 2, 3) + 1 #:: 2 #:: 3 #:: LazyList.Empty + val isEmpty: LazyList[_] => Boolean = { + case LazyList.Empty => true + case x #:: xs => false + } +} diff --git a/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala b/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala new file mode 100644 index 0000000000..5f53f9c055 --- /dev/null +++ b/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_Traversable.scala @@ -0,0 +1,10 @@ +package fix + +object Collectionstrawman_v0_Traversable { + def foo(xs: Iterable[(Int, String)], ys: List[Int]): Unit = { + xs.to(List) + xs.to(Set) + xs.iterator() + ys.iterator() + } +} diff --git a/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala b/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala new file mode 100644 index 0000000000..e43cbc9545 --- /dev/null +++ b/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_TupleNZipped.scala @@ -0,0 +1,33 @@ +package fix + +import scala.language.postfixOps +object Collectionstrawman_v0_Tuple2Zipped { + def zipped(xs: List[Int], ys: List[Int]): Unit = { + xs.lazyZip(ys) + xs.lazyZip(ys) + (xs.lazyZip(ys) ) + ((xs).lazyZip((ys))) + xs.lazyZip(// foo + ys) + /* a *//* b */ xs /* c */.lazyZip(/* d */ ys /* e */)/* f *//* g *//* h */ + coll(1).lazyZip(coll(2)) + List(1, 2, 3).lazyZip(LazyList.from(1)) + } + def coll(x: Int): List[Int] = ??? +} + +object Collectionstrawman_v0_Tuple3Zipped { + def zipped(xs: List[Int], ys: List[Int], zs: List[Int]): Unit = { + xs.lazyZip(ys).lazyZip(zs) + xs.lazyZip(ys).lazyZip(zs) + (xs.lazyZip(ys).lazyZip(zs) ) + ((xs).lazyZip((ys)).lazyZip((zs))) + xs.lazyZip(// foo + ys).lazyZip(// bar + zs) + /* a *//* b */ xs /* c */.lazyZip(/* d */ ys /* e */).lazyZip(/* f */ zs /* g */)/* h *//* i *//* j */ + coll(1).lazyZip(coll(2)).lazyZip(coll(3)) + List(1, 2, 3).lazyZip(Set(1, 2, 3)).lazyZip(LazyList.from(1)) + } + def coll(x: Int): List[Int] = ??? +} \ No newline at end of file diff --git a/scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala b/scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala new file mode 100644 index 0000000000..17204f058c --- /dev/null +++ b/scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala @@ -0,0 +1,94 @@ +package fix + +import scalafix._ +import scalafix.syntax._ +import scalafix.util._ +import scala.meta._ + +case class Collectionstrawman_v0(index: SemanticdbIndex) + extends SemanticRule(index, "Collectionstrawman_v0") { + + def replaceSymbols(ctx: RuleCtx): Patch = { + ctx.replaceSymbols( + "scala.Stream" -> "scala.LazyList", + "scala.collection.immutable.Stream" -> "scala.collection.immutable.LazyList", + "scala.Traversable" -> "scala.Iterable", + "scala.collection.Traversable" -> "scala.collection.Iterable", + "scala.TraversableOnce" -> "scala.IterableOnce", + "scala.collection.TraversableOnce" -> "scala.collection.IterableOnce" + ) + } + + val toTpe = SymbolMatcher.normalized( + Symbol("_root_.scala.collection.TraversableLike.to.") + ) + val iterator = SymbolMatcher.normalized( + Symbol("_root_.scala.collection.LinearSeqLike.iterator."), + Symbol("_root_.scala.collection.TraversableLike.toIterator.") + ) + val tupleZipped = SymbolMatcher.normalized( + Symbol("_root_.scala.runtime.Tuple2Zipped.Ops.zipped."), + Symbol("_root_.scala.runtime.Tuple3Zipped.Ops.zipped.") + ) + + def replaceToList(ctx: RuleCtx) = + ctx.tree.collect { + case iterator(t: Name) => + ctx.replaceTree(t, "iterator()") + case toTpe(n: Name) => + (for { + name <- n.tokens.lastOption + open <- ctx.tokenList.find(name)(t => t.is[Token.LeftBracket]) + close <- ctx.matchingParens.close(open.asInstanceOf[Token.LeftBracket]) + } yield + ctx.replaceToken(open, "(") + + ctx.replaceToken(close, ")") + ).asPatch + }.asPatch + + def replaceTupleZipped(ctx: RuleCtx) = + ctx.tree.collect { + case tupleZipped(Term.Select(Term.Tuple(args), name)) => + val removeTokensPatch = + (for { + zipped <- name.tokens.headOption + closeTuple <- ctx.tokenList.leading(zipped).find(_.is[Token.RightParen]) + openTuple <- ctx.matchingParens.open(closeTuple.asInstanceOf[Token.RightParen]) + maybeDot = ctx.tokenList.slice(closeTuple, zipped).find(_.is[Token.Dot]) + } yield { + ctx.removeToken(openTuple) + + maybeDot.map(ctx.removeToken).asPatch + + ctx.removeToken(zipped) + }).asPatch + + def removeSurroundingWhiteSpaces(tk: Token) = + (ctx.tokenList.trailing(tk).takeWhile(_.is[Token.Space]).map(ctx.removeToken) ++ + ctx.tokenList.leading(tk).takeWhile(_.is[Token.Space]).map(ctx.removeToken)).asPatch + + val commas = + for { + (prev, next) <- args.zip(args.tail) + tokensBetweenArgs = ctx.tokenList.slice(prev.tokens.last, next.tokens.head) + comma <- tokensBetweenArgs.find(_.is[Token.Comma]) + } yield comma + + val replaceCommasPatch = commas match { + case head :: tail => + ctx.replaceToken(head, ".lazyZip(") + + removeSurroundingWhiteSpaces(head) ++ + tail.map { comma => + ctx.replaceToken(comma, ").lazyZip(") + + removeSurroundingWhiteSpaces(comma) + } + case _ => Patch.empty + } + + removeTokensPatch + replaceCommasPatch + }.asPatch + + override def fix(ctx: RuleCtx): Patch = { + replaceToList(ctx) + + replaceSymbols(ctx) + + replaceTupleZipped(ctx) + } +} diff --git a/scalafix/2.13/tests/src/test/scala/fix/Collectionstrawman_Tests.scala b/scalafix/2.13/tests/src/test/scala/fix/Collectionstrawman_Tests.scala new file mode 100644 index 0000000000..023382b63b --- /dev/null +++ b/scalafix/2.13/tests/src/test/scala/fix/Collectionstrawman_Tests.scala @@ -0,0 +1,18 @@ +package fix + +import scala.meta._ +import scalafix.testkit._ +import scalafix._ + +class Collectionstrawman_Tests + extends SemanticRuleSuite( + SemanticdbIndex.load(Classpath(AbsolutePath(BuildInfo.inputClassdirectory))), + AbsolutePath(BuildInfo.inputSourceroot), + Seq(AbsolutePath(BuildInfo.outputSourceroot)) + ) { + override def assertNoDiff(a: String, b: String, c: String) = { + println(a) + super.assertNoDiff(a, b, c) + } + runAllTests() +} diff --git a/scalafix/build.sbt b/scalafix/build.sbt index 822d6bb4f3..4600781b70 100644 --- a/scalafix/build.sbt +++ b/scalafix/build.sbt @@ -7,19 +7,22 @@ inScope(Global)( lazy val root = project .in(file(".")) - .aggregate(rules, input, output, tests) + .aggregate( + rules, input, output, tests, + `rules-2_13`, `input-2_13`, `output-2_13`, `tests-2_13` + ) -lazy val rules = project.settings( +lazy val rules = project.in(file("2.12") / "rules").settings( libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % scalafixVersion ) -lazy val input = project.settings( +lazy val input = project.in(file("2.12") / "input").settings( scalafixSourceroot := sourceDirectory.in(Compile).value ) val collections = ProjectRef(file(".."), "collectionsJVM") -lazy val output = project +lazy val output = project.in(file("2.12") / "output") .settings( resolvers := resolvers.in(collections).value, libraryDependencies ++= libraryDependencies.in(collections).value, @@ -28,7 +31,7 @@ lazy val output = project ) .dependsOn(collections) // collections/publishLocal is still necessary. -lazy val tests = project +lazy val tests = project.in(file("2.12") / "tests") .settings( libraryDependencies += "ch.epfl.scala" % "scalafix-testkit" % scalafixVersion % Test cross CrossVersion.full, buildInfoPackage := "fix", @@ -43,3 +46,34 @@ lazy val tests = project ) .dependsOn(input, rules) .enablePlugins(BuildInfoPlugin) + +lazy val `rules-2_13` = project.in(file("2.13") / "rules").settings( + libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % scalafixVersion +) + +lazy val `input-2_13` = project.in(file("2.13") / "input") + .settings( + scalafixSourceroot := sourceDirectory.in(Compile).value + ) + +lazy val `output-2_13` = project.in(file("2.13") / "output") + .settings( + resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-pr-validation-snapshots/", + scalaVersion := "2.13.0-pre-47ffa9c-SNAPSHOT" + ) + +lazy val `tests-2_13` = project.in(file("2.13") / "tests") + .settings( + libraryDependencies += "ch.epfl.scala" % "scalafix-testkit" % scalafixVersion % Test cross CrossVersion.full, + buildInfoPackage := "fix", + buildInfoKeys := Seq[BuildInfoKey]( + "inputSourceroot" -> + sourceDirectory.in(`input-2_13`, Compile).value, + "outputSourceroot" -> + sourceDirectory.in(`output-2_13`, Compile).value, + "inputClassdirectory" -> + classDirectory.in(`input-2_13`, Compile).value + ) + ) + .dependsOn(`input-2_13`, `rules-2_13`) + .enablePlugins(BuildInfoPlugin) diff --git a/scalafix/project/plugins.sbt b/scalafix/project/plugins.sbt index f97e1b876c..b23cfd7c54 100644 --- a/scalafix/project/plugins.sbt +++ b/scalafix/project/plugins.sbt @@ -1,3 +1,3 @@ -addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.3") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC10") +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.7") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.6.1") \ No newline at end of file From 7c4580b75c86e50da910bdecae82fb47d53b9f53 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Fri, 19 Jan 2018 20:11:30 +0100 Subject: [PATCH 2/2] Add copyToBuffer rule --- .../fix/Collectionstrawman_v0_copyToBuffer.scala | 13 +++++++++++++ .../fix/Collectionstrawman_v0_copyToBuffer.scala | 10 ++++++++++ .../src/main/scala/fix/Collectionstrawman_v0.scala | 13 ++++++++++++- .../test/scala/fix/Collectionstrawman_Tests.scala | 1 - 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_copyToBuffer.scala create mode 100644 scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_copyToBuffer.scala diff --git a/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_copyToBuffer.scala b/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_copyToBuffer.scala new file mode 100644 index 0000000000..a75c4fbeb7 --- /dev/null +++ b/scalafix/2.13/input/src/main/scala/fix/Collectionstrawman_v0_copyToBuffer.scala @@ -0,0 +1,13 @@ +/* +rule = "scala:fix.Collectionstrawman_v0" + */ +package fix + +import scala.collection.mutable + +class Collectionstrawman_v0_copyToBuffer(xs: List[Int], b: mutable.Buffer[Int]) { + + xs.copyToBuffer(b) + (xs ++ xs).copyToBuffer(b) + +} diff --git a/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_copyToBuffer.scala b/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_copyToBuffer.scala new file mode 100644 index 0000000000..8615a47af8 --- /dev/null +++ b/scalafix/2.13/output/src/main/scala/fix/Collectionstrawman_v0_copyToBuffer.scala @@ -0,0 +1,10 @@ +package fix + +import scala.collection.mutable + +class Collectionstrawman_v0_copyToBuffer(xs: List[Int], b: mutable.Buffer[Int]) { + + b ++= xs + b ++= xs ++ xs + +} diff --git a/scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala b/scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala index 17204f058c..191c6beade 100644 --- a/scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala +++ b/scalafix/2.13/rules/src/main/scala/fix/Collectionstrawman_v0.scala @@ -86,9 +86,20 @@ case class Collectionstrawman_v0(index: SemanticdbIndex) removeTokensPatch + replaceCommasPatch }.asPatch + val copyToBuffer = SymbolMatcher.normalized( + Symbol("_root_.scala.collection.TraversableOnce.copyToBuffer.") + ) + + def replaceCopyToBuffer(ctx: RuleCtx): Patch = + ctx.tree.collect { + case t @ q"${copyToBuffer(Term.Select(collection, _))}($buffer)" => + ctx.replaceTree(t, q"$buffer ++= $collection".syntax) + }.asPatch + override def fix(ctx: RuleCtx): Patch = { replaceToList(ctx) + replaceSymbols(ctx) + - replaceTupleZipped(ctx) + replaceTupleZipped(ctx) + + replaceCopyToBuffer(ctx) } } diff --git a/scalafix/2.13/tests/src/test/scala/fix/Collectionstrawman_Tests.scala b/scalafix/2.13/tests/src/test/scala/fix/Collectionstrawman_Tests.scala index 023382b63b..83e8edb824 100644 --- a/scalafix/2.13/tests/src/test/scala/fix/Collectionstrawman_Tests.scala +++ b/scalafix/2.13/tests/src/test/scala/fix/Collectionstrawman_Tests.scala @@ -11,7 +11,6 @@ class Collectionstrawman_Tests Seq(AbsolutePath(BuildInfo.outputSourceroot)) ) { override def assertNoDiff(a: String, b: String, c: String) = { - println(a) super.assertNoDiff(a, b, c) } runAllTests()