From 4d94ab76ebca79646fd619b5af2d781b21eb71a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Thu, 28 Jun 2018 11:46:44 +0200 Subject: [PATCH 1/9] Move LazyList and Map.mapValue rules to separate rules (fix #56) --- README.md | 2 +- .../src/main/scala/fix/BreakoutSrc.scala | 4 +- .../main/scala/fix/CanBuildFromNegSrc.scala | 2 +- .../src/main/scala/fix/CanBuildFromSrc.scala | 2 +- .../src/main/scala/fix/CopyToBufferSrc.scala | 2 +- .../input/src/main/scala/fix/FoldSrc.scala | 2 +- .../src/main/scala/fix/IterableSrc.scala | 2 +- .../src/main/scala/fix/LinearSeqSrc.scala | 2 +- .../src/main/scala/fix/MutSetMapSrc.scala | 2 +- .../input/src/main/scala/fix/RetainSrc.scala | 2 +- .../input/src/main/scala/fix/SetMapSrc.scala | 5 +- .../input/src/main/scala/fix/TestsSrc.scala | 2 +- .../src/main/scala/fix/TraversableSrc.scala | 2 +- .../src/main/scala/fix/TupleNZippedSrc.scala | 6 +- .../main/scala/fix/UnstableMapValuesSrc.scala | 8 ++ ...cala => UnstableStreamToLazyListSrc.scala} | 4 +- .../src/main/scala/fix/CopyToBufferSrc.scala | 3 + .../output/src/main/scala/fix/RetainSrc.scala | 3 + .../output/src/main/scala/fix/SetMapSrc.scala | 1 - .../src/main/scala/fix/TraversableSrc.scala | 3 + .../src/main/scala/fix/TupleNZippedSrc.scala | 7 +- .../main/scala/fix/UnstableMapValuesSrc.scala | 8 ++ ...cala => UnstableStreamToLazyListSrc.scala} | 5 +- ...mpat_newcollections.scala => Stable.scala} | 111 +++++++----------- .../main/scala/fix/UnstableMapValues.scala | 24 ++++ .../fix/UnstableStreamToLazyListSrc.scala | 35 ++++++ 26 files changed, 155 insertions(+), 94 deletions(-) create mode 100644 scalafix/input/src/main/scala/fix/UnstableMapValuesSrc.scala rename scalafix/input/src/main/scala/fix/{StreamSrc.scala => UnstableStreamToLazyListSrc.scala} (72%) create mode 100644 scalafix/output/src/main/scala/fix/UnstableMapValuesSrc.scala rename scalafix/output/src/main/scala/fix/{StreamSrc.scala => UnstableStreamToLazyListSrc.scala} (84%) rename scalafix/rules/src/main/scala/fix/{Scalacollectioncompat_newcollections.scala => Stable.scala} (91%) create mode 100644 scalafix/rules/src/main/scala/fix/UnstableMapValues.scala create mode 100644 scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala diff --git a/README.md b/README.md index 750a6690..7df65bd8 100644 --- a/README.md +++ b/README.md @@ -54,5 +54,5 @@ report it as described in the Run the following sbt task on your project: ~~~ -> scalafix github:scala/scala-collection-compat/NewCollections +> scalafix github:scala/scala-collection-compat/Stable ~~~ diff --git a/scalafix/input/src/main/scala/fix/BreakoutSrc.scala b/scalafix/input/src/main/scala/fix/BreakoutSrc.scala index 09b7e16a..a1eab243 100644 --- a/scalafix/input/src/main/scala/fix/BreakoutSrc.scala +++ b/scalafix/input/src/main/scala/fix/BreakoutSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix @@ -22,4 +22,4 @@ object BreakoutSrc { (1 +: xs)(breakOut): Set[Int] (xs :+ 1)(breakOut): Set[Int] (xs ++: xs)(breakOut): Set[Int] -} \ No newline at end of file +} diff --git a/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala b/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala index f09a0604..2a699194 100644 --- a/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala +++ b/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala index e3cf22d2..ad4480d3 100644 --- a/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala +++ b/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala b/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala index 1650bc2e..2fb19021 100644 --- a/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala +++ b/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/FoldSrc.scala b/scalafix/input/src/main/scala/fix/FoldSrc.scala index 2d259110..b97e8e53 100644 --- a/scalafix/input/src/main/scala/fix/FoldSrc.scala +++ b/scalafix/input/src/main/scala/fix/FoldSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/IterableSrc.scala b/scalafix/input/src/main/scala/fix/IterableSrc.scala index e0e0b200..0bbb6d2e 100644 --- a/scalafix/input/src/main/scala/fix/IterableSrc.scala +++ b/scalafix/input/src/main/scala/fix/IterableSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala b/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala index cebc82ae..d894f04a 100644 --- a/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala +++ b/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala b/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala index e9329ab4..d33d4d76 100644 --- a/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala +++ b/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/RetainSrc.scala b/scalafix/input/src/main/scala/fix/RetainSrc.scala index 108e859e..52cf4771 100644 --- a/scalafix/input/src/main/scala/fix/RetainSrc.scala +++ b/scalafix/input/src/main/scala/fix/RetainSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/SetMapSrc.scala b/scalafix/input/src/main/scala/fix/SetMapSrc.scala index 7f70e202..a9f0f174 100644 --- a/scalafix/input/src/main/scala/fix/SetMapSrc.scala +++ b/scalafix/input/src/main/scala/fix/SetMapSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix @@ -8,5 +8,4 @@ class SetMapSrc(set: Set[Int], map: Map[Int, Int]) { map + (2 -> 3, 3 -> 4) (set + (2, 3)).toString set + (2, 3) - 4 - map.mapValues(_ + 1) -} \ No newline at end of file +} diff --git a/scalafix/input/src/main/scala/fix/TestsSrc.scala b/scalafix/input/src/main/scala/fix/TestsSrc.scala index 861757cf..f810f134 100644 --- a/scalafix/input/src/main/scala/fix/TestsSrc.scala +++ b/scalafix/input/src/main/scala/fix/TestsSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/TraversableSrc.scala b/scalafix/input/src/main/scala/fix/TraversableSrc.scala index ca2a3c57..42ceb106 100644 --- a/scalafix/input/src/main/scala/fix/TraversableSrc.scala +++ b/scalafix/input/src/main/scala/fix/TraversableSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix diff --git a/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala b/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala index e47ff35e..61b13bcf 100644 --- a/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala +++ b/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.Stable" */ package fix @@ -14,7 +14,7 @@ object Collectionstrawman_v0_Tuple2Zipped { 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 + (List(1, 2, 3), Array(1)).zipped } def coll(x: Int): List[Int] = ??? } @@ -30,7 +30,7 @@ object Collectionstrawman_v0_Tuple3Zipped { 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 + (List(1, 2, 3), Set(1, 2, 3), Array(1)).zipped } def coll(x: Int): List[Int] = ??? } \ No newline at end of file diff --git a/scalafix/input/src/main/scala/fix/UnstableMapValuesSrc.scala b/scalafix/input/src/main/scala/fix/UnstableMapValuesSrc.scala new file mode 100644 index 00000000..6d39e8b6 --- /dev/null +++ b/scalafix/input/src/main/scala/fix/UnstableMapValuesSrc.scala @@ -0,0 +1,8 @@ +/* +rule = "scala:fix.UnstableMapValues" + */ +package fix + +class UnstableMapValuesSrc(map: Map[Int, Int]) { + map.mapValues(_ + 1) +} diff --git a/scalafix/input/src/main/scala/fix/StreamSrc.scala b/scalafix/input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala similarity index 72% rename from scalafix/input/src/main/scala/fix/StreamSrc.scala rename to scalafix/input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala index 70d2df9e..80bd9940 100644 --- a/scalafix/input/src/main/scala/fix/StreamSrc.scala +++ b/scalafix/input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala @@ -1,9 +1,9 @@ /* -rule = "scala:fix.Scalacollectioncompat_newcollections" +rule = "scala:fix.UnstableStreamToLazyList" */ package fix -object StreamSrc { +class UnstableStreamToLazyListSrc() { val s = Stream(1, 2, 3) s.append(List(4, 5, 6)) 1 #:: 2 #:: 3 #:: Stream.Empty diff --git a/scalafix/output/src/main/scala/fix/CopyToBufferSrc.scala b/scalafix/output/src/main/scala/fix/CopyToBufferSrc.scala index e254f68c..56af8579 100644 --- a/scalafix/output/src/main/scala/fix/CopyToBufferSrc.scala +++ b/scalafix/output/src/main/scala/fix/CopyToBufferSrc.scala @@ -1,3 +1,6 @@ + + + package fix import scala.collection.mutable diff --git a/scalafix/output/src/main/scala/fix/RetainSrc.scala b/scalafix/output/src/main/scala/fix/RetainSrc.scala index c5ed3707..a41edbcb 100644 --- a/scalafix/output/src/main/scala/fix/RetainSrc.scala +++ b/scalafix/output/src/main/scala/fix/RetainSrc.scala @@ -1,3 +1,6 @@ + + + package fix import scala.collection.mutable.{Map, Set} diff --git a/scalafix/output/src/main/scala/fix/SetMapSrc.scala b/scalafix/output/src/main/scala/fix/SetMapSrc.scala index 526be356..2aa2afbd 100644 --- a/scalafix/output/src/main/scala/fix/SetMapSrc.scala +++ b/scalafix/output/src/main/scala/fix/SetMapSrc.scala @@ -8,5 +8,4 @@ class SetMapSrc(set: Set[Int], map: Map[Int, Int]) { map + (2 -> 3) + (3 -> 4) (set + 2 + 3).toString set + 2 + 3 - 4 - map.mapValues(_ + 1).toMap } \ No newline at end of file diff --git a/scalafix/output/src/main/scala/fix/TraversableSrc.scala b/scalafix/output/src/main/scala/fix/TraversableSrc.scala index e8232467..096f01d8 100644 --- a/scalafix/output/src/main/scala/fix/TraversableSrc.scala +++ b/scalafix/output/src/main/scala/fix/TraversableSrc.scala @@ -1,3 +1,6 @@ + + + package fix object TraversableSrc { diff --git a/scalafix/output/src/main/scala/fix/TupleNZippedSrc.scala b/scalafix/output/src/main/scala/fix/TupleNZippedSrc.scala index e43cbc95..0bf471ad 100644 --- a/scalafix/output/src/main/scala/fix/TupleNZippedSrc.scala +++ b/scalafix/output/src/main/scala/fix/TupleNZippedSrc.scala @@ -1,3 +1,6 @@ + + + package fix import scala.language.postfixOps @@ -11,7 +14,7 @@ object Collectionstrawman_v0_Tuple2Zipped { 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)) + List(1, 2, 3).lazyZip(Array(1)) } def coll(x: Int): List[Int] = ??? } @@ -27,7 +30,7 @@ object Collectionstrawman_v0_Tuple3Zipped { 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)) + List(1, 2, 3).lazyZip(Set(1, 2, 3)).lazyZip(Array(1)) } def coll(x: Int): List[Int] = ??? } \ No newline at end of file diff --git a/scalafix/output/src/main/scala/fix/UnstableMapValuesSrc.scala b/scalafix/output/src/main/scala/fix/UnstableMapValuesSrc.scala new file mode 100644 index 00000000..8952272a --- /dev/null +++ b/scalafix/output/src/main/scala/fix/UnstableMapValuesSrc.scala @@ -0,0 +1,8 @@ + + + +package fix + +class UnstableMapValuesSrc(map: Map[Int, Int]) { + map.mapValues(_ + 1).toMap +} diff --git a/scalafix/output/src/main/scala/fix/StreamSrc.scala b/scalafix/output/src/main/scala/fix/UnstableStreamToLazyListSrc.scala similarity index 84% rename from scalafix/output/src/main/scala/fix/StreamSrc.scala rename to scalafix/output/src/main/scala/fix/UnstableStreamToLazyListSrc.scala index 8f79829f..db6e3a56 100644 --- a/scalafix/output/src/main/scala/fix/StreamSrc.scala +++ b/scalafix/output/src/main/scala/fix/UnstableStreamToLazyListSrc.scala @@ -1,6 +1,9 @@ + + + package fix -object StreamSrc { +class UnstableStreamToLazyListSrc() { val s = LazyList(1, 2, 3) s.lazyAppendedAll(List(4, 5, 6)) 1 #:: 2 #:: 3 #:: LazyList.Empty diff --git a/scalafix/rules/src/main/scala/fix/Scalacollectioncompat_newcollections.scala b/scalafix/rules/src/main/scala/fix/Stable.scala similarity index 91% rename from scalafix/rules/src/main/scala/fix/Scalacollectioncompat_newcollections.scala rename to scalafix/rules/src/main/scala/fix/Stable.scala index 3c3662a0..89ae2d56 100644 --- a/scalafix/rules/src/main/scala/fix/Scalacollectioncompat_newcollections.scala +++ b/scalafix/rules/src/main/scala/fix/Stable.scala @@ -5,8 +5,7 @@ import scalafix.syntax._ import scalafix.util._ import scala.meta._ -case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) - extends SemanticRule(index, "Scalacollectioncompat_newcollections") { +case class Stable(index: SemanticdbIndex) extends SemanticRule(index, "Stable") { // Two rules triggers the same rewrite TraversableLike.to and CanBuildFrom // we keep track of what is handled in CanBuildFrom and guard against TraversableLike.to @@ -29,8 +28,6 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) def replaceSymbols(ctx: RuleCtx): Patch = { ctx.replaceSymbols( "scala.collection.LinearSeq" -> "scala.collection.immutable.List", - "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", @@ -38,17 +35,17 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) ) } - val collectionCanBuildFrom = + val collectionCanBuildFrom = SymbolMatcher.exact( Symbol("_root_.scala.collection.generic.CanBuildFrom#") ) - val collectionCanBuildFromImport = + val collectionCanBuildFromImport = SymbolMatcher.exact( Symbol("_root_.scala.collection.generic.CanBuildFrom.;_root_.scala.collection.generic.CanBuildFrom#") ) - - val nothing = + + val nothing = SymbolMatcher.exact( Symbol("_root_.scala.Nothing#") ) @@ -75,18 +72,18 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) val mutMapPlus = SymbolMatcher.exact( Symbol("_root_.scala.collection.mutable.MapLike#`+`(Lscala/Tuple2;)Lscala/collection/mutable/Map;.") ) - val mutMapUpdate = + val mutMapUpdate = SymbolMatcher.exact( Symbol("_root_.scala.collection.mutable.MapLike#updated(Ljava/lang/Object;Ljava/lang/Object;)Lscala/collection/mutable/Map;.") ) - val iterableSameElement = + val iterableSameElement = SymbolMatcher.exact( Symbol("_root_.scala.collection.IterableLike#sameElements(Lscala/collection/GenIterable;)Z.") ) def foldSymbol(isLeft: Boolean): SymbolMatcher = { - val op = + val op = if (isLeft) "/:" else ":\\" @@ -95,23 +92,20 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) val foldLeftSymbol = foldSymbol(isLeft = true) val foldRightSymbol = foldSymbol(isLeft = false) - val retainMap = + val retainMap = SymbolMatcher.normalized( Symbol("_root_.scala.collection.mutable.MapLike.retain.") ) - val mapMapValues = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.immutable.MapLike#mapValues(Lscala/Function1;)Lscala/collection/immutable/Map;.") - ) - val retainSet = + + val retainSet = SymbolMatcher.normalized( Symbol("_root_.scala.collection.mutable.SetLike.retain.") ) - val arrayBuilderMake = + val arrayBuilderMake = SymbolMatcher.normalized( Symbol("_root_.scala.collection.mutable.ArrayBuilder.make(Lscala/reflect/ClassTag;)Lscala/collection/mutable/ArrayBuilder;.") ) @@ -153,24 +147,24 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) val functionsReverseIteratorSymbols = List(`SeqLike.reverseMap`) val functionsSymbols = functionsIteratorSymbols ++ functionsViewSymbols ++ functionsReverseIteratorSymbols - val functionsIterator = SymbolMatcher.exact(functionsIteratorSymbols: _*) - val functionsReverseIterator = SymbolMatcher.exact(functionsReverseIteratorSymbols: _*) - val functionsView = SymbolMatcher.exact(functionsViewSymbols: _*) - val functions = SymbolMatcher.exact(functionsSymbols: _*) + val functionsIterator = SymbolMatcher.exact(functionsIteratorSymbols: _*) + val functionsReverseIterator = SymbolMatcher.exact(functionsReverseIteratorSymbols: _*) + val functionsView = SymbolMatcher.exact(functionsViewSymbols: _*) + val functions = SymbolMatcher.exact(functionsSymbols: _*) // special select // iterator val `TraversableLike.scanLeft` = SymbolMatcher.exact(Symbol("_root_.scala.collection.TraversableLike#scanLeft(Ljava/lang/Object;Lscala/Function2;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")) - def isLeftAssociative(tree: Tree): Boolean = + def isLeftAssociative(tree: Tree): Boolean = tree match { case Term.Name(value) => value.last != ':' case _ => false } } - def startsWithParens(tree: Tree): Boolean = + def startsWithParens(tree: Tree): Boolean = tree.tokens.headOption.map(_.is[Token.LeftParen]).getOrElse(false) def replaceMutableSet(ctx: RuleCtx) = @@ -192,9 +186,9 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) }.asPatch }.asPatch - def replaceSymbolicFold(ctx: RuleCtx) = + def replaceSymbolicFold(ctx: RuleCtx) = ctx.tree.collect { - case Term.Apply(ap @ Term.ApplyInfix(rhs, foldRightSymbol(_), _, List(lhs)), _) => + case Term.Apply(ap @ Term.ApplyInfix(rhs, foldRightSymbol(_), _, List(lhs)), _) => ctx.replaceTree(ap, s"$rhs.foldRight($lhs)") case Term.Apply(ap @ Term.ApplyInfix(lhs, foldLeftSymbol(_), _, List(rhs)), _) => @@ -261,16 +255,6 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) ctx.replaceTree(t, q"$buffer ++= $collection".syntax) }.asPatch - val streamAppend = SymbolMatcher.normalized( - Symbol("_root_.scala.collection.immutable.Stream.append.") - ) - - def replaceStreamAppend(ctx: RuleCtx): Patch = - ctx.tree.collect { - case streamAppend(t: Name) => - ctx.replaceTree(t, "lazyAppendedAll") - }.asPatch - def replaceSetMapPlus2(ctx: RuleCtx): Patch = { def rewritePlus(ap: Term.ApplyInfix, lhs: Term, op: Term.Name, rhs1: Term, rhs2: Term): Patch = { val tokensToReplace = @@ -279,7 +263,7 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) ap.tokens.slice(1, ap.tokens.size - 1) } else ap.tokens - val newTree = + val newTree = Term.ApplyInfix( Term.ApplyInfix(lhs, op, Nil, List(rhs1)), op, @@ -339,15 +323,6 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) ctx.removeTokens(extraParens) }.asPatch } - - - - def replaceMapMapValues(ctx: RuleCtx): Patch = { - ctx.tree.collect { - case ap @ Term.Apply(Term.Select(_, mapMapValues(_)), List(_)) => - ctx.addRight(ap, ".toMap") - }.asPatch - } object CanBuildFromNothing { def apply(paramss: List[List[Term.Param]], body: Term, ctx: RuleCtx): Patch = { @@ -355,12 +330,12 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) case Term.Param( List(Mod.Implicit()), - param, + param, Some( tpe @ Type.Apply( - collectionCanBuildFrom(_), + collectionCanBuildFrom(_), List( - nothing(_), + nothing(_), t, cct @ Type.Apply( cc, @@ -396,13 +371,13 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) // don't patch cbf.apply twice (cbf.apply and cbf.apply()) val visitedCbfCalls = scala.collection.mutable.Set[Tree]() - val cbfCalls = + val cbfCalls = body.collect { // cbf.apply() case ap @ Term.Apply(sel @ Term.Select(cbf2 @ matchCbf(_), apply), Nil) => visitedCbfCalls += sel replaceNewBuilder(ap, cbf2) - + // cbf.apply case sel @ Term.Select(cbf2 @ matchCbf(_), ap) if (!visitedCbfCalls.contains(sel)) => replaceNewBuilder(sel, cbf2) @@ -439,11 +414,11 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) // implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] => // implicit cbf: collection.Factory[Int, CC[Int]] - val parameterType = + val parameterType = ctx.replaceTree( tpe, Type.Apply(Type.Name("collection.Factory"), List(t, cct)).syntax - ) + ) parameterType + cbfCalls + toCalls } @@ -468,7 +443,7 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) param, Some( Type.Apply( - cbf @ collectionCanBuildFrom(_), + cbf @ collectionCanBuildFrom(_), List(p1, _, _) ) ), @@ -494,7 +469,7 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) Term.Apply(Term.Select(cbf2, Term.Name("newBuilder")), List(x)).syntax ) - val cbfCalls = + val cbfCalls = body.collect { // cbf.apply(x) case ap @ Term.Apply(sel @ Term.Select(cbf2 @ matchCbf(_), apply), List(x)) => @@ -505,7 +480,7 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) replaceNewBuilder(ap, cbf2, x) }.asPatch - val parameterType = + val parameterType = ctx.replaceTree(cbf, "collection.BuildFrom") parameterType + cbfCalls @@ -532,7 +507,7 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) def replaceBreakout(ctx: RuleCtx): Patch = { import Breakout._ - + def fixIt(intermediate: String, lhs: Term, ap: Term, breakout: Tree): Patch = { ctx.addRight(lhs, "." + intermediate) + ctx.addRight(ap, ".to") + @@ -548,18 +523,18 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) if(isLeftAssociative(op)) lhs else rhs - val intermediate = + val intermediate = op match { case operatorsIterator(_) => "iterator" case operatorsView(_) => "view" // since operators(op) matches iterator and view case _ => throw new Exception("impossible") } - + fixIt(intermediate, subject, ap, bo) case Term.Apply(ap @ Term.Apply(Term.Select(lhs, functions(op)), _), List(breakOut(bo))) => - val intermediate = + val intermediate = op match { case functionsIterator(_) => "iterator" case functionsView(_) => "view" @@ -573,33 +548,31 @@ case class Scalacollectioncompat_newcollections(index: SemanticdbIndex) else Patch.empty val isReversed = `SeqLike.reverseMap`.exact(op) - val replaceReverseMap = + val replaceReverseMap = if (isReversed) ctx.replaceTree(op, "map") else Patch.empty - + fixIt(intermediate, lhs, ap, bo) + replaceUnion + replaceReverseMap - case Term.Apply(ap @ Term.Apply(Term.Apply(Term.Select(lhs, `TraversableLike.scanLeft`(op)), _), _), List(breakOut(bo))) => + case Term.Apply(ap @ Term.Apply(Term.Apply(Term.Select(lhs, `TraversableLike.scanLeft`(op)), _), _), List(breakOut(bo))) => fixIt("iterator", lhs, ap, bo) }.asPatch } - + override def fix(ctx: RuleCtx): Patch = { replaceCanBuildFrom(ctx) + replaceToList(ctx) + replaceSymbols(ctx) + replaceTupleZipped(ctx) + replaceCopyToBuffer(ctx) + - replaceStreamAppend(ctx) + - replaceMutableMap(ctx) + + replaceMutableMap(ctx) + replaceMutableSet(ctx) + replaceSymbolicFold(ctx) + replaceSetMapPlus2(ctx) + replaceMutSetMapPlus(ctx) + replaceMutMapUpdated(ctx) + replaceArrayBuilderMake(ctx) + - replaceIterableSameElements(ctx) + - replaceMapMapValues(ctx) + - replaceBreakout(ctx) + replaceBreakout(ctx) + + replaceIterableSameElements(ctx) } } diff --git a/scalafix/rules/src/main/scala/fix/UnstableMapValues.scala b/scalafix/rules/src/main/scala/fix/UnstableMapValues.scala new file mode 100644 index 00000000..a1c2f797 --- /dev/null +++ b/scalafix/rules/src/main/scala/fix/UnstableMapValues.scala @@ -0,0 +1,24 @@ +package fix + +import scalafix._ +import scalafix.syntax._ +import scalafix.util._ +import scala.meta._ + + +/* + * This rules is marked unstable since Map.mapValues was lazy + */ +case class UnstableMapValues(index: SemanticdbIndex) extends SemanticRule(index, "UnstableMapValues") { + val mapMapValues = + SymbolMatcher.exact( + Symbol("_root_.scala.collection.immutable.MapLike#mapValues(Lscala/Function1;)Lscala/collection/immutable/Map;.") + ) + + override def fix(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case ap @ Term.Apply(Term.Select(_, mapMapValues(_)), List(_)) => + ctx.addRight(ap, ".toMap") + }.asPatch + } +} diff --git a/scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala new file mode 100644 index 00000000..8421af88 --- /dev/null +++ b/scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala @@ -0,0 +1,35 @@ +package fix + +import scalafix._ +import scalafix.syntax._ +import scalafix.util._ +import scala.meta._ + +/* + * This rules is marked unstable since Stream is not strictly equivalent to LazyList. + * LazyList has a lazy head but not Stream + */ +case class UnstableStreamToLazyList(index: SemanticdbIndex) extends SemanticRule(index, "UnstableStreamToLazyList") { + + val streamAppend = SymbolMatcher.normalized( + Symbol("_root_.scala.collection.immutable.Stream.append.") + ) + + def replaceStreamAppend(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case streamAppend(t: Name) => + ctx.replaceTree(t, "lazyAppendedAll") + }.asPatch + } + + def replaceSymbols(ctx: RuleCtx): Patch = { + ctx.replaceSymbols( + "scala.Stream" -> "scala.LazyList", + "scala.collection.immutable.Stream" -> "scala.collection.immutable.LazyList" + ) + } + + override def fix(ctx: RuleCtx): Patch = { + replaceStreamAppend(ctx) + replaceSymbols(ctx) + } +} From b1a314c2b98b0a154b9cd50c4f8ea5bb5af4432a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Thu, 28 Jun 2018 13:42:44 +0200 Subject: [PATCH 2/9] Split rules that can be used to cross compile --- admin/build.sh | 2 +- scalafix/build.sbt | 23 +- .../src/main/scala/fix/BreakoutSrc.scala | 2 +- .../main/scala/fix/CanBuildFromNegSrc.scala | 2 +- .../src/main/scala/fix/CanBuildFromSrc.scala | 2 +- .../src/main/scala/fix/CopyToBufferSrc.scala | 4 +- .../input/src/main/scala/fix/FoldSrc.scala | 2 +- .../src/main/scala/fix/IterableSrc.scala | 4 +- .../src/main/scala/fix/LinearSeqSrc.scala | 2 +- .../src/main/scala/fix/MutSetMapSrc.scala | 4 +- .../input/src/main/scala/fix/RetainSrc.scala | 4 +- .../input/src/main/scala/fix/SetMapSrc.scala | 2 +- .../input/src/main/scala/fix/TestsSrc.scala | 2 +- .../src/main/scala/fix/TraversableSrc.scala | 2 +- .../src/main/scala/fix/TupleNZippedSrc.scala | 4 +- .../src/main/scala/fix/CopyToBufferSrc.scala | 2 - .../src/main/scala/fix/ExperimentalSrc.scala | 0 .../src/main/scala/fix/FoldSrc.scala | 0 .../src/main/scala/fix/LinearSeqSrc.scala | 0 .../src/main/scala/fix/MutSetMapSrc.scala | 0 .../src/main/scala/fix/SetMapSrc.scala | 0 .../src/main/scala/fix/TestsSrc.scala | 0 .../main/scala/fix/UnstableMapValuesSrc.scala | 0 .../main/scala/fix/CanBuildFromNegSrc.scala | 0 .../src/main/scala/fix/BreakoutSrc.scala | 2 +- .../src/main/scala/fix/CanBuildFromSrc.scala | 0 .../src/main/scala/fix/IterableSrc.scala | 2 +- .../src/main/scala/fix/RetainSrc.scala | 2 +- .../src/main/scala/fix/TraversableSrc.scala | 0 .../src/main/scala/fix/TupleNZippedSrc.scala | 2 +- .../fix/UnstableStreamToLazyListSrc.scala | 0 .../src/main/scala/fix/CanBuildFrom.scala | 195 ++++++ .../src/main/scala/fix/CrossCompat.scala | 5 + .../src/main/scala/fix/Experimental.scala | 54 +- .../src/main/scala/fix/NewCollections.scala | 256 ++++++++ .../rules/src/main/scala/fix/Stable.scala | 578 ------------------ .../src/main/scala/fix/Stable212Base.scala | 129 ++++ .../src/main/scala/fix/TypeMatcher.scala | 22 + .../main/scala/fix/UnstableMapValues.scala | 5 +- .../fix/UnstableStreamToLazyListSrc.scala | 5 +- .../rules/src/main/scala/fix/package.scala | 29 + .../scala/fix/Collectionstrawman_Tests.scala | 5 +- 42 files changed, 693 insertions(+), 661 deletions(-) rename scalafix/{output => output212}/src/main/scala/fix/CopyToBufferSrc.scala (98%) rename scalafix/{output => output212}/src/main/scala/fix/ExperimentalSrc.scala (100%) rename scalafix/{output => output212}/src/main/scala/fix/FoldSrc.scala (100%) rename scalafix/{output => output212}/src/main/scala/fix/LinearSeqSrc.scala (100%) rename scalafix/{output => output212}/src/main/scala/fix/MutSetMapSrc.scala (100%) rename scalafix/{output => output212}/src/main/scala/fix/SetMapSrc.scala (100%) rename scalafix/{output => output212}/src/main/scala/fix/TestsSrc.scala (100%) rename scalafix/{output => output212}/src/main/scala/fix/UnstableMapValuesSrc.scala (100%) rename scalafix/{output-failure => output213-failure}/src/main/scala/fix/CanBuildFromNegSrc.scala (100%) rename scalafix/{output => output213}/src/main/scala/fix/BreakoutSrc.scala (99%) rename scalafix/{output => output213}/src/main/scala/fix/CanBuildFromSrc.scala (100%) rename scalafix/{output => output213}/src/main/scala/fix/IterableSrc.scala (97%) rename scalafix/{output => output213}/src/main/scala/fix/RetainSrc.scala (99%) rename scalafix/{output => output213}/src/main/scala/fix/TraversableSrc.scala (100%) rename scalafix/{output => output213}/src/main/scala/fix/TupleNZippedSrc.scala (99%) rename scalafix/{output => output213}/src/main/scala/fix/UnstableStreamToLazyListSrc.scala (100%) create mode 100644 scalafix/rules/src/main/scala/fix/CanBuildFrom.scala create mode 100644 scalafix/rules/src/main/scala/fix/CrossCompat.scala create mode 100644 scalafix/rules/src/main/scala/fix/NewCollections.scala delete mode 100644 scalafix/rules/src/main/scala/fix/Stable.scala create mode 100644 scalafix/rules/src/main/scala/fix/Stable212Base.scala create mode 100644 scalafix/rules/src/main/scala/fix/TypeMatcher.scala create mode 100644 scalafix/rules/src/main/scala/fix/package.scala diff --git a/admin/build.sh b/admin/build.sh index bffec523..9d13ccb0 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -19,7 +19,7 @@ set -e RELEASE_COMBO=true if [[ "$TEST_SCALAFIX" == "true" ]]; then - cd scalafix && sbt input/compile output/compile tests/test + cd scalafix && sbt tests/test exit 0 fi diff --git a/scalafix/build.sbt b/scalafix/build.sbt index 9406fe10..98e41d20 100644 --- a/scalafix/build.sbt +++ b/scalafix/build.sbt @@ -8,7 +8,7 @@ inScope(Global)( lazy val root = project .in(file(".")) .aggregate( - rules, input, output, tests + rules, input, output212, output213, output213Failure, tests ) lazy val rules = project.settings( @@ -20,13 +20,15 @@ lazy val input = project scalafixSourceroot := sourceDirectory.in(Compile).value ) -lazy val output = project +lazy val output212 = project + +lazy val output213 = project .settings( resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/", scalaVersion := "2.13.0-M4" ) -lazy val outputFailure = project.in(file("output-failure")) +lazy val output213Failure = project.in(file("output213-failure")) .settings( resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/", scalaVersion := "2.13.0-M4" @@ -39,14 +41,19 @@ lazy val tests = project buildInfoKeys := Seq[BuildInfoKey]( "inputSourceroot" -> sourceDirectory.in(input, Compile).value, - "outputSourceroot" -> - sourceDirectory.in(output, Compile).value, - "outputFailureSourceroot" -> - sourceDirectory.in(outputFailure, Compile).value, + "output212Sourceroot" -> + sourceDirectory.in(output212, Compile).value, + "output213Sourceroot" -> + sourceDirectory.in(output213, Compile).value, + "output213FailureSourceroot" -> + sourceDirectory.in(output213Failure, Compile).value, "inputClassdirectory" -> classDirectory.in(input, Compile).value ), - test in Test := (test in Test).dependsOn(compile in (output, Compile)).value + test in Test := (test in Test).dependsOn( + compile in (output212, Compile), + compile in (output213, Compile) + ).value ) .dependsOn(input, rules) .enablePlugins(BuildInfoPlugin) diff --git a/scalafix/input/src/main/scala/fix/BreakoutSrc.scala b/scalafix/input/src/main/scala/fix/BreakoutSrc.scala index a1eab243..50382e33 100644 --- a/scalafix/input/src/main/scala/fix/BreakoutSrc.scala +++ b/scalafix/input/src/main/scala/fix/BreakoutSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.NewCollections" */ package fix diff --git a/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala b/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala index 2a699194..138b6d8e 100644 --- a/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala +++ b/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.NewCollections" */ package fix diff --git a/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala index ad4480d3..34c79003 100644 --- a/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala +++ b/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.NewCollections" */ package fix diff --git a/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala b/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala index 2fb19021..071e0385 100644 --- a/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala +++ b/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala @@ -1,13 +1,11 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.CrossCompat" */ package fix import scala.collection.mutable class CopyToBufferSrc(xs: List[Int], b: mutable.Buffer[Int]) { - xs.copyToBuffer(b) (xs ++ xs).copyToBuffer(b) - } diff --git a/scalafix/input/src/main/scala/fix/FoldSrc.scala b/scalafix/input/src/main/scala/fix/FoldSrc.scala index b97e8e53..2e5970ac 100644 --- a/scalafix/input/src/main/scala/fix/FoldSrc.scala +++ b/scalafix/input/src/main/scala/fix/FoldSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.CrossCompat" */ package fix diff --git a/scalafix/input/src/main/scala/fix/IterableSrc.scala b/scalafix/input/src/main/scala/fix/IterableSrc.scala index 0bbb6d2e..8735a55b 100644 --- a/scalafix/input/src/main/scala/fix/IterableSrc.scala +++ b/scalafix/input/src/main/scala/fix/IterableSrc.scala @@ -1,8 +1,8 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.NewCollections" */ package fix class IterableSrc(it: Iterable[Int]) { it.sameElements(it) -} \ No newline at end of file +} diff --git a/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala b/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala index d894f04a..d60f5072 100644 --- a/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala +++ b/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.CrossCompat" */ package fix diff --git a/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala b/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala index d33d4d76..6b111ffb 100644 --- a/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala +++ b/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.CrossCompat" */ package fix @@ -10,4 +10,4 @@ class MutSetMapSrc(map: mutable.Map[Int, Int], set: mutable.Set[Int]) { map + (2 -> 3) (set + 2).size map.updated(1, 3) -} \ No newline at end of file +} diff --git a/scalafix/input/src/main/scala/fix/RetainSrc.scala b/scalafix/input/src/main/scala/fix/RetainSrc.scala index 52cf4771..f5bc3040 100644 --- a/scalafix/input/src/main/scala/fix/RetainSrc.scala +++ b/scalafix/input/src/main/scala/fix/RetainSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.NewCollections" */ package fix @@ -9,4 +9,4 @@ class MethodRenames(xs: Map[Int, Int], ys: Set[Int]) { xs.retain((_, _) => true) xs.retain{case (x, y) => true} ys.retain(_ => true) -} \ No newline at end of file +} diff --git a/scalafix/input/src/main/scala/fix/SetMapSrc.scala b/scalafix/input/src/main/scala/fix/SetMapSrc.scala index a9f0f174..fd31fa34 100644 --- a/scalafix/input/src/main/scala/fix/SetMapSrc.scala +++ b/scalafix/input/src/main/scala/fix/SetMapSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.CrossCompat" */ package fix diff --git a/scalafix/input/src/main/scala/fix/TestsSrc.scala b/scalafix/input/src/main/scala/fix/TestsSrc.scala index f810f134..876995b5 100644 --- a/scalafix/input/src/main/scala/fix/TestsSrc.scala +++ b/scalafix/input/src/main/scala/fix/TestsSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.CrossCompat" */ package fix diff --git a/scalafix/input/src/main/scala/fix/TraversableSrc.scala b/scalafix/input/src/main/scala/fix/TraversableSrc.scala index 42ceb106..8560160e 100644 --- a/scalafix/input/src/main/scala/fix/TraversableSrc.scala +++ b/scalafix/input/src/main/scala/fix/TraversableSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.NewCollections" */ package fix diff --git a/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala b/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala index 61b13bcf..0390857d 100644 --- a/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala +++ b/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.Stable" +rule = "scala:fix.NewCollections" */ package fix @@ -33,4 +33,4 @@ object Collectionstrawman_v0_Tuple3Zipped { (List(1, 2, 3), Set(1, 2, 3), Array(1)).zipped } def coll(x: Int): List[Int] = ??? -} \ No newline at end of file +} diff --git a/scalafix/output/src/main/scala/fix/CopyToBufferSrc.scala b/scalafix/output212/src/main/scala/fix/CopyToBufferSrc.scala similarity index 98% rename from scalafix/output/src/main/scala/fix/CopyToBufferSrc.scala rename to scalafix/output212/src/main/scala/fix/CopyToBufferSrc.scala index 56af8579..b3f33c9e 100644 --- a/scalafix/output/src/main/scala/fix/CopyToBufferSrc.scala +++ b/scalafix/output212/src/main/scala/fix/CopyToBufferSrc.scala @@ -6,8 +6,6 @@ package fix import scala.collection.mutable class CopyToBufferSrc(xs: List[Int], b: mutable.Buffer[Int]) { - b ++= xs b ++= xs ++ xs - } diff --git a/scalafix/output/src/main/scala/fix/ExperimentalSrc.scala b/scalafix/output212/src/main/scala/fix/ExperimentalSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/ExperimentalSrc.scala rename to scalafix/output212/src/main/scala/fix/ExperimentalSrc.scala diff --git a/scalafix/output/src/main/scala/fix/FoldSrc.scala b/scalafix/output212/src/main/scala/fix/FoldSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/FoldSrc.scala rename to scalafix/output212/src/main/scala/fix/FoldSrc.scala diff --git a/scalafix/output/src/main/scala/fix/LinearSeqSrc.scala b/scalafix/output212/src/main/scala/fix/LinearSeqSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/LinearSeqSrc.scala rename to scalafix/output212/src/main/scala/fix/LinearSeqSrc.scala diff --git a/scalafix/output/src/main/scala/fix/MutSetMapSrc.scala b/scalafix/output212/src/main/scala/fix/MutSetMapSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/MutSetMapSrc.scala rename to scalafix/output212/src/main/scala/fix/MutSetMapSrc.scala diff --git a/scalafix/output/src/main/scala/fix/SetMapSrc.scala b/scalafix/output212/src/main/scala/fix/SetMapSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/SetMapSrc.scala rename to scalafix/output212/src/main/scala/fix/SetMapSrc.scala diff --git a/scalafix/output/src/main/scala/fix/TestsSrc.scala b/scalafix/output212/src/main/scala/fix/TestsSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/TestsSrc.scala rename to scalafix/output212/src/main/scala/fix/TestsSrc.scala diff --git a/scalafix/output/src/main/scala/fix/UnstableMapValuesSrc.scala b/scalafix/output212/src/main/scala/fix/UnstableMapValuesSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/UnstableMapValuesSrc.scala rename to scalafix/output212/src/main/scala/fix/UnstableMapValuesSrc.scala diff --git a/scalafix/output-failure/src/main/scala/fix/CanBuildFromNegSrc.scala b/scalafix/output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala similarity index 100% rename from scalafix/output-failure/src/main/scala/fix/CanBuildFromNegSrc.scala rename to scalafix/output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala diff --git a/scalafix/output/src/main/scala/fix/BreakoutSrc.scala b/scalafix/output213/src/main/scala/fix/BreakoutSrc.scala similarity index 99% rename from scalafix/output/src/main/scala/fix/BreakoutSrc.scala rename to scalafix/output213/src/main/scala/fix/BreakoutSrc.scala index e9ef5a05..7a086ec5 100644 --- a/scalafix/output/src/main/scala/fix/BreakoutSrc.scala +++ b/scalafix/output213/src/main/scala/fix/BreakoutSrc.scala @@ -21,4 +21,4 @@ object BreakoutSrc { (1 +: xs.view).to(implicitly): Set[Int] (xs.view :+ 1).to(implicitly): Set[Int] (xs ++: xs.view).to(implicitly): Set[Int] -} \ No newline at end of file +} diff --git a/scalafix/output/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix/output213/src/main/scala/fix/CanBuildFromSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/CanBuildFromSrc.scala rename to scalafix/output213/src/main/scala/fix/CanBuildFromSrc.scala diff --git a/scalafix/output/src/main/scala/fix/IterableSrc.scala b/scalafix/output213/src/main/scala/fix/IterableSrc.scala similarity index 97% rename from scalafix/output/src/main/scala/fix/IterableSrc.scala rename to scalafix/output213/src/main/scala/fix/IterableSrc.scala index cd6b3c9a..cda2811d 100644 --- a/scalafix/output/src/main/scala/fix/IterableSrc.scala +++ b/scalafix/output213/src/main/scala/fix/IterableSrc.scala @@ -5,4 +5,4 @@ package fix class IterableSrc(it: Iterable[Int]) { it.iterator.sameElements(it) -} \ No newline at end of file +} diff --git a/scalafix/output/src/main/scala/fix/RetainSrc.scala b/scalafix/output213/src/main/scala/fix/RetainSrc.scala similarity index 99% rename from scalafix/output/src/main/scala/fix/RetainSrc.scala rename to scalafix/output213/src/main/scala/fix/RetainSrc.scala index a41edbcb..c09eee04 100644 --- a/scalafix/output/src/main/scala/fix/RetainSrc.scala +++ b/scalafix/output213/src/main/scala/fix/RetainSrc.scala @@ -9,4 +9,4 @@ class MethodRenames(xs: Map[Int, Int], ys: Set[Int]) { xs.filterInPlace{case (_, _) => true} xs.filterInPlace{case (x, y) => true} ys.filterInPlace(_ => true) -} \ No newline at end of file +} diff --git a/scalafix/output/src/main/scala/fix/TraversableSrc.scala b/scalafix/output213/src/main/scala/fix/TraversableSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/TraversableSrc.scala rename to scalafix/output213/src/main/scala/fix/TraversableSrc.scala diff --git a/scalafix/output/src/main/scala/fix/TupleNZippedSrc.scala b/scalafix/output213/src/main/scala/fix/TupleNZippedSrc.scala similarity index 99% rename from scalafix/output/src/main/scala/fix/TupleNZippedSrc.scala rename to scalafix/output213/src/main/scala/fix/TupleNZippedSrc.scala index 0bf471ad..8a8e7ff6 100644 --- a/scalafix/output/src/main/scala/fix/TupleNZippedSrc.scala +++ b/scalafix/output213/src/main/scala/fix/TupleNZippedSrc.scala @@ -33,4 +33,4 @@ object Collectionstrawman_v0_Tuple3Zipped { List(1, 2, 3).lazyZip(Set(1, 2, 3)).lazyZip(Array(1)) } def coll(x: Int): List[Int] = ??? -} \ No newline at end of file +} diff --git a/scalafix/output/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix/output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala similarity index 100% rename from scalafix/output/src/main/scala/fix/UnstableStreamToLazyListSrc.scala rename to scalafix/output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala diff --git a/scalafix/rules/src/main/scala/fix/CanBuildFrom.scala b/scalafix/rules/src/main/scala/fix/CanBuildFrom.scala new file mode 100644 index 00000000..ad95703c --- /dev/null +++ b/scalafix/rules/src/main/scala/fix/CanBuildFrom.scala @@ -0,0 +1,195 @@ +package fix + +import scalafix._ +import scalafix.syntax._ +import scalafix.util._ +import scala.meta._ + +object CanBuildFrom { + def apply(paramss: List[List[Term.Param]], + body: Term, + ctx: RuleCtx, + collectionCanBuildFrom: SymbolMatcher, + nothing: SymbolMatcher)(implicit index: SemanticdbIndex): Patch = { + // CanBuildFrom has def apply() but not CanBuild + def emptyApply(param: Name): Boolean = { + import scala.meta.contrib._ + val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get) + body.exists{ + case Term.Apply(Term.Select(matchCbf(_), _), Nil) => true + case Term.Apply(matchCbf(_), Nil) => true + case _ => false + } + } + + paramss.flatten.collect{ + case Term.Param( + List(Mod.Implicit()), + param, + Some( + Type.Apply( + cbf @ collectionCanBuildFrom(_), + List(p1, _, _) + ) + ), + _ + ) if !nothing.matches(p1) && !emptyApply(param) => new CanBuildFrom(param, cbf) + }.map(_.toBuildFrom(body, ctx)).asPatch + } +} + +// example: +// implicit cbf: collection.generic.CanBuildFrom[C0, Int, CC[Int]] +// param: cbf +// cbf : collection.generic.CanBuildFrom +case class CanBuildFrom(param: Name, cbf: Type) { + def toBuildFrom(body: Term, ctx: RuleCtx)(implicit index: SemanticdbIndex): Patch = { + + val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get) + + // cbf(x) / cbf.apply(x) => cbf.newBuilder(x) + def replaceNewBuilder(tree: Tree, cbf2: Term, x: Term): Patch = + ctx.replaceTree( + tree, + Term.Apply(Term.Select(cbf2, Term.Name("newBuilder")), List(x)).syntax + ) + + val cbfCalls = + body.collect { + // cbf.apply(x) + case ap @ Term.Apply(sel @ Term.Select(cbf2 @ matchCbf(_), apply), List(x)) => + replaceNewBuilder(ap, cbf2, x) + + // cbf(x) + case ap @ Term.Apply(cbf2 @ matchCbf(_), List(x)) => + replaceNewBuilder(ap, cbf2, x) + }.asPatch + + val parameterType = + ctx.replaceTree(cbf, "collection.BuildFrom") + + parameterType + cbfCalls + } +} + +object CanBuildFromNothing { + def apply(paramss: List[List[Term.Param]], + body: Term, + ctx: RuleCtx, + collectionCanBuildFrom: SymbolMatcher, + nothing: SymbolMatcher, + toTpe: SymbolMatcher)(implicit index: SemanticdbIndex): (Patch, Set[Tree]) = { + val handledTo = Set.newBuilder[Tree] + + val patches = + paramss.flatten.collect{ + case + Term.Param( + List(Mod.Implicit()), + param, + Some( + tpe @ Type.Apply( + collectionCanBuildFrom(_), + List( + nothing(_), + t, + cct @ Type.Apply( + cc, + _ + ) + ) + ) + ), + _ + ) => new CanBuildFromNothing(param, tpe, t, cct, cc, body, ctx, toTpe) + }.map{cbf => + val (ps, ht) = cbf.toFactory + handledTo ++= ht + ps + }.asPatch + + (patches, handledTo.result()) + } +} + +// example: +// implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] +// +// param: cbf +// tpe : collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] +// cbf : CanBuildFrom +// v : Int +// cct : CC[Int] +// cc : CC +case class CanBuildFromNothing(param: Name, + tpe: Type.Apply, + t: Type, + cct: Type.Apply, + cc: Type, + body: Term, + ctx: RuleCtx, + toTpe: SymbolMatcher) { + def toFactory(implicit index: SemanticdbIndex): (Patch, Set[Tree]) = { + val handledTo = Set.newBuilder[Tree] + + val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get) + + // cbf() / cbf.apply => cbf.newBuilder + def replaceNewBuilder(tree: Tree, cbf2: Term): Patch = + ctx.replaceTree(tree, Term.Select(cbf2, Term.Name("newBuilder")).syntax) + + // don't patch cbf.apply twice (cbf.apply and cbf.apply()) + val visitedCbfCalls = scala.collection.mutable.Set[Tree]() + + val cbfCalls = + body.collect { + // cbf.apply() + case ap @ Term.Apply(sel @ Term.Select(cbf2 @ matchCbf(_), apply), Nil) => + visitedCbfCalls += sel + replaceNewBuilder(ap, cbf2) + + // cbf.apply + case sel @ Term.Select(cbf2 @ matchCbf(_), ap) if (!visitedCbfCalls.contains(sel)) => + replaceNewBuilder(sel, cbf2) + + // cbf() + case ap @ Term.Apply(cbf2 @ matchCbf(_), Nil) => + replaceNewBuilder(ap, cbf2) + }.asPatch + + + val matchCC = SymbolMatcher.exact(ctx.index.symbol(cc).get) + + // e.to[CC] => e.to(cbf) + val toCalls = + body.collect { + case ap @ Term.ApplyType(Term.Select(_, to @ toTpe(_)), List(cc2 @ matchCC(_))) => + handledTo += to + + // e.to[CC](*cbf*) extract implicit parameter + val synth = ctx.index.synthetics.find(_.position.end == ap.pos.end).get + val Term.Apply(_, List(implicitCbf)) = synth.text.parse[Term].get + + // This is a bit unsafe + // https://github.com/scalameta/scalameta/issues/1636 + if (implicitCbf.syntax == param.syntax) { + trailingBrackets(to, ctx).map { case (open, close) => + ctx.replaceTree(cc2, implicitCbf.syntax) + + ctx.replaceToken(open, "(") + + ctx.replaceToken(close, ")") + }.asPatch + } else Patch.empty + + }.asPatch + + // implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] => + // implicit cbf: collection.Factory[Int, CC[Int]] + val parameterType = + ctx.replaceTree( + tpe, + Type.Apply(Type.Name("collection.Factory"), List(t, cct)).syntax + ) + + (parameterType + cbfCalls + toCalls, handledTo.result()) + } +} diff --git a/scalafix/rules/src/main/scala/fix/CrossCompat.scala b/scalafix/rules/src/main/scala/fix/CrossCompat.scala new file mode 100644 index 00000000..d6d4cd78 --- /dev/null +++ b/scalafix/rules/src/main/scala/fix/CrossCompat.scala @@ -0,0 +1,5 @@ +package fix + +import scalafix._ + +case class CrossCompat(index: SemanticdbIndex) extends SemanticRule(index, "CrossCompat") with Stable212Base diff --git a/scalafix/rules/src/main/scala/fix/Experimental.scala b/scalafix/rules/src/main/scala/fix/Experimental.scala index 0ffd9b11..b7e29d04 100644 --- a/scalafix/rules/src/main/scala/fix/Experimental.scala +++ b/scalafix/rules/src/main/scala/fix/Experimental.scala @@ -5,53 +5,21 @@ import scalafix.syntax._ import scalafix.util._ import scala.meta._ +// 2.12 Cross-Compatible case class Experimental(index: SemanticdbIndex) extends SemanticRule(index, "Experimental") { - // WARNING: TOTAL HACK - // this is only to unblock us until Term.tpe is available: https://github.com/scalameta/scalameta/issues/1212 - // if we have a simple identifier, we can look at his definition at query it's type - // this should be improved in future version of scalameta - object TypeMatcher { - def apply(symbols: Symbol*)(implicit index: SemanticdbIndex): TypeMatcher = - new TypeMatcher(symbols: _*)(index) - } - final class TypeMatcher(symbols: Symbol*)(implicit index: SemanticdbIndex) { - def unapply(tree: Tree): Boolean = { - index.denotation(tree) - .exists(_.names.headOption.exists(n => symbols.exists(_ == n.symbol))) - } - } - - val CollectionMap: TypeMatcher = TypeMatcher( + val CollectionMap = TypeMatcher( Symbol("_root_.scala.collection.immutable.Map#"), Symbol("_root_.scala.collection.mutable.Map#"), Symbol("_root_.scala.Predef.Map#") ) + val CollectionSet = TypeMatcher(Symbol("_root_.scala.collection.Set#")) - val CollectionSet: TypeMatcher = TypeMatcher(Symbol("_root_.scala.collection.Set#")) - - val mapZip = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.IterableLike#zip(Lscala/collection/GenIterable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - ) - - val mapPlus = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.MapLike#`+`(Lscala/Tuple2;)Lscala/collection/Map;.") - ) - - val setPlus = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.SetLike#`+`(Ljava/lang/Object;)Lscala/collection/Set;.") - ) - - val setMinus = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.SetLike#`-`(Ljava/lang/Object;)Lscala/collection/Set;.") - ) - - def startsWithParens(tree: Tree): Boolean = - tree.tokens.headOption.map(_.is[Token.LeftParen]).getOrElse(false) + // == Symbols == + val mapZip = exact("_root_.scala.collection.IterableLike#zip(Lscala/collection/GenIterable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val mapPlus = exact("_root_.scala.collection.MapLike#`+`(Lscala/Tuple2;)Lscala/collection/Map;.") + val setPlus = exact("_root_.scala.collection.SetLike#`+`(Ljava/lang/Object;)Lscala/collection/Set;.") + val setMinus = exact("_root_.scala.collection.SetLike#`-`(Ljava/lang/Object;)Lscala/collection/Set;.") def replaceMapZip(ctx: RuleCtx): Patch = { ctx.tree.collect { @@ -65,7 +33,7 @@ case class Experimental(index: SemanticdbIndex) extends SemanticRule(index, "Exp val col = "_root_.scala.collection." + col0 val callSite = if (startsWithParens(rhs)) { - ctx.addLeft(rhs, col) + ctx.addLeft(rhs, col) } else { ctx.addLeft(rhs, col + "(") + @@ -78,7 +46,7 @@ case class Experimental(index: SemanticdbIndex) extends SemanticRule(index, "Exp ctx.tree.collect { case Term.ApplyInfix(CollectionSet(), op @ setPlus(_), Nil, List(rhs)) => rewriteOp(op, rhs, "+", "Set") - + case Term.ApplyInfix(CollectionSet(), op @ setMinus(_), Nil, List(rhs)) => rewriteOp(op, rhs, "-", "Set") @@ -90,4 +58,4 @@ case class Experimental(index: SemanticdbIndex) extends SemanticRule(index, "Exp override def fix(ctx: RuleCtx): Patch = replaceSetMapPlusMinus(ctx) + replaceMapZip(ctx) -} \ No newline at end of file +} diff --git a/scalafix/rules/src/main/scala/fix/NewCollections.scala b/scalafix/rules/src/main/scala/fix/NewCollections.scala new file mode 100644 index 00000000..05e50eb2 --- /dev/null +++ b/scalafix/rules/src/main/scala/fix/NewCollections.scala @@ -0,0 +1,256 @@ +package fix + +import scalafix._ +import scalafix.syntax._ +import scalafix.util._ +import scala.meta._ + +// Not 2.12 Cross-Compatible +case class NewCollections(index: SemanticdbIndex) extends SemanticRule(index, "NewCollections") with Stable212Base { + // Two rules triggers the same rewrite TraversableLike.to and CanBuildFrom + // we keep track of what is handled in CanBuildFrom and guard against TraversableLike.to + val handledTo = scala.collection.mutable.Set[Tree]() + + // == Symbols == + val collectionCanBuildFrom = exact("_root_.scala.collection.generic.CanBuildFrom#") + val collectionCanBuildFromImport = exact("_root_.scala.collection.generic.CanBuildFrom.;_root_.scala.collection.generic.CanBuildFrom#") + val nothing = exact("_root_.scala.Nothing#") + val iterableSameElement = exact("_root_.scala.collection.IterableLike#sameElements(Lscala/collection/GenIterable;)Z.") + val toTpe = normalized("_root_.scala.collection.TraversableLike.to.") + val iterator = normalized("_root_.scala.collection.TraversableLike.toIterator.") + val tupleZipped = normalized("_root_.scala.runtime.Tuple2Zipped.Ops.zipped.", + "_root_.scala.runtime.Tuple3Zipped.Ops.zipped.") + val retainMap = normalized("_root_.scala.collection.mutable.MapLike.retain.") + val retainSet = normalized("_root_.scala.collection.mutable.SetLike.retain.") + + object Breakout { + implicit class RichSymbol(val symbol: Symbol) { + def exact(tree: Tree)(implicit index: SemanticdbIndex): Boolean = + index.symbol(tree).fold(false)(_ == symbol) + } + + val breakOut = SymbolMatcher.exact(Symbol("_root_.scala.collection.package.breakOut(Lscala/collection/generic/CanBuildFrom;)Lscala/collection/generic/CanBuildFrom;.")) + + // infix operators + val `List ++` = Symbol("_root_.scala.collection.immutable.List#`++`(Lscala/collection/GenTraversableOnce;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `List +:` = Symbol("_root_.scala.collection.immutable.List#`+:`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `SeqLike :+` = Symbol("_root_.scala.collection.SeqLike#`:+`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `TraversableLike ++:` = Symbol("_root_.scala.collection.TraversableLike#`++:`(Lscala/collection/Traversable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + + val operatorsIteratorSymbols = List(`List ++`) + val operatorsViewSymbols = List(`List +:`, `SeqLike :+`, `TraversableLike ++:`) + val operatorsSymbols = operatorsViewSymbols ++ operatorsIteratorSymbols + + val operatorsIterator = SymbolMatcher.exact(operatorsIteratorSymbols: _*) + val operatorsView = SymbolMatcher.exact(operatorsViewSymbols: _*) + val operators = SymbolMatcher.exact(operatorsSymbols: _*) + + // select + val `List.collect` = Symbol("_root_.scala.collection.immutable.List#collect(Lscala/PartialFunction;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `List.flatMap` = Symbol("_root_.scala.collection.immutable.List#flatMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `List.map` = Symbol("_root_.scala.collection.immutable.List#map(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `IterableLike.zip` = Symbol("_root_.scala.collection.IterableLike#zip(Lscala/collection/GenIterable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `IterableLike.zipAll` = Symbol("_root_.scala.collection.IterableLike#zipAll(Lscala/collection/GenIterable;Ljava/lang/Object;Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `SeqLike.union` = Symbol("_root_.scala.collection.SeqLike#union(Lscala/collection/GenSeq;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `SeqLike.updated` = Symbol("_root_.scala.collection.SeqLike#updated(ILjava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + val `SeqLike.reverseMap` = Symbol("_root_.scala.collection.SeqLike#reverseMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") + + val functionsIteratorSymbols = List(`List.collect`, `List.flatMap`, `List.map`, `IterableLike.zip`, `IterableLike.zipAll`, `SeqLike.union`) + val functionsViewSymbols = List(`SeqLike.updated`) + val functionsReverseIteratorSymbols = List(`SeqLike.reverseMap`) + val functionsSymbols = functionsIteratorSymbols ++ functionsViewSymbols ++ functionsReverseIteratorSymbols + + val functionsIterator = SymbolMatcher.exact(functionsIteratorSymbols: _*) + val functionsReverseIterator = SymbolMatcher.exact(functionsReverseIteratorSymbols: _*) + val functionsView = SymbolMatcher.exact(functionsViewSymbols: _*) + val functions = SymbolMatcher.exact(functionsSymbols: _*) + + // special select + + // iterator + val `TraversableLike.scanLeft` = SymbolMatcher.exact(Symbol("_root_.scala.collection.TraversableLike#scanLeft(Ljava/lang/Object;Lscala/Function2;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")) + + def isLeftAssociative(tree: Tree): Boolean = + tree match { + case Term.Name(value) => value.last != ':' + case _ => false + } + } + + // == Rules == + + def replaceSymbols(ctx: RuleCtx): Patch = { + ctx.replaceSymbols( + "scala.TraversableOnce" -> "scala.IterableOnce", + "scala.collection.TraversableOnce" -> "scala.collection.IterableOnce" + ) + } + + def replaceMutableSet(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case retainSet(n: Name) => + ctx.replaceTree(n, "filterInPlace") + }.asPatch + } + + def replaceMutableMap(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case Term.Apply(Term.Select(_, retainMap(n: Name)), List(_: Term.PartialFunction)) => + ctx.replaceTree(n, "filterInPlace") + + case Term.Apply(Term.Select(_, retainMap(n: Name)), List(_: Term.Function)) => + trailingParens(n, ctx).map { case (open, close) => + ctx.replaceToken(open, "{case ") + + ctx.replaceToken(close, "}") + + ctx.replaceTree(n, "filterInPlace") + }.asPatch + }.asPatch + } + + def replaceToList(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case iterator(t: Name) => + ctx.replaceTree(t, "iterator") + + case t @ toTpe(n: Name) if !handledTo.contains(n) => + trailingBrackets(n, ctx).map { case (open, close) => + ctx.replaceToken(open, "(") + ctx.replaceToken(close, ")") + }.asPatch + }.asPatch + } + + def replaceTupleZipped(ctx: RuleCtx): Patch = { + 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 + } + + def replaceIterableSameElements(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case Term.Apply(Term.Select(lhs, iterableSameElement(_)), List(_)) => + ctx.addRight(lhs, ".iterator") + }.asPatch + } + + def replaceCanBuildFrom(ctx: RuleCtx): Patch = { + val useSites = + ctx.tree.collect { + case Defn.Def(_, _, _, paramss, _, body) => + val (ps1, ht) = CanBuildFromNothing(paramss, body, ctx, collectionCanBuildFrom, nothing, toTpe) + val ps2 = CanBuildFrom (paramss, body, ctx, collectionCanBuildFrom, nothing) + handledTo ++= ht + + ps1 + ps2 + }.asPatch + + val imports = + ctx.tree.collect { + case i: Importee if collectionCanBuildFromImport.matches(i) => + ctx.removeImportee(i) + }.asPatch + + if (useSites.nonEmpty) useSites + imports + else Patch.empty + } + + def replaceBreakout(ctx: RuleCtx): Patch = { + import Breakout._ + + def fixIt(intermediate: String, lhs: Term, ap: Term, breakout: Tree): Patch = { + ctx.addRight(lhs, "." + intermediate) + + ctx.addRight(ap, ".to") + + ctx.replaceTree(breakout, "implicitly") + } + + ctx.tree.collect { + case i: Importee if breakOut.matches(i) => + ctx.removeImportee(i) + + case Term.Apply(ap @ Term.ApplyInfix(lhs, operators(op), _, List(rhs)), List(breakOut(bo))) => + val subject = + if(isLeftAssociative(op)) lhs + else rhs + + val intermediate = + op match { + case operatorsIterator(_) => "iterator" + case operatorsView(_) => "view" + // since operators(op) matches iterator and view + case _ => throw new Exception("impossible") + } + + fixIt(intermediate, subject, ap, bo) + + case Term.Apply(ap @ Term.Apply(Term.Select(lhs, functions(op)), _), List(breakOut(bo))) => + val intermediate = + op match { + case functionsIterator(_) => "iterator" + case functionsView(_) => "view" + case functionsReverseIterator(_) => "reverseIterator" + // since functions(op) matches iterator, view and reverseIterator + case _ => throw new Exception("impossible") + } + + val replaceUnion = + if (`SeqLike.union`.exact(op)) ctx.replaceTree(op, "concat") + else Patch.empty + + val isReversed = `SeqLike.reverseMap`.exact(op) + val replaceReverseMap = + if (isReversed) ctx.replaceTree(op, "map") + else Patch.empty + + fixIt(intermediate, lhs, ap, bo) + replaceUnion + replaceReverseMap + + case Term.Apply(ap @ Term.Apply(Term.Apply(Term.Select(lhs, `TraversableLike.scanLeft`(op)), _), _), List(breakOut(bo))) => + fixIt("iterator", lhs, ap, bo) + }.asPatch + } + + override def fix(ctx: RuleCtx): Patch = { + super.fix(ctx) + + replaceCanBuildFrom(ctx) + + replaceToList(ctx) + + replaceSymbols(ctx) + + replaceTupleZipped(ctx) + + replaceMutableMap(ctx) + + replaceMutableSet(ctx) + + replaceBreakout(ctx) + + replaceIterableSameElements(ctx) + } +} diff --git a/scalafix/rules/src/main/scala/fix/Stable.scala b/scalafix/rules/src/main/scala/fix/Stable.scala deleted file mode 100644 index 89ae2d56..00000000 --- a/scalafix/rules/src/main/scala/fix/Stable.scala +++ /dev/null @@ -1,578 +0,0 @@ -package fix - -import scalafix._ -import scalafix.syntax._ -import scalafix.util._ -import scala.meta._ - -case class Stable(index: SemanticdbIndex) extends SemanticRule(index, "Stable") { - - // Two rules triggers the same rewrite TraversableLike.to and CanBuildFrom - // we keep track of what is handled in CanBuildFrom and guard against TraversableLike.to - val handledTo = scala.collection.mutable.Set[Tree]() - - def trailingParens(tree: Tree, ctx: RuleCtx): Option[(Token.LeftParen, Token.RightParen)] = - for { - end <- tree.tokens.lastOption - open <- ctx.tokenList.find(end)(_.is[Token.LeftParen]).map(_.asInstanceOf[Token.LeftParen]) - close <- ctx.matchingParens.close(open) - } yield (open, close) - - def trailingBrackets(tree: Tree, ctx: RuleCtx): Option[(Token.LeftBracket, Token.RightBracket)] = - for { - end <- tree.tokens.lastOption - open <- ctx.tokenList.find(end)(_.is[Token.LeftBracket]).map(_.asInstanceOf[Token.LeftBracket]) - close <- ctx.matchingParens.close(open) - } yield (open, close) - - def replaceSymbols(ctx: RuleCtx): Patch = { - ctx.replaceSymbols( - "scala.collection.LinearSeq" -> "scala.collection.immutable.List", - "scala.Traversable" -> "scala.Iterable", - "scala.collection.Traversable" -> "scala.collection.Iterable", - "scala.TraversableOnce" -> "scala.IterableOnce", - "scala.collection.TraversableOnce" -> "scala.collection.IterableOnce" - ) - } - - val collectionCanBuildFrom = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.generic.CanBuildFrom#") - ) - - val collectionCanBuildFromImport = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.generic.CanBuildFrom.;_root_.scala.collection.generic.CanBuildFrom#") - ) - - val nothing = - SymbolMatcher.exact( - Symbol("_root_.scala.Nothing#") - ) - - val toTpe = SymbolMatcher.normalized( - Symbol("_root_.scala.collection.TraversableLike.to.") - ) - val iterator = SymbolMatcher.normalized( - Symbol("_root_.scala.collection.TraversableLike.toIterator.") - ) - val tupleZipped = SymbolMatcher.normalized( - Symbol("_root_.scala.runtime.Tuple2Zipped.Ops.zipped."), - Symbol("_root_.scala.runtime.Tuple3Zipped.Ops.zipped.") - ) - val setPlus2 = SymbolMatcher.exact( - Symbol("_root_.scala.collection.SetLike#`+`(Ljava/lang/Object;Ljava/lang/Object;Lscala/collection/Seq;)Lscala/collection/Set;.") - ) - val mapPlus2 = SymbolMatcher.exact( - Symbol("_root_.scala.collection.immutable.MapLike#`+`(Lscala/Tuple2;Lscala/Tuple2;Lscala/collection/Seq;)Lscala/collection/immutable/Map;.") - ) - val mutSetPlus = SymbolMatcher.exact( - Symbol("_root_.scala.collection.mutable.SetLike#`+`(Ljava/lang/Object;)Lscala/collection/mutable/Set;.") - ) - val mutMapPlus = SymbolMatcher.exact( - Symbol("_root_.scala.collection.mutable.MapLike#`+`(Lscala/Tuple2;)Lscala/collection/mutable/Map;.") - ) - val mutMapUpdate = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.mutable.MapLike#updated(Ljava/lang/Object;Ljava/lang/Object;)Lscala/collection/mutable/Map;.") - ) - - val iterableSameElement = - SymbolMatcher.exact( - Symbol("_root_.scala.collection.IterableLike#sameElements(Lscala/collection/GenIterable;)Z.") - ) - - def foldSymbol(isLeft: Boolean): SymbolMatcher = { - val op = - if (isLeft) "/:" - else ":\\" - - SymbolMatcher.normalized(Symbol(s"_root_.scala.collection.TraversableOnce.`$op`.")) - } - val foldLeftSymbol = foldSymbol(isLeft = true) - val foldRightSymbol = foldSymbol(isLeft = false) - - val retainMap = - SymbolMatcher.normalized( - Symbol("_root_.scala.collection.mutable.MapLike.retain.") - ) - - - - val retainSet = - SymbolMatcher.normalized( - Symbol("_root_.scala.collection.mutable.SetLike.retain.") - ) - - - val arrayBuilderMake = - SymbolMatcher.normalized( - Symbol("_root_.scala.collection.mutable.ArrayBuilder.make(Lscala/reflect/ClassTag;)Lscala/collection/mutable/ArrayBuilder;.") - ) - - object Breakout { - implicit class RichSymbol(val symbol: Symbol) { - def exact(tree: Tree)(implicit index: SemanticdbIndex): Boolean = - index.symbol(tree).fold(false)(_ == symbol) - } - - val breakOut = SymbolMatcher.exact(Symbol("_root_.scala.collection.package.breakOut(Lscala/collection/generic/CanBuildFrom;)Lscala/collection/generic/CanBuildFrom;.")) - - // infix operators - val `List ++` = Symbol("_root_.scala.collection.immutable.List#`++`(Lscala/collection/GenTraversableOnce;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `List +:` = Symbol("_root_.scala.collection.immutable.List#`+:`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `SeqLike :+` = Symbol("_root_.scala.collection.SeqLike#`:+`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `TraversableLike ++:` = Symbol("_root_.scala.collection.TraversableLike#`++:`(Lscala/collection/Traversable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - - val operatorsIteratorSymbols = List(`List ++`) - val operatorsViewSymbols = List(`List +:`, `SeqLike :+`, `TraversableLike ++:`) - val operatorsSymbols = operatorsViewSymbols ++ operatorsIteratorSymbols - - val operatorsIterator = SymbolMatcher.exact(operatorsIteratorSymbols: _*) - val operatorsView = SymbolMatcher.exact(operatorsViewSymbols: _*) - val operators = SymbolMatcher.exact(operatorsSymbols: _*) - - // select - val `List.collect` = Symbol("_root_.scala.collection.immutable.List#collect(Lscala/PartialFunction;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `List.flatMap` = Symbol("_root_.scala.collection.immutable.List#flatMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `List.map` = Symbol("_root_.scala.collection.immutable.List#map(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `IterableLike.zip` = Symbol("_root_.scala.collection.IterableLike#zip(Lscala/collection/GenIterable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `IterableLike.zipAll` = Symbol("_root_.scala.collection.IterableLike#zipAll(Lscala/collection/GenIterable;Ljava/lang/Object;Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `SeqLike.union` = Symbol("_root_.scala.collection.SeqLike#union(Lscala/collection/GenSeq;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `SeqLike.updated` = Symbol("_root_.scala.collection.SeqLike#updated(ILjava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - val `SeqLike.reverseMap` = Symbol("_root_.scala.collection.SeqLike#reverseMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.") - - val functionsIteratorSymbols = List(`List.collect`, `List.flatMap`, `List.map`, `IterableLike.zip`, `IterableLike.zipAll`, `SeqLike.union`) - val functionsViewSymbols = List(`SeqLike.updated`) - val functionsReverseIteratorSymbols = List(`SeqLike.reverseMap`) - val functionsSymbols = functionsIteratorSymbols ++ functionsViewSymbols ++ functionsReverseIteratorSymbols - - val functionsIterator = SymbolMatcher.exact(functionsIteratorSymbols: _*) - val functionsReverseIterator = SymbolMatcher.exact(functionsReverseIteratorSymbols: _*) - val functionsView = SymbolMatcher.exact(functionsViewSymbols: _*) - val functions = SymbolMatcher.exact(functionsSymbols: _*) - - // special select - - // iterator - val `TraversableLike.scanLeft` = SymbolMatcher.exact(Symbol("_root_.scala.collection.TraversableLike#scanLeft(Ljava/lang/Object;Lscala/Function2;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")) - - def isLeftAssociative(tree: Tree): Boolean = - tree match { - case Term.Name(value) => value.last != ':' - case _ => false - } - } - - def startsWithParens(tree: Tree): Boolean = - tree.tokens.headOption.map(_.is[Token.LeftParen]).getOrElse(false) - - def replaceMutableSet(ctx: RuleCtx) = - ctx.tree.collect { - case retainSet(n: Name) => - ctx.replaceTree(n, "filterInPlace") - }.asPatch - - def replaceMutableMap(ctx: RuleCtx) = - ctx.tree.collect { - case Term.Apply(Term.Select(_, retainMap(n: Name)), List(_: Term.PartialFunction)) => - ctx.replaceTree(n, "filterInPlace") - - case Term.Apply(Term.Select(_, retainMap(n: Name)), List(_: Term.Function)) => - trailingParens(n, ctx).map { case (open, close) => - ctx.replaceToken(open, "{case ") + - ctx.replaceToken(close, "}") + - ctx.replaceTree(n, "filterInPlace") - }.asPatch - }.asPatch - - def replaceSymbolicFold(ctx: RuleCtx) = - ctx.tree.collect { - case Term.Apply(ap @ Term.ApplyInfix(rhs, foldRightSymbol(_), _, List(lhs)), _) => - ctx.replaceTree(ap, s"$rhs.foldRight($lhs)") - - case Term.Apply(ap @ Term.ApplyInfix(lhs, foldLeftSymbol(_), _, List(rhs)), _) => - ctx.replaceTree(ap, s"$rhs.foldLeft($lhs)") - }.asPatch - - def replaceToList(ctx: RuleCtx) = - ctx.tree.collect { - case iterator(t: Name) => - ctx.replaceTree(t, "iterator") - case t @ toTpe(n: Name) if !handledTo.contains(n) => - trailingBrackets(n, ctx).map { case (open, close) => - 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 - - 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 - - def replaceSetMapPlus2(ctx: RuleCtx): Patch = { - def rewritePlus(ap: Term.ApplyInfix, lhs: Term, op: Term.Name, rhs1: Term, rhs2: Term): Patch = { - val tokensToReplace = - if(startsWithParens(ap)) { - // don't drop surrounding parens - ap.tokens.slice(1, ap.tokens.size - 1) - } else ap.tokens - - val newTree = - Term.ApplyInfix( - Term.ApplyInfix(lhs, op, Nil, List(rhs1)), - op, - Nil, - List(rhs2) - ).syntax - - ctx.removeTokens(tokensToReplace) + - tokensToReplace.headOption.map(x => ctx.addRight(x, newTree)) - } - ctx.tree.collect { - case ap @ Term.ApplyInfix(lhs, op @ mapPlus2(_), _, List(a, b)) => - rewritePlus(ap, lhs, op, a, b) - - case ap @ Term.ApplyInfix(lhs, op @ setPlus2(_), _, List(a, b)) => - rewritePlus(ap, lhs, op, a, b) - }.asPatch - } - - def replaceMutSetMapPlus(ctx: RuleCtx): Patch = { - def rewriteMutPlus(lhs: Term, op: Term.Name): Patch = { - ctx.addRight(lhs, ".clone()") + - ctx.addRight(op, "=") - } - - ctx.tree.collect { - case Term.ApplyInfix(lhs, op @ mutSetPlus(_), _, List(_)) => - rewriteMutPlus(lhs, op) - - case Term.ApplyInfix(lhs, op @ mutMapPlus(_), _, List(_)) => - rewriteMutPlus(lhs, op) - }.asPatch - } - - def replaceMutMapUpdated(ctx: RuleCtx): Patch = { - ctx.tree.collect { - case Term.Apply(Term.Select(a, up @ mutMapUpdate(_)), List(k, v)) => { - ctx.addRight(up, "clone() += (") + - ctx.removeTokens(up.tokens) + - ctx.addRight(v, ")") - } - }.asPatch - } - - def replaceIterableSameElements(ctx: RuleCtx): Patch = { - ctx.tree.collect { - case Term.Apply(Term.Select(lhs, iterableSameElement(_)), List(_)) => - ctx.addRight(lhs, ".iterator") - }.asPatch - } - - def replaceArrayBuilderMake(ctx: RuleCtx): Patch = { - ctx.tree.collect { - case ap @ Term.Apply(at @ Term.ApplyType(Term.Select(lhs, arrayBuilderMake(_)), args), Nil) => - val extraParens = - ap.tokens.slice(at.tokens.size, ap.tokens.size) - ctx.removeTokens(extraParens) - }.asPatch - } - - object CanBuildFromNothing { - def apply(paramss: List[List[Term.Param]], body: Term, ctx: RuleCtx): Patch = { - paramss.flatten.collect{ - case - Term.Param( - List(Mod.Implicit()), - param, - Some( - tpe @ Type.Apply( - collectionCanBuildFrom(_), - List( - nothing(_), - t, - cct @ Type.Apply( - cc, - _ - ) - ) - ) - ), - _ - ) => new CanBuildFromNothing(param, tpe, t, cct, cc) - }.map(_.toFactory(body, ctx)).asPatch - } - } - - // example: - // implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] - // - // param: cbf - // tpe : collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] - // cbf : CanBuildFrom - // v : Int - // cct : CC[Int] - // cc : CC - - case class CanBuildFromNothing(param: Name, tpe: Type.Apply, t: Type, cct: Type.Apply, cc: Type) { - def toFactory(body: Term, ctx: RuleCtx): Patch = { - val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get) - - // cbf() / cbf.apply => cbf.newBuilder - def replaceNewBuilder(tree: Tree, cbf2: Term): Patch = - ctx.replaceTree(tree, Term.Select(cbf2, Term.Name("newBuilder")).syntax) - - // don't patch cbf.apply twice (cbf.apply and cbf.apply()) - val visitedCbfCalls = scala.collection.mutable.Set[Tree]() - - val cbfCalls = - body.collect { - // cbf.apply() - case ap @ Term.Apply(sel @ Term.Select(cbf2 @ matchCbf(_), apply), Nil) => - visitedCbfCalls += sel - replaceNewBuilder(ap, cbf2) - - // cbf.apply - case sel @ Term.Select(cbf2 @ matchCbf(_), ap) if (!visitedCbfCalls.contains(sel)) => - replaceNewBuilder(sel, cbf2) - - // cbf() - case ap @ Term.Apply(cbf2 @ matchCbf(_), Nil) => - replaceNewBuilder(ap, cbf2) - }.asPatch - - - val matchCC = SymbolMatcher.exact(ctx.index.symbol(cc).get) - - // e.to[CC] => e.to(cbf) - val toCalls = - body.collect { - case ap @ Term.ApplyType(Term.Select(_, to @ toTpe(_)), List(cc2 @ matchCC(_))) => - handledTo += to - - // e.to[CC](*cbf*) extract implicit parameter - val synth = ctx.index.synthetics.find(_.position.end == ap.pos.end).get - val Term.Apply(_, List(implicitCbf)) = synth.text.parse[Term].get - - // This is a bit unsafe - // https://github.com/scalameta/scalameta/issues/1636 - if (implicitCbf.syntax == param.syntax) { - trailingBrackets(to, ctx).map { case (open, close) => - ctx.replaceTree(cc2, implicitCbf.syntax) + - ctx.replaceToken(open, "(") + - ctx.replaceToken(close, ")") - }.asPatch - } else Patch.empty - - }.asPatch - - // implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] => - // implicit cbf: collection.Factory[Int, CC[Int]] - val parameterType = - ctx.replaceTree( - tpe, - Type.Apply(Type.Name("collection.Factory"), List(t, cct)).syntax - ) - - parameterType + cbfCalls + toCalls - } - } - - object CanBuildFrom { - def apply(paramss: List[List[Term.Param]], body: Term, ctx: RuleCtx): Patch = { - // CanBuildFrom has def apply() but not CanBuild - def emptyApply(param: Name): Boolean = { - import scala.meta.contrib._ - val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get) - body.exists{ - case Term.Apply(Term.Select(matchCbf(_), _), Nil) => true - case Term.Apply(matchCbf(_), Nil) => true - case _ => false - } - } - - paramss.flatten.collect{ - case Term.Param( - List(Mod.Implicit()), - param, - Some( - Type.Apply( - cbf @ collectionCanBuildFrom(_), - List(p1, _, _) - ) - ), - _ - ) if !nothing.matches(p1) && !emptyApply(param) => new CanBuildFrom(param, cbf) - }.map(_.toBuildFrom(body, ctx)).asPatch - } - } - - // example: - // implicit cbf: collection.generic.CanBuildFrom[C0, Int, CC[Int]] - // param: cbf - // cbf : collection.generic.CanBuildFrom - case class CanBuildFrom(param: Name, cbf: Type) { - def toBuildFrom(body: Term, ctx: RuleCtx): Patch = { - - val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get) - - // cbf(x) / cbf.apply(x) => cbf.newBuilder(x) - def replaceNewBuilder(tree: Tree, cbf2: Term, x: Term): Patch = - ctx.replaceTree( - tree, - Term.Apply(Term.Select(cbf2, Term.Name("newBuilder")), List(x)).syntax - ) - - val cbfCalls = - body.collect { - // cbf.apply(x) - case ap @ Term.Apply(sel @ Term.Select(cbf2 @ matchCbf(_), apply), List(x)) => - replaceNewBuilder(ap, cbf2, x) - - // cbf(x) - case ap @ Term.Apply(cbf2 @ matchCbf(_), List(x)) => - replaceNewBuilder(ap, cbf2, x) - }.asPatch - - val parameterType = - ctx.replaceTree(cbf, "collection.BuildFrom") - - parameterType + cbfCalls - } - } - - def replaceCanBuildFrom(ctx: RuleCtx): Patch = { - val useSites = - ctx.tree.collect { - case Defn.Def(_, _, _, paramss, _, body) => - CanBuildFromNothing(paramss, body, ctx) + - CanBuildFrom(paramss, body, ctx) - }.asPatch - - val imports = - ctx.tree.collect { - case i: Importee if collectionCanBuildFromImport.matches(i) => - ctx.removeImportee(i) - }.asPatch - - if (useSites.nonEmpty) useSites + imports - else Patch.empty - } - - def replaceBreakout(ctx: RuleCtx): Patch = { - import Breakout._ - - def fixIt(intermediate: String, lhs: Term, ap: Term, breakout: Tree): Patch = { - ctx.addRight(lhs, "." + intermediate) + - ctx.addRight(ap, ".to") + - ctx.replaceTree(breakout, "implicitly") - } - - ctx.tree.collect { - case i: Importee if breakOut.matches(i) => - ctx.removeImportee(i) - - case Term.Apply(ap @ Term.ApplyInfix(lhs, operators(op), _, List(rhs)), List(breakOut(bo))) => - val subject = - if(isLeftAssociative(op)) lhs - else rhs - - val intermediate = - op match { - case operatorsIterator(_) => "iterator" - case operatorsView(_) => "view" - // since operators(op) matches iterator and view - case _ => throw new Exception("impossible") - } - - fixIt(intermediate, subject, ap, bo) - - case Term.Apply(ap @ Term.Apply(Term.Select(lhs, functions(op)), _), List(breakOut(bo))) => - val intermediate = - op match { - case functionsIterator(_) => "iterator" - case functionsView(_) => "view" - case functionsReverseIterator(_) => "reverseIterator" - // since functions(op) matches iterator, view and reverseIterator - case _ => throw new Exception("impossible") - } - - val replaceUnion = - if (`SeqLike.union`.exact(op)) ctx.replaceTree(op, "concat") - else Patch.empty - - val isReversed = `SeqLike.reverseMap`.exact(op) - val replaceReverseMap = - if (isReversed) ctx.replaceTree(op, "map") - else Patch.empty - - fixIt(intermediate, lhs, ap, bo) + replaceUnion + replaceReverseMap - - case Term.Apply(ap @ Term.Apply(Term.Apply(Term.Select(lhs, `TraversableLike.scanLeft`(op)), _), _), List(breakOut(bo))) => - fixIt("iterator", lhs, ap, bo) - }.asPatch - } - - override def fix(ctx: RuleCtx): Patch = { - replaceCanBuildFrom(ctx) + - replaceToList(ctx) + - replaceSymbols(ctx) + - replaceTupleZipped(ctx) + - replaceCopyToBuffer(ctx) + - replaceMutableMap(ctx) + - replaceMutableSet(ctx) + - replaceSymbolicFold(ctx) + - replaceSetMapPlus2(ctx) + - replaceMutSetMapPlus(ctx) + - replaceMutMapUpdated(ctx) + - replaceArrayBuilderMake(ctx) + - replaceBreakout(ctx) + - replaceIterableSameElements(ctx) - } -} diff --git a/scalafix/rules/src/main/scala/fix/Stable212Base.scala b/scalafix/rules/src/main/scala/fix/Stable212Base.scala new file mode 100644 index 00000000..c378180c --- /dev/null +++ b/scalafix/rules/src/main/scala/fix/Stable212Base.scala @@ -0,0 +1,129 @@ +package fix + +import scalafix._ +import scalafix.syntax._ +import scalafix.util._ +import scala.meta._ + +// 2.12 Cross-Compatible +trait Stable212Base { self: SemanticRule => + + // == Symbols == + def foldSymbol(isLeft: Boolean): SymbolMatcher = { + val op = + if (isLeft) "/:" + else ":\\" + + normalized(s"_root_.scala.collection.TraversableOnce.`$op`.") + } + + val copyToBuffer = normalized("_root_.scala.collection.TraversableOnce.copyToBuffer.") + val arrayBuilderMake = normalized("_root_.scala.collection.mutable.ArrayBuilder.make(Lscala/reflect/ClassTag;)Lscala/collection/mutable/ArrayBuilder;.") + val setPlus2 = exact("_root_.scala.collection.SetLike#`+`(Ljava/lang/Object;Ljava/lang/Object;Lscala/collection/Seq;)Lscala/collection/Set;.") + val mapPlus2 = exact("_root_.scala.collection.immutable.MapLike#`+`(Lscala/Tuple2;Lscala/Tuple2;Lscala/collection/Seq;)Lscala/collection/immutable/Map;.") + val mutSetPlus = exact("_root_.scala.collection.mutable.SetLike#`+`(Ljava/lang/Object;)Lscala/collection/mutable/Set;.") + val mutMapPlus = exact("_root_.scala.collection.mutable.MapLike#`+`(Lscala/Tuple2;)Lscala/collection/mutable/Map;.") + val mutMapUpdate = exact("_root_.scala.collection.mutable.MapLike#updated(Ljava/lang/Object;Ljava/lang/Object;)Lscala/collection/mutable/Map;.") + val foldLeftSymbol = foldSymbol(isLeft = true) + val foldRightSymbol = foldSymbol(isLeft = false) + + // == Rules == + + def replaceSymbols0(ctx: RuleCtx): Patch = { + ctx.replaceSymbols( + "scala.collection.LinearSeq" -> "scala.collection.immutable.List", + "scala.Traversable" -> "scala.Iterable", + "scala.collection.Traversable" -> "scala.collection.Iterable" + ) + } + + def replaceSymbolicFold(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case Term.Apply(ap @ Term.ApplyInfix(rhs, foldRightSymbol(_), _, List(lhs)), _) => + ctx.replaceTree(ap, s"$rhs.foldRight($lhs)") + + case Term.Apply(ap @ Term.ApplyInfix(lhs, foldLeftSymbol(_), _, List(rhs)), _) => + ctx.replaceTree(ap, s"$rhs.foldLeft($lhs)") + }.asPatch + } + + def replaceCopyToBuffer(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case t @ q"${copyToBuffer(Term.Select(collection, _))}($buffer)" => + ctx.replaceTree(t, q"$buffer ++= $collection".syntax) + }.asPatch + } + + def replaceSetMapPlus2(ctx: RuleCtx): Patch = { + def rewritePlus(ap: Term.ApplyInfix, lhs: Term, op: Term.Name, rhs1: Term, rhs2: Term): Patch = { + val tokensToReplace = + if(startsWithParens(ap)) { + // don't drop surrounding parens + ap.tokens.slice(1, ap.tokens.size - 1) + } else ap.tokens + + val newTree = + Term.ApplyInfix( + Term.ApplyInfix(lhs, op, Nil, List(rhs1)), + op, + Nil, + List(rhs2) + ).syntax + + ctx.removeTokens(tokensToReplace) + + tokensToReplace.headOption.map(x => ctx.addRight(x, newTree)) + } + ctx.tree.collect { + case ap @ Term.ApplyInfix(lhs, op @ mapPlus2(_), _, List(a, b)) => + rewritePlus(ap, lhs, op, a, b) + + case ap @ Term.ApplyInfix(lhs, op @ setPlus2(_), _, List(a, b)) => + rewritePlus(ap, lhs, op, a, b) + }.asPatch + } + + def replaceMutSetMapPlus(ctx: RuleCtx): Patch = { + def rewriteMutPlus(lhs: Term, op: Term.Name): Patch = { + ctx.addRight(lhs, ".clone()") + + ctx.addRight(op, "=") + } + + ctx.tree.collect { + case Term.ApplyInfix(lhs, op @ mutSetPlus(_), _, List(_)) => + rewriteMutPlus(lhs, op) + + case Term.ApplyInfix(lhs, op @ mutMapPlus(_), _, List(_)) => + rewriteMutPlus(lhs, op) + }.asPatch + } + + def replaceMutMapUpdated(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case Term.Apply(Term.Select(a, up @ mutMapUpdate(_)), List(k, v)) => { + ctx.addRight(up, "clone() += (") + + ctx.removeTokens(up.tokens) + + ctx.addRight(v, ")") + } + }.asPatch + } + + def replaceArrayBuilderMake(ctx: RuleCtx): Patch = { + ctx.tree.collect { + case ap @ Term.Apply(at @ Term.ApplyType(Term.Select(lhs, arrayBuilderMake(_)), args), Nil) => + val extraParens = + ap.tokens.slice(at.tokens.size, ap.tokens.size) + ctx.removeTokens(extraParens) + }.asPatch + } + + override def fix(ctx: RuleCtx): Patch = { + replaceSymbols0(ctx) + + replaceCopyToBuffer(ctx) + + replaceSymbolicFold(ctx) + + replaceSetMapPlus2(ctx) + + replaceMutSetMapPlus(ctx) + + replaceMutMapUpdated(ctx) + + replaceArrayBuilderMake(ctx) + } + +} diff --git a/scalafix/rules/src/main/scala/fix/TypeMatcher.scala b/scalafix/rules/src/main/scala/fix/TypeMatcher.scala new file mode 100644 index 00000000..aef83673 --- /dev/null +++ b/scalafix/rules/src/main/scala/fix/TypeMatcher.scala @@ -0,0 +1,22 @@ +package fix + +import scalafix._ +import scalafix.syntax._ +import scalafix.util._ +import scala.meta._ + +// WARNING: TOTAL HACK +// this is only to unblock us until Term.tpe is available: https://github.com/scalameta/scalameta/issues/1212 +// if we have a simple identifier, we can look at his definition at query it's type +// this should be improved in future version of scalameta +object TypeMatcher { + def apply(symbols: Symbol*)(implicit index: SemanticdbIndex): TypeMatcher = + new TypeMatcher(symbols: _*)(index) +} + +final class TypeMatcher(symbols: Symbol*)(implicit index: SemanticdbIndex) { + def unapply(tree: Tree): Boolean = { + index.denotation(tree) + .exists(_.names.headOption.exists(n => symbols.exists(_ == n.symbol))) + } +} diff --git a/scalafix/rules/src/main/scala/fix/UnstableMapValues.scala b/scalafix/rules/src/main/scala/fix/UnstableMapValues.scala index a1c2f797..e530abc9 100644 --- a/scalafix/rules/src/main/scala/fix/UnstableMapValues.scala +++ b/scalafix/rules/src/main/scala/fix/UnstableMapValues.scala @@ -6,11 +6,12 @@ import scalafix.util._ import scala.meta._ -/* +/* 2.12 Cross-Compatible + * * This rules is marked unstable since Map.mapValues was lazy */ case class UnstableMapValues(index: SemanticdbIndex) extends SemanticRule(index, "UnstableMapValues") { - val mapMapValues = + val mapMapValues = SymbolMatcher.exact( Symbol("_root_.scala.collection.immutable.MapLike#mapValues(Lscala/Function1;)Lscala/collection/immutable/Map;.") ) diff --git a/scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala index 8421af88..cd5e2e59 100644 --- a/scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala +++ b/scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala @@ -5,7 +5,8 @@ import scalafix.syntax._ import scalafix.util._ import scala.meta._ -/* +/* Not 2.12 Cross-Compatible + * * This rules is marked unstable since Stream is not strictly equivalent to LazyList. * LazyList has a lazy head but not Stream */ @@ -31,5 +32,5 @@ case class UnstableStreamToLazyList(index: SemanticdbIndex) extends SemanticRule override def fix(ctx: RuleCtx): Patch = { replaceStreamAppend(ctx) + replaceSymbols(ctx) - } + } } diff --git a/scalafix/rules/src/main/scala/fix/package.scala b/scalafix/rules/src/main/scala/fix/package.scala new file mode 100644 index 00000000..7a7e5b6a --- /dev/null +++ b/scalafix/rules/src/main/scala/fix/package.scala @@ -0,0 +1,29 @@ +import scalafix._ +import scalafix.syntax._ +import scalafix.util._ +import scala.meta._ + +package object fix { + def normalized(symbols: String*)(implicit index: SemanticdbIndex): SymbolMatcher = + SymbolMatcher.normalized(symbols.map(Symbol(_)): _*) + + def exact(symbols: String*)(implicit index: SemanticdbIndex): SymbolMatcher = + SymbolMatcher.exact(symbols.map(Symbol(_)): _*) + + def trailingBrackets(tree: Tree, ctx: RuleCtx): Option[(Token.LeftBracket, Token.RightBracket)] = + for { + end <- tree.tokens.lastOption + open <- ctx.tokenList.find(end)(_.is[Token.LeftBracket]).map(_.asInstanceOf[Token.LeftBracket]) + close <- ctx.matchingParens.close(open) + } yield (open, close) + + def startsWithParens(tree: Tree): Boolean = + tree.tokens.headOption.map(_.is[Token.LeftParen]).getOrElse(false) + + def trailingParens(tree: Tree, ctx: RuleCtx): Option[(Token.LeftParen, Token.RightParen)] = + for { + end <- tree.tokens.lastOption + open <- ctx.tokenList.find(end)(_.is[Token.LeftParen]).map(_.asInstanceOf[Token.LeftParen]) + close <- ctx.matchingParens.close(open) + } yield (open, close) +} diff --git a/scalafix/tests/src/test/scala/fix/Collectionstrawman_Tests.scala b/scalafix/tests/src/test/scala/fix/Collectionstrawman_Tests.scala index 65a58ddc..bf86d625 100644 --- a/scalafix/tests/src/test/scala/fix/Collectionstrawman_Tests.scala +++ b/scalafix/tests/src/test/scala/fix/Collectionstrawman_Tests.scala @@ -9,8 +9,9 @@ class Collectionstrawman_Tests SemanticdbIndex.load(Classpath(AbsolutePath(BuildInfo.inputClassdirectory))), AbsolutePath(BuildInfo.inputSourceroot), Seq( - AbsolutePath(BuildInfo.outputSourceroot), - AbsolutePath(BuildInfo.outputFailureSourceroot) + AbsolutePath(BuildInfo.output212Sourceroot), + AbsolutePath(BuildInfo.output213Sourceroot), + AbsolutePath(BuildInfo.output213FailureSourceroot) ) ) { runAllTests() From bba4bc28a0cb3da48acea80ed8327346851a5bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Thu, 28 Jun 2018 15:06:29 +0200 Subject: [PATCH 3/9] Update doc & Remove GitHub rule usage since rules are split accross multiple files it's not possible to use GitHub to publish te rule. We need to publish on maven central: https://github.com/scala/scala-collection-compat/issues/73 --- CONTRIBUTING.md | 10 +++++----- README.md | 8 -------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1e68f962..74d48e16 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,16 +31,16 @@ Even better, instead of providing a diff, you can directly add it as a test case 2. Add a file in the `scalafix/input/src/main/scala/fix/` directory with code that uses the standard collections: - + ~~~ scala class toIteratorVsIterator(xs: Iterable[Int]) { xs.toIterator } ~~~ -3. Add a corresponding file in the `scalafix/output/src/main/scala/fix/` directory +3. Add a corresponding file in the `scalafix/output213/src/main/scala/fix/` directory with the same code but using the strawman: - + ~~~ scala import strawman.collection.Iterable @@ -51,7 +51,7 @@ class toIteratorVsIterator(xs: Iterable[Int]) { 4. Check that your code example compiles - run sbt from the `scalafix/` directory - and then run the following tasks `; input/compile ; output/compile`; + and then run the following task `compile`; 5. Commit your changes, push your branch to your fork and create a pull request. @@ -72,6 +72,6 @@ expected output files: ~~~ Fix the implementation of the rule (in the -`rules/src/main/scala/fix/Scalacollectioncompat_v0.scala` file) until the +`rules/src/main/scala/fix/NewCollections.scala` file) until the tests are green. You can find more help about the scalafix API in its [documentation](https://scalacenter.github.io/scalafix/docs/rule-authors/setup). diff --git a/README.md b/README.md index 7df65bd8..74d90f4e 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,3 @@ 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 - -Run the following sbt task on your project: - -~~~ -> scalafix github:scala/scala-collection-compat/Stable -~~~ From 5c7fe480ce4568fb946125809e3756de1e97c799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Thu, 28 Jun 2018 15:45:28 +0200 Subject: [PATCH 4/9] Move scalafix to main build --- CONTRIBUTING.md | 12 +-- admin/build.sh | 6 +- build.sbt | 85 +++++++++++++++++-- .../scala/collection/compat/BuildFrom.scala | 0 .../scala/collection/compat/CompatImpl.scala | 0 .../scala/collection/compat/Factory.scala | 0 .../compat/immutable/ArraySeq.scala | 0 .../scala/collection/compat/package.scala | 0 .../collection/compat/immutable/package.scala | 0 .../scala/collection/compat/package.scala | 0 .../test/scala/collection/ArraySeqTest.scala | 0 .../test/scala/collection/BuildFromTest.scala | 0 .../scala/collection/CollectionTest.scala | 0 .../test/scala/collection/FactoryTest.scala | 0 .../test/scala/collection/StreamTest.scala | 0 .../scala/collection/generic/SortedTest.scala | 0 project/plugins.sbt | 11 +-- .../main/scala/fix/CanBuildFromNegSrc.scala | 0 .../src/main/scala/fix/CanBuildFromSrc.scala | 0 .../src/main/scala/fix/CopyToBufferSrc.scala | 0 .../src/main/scala/fix/ExperimentalSrc.scala | 0 .../src/main/scala/fix/FoldSrc.scala | 0 .../src/main/scala/fix/IterableSrc.scala | 0 .../src/main/scala/fix/LinearSeqSrc.scala | 0 .../src/main/scala/fix/MutSetMapSrc.scala | 0 .../src/main/scala/fix/RetainSrc.scala | 0 .../src/main/scala/fix/SetMapSrc.scala | 0 .../src/main/scala/fix/TestsSrc.scala | 0 .../src/main/scala/fix/TraversableSrc.scala | 0 .../src/main/scala/fix/TupleNZippedSrc.scala | 0 .../main/scala/fix/UnstableMapValuesSrc.scala | 0 .../fix/UnstableStreamToLazyListSrc.scala | 0 .../src/main/scala/fix/CopyToBufferSrc.scala | 0 .../src/main/scala/fix/ExperimentalSrc.scala | 0 .../src/main/scala/fix/FoldSrc.scala | 0 .../src/main/scala/fix/LinearSeqSrc.scala | 0 .../src/main/scala/fix/MutSetMapSrc.scala | 0 .../src/main/scala/fix/SetMapSrc.scala | 0 .../src/main/scala/fix/TestsSrc.scala | 0 .../main/scala/fix/UnstableMapValuesSrc.scala | 0 .../main/scala/fix/CanBuildFromNegSrc.scala | 0 .../src/main/scala/fix/CanBuildFromSrc.scala | 0 .../src/main/scala/fix/IterableSrc.scala | 0 .../src/main/scala/fix/RetainSrc.scala | 0 .../src/main/scala/fix/TraversableSrc.scala | 0 .../src/main/scala/fix/TupleNZippedSrc.scala | 0 .../fix/UnstableStreamToLazyListSrc.scala | 0 .../src/main/scala/fix/CanBuildFrom.scala | 0 .../src/main/scala/fix/CrossCompat.scala | 0 .../src/main/scala/fix/Experimental.scala | 0 .../src/main/scala/fix/NewCollections.scala | 0 .../src/main/scala/fix/Stable212Base.scala | 0 .../src/main/scala/fix/TypeMatcher.scala | 0 .../main/scala/fix/UnstableMapValues.scala | 0 .../fix/UnstableStreamToLazyListSrc.scala | 0 .../src/main/scala/fix/package.scala | 0 .../scala/fix/Collectionstrawman_Tests.scala | 0 scalafix/build.sbt | 59 ------------- scalafix/project/build.properties | 1 - scalafix/project/plugins.sbt | 3 - 60 files changed, 93 insertions(+), 84 deletions(-) rename {src => compat/src}/main/scala-2.11_2.12/scala/collection/compat/BuildFrom.scala (100%) rename {src => compat/src}/main/scala-2.11_2.12/scala/collection/compat/CompatImpl.scala (100%) rename {src => compat/src}/main/scala-2.11_2.12/scala/collection/compat/Factory.scala (100%) rename {src => compat/src}/main/scala-2.11_2.12/scala/collection/compat/immutable/ArraySeq.scala (100%) rename {src => compat/src}/main/scala-2.11_2.12/scala/collection/compat/package.scala (100%) rename {src => compat/src}/main/scala-2.13/scala/collection/compat/immutable/package.scala (100%) rename {src => compat/src}/main/scala-2.13/scala/collection/compat/package.scala (100%) rename {src => compat/src}/test/scala/test/scala/collection/ArraySeqTest.scala (100%) rename {src => compat/src}/test/scala/test/scala/collection/BuildFromTest.scala (100%) rename {src => compat/src}/test/scala/test/scala/collection/CollectionTest.scala (100%) rename {src => compat/src}/test/scala/test/scala/collection/FactoryTest.scala (100%) rename {src => compat/src}/test/scala/test/scala/collection/StreamTest.scala (100%) rename {src => compat/src}/test/scala/test/scala/collection/generic/SortedTest.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/CanBuildFromNegSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/CanBuildFromSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/CopyToBufferSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/ExperimentalSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/FoldSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/IterableSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/LinearSeqSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/MutSetMapSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/RetainSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/SetMapSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/TestsSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/TraversableSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/TupleNZippedSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/UnstableMapValuesSrc.scala (100%) rename {scalafix/input => scalafix-input}/src/main/scala/fix/UnstableStreamToLazyListSrc.scala (100%) rename {scalafix/output212 => scalafix-output212}/src/main/scala/fix/CopyToBufferSrc.scala (100%) rename {scalafix/output212 => scalafix-output212}/src/main/scala/fix/ExperimentalSrc.scala (100%) rename {scalafix/output212 => scalafix-output212}/src/main/scala/fix/FoldSrc.scala (100%) rename {scalafix/output212 => scalafix-output212}/src/main/scala/fix/LinearSeqSrc.scala (100%) rename {scalafix/output212 => scalafix-output212}/src/main/scala/fix/MutSetMapSrc.scala (100%) rename {scalafix/output212 => scalafix-output212}/src/main/scala/fix/SetMapSrc.scala (100%) rename {scalafix/output212 => scalafix-output212}/src/main/scala/fix/TestsSrc.scala (100%) rename {scalafix/output212 => scalafix-output212}/src/main/scala/fix/UnstableMapValuesSrc.scala (100%) rename {scalafix/output213-failure => scalafix-output213-failure}/src/main/scala/fix/CanBuildFromNegSrc.scala (100%) rename {scalafix/output213 => scalafix-output213}/src/main/scala/fix/CanBuildFromSrc.scala (100%) rename {scalafix/output213 => scalafix-output213}/src/main/scala/fix/IterableSrc.scala (100%) rename {scalafix/output213 => scalafix-output213}/src/main/scala/fix/RetainSrc.scala (100%) rename {scalafix/output213 => scalafix-output213}/src/main/scala/fix/TraversableSrc.scala (100%) rename {scalafix/output213 => scalafix-output213}/src/main/scala/fix/TupleNZippedSrc.scala (100%) rename {scalafix/output213 => scalafix-output213}/src/main/scala/fix/UnstableStreamToLazyListSrc.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/CanBuildFrom.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/CrossCompat.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/Experimental.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/NewCollections.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/Stable212Base.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/TypeMatcher.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/UnstableMapValues.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/UnstableStreamToLazyListSrc.scala (100%) rename {scalafix/rules => scalafix-rules}/src/main/scala/fix/package.scala (100%) rename {scalafix/tests => scalafix-tests}/src/test/scala/fix/Collectionstrawman_Tests.scala (100%) delete mode 100644 scalafix/build.sbt delete mode 100644 scalafix/project/build.properties delete mode 100644 scalafix/project/plugins.sbt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 74d48e16..ba8057aa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,8 +4,8 @@ ### Sbt Projects -- `scala-collection-compat` project (in the root directory): implementation of the compatibility library ; -- In directory `scalafix/` there is an independent build containing the implementation of the migration tool. +- `compat` project: implementation of the compatibility library ; +- `scalafix*`: implementation of the migration tool. ## Migration tool @@ -29,7 +29,7 @@ Even better, instead of providing a diff, you can directly add it as a test case 1. Fork this repository and create a separate branch; -2. Add a file in the `scalafix/input/src/main/scala/fix/` directory with code +2. Add a file in the `scalafix-input/src/main/scala/fix/` directory with code that uses the standard collections: ~~~ scala @@ -38,7 +38,7 @@ class toIteratorVsIterator(xs: Iterable[Int]) { } ~~~ -3. Add a corresponding file in the `scalafix/output213/src/main/scala/fix/` directory +3. Add a corresponding file in the `scalafix-output213/src/main/scala/fix/` directory with the same code but using the strawman: ~~~ scala @@ -50,7 +50,7 @@ class toIteratorVsIterator(xs: Iterable[Int]) { ~~~ 4. Check that your code example compiles - - run sbt from the `scalafix/` directory + - run sbt and then run the following task `compile`; 5. Commit your changes, push your branch to your fork and create a pull request. @@ -68,7 +68,7 @@ migration tool on the input files and check whether the result matches the expected output files: ~~~ -> tests/test +> scalafixTests/test ~~~ Fix the implementation of the rule (in the diff --git a/admin/build.sh b/admin/build.sh index 9d13ccb0..22c21fb3 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -19,14 +19,14 @@ set -e RELEASE_COMBO=true if [[ "$TEST_SCALAFIX" == "true" ]]; then - cd scalafix && sbt tests/test + sbt scalafixTests/test exit 0 fi if [ "$SCALAJS_VERSION" = "" ]; then - projectPrefix="scala-collection-compat" + projectPrefix="compat" else - projectPrefix="scala-collection-compatJS" + projectPrefix="compatJS" fi verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" diff --git a/build.sbt b/build.sbt index bf43cc3d..e679c1d2 100644 --- a/build.sbt +++ b/build.sbt @@ -1,16 +1,86 @@ -import sbtcrossproject.{crossProject, CrossType} import ScalaModulePlugin._ +import sbtcrossproject.{crossProject, CrossType} +import _root_.scalafix.Versions.{version => scalafixVersion, scala212 => scalafixScala212} + +lazy val scala212 = "2.12.6" +lazy val scala213 = "2.13.0-M4" + +lazy val scala213Settings = Seq( + resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/", + scalaVersion := scala213 +) inThisBuild(Seq( - crossScalaVersions := Seq("2.12.6", "2.13.0-M4", "2.11.12") + crossScalaVersions := Seq(scala212, scala213, "2.11.12") )) -disablePlugins(JvmPlugin) -lazy val `scala-collection-compat` = crossProject(JSPlatform, JVMPlatform) +lazy val root = project + .in(file(".")) + .aggregate( + compatJVM, compatJS, + scalafixRules, scalafixInput, scalafixTests, + scalafixOutput212, scalafixOutput213 + ) + .disablePlugins(ScalafixPlugin) + +lazy val scalafixInput = project + .in(file("scalafix-input")) + .settings( + scalaVersion := scalafixScala212, + scalafixSourceroot := sourceDirectory.in(Compile).value + ) + +lazy val scalafixOutput212 = project + .in(file("scalafix-output212")) + .settings(scalaVersion := scalafixScala212) + .dependsOn(compatJVM) + +lazy val scalafixOutput213 = project + .in(file("scalafix-output213")) + .settings(scala213Settings) + +lazy val scalafixOutput213Failure = project + .in(file("scalafix-output213-failure")) + .settings(scala213Settings) + +lazy val scalafixRules = project + .in(file("scalafix-rules")) + .settings( + scalaVersion := scalafixScala212, + libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % scalafixVersion + ) + +lazy val scalafixTests = project + .in(file("scalafix-tests")) + .settings( + scalaVersion := scalafixScala212, + libraryDependencies += "ch.epfl.scala" % "scalafix-testkit" % scalafixVersion % Test cross CrossVersion.full, + buildInfoPackage := "fix", + buildInfoKeys := Seq[BuildInfoKey]( + "inputSourceroot" -> + sourceDirectory.in(scalafixInput, Compile).value, + "output212Sourceroot" -> + sourceDirectory.in(scalafixOutput212, Compile).value, + "output213Sourceroot" -> + sourceDirectory.in(scalafixOutput213, Compile).value, + "output213FailureSourceroot" -> + sourceDirectory.in(scalafixOutput213Failure, Compile).value, + "inputClassdirectory" -> + classDirectory.in(scalafixInput, Compile).value + ), + test in Test := (test in Test).dependsOn( + compile in (scalafixOutput212, Compile), + compile in (scalafixOutput213, Compile) + ).value + ) + .dependsOn(scalafixInput, scalafixRules) + .enablePlugins(BuildInfoPlugin) + +lazy val compat = crossProject(JSPlatform, JVMPlatform) .withoutSuffixFor(JVMPlatform) .crossType(CrossType.Pure) - .in(file(".")) + .in(file("compat")) .settings(scalaModuleSettings) .jvmSettings(scalaModuleSettingsJVM) .settings( @@ -36,6 +106,7 @@ lazy val `scala-collection-compat` = crossProject(JSPlatform, JVMPlatform) fork in Test := false // Scala.js cannot run forked tests ) .jsConfigure(_.enablePlugins(ScalaJSJUnitPlugin)) + .disablePlugins(ScalafixPlugin) -lazy val `scala-collection-compatJVM` = `scala-collection-compat`.jvm -lazy val `scala-collection-compatJS` = `scala-collection-compat`.js +lazy val compatJVM = compat.jvm +lazy val compatJS = compat.js diff --git a/src/main/scala-2.11_2.12/scala/collection/compat/BuildFrom.scala b/compat/src/main/scala-2.11_2.12/scala/collection/compat/BuildFrom.scala similarity index 100% rename from src/main/scala-2.11_2.12/scala/collection/compat/BuildFrom.scala rename to compat/src/main/scala-2.11_2.12/scala/collection/compat/BuildFrom.scala diff --git a/src/main/scala-2.11_2.12/scala/collection/compat/CompatImpl.scala b/compat/src/main/scala-2.11_2.12/scala/collection/compat/CompatImpl.scala similarity index 100% rename from src/main/scala-2.11_2.12/scala/collection/compat/CompatImpl.scala rename to compat/src/main/scala-2.11_2.12/scala/collection/compat/CompatImpl.scala diff --git a/src/main/scala-2.11_2.12/scala/collection/compat/Factory.scala b/compat/src/main/scala-2.11_2.12/scala/collection/compat/Factory.scala similarity index 100% rename from src/main/scala-2.11_2.12/scala/collection/compat/Factory.scala rename to compat/src/main/scala-2.11_2.12/scala/collection/compat/Factory.scala diff --git a/src/main/scala-2.11_2.12/scala/collection/compat/immutable/ArraySeq.scala b/compat/src/main/scala-2.11_2.12/scala/collection/compat/immutable/ArraySeq.scala similarity index 100% rename from src/main/scala-2.11_2.12/scala/collection/compat/immutable/ArraySeq.scala rename to compat/src/main/scala-2.11_2.12/scala/collection/compat/immutable/ArraySeq.scala diff --git a/src/main/scala-2.11_2.12/scala/collection/compat/package.scala b/compat/src/main/scala-2.11_2.12/scala/collection/compat/package.scala similarity index 100% rename from src/main/scala-2.11_2.12/scala/collection/compat/package.scala rename to compat/src/main/scala-2.11_2.12/scala/collection/compat/package.scala diff --git a/src/main/scala-2.13/scala/collection/compat/immutable/package.scala b/compat/src/main/scala-2.13/scala/collection/compat/immutable/package.scala similarity index 100% rename from src/main/scala-2.13/scala/collection/compat/immutable/package.scala rename to compat/src/main/scala-2.13/scala/collection/compat/immutable/package.scala diff --git a/src/main/scala-2.13/scala/collection/compat/package.scala b/compat/src/main/scala-2.13/scala/collection/compat/package.scala similarity index 100% rename from src/main/scala-2.13/scala/collection/compat/package.scala rename to compat/src/main/scala-2.13/scala/collection/compat/package.scala diff --git a/src/test/scala/test/scala/collection/ArraySeqTest.scala b/compat/src/test/scala/test/scala/collection/ArraySeqTest.scala similarity index 100% rename from src/test/scala/test/scala/collection/ArraySeqTest.scala rename to compat/src/test/scala/test/scala/collection/ArraySeqTest.scala diff --git a/src/test/scala/test/scala/collection/BuildFromTest.scala b/compat/src/test/scala/test/scala/collection/BuildFromTest.scala similarity index 100% rename from src/test/scala/test/scala/collection/BuildFromTest.scala rename to compat/src/test/scala/test/scala/collection/BuildFromTest.scala diff --git a/src/test/scala/test/scala/collection/CollectionTest.scala b/compat/src/test/scala/test/scala/collection/CollectionTest.scala similarity index 100% rename from src/test/scala/test/scala/collection/CollectionTest.scala rename to compat/src/test/scala/test/scala/collection/CollectionTest.scala diff --git a/src/test/scala/test/scala/collection/FactoryTest.scala b/compat/src/test/scala/test/scala/collection/FactoryTest.scala similarity index 100% rename from src/test/scala/test/scala/collection/FactoryTest.scala rename to compat/src/test/scala/test/scala/collection/FactoryTest.scala diff --git a/src/test/scala/test/scala/collection/StreamTest.scala b/compat/src/test/scala/test/scala/collection/StreamTest.scala similarity index 100% rename from src/test/scala/test/scala/collection/StreamTest.scala rename to compat/src/test/scala/test/scala/collection/StreamTest.scala diff --git a/src/test/scala/test/scala/collection/generic/SortedTest.scala b/compat/src/test/scala/test/scala/collection/generic/SortedTest.scala similarity index 100% rename from src/test/scala/test/scala/collection/generic/SortedTest.scala rename to compat/src/test/scala/test/scala/collection/generic/SortedTest.scala diff --git a/project/plugins.sbt b/project/plugins.sbt index 0670f0ee..2979ce34 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,9 +5,10 @@ else // see https://github.com/scala/sbt-scala-module/issues/35 Seq(addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.3")) -val scalaJSVersion = - Option(System.getenv("SCALAJS_VERSION")).filter(_.nonEmpty).getOrElse("0.6.23") +val scalaJSVersion = Option(System.getenv("SCALAJS_VERSION")).filter(_.nonEmpty).getOrElse("0.6.23") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % scalaJSVersion) -addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.4.0") -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.14") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % scalaJSVersion) +addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.4.0") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.14") +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.10") +addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") diff --git a/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala b/scalafix-input/src/main/scala/fix/CanBuildFromNegSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala rename to scalafix-input/src/main/scala/fix/CanBuildFromNegSrc.scala diff --git a/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix-input/src/main/scala/fix/CanBuildFromSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala rename to scalafix-input/src/main/scala/fix/CanBuildFromSrc.scala diff --git a/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala b/scalafix-input/src/main/scala/fix/CopyToBufferSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala rename to scalafix-input/src/main/scala/fix/CopyToBufferSrc.scala diff --git a/scalafix/input/src/main/scala/fix/ExperimentalSrc.scala b/scalafix-input/src/main/scala/fix/ExperimentalSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/ExperimentalSrc.scala rename to scalafix-input/src/main/scala/fix/ExperimentalSrc.scala diff --git a/scalafix/input/src/main/scala/fix/FoldSrc.scala b/scalafix-input/src/main/scala/fix/FoldSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/FoldSrc.scala rename to scalafix-input/src/main/scala/fix/FoldSrc.scala diff --git a/scalafix/input/src/main/scala/fix/IterableSrc.scala b/scalafix-input/src/main/scala/fix/IterableSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/IterableSrc.scala rename to scalafix-input/src/main/scala/fix/IterableSrc.scala diff --git a/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala b/scalafix-input/src/main/scala/fix/LinearSeqSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/LinearSeqSrc.scala rename to scalafix-input/src/main/scala/fix/LinearSeqSrc.scala diff --git a/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala b/scalafix-input/src/main/scala/fix/MutSetMapSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/MutSetMapSrc.scala rename to scalafix-input/src/main/scala/fix/MutSetMapSrc.scala diff --git a/scalafix/input/src/main/scala/fix/RetainSrc.scala b/scalafix-input/src/main/scala/fix/RetainSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/RetainSrc.scala rename to scalafix-input/src/main/scala/fix/RetainSrc.scala diff --git a/scalafix/input/src/main/scala/fix/SetMapSrc.scala b/scalafix-input/src/main/scala/fix/SetMapSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/SetMapSrc.scala rename to scalafix-input/src/main/scala/fix/SetMapSrc.scala diff --git a/scalafix/input/src/main/scala/fix/TestsSrc.scala b/scalafix-input/src/main/scala/fix/TestsSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/TestsSrc.scala rename to scalafix-input/src/main/scala/fix/TestsSrc.scala diff --git a/scalafix/input/src/main/scala/fix/TraversableSrc.scala b/scalafix-input/src/main/scala/fix/TraversableSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/TraversableSrc.scala rename to scalafix-input/src/main/scala/fix/TraversableSrc.scala diff --git a/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala b/scalafix-input/src/main/scala/fix/TupleNZippedSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala rename to scalafix-input/src/main/scala/fix/TupleNZippedSrc.scala diff --git a/scalafix/input/src/main/scala/fix/UnstableMapValuesSrc.scala b/scalafix-input/src/main/scala/fix/UnstableMapValuesSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/UnstableMapValuesSrc.scala rename to scalafix-input/src/main/scala/fix/UnstableMapValuesSrc.scala diff --git a/scalafix/input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix-input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala similarity index 100% rename from scalafix/input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala rename to scalafix-input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/CopyToBufferSrc.scala b/scalafix-output212/src/main/scala/fix/CopyToBufferSrc.scala similarity index 100% rename from scalafix/output212/src/main/scala/fix/CopyToBufferSrc.scala rename to scalafix-output212/src/main/scala/fix/CopyToBufferSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/ExperimentalSrc.scala b/scalafix-output212/src/main/scala/fix/ExperimentalSrc.scala similarity index 100% rename from scalafix/output212/src/main/scala/fix/ExperimentalSrc.scala rename to scalafix-output212/src/main/scala/fix/ExperimentalSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/FoldSrc.scala b/scalafix-output212/src/main/scala/fix/FoldSrc.scala similarity index 100% rename from scalafix/output212/src/main/scala/fix/FoldSrc.scala rename to scalafix-output212/src/main/scala/fix/FoldSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/LinearSeqSrc.scala b/scalafix-output212/src/main/scala/fix/LinearSeqSrc.scala similarity index 100% rename from scalafix/output212/src/main/scala/fix/LinearSeqSrc.scala rename to scalafix-output212/src/main/scala/fix/LinearSeqSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/MutSetMapSrc.scala b/scalafix-output212/src/main/scala/fix/MutSetMapSrc.scala similarity index 100% rename from scalafix/output212/src/main/scala/fix/MutSetMapSrc.scala rename to scalafix-output212/src/main/scala/fix/MutSetMapSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/SetMapSrc.scala b/scalafix-output212/src/main/scala/fix/SetMapSrc.scala similarity index 100% rename from scalafix/output212/src/main/scala/fix/SetMapSrc.scala rename to scalafix-output212/src/main/scala/fix/SetMapSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/TestsSrc.scala b/scalafix-output212/src/main/scala/fix/TestsSrc.scala similarity index 100% rename from scalafix/output212/src/main/scala/fix/TestsSrc.scala rename to scalafix-output212/src/main/scala/fix/TestsSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/UnstableMapValuesSrc.scala b/scalafix-output212/src/main/scala/fix/UnstableMapValuesSrc.scala similarity index 100% rename from scalafix/output212/src/main/scala/fix/UnstableMapValuesSrc.scala rename to scalafix-output212/src/main/scala/fix/UnstableMapValuesSrc.scala diff --git a/scalafix/output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala b/scalafix-output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala similarity index 100% rename from scalafix/output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala rename to scalafix-output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala diff --git a/scalafix/output213/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix-output213/src/main/scala/fix/CanBuildFromSrc.scala similarity index 100% rename from scalafix/output213/src/main/scala/fix/CanBuildFromSrc.scala rename to scalafix-output213/src/main/scala/fix/CanBuildFromSrc.scala diff --git a/scalafix/output213/src/main/scala/fix/IterableSrc.scala b/scalafix-output213/src/main/scala/fix/IterableSrc.scala similarity index 100% rename from scalafix/output213/src/main/scala/fix/IterableSrc.scala rename to scalafix-output213/src/main/scala/fix/IterableSrc.scala diff --git a/scalafix/output213/src/main/scala/fix/RetainSrc.scala b/scalafix-output213/src/main/scala/fix/RetainSrc.scala similarity index 100% rename from scalafix/output213/src/main/scala/fix/RetainSrc.scala rename to scalafix-output213/src/main/scala/fix/RetainSrc.scala diff --git a/scalafix/output213/src/main/scala/fix/TraversableSrc.scala b/scalafix-output213/src/main/scala/fix/TraversableSrc.scala similarity index 100% rename from scalafix/output213/src/main/scala/fix/TraversableSrc.scala rename to scalafix-output213/src/main/scala/fix/TraversableSrc.scala diff --git a/scalafix/output213/src/main/scala/fix/TupleNZippedSrc.scala b/scalafix-output213/src/main/scala/fix/TupleNZippedSrc.scala similarity index 100% rename from scalafix/output213/src/main/scala/fix/TupleNZippedSrc.scala rename to scalafix-output213/src/main/scala/fix/TupleNZippedSrc.scala diff --git a/scalafix/output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix-output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala similarity index 100% rename from scalafix/output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala rename to scalafix-output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala diff --git a/scalafix/rules/src/main/scala/fix/CanBuildFrom.scala b/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/CanBuildFrom.scala rename to scalafix-rules/src/main/scala/fix/CanBuildFrom.scala diff --git a/scalafix/rules/src/main/scala/fix/CrossCompat.scala b/scalafix-rules/src/main/scala/fix/CrossCompat.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/CrossCompat.scala rename to scalafix-rules/src/main/scala/fix/CrossCompat.scala diff --git a/scalafix/rules/src/main/scala/fix/Experimental.scala b/scalafix-rules/src/main/scala/fix/Experimental.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/Experimental.scala rename to scalafix-rules/src/main/scala/fix/Experimental.scala diff --git a/scalafix/rules/src/main/scala/fix/NewCollections.scala b/scalafix-rules/src/main/scala/fix/NewCollections.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/NewCollections.scala rename to scalafix-rules/src/main/scala/fix/NewCollections.scala diff --git a/scalafix/rules/src/main/scala/fix/Stable212Base.scala b/scalafix-rules/src/main/scala/fix/Stable212Base.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/Stable212Base.scala rename to scalafix-rules/src/main/scala/fix/Stable212Base.scala diff --git a/scalafix/rules/src/main/scala/fix/TypeMatcher.scala b/scalafix-rules/src/main/scala/fix/TypeMatcher.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/TypeMatcher.scala rename to scalafix-rules/src/main/scala/fix/TypeMatcher.scala diff --git a/scalafix/rules/src/main/scala/fix/UnstableMapValues.scala b/scalafix-rules/src/main/scala/fix/UnstableMapValues.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/UnstableMapValues.scala rename to scalafix-rules/src/main/scala/fix/UnstableMapValues.scala diff --git a/scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala rename to scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala diff --git a/scalafix/rules/src/main/scala/fix/package.scala b/scalafix-rules/src/main/scala/fix/package.scala similarity index 100% rename from scalafix/rules/src/main/scala/fix/package.scala rename to scalafix-rules/src/main/scala/fix/package.scala diff --git a/scalafix/tests/src/test/scala/fix/Collectionstrawman_Tests.scala b/scalafix-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-tests/src/test/scala/fix/Collectionstrawman_Tests.scala diff --git a/scalafix/build.sbt b/scalafix/build.sbt deleted file mode 100644 index 98e41d20..00000000 --- a/scalafix/build.sbt +++ /dev/null @@ -1,59 +0,0 @@ -def scalafixVersion = _root_.scalafix.Versions.version -inScope(Global)( - List( - scalaVersion := _root_.scalafix.Versions.scala212 - ) -) - -lazy val root = project - .in(file(".")) - .aggregate( - rules, input, output212, output213, output213Failure, tests - ) - -lazy val rules = project.settings( - libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % scalafixVersion -) - -lazy val input = project - .settings( - scalafixSourceroot := sourceDirectory.in(Compile).value - ) - -lazy val output212 = project - -lazy val output213 = project - .settings( - resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/", - scalaVersion := "2.13.0-M4" - ) - -lazy val output213Failure = project.in(file("output213-failure")) - .settings( - resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/", - scalaVersion := "2.13.0-M4" - ) - -lazy val tests = project - .settings( - libraryDependencies += "ch.epfl.scala" % "scalafix-testkit" % scalafixVersion % Test cross CrossVersion.full, - buildInfoPackage := "fix", - buildInfoKeys := Seq[BuildInfoKey]( - "inputSourceroot" -> - sourceDirectory.in(input, Compile).value, - "output212Sourceroot" -> - sourceDirectory.in(output212, Compile).value, - "output213Sourceroot" -> - sourceDirectory.in(output213, Compile).value, - "output213FailureSourceroot" -> - sourceDirectory.in(output213Failure, Compile).value, - "inputClassdirectory" -> - classDirectory.in(input, Compile).value - ), - test in Test := (test in Test).dependsOn( - compile in (output212, Compile), - compile in (output213, Compile) - ).value - ) - .dependsOn(input, rules) - .enablePlugins(BuildInfoPlugin) diff --git a/scalafix/project/build.properties b/scalafix/project/build.properties deleted file mode 100644 index c091b86c..00000000 --- a/scalafix/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version=0.13.16 diff --git a/scalafix/project/plugins.sbt b/scalafix/project/plugins.sbt deleted file mode 100644 index 0fd7a907..00000000 --- a/scalafix/project/plugins.sbt +++ /dev/null @@ -1,3 +0,0 @@ -addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.10") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0") -addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.6.1") \ No newline at end of file From 0aacee761bc1d5dd83dde71a26157ee93b63d2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Thu, 28 Jun 2018 15:49:32 +0200 Subject: [PATCH 5/9] Appropriate name for tests --- .../fix/{Collectionstrawman_Tests.scala => ScalafixTests.scala} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename scalafix-tests/src/test/scala/fix/{Collectionstrawman_Tests.scala => ScalafixTests.scala} (93%) diff --git a/scalafix-tests/src/test/scala/fix/Collectionstrawman_Tests.scala b/scalafix-tests/src/test/scala/fix/ScalafixTests.scala similarity index 93% rename from scalafix-tests/src/test/scala/fix/Collectionstrawman_Tests.scala rename to scalafix-tests/src/test/scala/fix/ScalafixTests.scala index bf86d625..2ab26e4d 100644 --- a/scalafix-tests/src/test/scala/fix/Collectionstrawman_Tests.scala +++ b/scalafix-tests/src/test/scala/fix/ScalafixTests.scala @@ -4,7 +4,7 @@ import scala.meta._ import scalafix.testkit._ import scalafix._ -class Collectionstrawman_Tests +class ScalafixTests extends SemanticRuleSuite( SemanticdbIndex.load(Classpath(AbsolutePath(BuildInfo.inputClassdirectory))), AbsolutePath(BuildInfo.inputSourceroot), From e1a5c59f600225aebc19efde1f5d0ce0142d24bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Thu, 28 Jun 2018 16:56:20 +0200 Subject: [PATCH 6/9] Rewrite: CrossCompat CanBuildFrom --- .../main/scala/fix/CanBuildFromNegSrc.scala | 2 +- .../src/main/scala/fix/CanBuildFromSrc.scala | 2 +- .../src/main/scala/fix/CanBuildFromSrc.scala | 36 +++++++++ .../src/main/scala/fix/CanBuildFromSrc.scala | 35 --------- .../src/main/scala/fix/CanBuildFrom.scala | 78 ++++++++----------- .../src/main/scala/fix/NewCollections.scala | 46 +++-------- .../src/main/scala/fix/Stable212Base.scala | 42 ++++++++-- 7 files changed, 115 insertions(+), 126 deletions(-) create mode 100644 scalafix-output212/src/main/scala/fix/CanBuildFromSrc.scala delete mode 100644 scalafix-output213/src/main/scala/fix/CanBuildFromSrc.scala diff --git a/scalafix-input/src/main/scala/fix/CanBuildFromNegSrc.scala b/scalafix-input/src/main/scala/fix/CanBuildFromNegSrc.scala index 138b6d8e..8e0109ed 100644 --- a/scalafix-input/src/main/scala/fix/CanBuildFromNegSrc.scala +++ b/scalafix-input/src/main/scala/fix/CanBuildFromNegSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.NewCollections" +rule = "scala:fix.CrossCompat" */ package fix diff --git a/scalafix-input/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix-input/src/main/scala/fix/CanBuildFromSrc.scala index 34c79003..43311424 100644 --- a/scalafix-input/src/main/scala/fix/CanBuildFromSrc.scala +++ b/scalafix-input/src/main/scala/fix/CanBuildFromSrc.scala @@ -1,5 +1,5 @@ /* -rule = "scala:fix.NewCollections" +rule = "scala:fix.CrossCompat" */ package fix diff --git a/scalafix-output212/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix-output212/src/main/scala/fix/CanBuildFromSrc.scala new file mode 100644 index 00000000..00abbbeb --- /dev/null +++ b/scalafix-output212/src/main/scala/fix/CanBuildFromSrc.scala @@ -0,0 +1,36 @@ + + + +package fix + +import scala.language.higherKinds + +import scala.collection.compat._ + +class CanBuildFromSrc() { + + def f[C0, A, C1[_]](c0: C0)(implicit + cbf: Factory[Int, C1[Int]], + cbf2: Factory[String, C1[String]], + cbf3: BuildFrom[C0, A, C1[A]]): C1[Int] = { + + val b = cbf.newBuilder + val b2 = cbf.newBuilder + val b3 = cbf.newBuilder + val b4 = cbf2.newBuilder + val b5 = cbf3.newBuilder(c0) + val b6 = cbf3.newBuilder(c0) + + cbf.fromSpecific(List.empty[Int]) + cbf2.fromSpecific(List.empty[String]) + b.result() + } + + def kind(implicit cbf: BuildFrom[String, Char, String], + cbf2: BuildFrom[String, (Int, Boolean), Map[Int, Boolean]]): Unit = { + + cbf.newBuilder("") + cbf2.newBuilder("") + () + } +} diff --git a/scalafix-output213/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix-output213/src/main/scala/fix/CanBuildFromSrc.scala deleted file mode 100644 index 34021461..00000000 --- a/scalafix-output213/src/main/scala/fix/CanBuildFromSrc.scala +++ /dev/null @@ -1,35 +0,0 @@ - - - -package fix - -import scala.language.higherKinds - - -class CanBuildFromSrc() { - - def f[C0, A, C1[_]](c0: C0)(implicit - cbf: collection.Factory[Int, C1[Int]], - cbf2: collection.Factory[String, C1[String]], - cbf3: collection.BuildFrom[C0, A, C1[A]]): C1[Int] = { - - val b = cbf.newBuilder - val b2 = cbf.newBuilder - val b3 = cbf.newBuilder - val b4 = cbf2.newBuilder - val b5 = cbf3.newBuilder(c0) - val b6 = cbf3.newBuilder(c0) - - List.empty[Int].to(cbf) - List.empty[String].to(cbf2) - b.result() - } - - def kind(implicit cbf: collection.BuildFrom[String, Char, String], - cbf2: collection.BuildFrom[String, (Int, Boolean), Map[Int, Boolean]]): Unit = { - - cbf.newBuilder("") - cbf2.newBuilder("") - () - } -} diff --git a/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala b/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala index ad95703c..925f63d8 100644 --- a/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala +++ b/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala @@ -66,7 +66,7 @@ case class CanBuildFrom(param: Name, cbf: Type) { }.asPatch val parameterType = - ctx.replaceTree(cbf, "collection.BuildFrom") + ctx.replaceTree(cbf, "BuildFrom") parameterType + cbfCalls } @@ -78,37 +78,28 @@ object CanBuildFromNothing { ctx: RuleCtx, collectionCanBuildFrom: SymbolMatcher, nothing: SymbolMatcher, - toTpe: SymbolMatcher)(implicit index: SemanticdbIndex): (Patch, Set[Tree]) = { - val handledTo = Set.newBuilder[Tree] - - val patches = - paramss.flatten.collect{ - case - Term.Param( - List(Mod.Implicit()), - param, - Some( - tpe @ Type.Apply( - collectionCanBuildFrom(_), - List( - nothing(_), - t, - cct @ Type.Apply( - cc, - _ - ) + toTpe: SymbolMatcher)(implicit index: SemanticdbIndex): Patch = { + paramss.flatten.collect{ + case + Term.Param( + List(Mod.Implicit()), + param, + Some( + tpe @ Type.Apply( + collectionCanBuildFrom(_), + List( + nothing(_), + t, + cct @ Type.Apply( + cc, + _ ) ) - ), - _ - ) => new CanBuildFromNothing(param, tpe, t, cct, cc, body, ctx, toTpe) - }.map{cbf => - val (ps, ht) = cbf.toFactory - handledTo ++= ht - ps - }.asPatch - - (patches, handledTo.result()) + ) + ), + _ + ) => new CanBuildFromNothing(param, tpe, t, cct, cc, body, ctx, toTpe) + }.map(_.toFactory).asPatch } } @@ -129,9 +120,7 @@ case class CanBuildFromNothing(param: Name, body: Term, ctx: RuleCtx, toTpe: SymbolMatcher) { - def toFactory(implicit index: SemanticdbIndex): (Patch, Set[Tree]) = { - val handledTo = Set.newBuilder[Tree] - + def toFactory(implicit index: SemanticdbIndex): Patch = { val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get) // cbf() / cbf.apply => cbf.newBuilder @@ -160,11 +149,10 @@ case class CanBuildFromNothing(param: Name, val matchCC = SymbolMatcher.exact(ctx.index.symbol(cc).get) - // e.to[CC] => e.to(cbf) + // e.to[CC] => cbf.fromSpecific(e) val toCalls = body.collect { - case ap @ Term.ApplyType(Term.Select(_, to @ toTpe(_)), List(cc2 @ matchCC(_))) => - handledTo += to + case ap @ Term.ApplyType(Term.Select(e, to @ toTpe(_)), List(cc2 @ matchCC(_))) => // e.to[CC](*cbf*) extract implicit parameter val synth = ctx.index.synthetics.find(_.position.end == ap.pos.end).get @@ -173,23 +161,25 @@ case class CanBuildFromNothing(param: Name, // This is a bit unsafe // https://github.com/scalameta/scalameta/issues/1636 if (implicitCbf.syntax == param.syntax) { - trailingBrackets(to, ctx).map { case (open, close) => - ctx.replaceTree(cc2, implicitCbf.syntax) + - ctx.replaceToken(open, "(") + - ctx.replaceToken(close, ")") - }.asPatch + + // .to[CC] + val apToRemove = ap.tokens.slice(e.tokens.end - ap.tokens.start, ap.tokens.size) + + ctx.removeTokens(apToRemove) + + ctx.addLeft(e, implicitCbf.syntax + ".fromSpecific(") + + ctx.addRight(e, ")") } else Patch.empty }.asPatch // implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] => - // implicit cbf: collection.Factory[Int, CC[Int]] + // implicit cbf: Factory[Int, CC[Int]] val parameterType = ctx.replaceTree( tpe, - Type.Apply(Type.Name("collection.Factory"), List(t, cct)).syntax + Type.Apply(Type.Name("Factory"), List(t, cct)).syntax ) - (parameterType + cbfCalls + toCalls, handledTo.result()) + parameterType + cbfCalls + toCalls } } diff --git a/scalafix-rules/src/main/scala/fix/NewCollections.scala b/scalafix-rules/src/main/scala/fix/NewCollections.scala index 05e50eb2..8c52a022 100644 --- a/scalafix-rules/src/main/scala/fix/NewCollections.scala +++ b/scalafix-rules/src/main/scala/fix/NewCollections.scala @@ -7,21 +7,15 @@ import scala.meta._ // Not 2.12 Cross-Compatible case class NewCollections(index: SemanticdbIndex) extends SemanticRule(index, "NewCollections") with Stable212Base { - // Two rules triggers the same rewrite TraversableLike.to and CanBuildFrom - // we keep track of what is handled in CanBuildFrom and guard against TraversableLike.to - val handledTo = scala.collection.mutable.Set[Tree]() - // == Symbols == - val collectionCanBuildFrom = exact("_root_.scala.collection.generic.CanBuildFrom#") - val collectionCanBuildFromImport = exact("_root_.scala.collection.generic.CanBuildFrom.;_root_.scala.collection.generic.CanBuildFrom#") - val nothing = exact("_root_.scala.Nothing#") - val iterableSameElement = exact("_root_.scala.collection.IterableLike#sameElements(Lscala/collection/GenIterable;)Z.") - val toTpe = normalized("_root_.scala.collection.TraversableLike.to.") - val iterator = normalized("_root_.scala.collection.TraversableLike.toIterator.") - val tupleZipped = normalized("_root_.scala.runtime.Tuple2Zipped.Ops.zipped.", - "_root_.scala.runtime.Tuple3Zipped.Ops.zipped.") - val retainMap = normalized("_root_.scala.collection.mutable.MapLike.retain.") - val retainSet = normalized("_root_.scala.collection.mutable.SetLike.retain.") + val iterableSameElement = exact("_root_.scala.collection.IterableLike#sameElements(Lscala/collection/GenIterable;)Z.") + val iterator = normalized("_root_.scala.collection.TraversableLike.toIterator.") + val tupleZipped = normalized( + "_root_.scala.runtime.Tuple2Zipped.Ops.zipped.", + "_root_.scala.runtime.Tuple3Zipped.Ops.zipped." + ) + val retainMap = normalized("_root_.scala.collection.mutable.MapLike.retain.") + val retainSet = normalized("_root_.scala.collection.mutable.SetLike.retain.") object Breakout { implicit class RichSymbol(val symbol: Symbol) { @@ -112,7 +106,7 @@ case class NewCollections(index: SemanticdbIndex) extends SemanticRule(index, "N case iterator(t: Name) => ctx.replaceTree(t, "iterator") - case t @ toTpe(n: Name) if !handledTo.contains(n) => + case t @ toTpe(n: Name) => trailingBrackets(n, ctx).map { case (open, close) => ctx.replaceToken(open, "(") + ctx.replaceToken(close, ")") }.asPatch @@ -167,27 +161,6 @@ case class NewCollections(index: SemanticdbIndex) extends SemanticRule(index, "N }.asPatch } - def replaceCanBuildFrom(ctx: RuleCtx): Patch = { - val useSites = - ctx.tree.collect { - case Defn.Def(_, _, _, paramss, _, body) => - val (ps1, ht) = CanBuildFromNothing(paramss, body, ctx, collectionCanBuildFrom, nothing, toTpe) - val ps2 = CanBuildFrom (paramss, body, ctx, collectionCanBuildFrom, nothing) - handledTo ++= ht - - ps1 + ps2 - }.asPatch - - val imports = - ctx.tree.collect { - case i: Importee if collectionCanBuildFromImport.matches(i) => - ctx.removeImportee(i) - }.asPatch - - if (useSites.nonEmpty) useSites + imports - else Patch.empty - } - def replaceBreakout(ctx: RuleCtx): Patch = { import Breakout._ @@ -244,7 +217,6 @@ case class NewCollections(index: SemanticdbIndex) extends SemanticRule(index, "N override def fix(ctx: RuleCtx): Patch = { super.fix(ctx) + - replaceCanBuildFrom(ctx) + replaceToList(ctx) + replaceSymbols(ctx) + replaceTupleZipped(ctx) + diff --git a/scalafix-rules/src/main/scala/fix/Stable212Base.scala b/scalafix-rules/src/main/scala/fix/Stable212Base.scala index c378180c..663fc3a9 100644 --- a/scalafix-rules/src/main/scala/fix/Stable212Base.scala +++ b/scalafix-rules/src/main/scala/fix/Stable212Base.scala @@ -17,15 +17,19 @@ trait Stable212Base { self: SemanticRule => normalized(s"_root_.scala.collection.TraversableOnce.`$op`.") } - val copyToBuffer = normalized("_root_.scala.collection.TraversableOnce.copyToBuffer.") + val toTpe = normalized("_root_.scala.collection.TraversableLike.to.") + val copyToBuffer = normalized("_root_.scala.collection.TraversableOnce.copyToBuffer.") val arrayBuilderMake = normalized("_root_.scala.collection.mutable.ArrayBuilder.make(Lscala/reflect/ClassTag;)Lscala/collection/mutable/ArrayBuilder;.") - val setPlus2 = exact("_root_.scala.collection.SetLike#`+`(Ljava/lang/Object;Ljava/lang/Object;Lscala/collection/Seq;)Lscala/collection/Set;.") - val mapPlus2 = exact("_root_.scala.collection.immutable.MapLike#`+`(Lscala/Tuple2;Lscala/Tuple2;Lscala/collection/Seq;)Lscala/collection/immutable/Map;.") - val mutSetPlus = exact("_root_.scala.collection.mutable.SetLike#`+`(Ljava/lang/Object;)Lscala/collection/mutable/Set;.") - val mutMapPlus = exact("_root_.scala.collection.mutable.MapLike#`+`(Lscala/Tuple2;)Lscala/collection/mutable/Map;.") - val mutMapUpdate = exact("_root_.scala.collection.mutable.MapLike#updated(Ljava/lang/Object;Ljava/lang/Object;)Lscala/collection/mutable/Map;.") - val foldLeftSymbol = foldSymbol(isLeft = true) - val foldRightSymbol = foldSymbol(isLeft = false) + val collectionCanBuildFrom = exact("_root_.scala.collection.generic.CanBuildFrom#") + val collectionCanBuildFromImport = exact("_root_.scala.collection.generic.CanBuildFrom.;_root_.scala.collection.generic.CanBuildFrom#") + val nothing = exact("_root_.scala.Nothing#") + val setPlus2 = exact("_root_.scala.collection.SetLike#`+`(Ljava/lang/Object;Ljava/lang/Object;Lscala/collection/Seq;)Lscala/collection/Set;.") + val mapPlus2 = exact("_root_.scala.collection.immutable.MapLike#`+`(Lscala/Tuple2;Lscala/Tuple2;Lscala/collection/Seq;)Lscala/collection/immutable/Map;.") + val mutSetPlus = exact("_root_.scala.collection.mutable.SetLike#`+`(Ljava/lang/Object;)Lscala/collection/mutable/Set;.") + val mutMapPlus = exact("_root_.scala.collection.mutable.MapLike#`+`(Lscala/Tuple2;)Lscala/collection/mutable/Map;.") + val mutMapUpdate = exact("_root_.scala.collection.mutable.MapLike#updated(Ljava/lang/Object;Ljava/lang/Object;)Lscala/collection/mutable/Map;.") + val foldLeftSymbol = foldSymbol(isLeft = true) + val foldRightSymbol = foldSymbol(isLeft = false) // == Rules == @@ -116,8 +120,30 @@ trait Stable212Base { self: SemanticRule => }.asPatch } + def replaceCanBuildFrom(ctx: RuleCtx): Patch = { + val useSites = + ctx.tree.collect { + case Defn.Def(_, _, _, paramss, _, body) => + CanBuildFromNothing(paramss, body, ctx, collectionCanBuildFrom, nothing, toTpe) + + CanBuildFrom(paramss, body, ctx, collectionCanBuildFrom, nothing) + }.asPatch + + val imports = + ctx.tree.collect { + case i: Importee if collectionCanBuildFromImport.matches(i) => + ctx.removeImportee(i) + }.asPatch + + val compatImport = + ctx.addGlobalImport(importer"scala.collection.compat._") + + if (useSites.nonEmpty) useSites + imports + compatImport + else Patch.empty + } + override def fix(ctx: RuleCtx): Patch = { replaceSymbols0(ctx) + + replaceCanBuildFrom(ctx) + replaceCopyToBuffer(ctx) + replaceSymbolicFold(ctx) + replaceSetMapPlus2(ctx) + From 0f5ceb32f35bbc33d600f54b2b149d9e32708e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Fri, 29 Jun 2018 09:50:46 +0200 Subject: [PATCH 7/9] Setup publishing for scalafix migrations --- build.sbt | 124 ++++++++++-------- .../src/main/scala/fix/CanBuildFrom.scala | 1 - .../src/main/scala/fix/Experimental.scala | 1 - .../src/main/scala/fix/NewCollections.scala | 1 - .../src/main/scala/fix/Stable212Base.scala | 1 - .../src/main/scala/fix/TypeMatcher.scala | 1 - .../main/scala/fix/UnstableMapValues.scala | 1 - .../fix/UnstableStreamToLazyListSrc.scala | 1 - 8 files changed, 72 insertions(+), 59 deletions(-) diff --git a/build.sbt b/build.sbt index e679c1d2..eab218b5 100644 --- a/build.sbt +++ b/build.sbt @@ -2,21 +2,9 @@ import ScalaModulePlugin._ import sbtcrossproject.{crossProject, CrossType} import _root_.scalafix.Versions.{version => scalafixVersion, scala212 => scalafixScala212} -lazy val scala212 = "2.12.6" -lazy val scala213 = "2.13.0-M4" - -lazy val scala213Settings = Seq( - resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/", - scalaVersion := scala213 -) - -inThisBuild(Seq( - crossScalaVersions := Seq(scala212, scala213, "2.11.12") -)) - - lazy val root = project .in(file(".")) + .settings(dontPublish) .aggregate( compatJVM, compatJS, scalafixRules, scalafixInput, scalafixTests, @@ -24,8 +12,57 @@ lazy val root = project ) .disablePlugins(ScalafixPlugin) +// == Core Libraries == + +lazy val compat = crossProject(JSPlatform, JVMPlatform) + .withoutSuffixFor(JVMPlatform) + .crossType(CrossType.Pure) + .in(file("compat")) + .settings(scalaModuleSettings) + .jvmSettings(scalaModuleSettingsJVM) + .settings( + name := "scala-collection-compat", + version := "0.1-SNAPSHOT", + scalacOptions ++= Seq("-feature", "-language:higherKinds", "-language:implicitConversions"), + unmanagedSourceDirectories in Compile += { + val sharedSourceDir = baseDirectory.value.getParentFile / "src/main" + if (scalaVersion.value.startsWith("2.13.")) sharedSourceDir / "scala-2.13" + else sharedSourceDir / "scala-2.11_2.12" + } + ) + .jvmSettings( + OsgiKeys.exportPackage := Seq(s"scala.collection.compat.*;version=${version.value}"), + libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test" + ) + .jsSettings( + scalacOptions += { + val x = (baseDirectory in LocalRootProject).value.toURI.toString + val y = "https://raw.githubusercontent.com/scala/scala-collection-compat/" + sys.process.Process("git rev-parse HEAD").lines_!.head + s"-P:scalajs:mapSourceURI:$x->$y/" + }, + fork in Test := false // Scala.js cannot run forked tests + ) + .jsConfigure(_.enablePlugins(ScalaJSJUnitPlugin)) + .disablePlugins(ScalafixPlugin) + +lazy val compatJVM = compat.jvm +lazy val compatJS = compat.js + +lazy val scalafixRules = project + .in(file("scalafix-rules")) + .settings(scalaModuleSettings) + .settings( + name := "scala-collection-migrations", + scalaVersion := scalafixScala212, + libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % scalafixVersion + ) + + +// == Scalafix Test Setup == + lazy val scalafixInput = project .in(file("scalafix-input")) + .settings(dontPublish) .settings( scalaVersion := scalafixScala212, scalafixSourceroot := sourceDirectory.in(Compile).value @@ -34,25 +71,22 @@ lazy val scalafixInput = project lazy val scalafixOutput212 = project .in(file("scalafix-output212")) .settings(scalaVersion := scalafixScala212) + .settings(dontPublish) .dependsOn(compatJVM) lazy val scalafixOutput213 = project .in(file("scalafix-output213")) .settings(scala213Settings) + .settings(dontPublish) lazy val scalafixOutput213Failure = project .in(file("scalafix-output213-failure")) .settings(scala213Settings) - -lazy val scalafixRules = project - .in(file("scalafix-rules")) - .settings( - scalaVersion := scalafixScala212, - libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % scalafixVersion - ) + .settings(dontPublish) lazy val scalafixTests = project .in(file("scalafix-tests")) + .settings(dontPublish) .settings( scalaVersion := scalafixScala212, libraryDependencies += "ch.epfl.scala" % "scalafix-testkit" % scalafixVersion % Test cross CrossVersion.full, @@ -77,36 +111,22 @@ lazy val scalafixTests = project .dependsOn(scalafixInput, scalafixRules) .enablePlugins(BuildInfoPlugin) -lazy val compat = crossProject(JSPlatform, JVMPlatform) - .withoutSuffixFor(JVMPlatform) - .crossType(CrossType.Pure) - .in(file("compat")) - .settings(scalaModuleSettings) - .jvmSettings(scalaModuleSettingsJVM) - .settings( - name := "scala-collection-compat", - version := "0.1-SNAPSHOT", - scalacOptions ++= Seq("-feature", "-language:higherKinds", "-language:implicitConversions"), - unmanagedSourceDirectories in Compile += { - val sharedSourceDir = baseDirectory.value.getParentFile / "src/main" - if (scalaVersion.value.startsWith("2.13.")) sharedSourceDir / "scala-2.13" - else sharedSourceDir / "scala-2.11_2.12" - } - ) - .jvmSettings( - OsgiKeys.exportPackage := Seq(s"scala.collection.compat.*;version=${version.value}"), - libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test" - ) - .jsSettings( - scalacOptions += { - val x = (baseDirectory in LocalRootProject).value.toURI.toString - val y = "https://raw.githubusercontent.com/scala/scala-collection-compat/" + sys.process.Process("git rev-parse HEAD").lines_!.head - s"-P:scalajs:mapSourceURI:$x->$y/" - }, - fork in Test := false // Scala.js cannot run forked tests - ) - .jsConfigure(_.enablePlugins(ScalaJSJUnitPlugin)) - .disablePlugins(ScalafixPlugin) +lazy val dontPublish = Seq( + publishArtifact := false, + packagedArtifacts := Map.empty, + publish := {}, + publishLocal := {} +) -lazy val compatJVM = compat.jvm -lazy val compatJS = compat.js +lazy val scala212 = "2.12.6" +lazy val scala213 = "2.13.0-M4" + +lazy val scala213Settings = Seq( + resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/", + scalaVersion := scala213 +) + +// required by sbt-scala-module +inThisBuild(Seq( + crossScalaVersions := Seq(scala212, scala213, "2.11.12") +)) diff --git a/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala b/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala index 925f63d8..86a09837 100644 --- a/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala +++ b/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala @@ -1,7 +1,6 @@ package fix import scalafix._ -import scalafix.syntax._ import scalafix.util._ import scala.meta._ diff --git a/scalafix-rules/src/main/scala/fix/Experimental.scala b/scalafix-rules/src/main/scala/fix/Experimental.scala index b7e29d04..920618f5 100644 --- a/scalafix-rules/src/main/scala/fix/Experimental.scala +++ b/scalafix-rules/src/main/scala/fix/Experimental.scala @@ -1,7 +1,6 @@ package fix import scalafix._ -import scalafix.syntax._ import scalafix.util._ import scala.meta._ diff --git a/scalafix-rules/src/main/scala/fix/NewCollections.scala b/scalafix-rules/src/main/scala/fix/NewCollections.scala index 8c52a022..9cf99a0d 100644 --- a/scalafix-rules/src/main/scala/fix/NewCollections.scala +++ b/scalafix-rules/src/main/scala/fix/NewCollections.scala @@ -1,7 +1,6 @@ package fix import scalafix._ -import scalafix.syntax._ import scalafix.util._ import scala.meta._ diff --git a/scalafix-rules/src/main/scala/fix/Stable212Base.scala b/scalafix-rules/src/main/scala/fix/Stable212Base.scala index 663fc3a9..530fc83a 100644 --- a/scalafix-rules/src/main/scala/fix/Stable212Base.scala +++ b/scalafix-rules/src/main/scala/fix/Stable212Base.scala @@ -1,7 +1,6 @@ package fix import scalafix._ -import scalafix.syntax._ import scalafix.util._ import scala.meta._ diff --git a/scalafix-rules/src/main/scala/fix/TypeMatcher.scala b/scalafix-rules/src/main/scala/fix/TypeMatcher.scala index aef83673..7c42bf9d 100644 --- a/scalafix-rules/src/main/scala/fix/TypeMatcher.scala +++ b/scalafix-rules/src/main/scala/fix/TypeMatcher.scala @@ -1,7 +1,6 @@ package fix import scalafix._ -import scalafix.syntax._ import scalafix.util._ import scala.meta._ diff --git a/scalafix-rules/src/main/scala/fix/UnstableMapValues.scala b/scalafix-rules/src/main/scala/fix/UnstableMapValues.scala index e530abc9..57a5ce6a 100644 --- a/scalafix-rules/src/main/scala/fix/UnstableMapValues.scala +++ b/scalafix-rules/src/main/scala/fix/UnstableMapValues.scala @@ -1,7 +1,6 @@ package fix import scalafix._ -import scalafix.syntax._ import scalafix.util._ import scala.meta._ diff --git a/scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala index cd5e2e59..f6344ea9 100644 --- a/scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala +++ b/scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala @@ -1,7 +1,6 @@ package fix import scalafix._ -import scalafix.syntax._ import scalafix.util._ import scala.meta._ From f12b134968726e87aa7d8fe0b36b1f60f06e5447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Fri, 29 Jun 2018 10:08:02 +0200 Subject: [PATCH 8/9] Setup publishing to maven central for scalafix rules (fix #73) --- .travis.yml | 21 ++++++++++++++------- admin/build.sh | 15 ++++++++++++--- build.sbt | 2 +- project/plugins.sbt | 3 +++ project/project/plugins.sbt | 1 + 5 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 project/project/plugins.sbt diff --git a/.travis.yml b/.travis.yml index 03d765ee..80eaa60a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,17 +54,24 @@ matrix: # | oraclejdk8 | 2.13.0-M4 | jvm | | | # | oraclejdk8 | 2.13.0-M4 | js | 0.6.23 | | # | oraclejdk8 | 2.12.6 | jvm | | true | - + before_script: ./checkCLA.sh script: - java -version - admin/build.sh -before_cache: - - find $HOME/.sbt -name "*.lock" | xargs rm - - find $HOME/.ivy2/cache -name "ivydata-*.properties" | xargs rm cache: directories: - - $HOME/.ivy2/cache - - $HOME/.sbt/boot - - $HOME/.sbt/launchers + - "$HOME/.sbt/0.13/dependency" + - "$HOME/.sbt/boot/scala*" + - "$HOME/.sbt/launchers" + - "$HOME/.ivy2/cache" + - "$HOME/.coursier" + +before_cache: +- du -h -d 1 $HOME/.ivy2/cache +- du -h -d 2 $HOME/.sbt/ +- find $HOME/.sbt -name "*.lock" -type f -delete +- find $HOME/.ivy2/cache -name "ivydata-*.properties" -type f -delete +- find $HOME/.ivy2/cache -name "*scalafix*.xml" -type f -delete +- rm -rf $HOME/.ivy2/local diff --git a/admin/build.sh b/admin/build.sh index 22c21fb3..0ffdd595 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -20,11 +20,14 @@ RELEASE_COMBO=true if [[ "$TEST_SCALAFIX" == "true" ]]; then sbt scalafixTests/test - exit 0 fi if [ "$SCALAJS_VERSION" = "" ]; then - projectPrefix="compat" + if [[ "$TEST_SCALAFIX" == "true" ]]; then + projectPrefix="scalafixRules" + else + projectPrefix="compat" + fi else projectPrefix="compatJS" fi @@ -52,4 +55,10 @@ if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then fi fi -sbt -Dhttps.protocols=TLSv1.2 "++$TRAVIS_SCALA_VERSION" "$publishVersion" "$projectPrefix/clean" "$projectPrefix/test" "$projectPrefix/publishLocal" "$publishTask" +sbt -Dhttps.protocols=TLSv1.2 \ + "++$TRAVIS_SCALA_VERSION" \ + "$publishVersion" \ + "$projectPrefix/clean" \ + "$projectPrefix/test" \ + "$projectPrefix/publishLocal" \ + "$publishTask" diff --git a/build.sbt b/build.sbt index eab218b5..256a7e07 100644 --- a/build.sbt +++ b/build.sbt @@ -51,13 +51,13 @@ lazy val compatJS = compat.js lazy val scalafixRules = project .in(file("scalafix-rules")) .settings(scalaModuleSettings) + .settings(scalaModuleSettingsJVM) .settings( name := "scala-collection-migrations", scalaVersion := scalafixScala212, libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % scalafixVersion ) - // == Scalafix Test Setup == lazy val scalafixInput = project diff --git a/project/plugins.sbt b/project/plugins.sbt index 2979ce34..2fe235cc 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,5 @@ +import coursier.util.Properties.{version => coursierVersion} + if (System.getProperty("java.version").startsWith("1.")) Seq() else @@ -12,3 +14,4 @@ addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.4.0") addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.14") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.10") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % coursierVersion) diff --git a/project/project/plugins.sbt b/project/project/plugins.sbt new file mode 100644 index 00000000..cc0b7247 --- /dev/null +++ b/project/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.1.0-M4") From 282e4801454dbb5ec5bec8df4d6b870e6f3817e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Fri, 29 Jun 2018 11:15:17 +0200 Subject: [PATCH 9/9] keep scalafix/ folder, Unstable => Roughtly --- CONTRIBUTING.md | 4 +-- admin/build.sh | 25 ++++++++++--------- admin/encryptEnvVars.sh | 3 ++- admin/genKeyPair.sh | 3 ++- build.sbt | 18 +++++++------ project/plugins.sbt | 5 +--- project/project/plugins.sbt | 1 - .../main/scala/fix/UnstableMapValuesSrc.scala | 8 ------ .../main/scala/fix/UnstableMapValuesSrc.scala | 8 ------ .../src/main/scala/fix/BreakoutSrc.scala | 25 ------------------- .../main/scala/fix/CanBuildFromNegSrc.scala | 0 .../src/main/scala/fix/CanBuildFromSrc.scala | 0 .../src/main/scala/fix/CopyToBufferSrc.scala | 0 .../src/main/scala/fix/ExperimentalSrc.scala | 0 .../input}/src/main/scala/fix/FoldSrc.scala | 0 .../src/main/scala/fix/IterableSrc.scala | 0 .../src/main/scala/fix/LinearSeqSrc.scala | 0 .../src/main/scala/fix/MutSetMapSrc.scala | 0 .../input}/src/main/scala/fix/RetainSrc.scala | 0 .../main/scala/fix/RoughlyMapValuesSrc.scala | 8 ++++++ .../fix/RoughlyStreamToLazyListSrc.scala | 4 +-- .../input}/src/main/scala/fix/SetMapSrc.scala | 0 .../input}/src/main/scala/fix/TestsSrc.scala | 0 .../src/main/scala/fix/TraversableSrc.scala | 0 .../src/main/scala/fix/TupleNZippedSrc.scala | 0 .../src/main/scala/fix/CanBuildFromSrc.scala | 0 .../src/main/scala/fix/CopyToBufferSrc.scala | 0 .../src/main/scala/fix/ExperimentalSrc.scala | 0 .../src/main/scala/fix/FoldSrc.scala | 0 .../src/main/scala/fix/LinearSeqSrc.scala | 0 .../src/main/scala/fix/MutSetMapSrc.scala | 0 .../main/scala/fix/RoughlyMapValuesSrc.scala | 8 ++++++ .../src/main/scala/fix/SetMapSrc.scala | 0 .../src/main/scala/fix/TestsSrc.scala | 0 .../main/scala/fix/CanBuildFromNegSrc.scala | 0 .../src/main/scala/fix/BreakoutSrc.scala | 24 ------------------ .../src/main/scala/fix/IterableSrc.scala | 0 .../src/main/scala/fix/RetainSrc.scala | 0 .../fix/RoughlyStreamToLazyListSrc.scala | 2 +- .../src/main/scala/fix/TraversableSrc.scala | 0 .../src/main/scala/fix/TupleNZippedSrc.scala | 0 .../src/main/scala/fix/CanBuildFrom.scala | 0 .../src/main/scala/fix/CrossCompat.scala | 0 .../src/main/scala/fix/Experimental.scala | 0 .../src/main/scala/fix/NewCollections.scala | 0 .../src/main/scala/fix/RoughlyMapValues.scala | 2 +- .../fix/RoughlyStreamToLazyListSrc.scala | 2 +- .../src/main/scala/fix/Stable212Base.scala | 0 .../src/main/scala/fix/TypeMatcher.scala | 0 .../rules}/src/main/scala/fix/package.scala | 1 - .../src/test/scala/fix/ScalafixTests.scala | 0 51 files changed, 52 insertions(+), 99 deletions(-) delete mode 100644 project/project/plugins.sbt delete mode 100644 scalafix-input/src/main/scala/fix/UnstableMapValuesSrc.scala delete mode 100644 scalafix-output212/src/main/scala/fix/UnstableMapValuesSrc.scala delete mode 100644 scalafix/input/src/main/scala/fix/BreakoutSrc.scala rename {scalafix-input => scalafix/input}/src/main/scala/fix/CanBuildFromNegSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/CanBuildFromSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/CopyToBufferSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/ExperimentalSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/FoldSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/IterableSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/LinearSeqSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/MutSetMapSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/RetainSrc.scala (100%) create mode 100644 scalafix/input/src/main/scala/fix/RoughlyMapValuesSrc.scala rename scalafix-input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala => scalafix/input/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala (72%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/SetMapSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/TestsSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/TraversableSrc.scala (100%) rename {scalafix-input => scalafix/input}/src/main/scala/fix/TupleNZippedSrc.scala (100%) rename {scalafix-output212 => scalafix/output212}/src/main/scala/fix/CanBuildFromSrc.scala (100%) rename {scalafix-output212 => scalafix/output212}/src/main/scala/fix/CopyToBufferSrc.scala (100%) rename {scalafix-output212 => scalafix/output212}/src/main/scala/fix/ExperimentalSrc.scala (100%) rename {scalafix-output212 => scalafix/output212}/src/main/scala/fix/FoldSrc.scala (100%) rename {scalafix-output212 => scalafix/output212}/src/main/scala/fix/LinearSeqSrc.scala (100%) rename {scalafix-output212 => scalafix/output212}/src/main/scala/fix/MutSetMapSrc.scala (100%) create mode 100644 scalafix/output212/src/main/scala/fix/RoughlyMapValuesSrc.scala rename {scalafix-output212 => scalafix/output212}/src/main/scala/fix/SetMapSrc.scala (100%) rename {scalafix-output212 => scalafix/output212}/src/main/scala/fix/TestsSrc.scala (100%) rename {scalafix-output213-failure => scalafix/output213-failure}/src/main/scala/fix/CanBuildFromNegSrc.scala (100%) delete mode 100644 scalafix/output213/src/main/scala/fix/BreakoutSrc.scala rename {scalafix-output213 => scalafix/output213}/src/main/scala/fix/IterableSrc.scala (100%) rename {scalafix-output213 => scalafix/output213}/src/main/scala/fix/RetainSrc.scala (100%) rename scalafix-output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala => scalafix/output213/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala (85%) rename {scalafix-output213 => scalafix/output213}/src/main/scala/fix/TraversableSrc.scala (100%) rename {scalafix-output213 => scalafix/output213}/src/main/scala/fix/TupleNZippedSrc.scala (100%) rename {scalafix-rules => scalafix/rules}/src/main/scala/fix/CanBuildFrom.scala (100%) rename {scalafix-rules => scalafix/rules}/src/main/scala/fix/CrossCompat.scala (100%) rename {scalafix-rules => scalafix/rules}/src/main/scala/fix/Experimental.scala (100%) rename {scalafix-rules => scalafix/rules}/src/main/scala/fix/NewCollections.scala (100%) rename scalafix-rules/src/main/scala/fix/UnstableMapValues.scala => scalafix/rules/src/main/scala/fix/RoughlyMapValues.scala (83%) rename scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala => scalafix/rules/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala (87%) rename {scalafix-rules => scalafix/rules}/src/main/scala/fix/Stable212Base.scala (100%) rename {scalafix-rules => scalafix/rules}/src/main/scala/fix/TypeMatcher.scala (100%) rename {scalafix-rules => scalafix/rules}/src/main/scala/fix/package.scala (97%) rename {scalafix-tests => scalafix/tests}/src/test/scala/fix/ScalafixTests.scala (100%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ba8057aa..abb2a72f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,7 @@ Even better, instead of providing a diff, you can directly add it as a test case 1. Fork this repository and create a separate branch; -2. Add a file in the `scalafix-input/src/main/scala/fix/` directory with code +2. Add a file in the `scalafix/input/src/main/scala/fix/` directory with code that uses the standard collections: ~~~ scala @@ -38,7 +38,7 @@ class toIteratorVsIterator(xs: Iterable[Int]) { } ~~~ -3. Add a corresponding file in the `scalafix-output213/src/main/scala/fix/` directory +3. Add a corresponding file in the `scalafix/output213/src/main/scala/fix/` directory with the same code but using the strawman: ~~~ scala diff --git a/admin/build.sh b/admin/build.sh index 0ffdd595..52a555dd 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e @@ -18,10 +18,6 @@ set -e RELEASE_COMBO=true -if [[ "$TEST_SCALAFIX" == "true" ]]; then - sbt scalafixTests/test -fi - if [ "$SCALAJS_VERSION" = "" ]; then if [[ "$TEST_SCALAFIX" == "true" ]]; then projectPrefix="scalafixRules" @@ -32,9 +28,20 @@ else projectPrefix="compatJS" fi +if [[ "$TEST_SCALAFIX" == "true" ]]; then + crossScalaVersion="noop" + testProjectPrefix="scalafixTests" +else + crossScalaVersion="++$TRAVIS_SCALA_VERSION" + testProjectPrefix="$projectPrefix" +fi + verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" tagPat="^v$verPat(#.*)?$" +publishVersion="noop" +publishTask="noop" + if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then tagVer=$(echo $TRAVIS_TAG | sed s/#.*// | sed s/^v//) publishVersion='set every version := "'$tagVer'"' @@ -55,10 +62,4 @@ if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then fi fi -sbt -Dhttps.protocols=TLSv1.2 \ - "++$TRAVIS_SCALA_VERSION" \ - "$publishVersion" \ - "$projectPrefix/clean" \ - "$projectPrefix/test" \ - "$projectPrefix/publishLocal" \ - "$publishTask" +sbt -Dhttps.protocols=TLSv1.2 -sbt-dir=/home/travis/.sbt ";$crossScalaVersion ;$publishVersion ;$projectPrefix/clean ;$testProjectPrefix/test ;$projectPrefix/publishLocal ;$publishTask" diff --git a/admin/encryptEnvVars.sh b/admin/encryptEnvVars.sh index b6256679..1dac942c 100755 --- a/admin/encryptEnvVars.sh +++ b/admin/encryptEnvVars.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash + # # Encrypt sonatype credentials so that they can be # decrypted in trusted builds on Travis CI. diff --git a/admin/genKeyPair.sh b/admin/genKeyPair.sh index 17db3f39..2b731a33 100755 --- a/admin/genKeyPair.sh +++ b/admin/genKeyPair.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash + # # Generates a key pair for this repository to sign artifacts. # Encrypt the private key and its passphrase in trusted builds diff --git a/build.sbt b/build.sbt index 256a7e07..cc7362c6 100644 --- a/build.sbt +++ b/build.sbt @@ -49,7 +49,7 @@ lazy val compatJVM = compat.jvm lazy val compatJS = compat.js lazy val scalafixRules = project - .in(file("scalafix-rules")) + .in(file("scalafix/rules")) .settings(scalaModuleSettings) .settings(scalaModuleSettingsJVM) .settings( @@ -61,7 +61,7 @@ lazy val scalafixRules = project // == Scalafix Test Setup == lazy val scalafixInput = project - .in(file("scalafix-input")) + .in(file("scalafix/input")) .settings(dontPublish) .settings( scalaVersion := scalafixScala212, @@ -69,23 +69,23 @@ lazy val scalafixInput = project ) lazy val scalafixOutput212 = project - .in(file("scalafix-output212")) + .in(file("scalafix/output212")) .settings(scalaVersion := scalafixScala212) .settings(dontPublish) .dependsOn(compatJVM) lazy val scalafixOutput213 = project - .in(file("scalafix-output213")) + .in(file("scalafix/output213")) .settings(scala213Settings) .settings(dontPublish) lazy val scalafixOutput213Failure = project - .in(file("scalafix-output213-failure")) + .in(file("scalafix/output213-failure")) .settings(scala213Settings) .settings(dontPublish) lazy val scalafixTests = project - .in(file("scalafix-tests")) + .in(file("scalafix/tests")) .settings(dontPublish) .settings( scalaVersion := scalafixScala212, @@ -128,5 +128,9 @@ lazy val scala213Settings = Seq( // required by sbt-scala-module inThisBuild(Seq( - crossScalaVersions := Seq(scala212, scala213, "2.11.12") + crossScalaVersions := Seq(scala212, scala213, "2.11.12"), + commands += Command.command("noop") { state => + println("noop") + state + } )) diff --git a/project/plugins.sbt b/project/plugins.sbt index 2fe235cc..dc26cc39 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,3 @@ -import coursier.util.Properties.{version => coursierVersion} - if (System.getProperty("java.version").startsWith("1.")) Seq() else @@ -10,8 +8,7 @@ else val scalaJSVersion = Option(System.getenv("SCALAJS_VERSION")).filter(_.nonEmpty).getOrElse("0.6.23") addSbtPlugin("org.scala-js" % "sbt-scalajs" % scalaJSVersion) -addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.4.0") +addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.5.0") addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.14") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.10") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % coursierVersion) diff --git a/project/project/plugins.sbt b/project/project/plugins.sbt deleted file mode 100644 index cc0b7247..00000000 --- a/project/project/plugins.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.1.0-M4") diff --git a/scalafix-input/src/main/scala/fix/UnstableMapValuesSrc.scala b/scalafix-input/src/main/scala/fix/UnstableMapValuesSrc.scala deleted file mode 100644 index 6d39e8b6..00000000 --- a/scalafix-input/src/main/scala/fix/UnstableMapValuesSrc.scala +++ /dev/null @@ -1,8 +0,0 @@ -/* -rule = "scala:fix.UnstableMapValues" - */ -package fix - -class UnstableMapValuesSrc(map: Map[Int, Int]) { - map.mapValues(_ + 1) -} diff --git a/scalafix-output212/src/main/scala/fix/UnstableMapValuesSrc.scala b/scalafix-output212/src/main/scala/fix/UnstableMapValuesSrc.scala deleted file mode 100644 index 8952272a..00000000 --- a/scalafix-output212/src/main/scala/fix/UnstableMapValuesSrc.scala +++ /dev/null @@ -1,8 +0,0 @@ - - - -package fix - -class UnstableMapValuesSrc(map: Map[Int, Int]) { - map.mapValues(_ + 1).toMap -} diff --git a/scalafix/input/src/main/scala/fix/BreakoutSrc.scala b/scalafix/input/src/main/scala/fix/BreakoutSrc.scala deleted file mode 100644 index 50382e33..00000000 --- a/scalafix/input/src/main/scala/fix/BreakoutSrc.scala +++ /dev/null @@ -1,25 +0,0 @@ -/* -rule = "scala:fix.NewCollections" - */ -package fix - -import scala.collection.breakOut - -object BreakoutSrc { - val xs = List(1, 2, 3) - - xs.collect{ case x => x }(breakOut): Set[Int] - xs.flatMap(x => List(x))(breakOut): collection.SortedSet[Int] - xs.map(_ + 1)(breakOut): Set[Int] - xs.reverseMap(_ + 1)(breakOut): Set[Int] - xs.scanLeft(0)((a, b) => a + b)(breakOut): Set[Int] - xs.union(xs)(breakOut): Set[Int] - xs.updated(0, 1)(breakOut): Set[Int] - xs.zip(xs)(breakOut): Map[Int, Int] - xs.zipAll(xs, 0, 0)(breakOut): Array[(Int, Int)] - - (xs ++ xs)(breakOut): Set[Int] - (1 +: xs)(breakOut): Set[Int] - (xs :+ 1)(breakOut): Set[Int] - (xs ++: xs)(breakOut): Set[Int] -} diff --git a/scalafix-input/src/main/scala/fix/CanBuildFromNegSrc.scala b/scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/CanBuildFromNegSrc.scala rename to scalafix/input/src/main/scala/fix/CanBuildFromNegSrc.scala diff --git a/scalafix-input/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/CanBuildFromSrc.scala rename to scalafix/input/src/main/scala/fix/CanBuildFromSrc.scala diff --git a/scalafix-input/src/main/scala/fix/CopyToBufferSrc.scala b/scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/CopyToBufferSrc.scala rename to scalafix/input/src/main/scala/fix/CopyToBufferSrc.scala diff --git a/scalafix-input/src/main/scala/fix/ExperimentalSrc.scala b/scalafix/input/src/main/scala/fix/ExperimentalSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/ExperimentalSrc.scala rename to scalafix/input/src/main/scala/fix/ExperimentalSrc.scala diff --git a/scalafix-input/src/main/scala/fix/FoldSrc.scala b/scalafix/input/src/main/scala/fix/FoldSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/FoldSrc.scala rename to scalafix/input/src/main/scala/fix/FoldSrc.scala diff --git a/scalafix-input/src/main/scala/fix/IterableSrc.scala b/scalafix/input/src/main/scala/fix/IterableSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/IterableSrc.scala rename to scalafix/input/src/main/scala/fix/IterableSrc.scala diff --git a/scalafix-input/src/main/scala/fix/LinearSeqSrc.scala b/scalafix/input/src/main/scala/fix/LinearSeqSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/LinearSeqSrc.scala rename to scalafix/input/src/main/scala/fix/LinearSeqSrc.scala diff --git a/scalafix-input/src/main/scala/fix/MutSetMapSrc.scala b/scalafix/input/src/main/scala/fix/MutSetMapSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/MutSetMapSrc.scala rename to scalafix/input/src/main/scala/fix/MutSetMapSrc.scala diff --git a/scalafix-input/src/main/scala/fix/RetainSrc.scala b/scalafix/input/src/main/scala/fix/RetainSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/RetainSrc.scala rename to scalafix/input/src/main/scala/fix/RetainSrc.scala diff --git a/scalafix/input/src/main/scala/fix/RoughlyMapValuesSrc.scala b/scalafix/input/src/main/scala/fix/RoughlyMapValuesSrc.scala new file mode 100644 index 00000000..5a545ab8 --- /dev/null +++ b/scalafix/input/src/main/scala/fix/RoughlyMapValuesSrc.scala @@ -0,0 +1,8 @@ +/* +rule = "scala:fix.RoughlyMapValues" + */ +package fix + +class RoughlyMapValuesSrc(map: Map[Int, Int]) { + map.mapValues(_ + 1) +} diff --git a/scalafix-input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix/input/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala similarity index 72% rename from scalafix-input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala rename to scalafix/input/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala index 80bd9940..25e0bbc0 100644 --- a/scalafix-input/src/main/scala/fix/UnstableStreamToLazyListSrc.scala +++ b/scalafix/input/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala @@ -1,9 +1,9 @@ /* -rule = "scala:fix.UnstableStreamToLazyList" +rule = "scala:fix.RoughlyStreamToLazyList" */ package fix -class UnstableStreamToLazyListSrc() { +class RoughlyStreamToLazyListSrc() { val s = Stream(1, 2, 3) s.append(List(4, 5, 6)) 1 #:: 2 #:: 3 #:: Stream.Empty diff --git a/scalafix-input/src/main/scala/fix/SetMapSrc.scala b/scalafix/input/src/main/scala/fix/SetMapSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/SetMapSrc.scala rename to scalafix/input/src/main/scala/fix/SetMapSrc.scala diff --git a/scalafix-input/src/main/scala/fix/TestsSrc.scala b/scalafix/input/src/main/scala/fix/TestsSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/TestsSrc.scala rename to scalafix/input/src/main/scala/fix/TestsSrc.scala diff --git a/scalafix-input/src/main/scala/fix/TraversableSrc.scala b/scalafix/input/src/main/scala/fix/TraversableSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/TraversableSrc.scala rename to scalafix/input/src/main/scala/fix/TraversableSrc.scala diff --git a/scalafix-input/src/main/scala/fix/TupleNZippedSrc.scala b/scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala similarity index 100% rename from scalafix-input/src/main/scala/fix/TupleNZippedSrc.scala rename to scalafix/input/src/main/scala/fix/TupleNZippedSrc.scala diff --git a/scalafix-output212/src/main/scala/fix/CanBuildFromSrc.scala b/scalafix/output212/src/main/scala/fix/CanBuildFromSrc.scala similarity index 100% rename from scalafix-output212/src/main/scala/fix/CanBuildFromSrc.scala rename to scalafix/output212/src/main/scala/fix/CanBuildFromSrc.scala diff --git a/scalafix-output212/src/main/scala/fix/CopyToBufferSrc.scala b/scalafix/output212/src/main/scala/fix/CopyToBufferSrc.scala similarity index 100% rename from scalafix-output212/src/main/scala/fix/CopyToBufferSrc.scala rename to scalafix/output212/src/main/scala/fix/CopyToBufferSrc.scala diff --git a/scalafix-output212/src/main/scala/fix/ExperimentalSrc.scala b/scalafix/output212/src/main/scala/fix/ExperimentalSrc.scala similarity index 100% rename from scalafix-output212/src/main/scala/fix/ExperimentalSrc.scala rename to scalafix/output212/src/main/scala/fix/ExperimentalSrc.scala diff --git a/scalafix-output212/src/main/scala/fix/FoldSrc.scala b/scalafix/output212/src/main/scala/fix/FoldSrc.scala similarity index 100% rename from scalafix-output212/src/main/scala/fix/FoldSrc.scala rename to scalafix/output212/src/main/scala/fix/FoldSrc.scala diff --git a/scalafix-output212/src/main/scala/fix/LinearSeqSrc.scala b/scalafix/output212/src/main/scala/fix/LinearSeqSrc.scala similarity index 100% rename from scalafix-output212/src/main/scala/fix/LinearSeqSrc.scala rename to scalafix/output212/src/main/scala/fix/LinearSeqSrc.scala diff --git a/scalafix-output212/src/main/scala/fix/MutSetMapSrc.scala b/scalafix/output212/src/main/scala/fix/MutSetMapSrc.scala similarity index 100% rename from scalafix-output212/src/main/scala/fix/MutSetMapSrc.scala rename to scalafix/output212/src/main/scala/fix/MutSetMapSrc.scala diff --git a/scalafix/output212/src/main/scala/fix/RoughlyMapValuesSrc.scala b/scalafix/output212/src/main/scala/fix/RoughlyMapValuesSrc.scala new file mode 100644 index 00000000..a7b1f620 --- /dev/null +++ b/scalafix/output212/src/main/scala/fix/RoughlyMapValuesSrc.scala @@ -0,0 +1,8 @@ + + + +package fix + +class RoughlyMapValuesSrc(map: Map[Int, Int]) { + map.mapValues(_ + 1).toMap +} diff --git a/scalafix-output212/src/main/scala/fix/SetMapSrc.scala b/scalafix/output212/src/main/scala/fix/SetMapSrc.scala similarity index 100% rename from scalafix-output212/src/main/scala/fix/SetMapSrc.scala rename to scalafix/output212/src/main/scala/fix/SetMapSrc.scala diff --git a/scalafix-output212/src/main/scala/fix/TestsSrc.scala b/scalafix/output212/src/main/scala/fix/TestsSrc.scala similarity index 100% rename from scalafix-output212/src/main/scala/fix/TestsSrc.scala rename to scalafix/output212/src/main/scala/fix/TestsSrc.scala diff --git a/scalafix-output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala b/scalafix/output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala similarity index 100% rename from scalafix-output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala rename to scalafix/output213-failure/src/main/scala/fix/CanBuildFromNegSrc.scala diff --git a/scalafix/output213/src/main/scala/fix/BreakoutSrc.scala b/scalafix/output213/src/main/scala/fix/BreakoutSrc.scala deleted file mode 100644 index 7a086ec5..00000000 --- a/scalafix/output213/src/main/scala/fix/BreakoutSrc.scala +++ /dev/null @@ -1,24 +0,0 @@ - - - -package fix - - -object BreakoutSrc { - val xs = List(1, 2, 3) - - xs.iterator.collect{ case x => x }.to(implicitly): Set[Int] - xs.iterator.flatMap(x => List(x)).to(implicitly): collection.SortedSet[Int] - xs.iterator.map(_ + 1).to(implicitly): Set[Int] - xs.reverseIterator.map(_ + 1).to(implicitly): Set[Int] - xs.iterator.scanLeft(0)((a, b) => a + b).to(implicitly): Set[Int] - xs.iterator.concat(xs).to(implicitly): Set[Int] - xs.view.updated(0, 1).to(implicitly): Set[Int] - xs.iterator.zip(xs).to(implicitly): Map[Int, Int] - xs.iterator.zipAll(xs, 0, 0).to(implicitly): Array[(Int, Int)] - - (xs.iterator ++ xs).to(implicitly): Set[Int] - (1 +: xs.view).to(implicitly): Set[Int] - (xs.view :+ 1).to(implicitly): Set[Int] - (xs ++: xs.view).to(implicitly): Set[Int] -} diff --git a/scalafix-output213/src/main/scala/fix/IterableSrc.scala b/scalafix/output213/src/main/scala/fix/IterableSrc.scala similarity index 100% rename from scalafix-output213/src/main/scala/fix/IterableSrc.scala rename to scalafix/output213/src/main/scala/fix/IterableSrc.scala diff --git a/scalafix-output213/src/main/scala/fix/RetainSrc.scala b/scalafix/output213/src/main/scala/fix/RetainSrc.scala similarity index 100% rename from scalafix-output213/src/main/scala/fix/RetainSrc.scala rename to scalafix/output213/src/main/scala/fix/RetainSrc.scala diff --git a/scalafix-output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix/output213/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala similarity index 85% rename from scalafix-output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala rename to scalafix/output213/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala index db6e3a56..87ad201e 100644 --- a/scalafix-output213/src/main/scala/fix/UnstableStreamToLazyListSrc.scala +++ b/scalafix/output213/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala @@ -3,7 +3,7 @@ package fix -class UnstableStreamToLazyListSrc() { +class RoughlyStreamToLazyListSrc() { val s = LazyList(1, 2, 3) s.lazyAppendedAll(List(4, 5, 6)) 1 #:: 2 #:: 3 #:: LazyList.Empty diff --git a/scalafix-output213/src/main/scala/fix/TraversableSrc.scala b/scalafix/output213/src/main/scala/fix/TraversableSrc.scala similarity index 100% rename from scalafix-output213/src/main/scala/fix/TraversableSrc.scala rename to scalafix/output213/src/main/scala/fix/TraversableSrc.scala diff --git a/scalafix-output213/src/main/scala/fix/TupleNZippedSrc.scala b/scalafix/output213/src/main/scala/fix/TupleNZippedSrc.scala similarity index 100% rename from scalafix-output213/src/main/scala/fix/TupleNZippedSrc.scala rename to scalafix/output213/src/main/scala/fix/TupleNZippedSrc.scala diff --git a/scalafix-rules/src/main/scala/fix/CanBuildFrom.scala b/scalafix/rules/src/main/scala/fix/CanBuildFrom.scala similarity index 100% rename from scalafix-rules/src/main/scala/fix/CanBuildFrom.scala rename to scalafix/rules/src/main/scala/fix/CanBuildFrom.scala diff --git a/scalafix-rules/src/main/scala/fix/CrossCompat.scala b/scalafix/rules/src/main/scala/fix/CrossCompat.scala similarity index 100% rename from scalafix-rules/src/main/scala/fix/CrossCompat.scala rename to scalafix/rules/src/main/scala/fix/CrossCompat.scala diff --git a/scalafix-rules/src/main/scala/fix/Experimental.scala b/scalafix/rules/src/main/scala/fix/Experimental.scala similarity index 100% rename from scalafix-rules/src/main/scala/fix/Experimental.scala rename to scalafix/rules/src/main/scala/fix/Experimental.scala diff --git a/scalafix-rules/src/main/scala/fix/NewCollections.scala b/scalafix/rules/src/main/scala/fix/NewCollections.scala similarity index 100% rename from scalafix-rules/src/main/scala/fix/NewCollections.scala rename to scalafix/rules/src/main/scala/fix/NewCollections.scala diff --git a/scalafix-rules/src/main/scala/fix/UnstableMapValues.scala b/scalafix/rules/src/main/scala/fix/RoughlyMapValues.scala similarity index 83% rename from scalafix-rules/src/main/scala/fix/UnstableMapValues.scala rename to scalafix/rules/src/main/scala/fix/RoughlyMapValues.scala index 57a5ce6a..07838667 100644 --- a/scalafix-rules/src/main/scala/fix/UnstableMapValues.scala +++ b/scalafix/rules/src/main/scala/fix/RoughlyMapValues.scala @@ -9,7 +9,7 @@ import scala.meta._ * * This rules is marked unstable since Map.mapValues was lazy */ -case class UnstableMapValues(index: SemanticdbIndex) extends SemanticRule(index, "UnstableMapValues") { +case class RoughlyMapValues(index: SemanticdbIndex) extends SemanticRule(index, "RoughlyMapValues") { val mapMapValues = SymbolMatcher.exact( Symbol("_root_.scala.collection.immutable.MapLike#mapValues(Lscala/Function1;)Lscala/collection/immutable/Map;.") diff --git a/scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala b/scalafix/rules/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala similarity index 87% rename from scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala rename to scalafix/rules/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala index f6344ea9..90a04b11 100644 --- a/scalafix-rules/src/main/scala/fix/UnstableStreamToLazyListSrc.scala +++ b/scalafix/rules/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala @@ -9,7 +9,7 @@ import scala.meta._ * This rules is marked unstable since Stream is not strictly equivalent to LazyList. * LazyList has a lazy head but not Stream */ -case class UnstableStreamToLazyList(index: SemanticdbIndex) extends SemanticRule(index, "UnstableStreamToLazyList") { +case class RoughlyStreamToLazyList(index: SemanticdbIndex) extends SemanticRule(index, "RoughlyStreamToLazyList") { val streamAppend = SymbolMatcher.normalized( Symbol("_root_.scala.collection.immutable.Stream.append.") diff --git a/scalafix-rules/src/main/scala/fix/Stable212Base.scala b/scalafix/rules/src/main/scala/fix/Stable212Base.scala similarity index 100% rename from scalafix-rules/src/main/scala/fix/Stable212Base.scala rename to scalafix/rules/src/main/scala/fix/Stable212Base.scala diff --git a/scalafix-rules/src/main/scala/fix/TypeMatcher.scala b/scalafix/rules/src/main/scala/fix/TypeMatcher.scala similarity index 100% rename from scalafix-rules/src/main/scala/fix/TypeMatcher.scala rename to scalafix/rules/src/main/scala/fix/TypeMatcher.scala diff --git a/scalafix-rules/src/main/scala/fix/package.scala b/scalafix/rules/src/main/scala/fix/package.scala similarity index 97% rename from scalafix-rules/src/main/scala/fix/package.scala rename to scalafix/rules/src/main/scala/fix/package.scala index 7a7e5b6a..249afd4b 100644 --- a/scalafix-rules/src/main/scala/fix/package.scala +++ b/scalafix/rules/src/main/scala/fix/package.scala @@ -1,5 +1,4 @@ import scalafix._ -import scalafix.syntax._ import scalafix.util._ import scala.meta._ diff --git a/scalafix-tests/src/test/scala/fix/ScalafixTests.scala b/scalafix/tests/src/test/scala/fix/ScalafixTests.scala similarity index 100% rename from scalafix-tests/src/test/scala/fix/ScalafixTests.scala rename to scalafix/tests/src/test/scala/fix/ScalafixTests.scala