Skip to content

Commit ac48c15

Browse files
Add more cases for breakout
1 parent 263d569 commit ac48c15

File tree

3 files changed

+244
-50
lines changed

3 files changed

+244
-50
lines changed

scalafix/input/src/main/scala/fix/BreakoutSrc.scala

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,90 @@ rule = "scala:fix.CrossCompat"
44
package fix
55

66
import scala.collection.breakOut
7+
import scala.collection.{immutable, mutable}
78

8-
object BreakoutSrc {
9-
val xs = List(1, 2, 3)
9+
import scala.concurrent.Future
10+
import scala.concurrent.ExecutionContext.Implicits.global
1011

11-
xs.collect{ case x => x }(breakOut): Set[Int]
12-
xs.flatMap(x => List(x))(breakOut): collection.SortedSet[Int]
13-
xs.map(_ + 1)(breakOut): Set[Int]
14-
xs.reverseMap(_ + 1)(breakOut): Set[Int]
15-
xs.scanLeft(0)((a, b) => a + b)(breakOut): Set[Int]
16-
xs.updated(0, 1)(breakOut): Set[Int]
12+
class BreakoutSrc(ts: Traversable[Int], vec: Vector[Int], list: List[Int], seq: Seq[Int]) {
1713

18-
(xs ++ xs)(breakOut): Set[Int]
19-
(1 +: xs)(breakOut): Set[Int]
20-
(xs :+ 1)(breakOut): Set[Int]
21-
(xs ++: xs)(breakOut): Set[Int]
14+
// `IndexedSeqOptimized.zip`
15+
vec.zip(vec)(breakOut): Map[Int, Int]
2216

23-
xs.union(xs)(breakOut): Set[Int]
24-
xs.zip(xs)(breakOut): Map[Int, Int]
25-
xs.zipAll(xs, 0, 0)(breakOut): Array[(Int, Int)]
17+
// `IterableLike.zip`
18+
seq.zip(seq)(breakOut): Map[Int, Int]
19+
20+
// `IterableLike.zipAll`
21+
seq.zipAll(seq, 0, 0)(breakOut): Array[(Int, Int)]
22+
23+
// `List ++`
24+
(list ++ list)(breakOut): Set[Int]
25+
26+
// `List +:`
27+
(1 +: list)(breakOut): Set[Int]
28+
29+
// `List.collect`
30+
list.collect{ case x => x}(breakOut): Set[Int]
31+
32+
// `List.flatMap`
33+
list.flatMap(x => List(x))(breakOut): Set[Int]
34+
35+
// `List.map`
36+
list.map(x => x)(breakOut): Set[Int]
37+
38+
39+
// `SeqLike.reverseMap`
40+
seq.reverseMap(_ + 1)(breakOut): Set[Int]
41+
42+
// `SeqLike +:`
43+
(1 +: seq)(breakOut): List[Int]
44+
45+
// `SeqLike :+`
46+
(seq :+ 1)(breakOut): List[Int]
47+
48+
// `SeqLike.updated`
49+
(seq.updated(0, 0))(breakOut): List[Int]
50+
51+
// `SeqLike.union`
52+
seq.union(seq)(breakOut): List[Int]
53+
54+
55+
//`SetLike.map`
56+
Set(1).map(x => x)(breakOut): List[Int]
57+
58+
59+
// `TraversableLike ++`
60+
(ts ++ ts )(breakOut): Set[Int]
61+
62+
// `TraversableLike ++:`
63+
(ts ++: ts)(breakOut): Set[Int]
64+
65+
// `TraversableLike.collect`
66+
ts.collect{ case x => x }(breakOut): Set[Int]
67+
68+
// `TraversableLike.flatMap`
69+
ts.flatMap(x => List(x))(breakOut): collection.SortedSet[Int]
70+
71+
// `TraversableLike.map`
72+
ts.map(_ + 1)(breakOut): Set[Int]
73+
74+
// `TraversableLike.scanLeft`
75+
ts.scanLeft(0)((a, b) => a + b)(breakOut): Set[Int]
76+
77+
78+
// `Vector ++`
79+
(vec ++ List(1))(breakOut): List[Int]
80+
81+
// `Vector +:`
82+
(1 +: vec)(breakOut): List[Int]
83+
84+
// `Vector :+`
85+
(vec :+ 1)(breakOut): List[Int]
86+
87+
// `Vector.updated`
88+
(vec.updated(0, 0))(breakOut): List[Int]
89+
90+
// TODO
91+
// Future.sequence(List(Future(1)))(breakOut, global): Future[Seq[Int]]
92+
// Future.traverse(List(1))(x => Future(x))(breakOut, global): Future[Seq[Int]]
2693
}

scalafix/output212/src/main/scala/fix/BreakoutSrc.scala

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,91 @@
33

44
package fix
55

6+
import scala.collection.{immutable, mutable}
7+
8+
import scala.concurrent.Future
9+
import scala.concurrent.ExecutionContext.Implicits.global
610
import scala.collection.compat._
711

8-
object BreakoutSrc {
9-
val xs = List(1, 2, 3)
12+
class BreakoutSrc(ts: Iterable[Int], vec: Vector[Int], list: List[Int], seq: Seq[Int]) {
1013

11-
xs.iterator.collect{ case x => x }.to(scala.collection.immutable.Set): Set[Int]
12-
xs.iterator.flatMap(x => List(x)).to(scala.collection.SortedSet): collection.SortedSet[Int]
13-
xs.iterator.map(_ + 1).to(scala.collection.immutable.Set): Set[Int]
14-
xs.reverseIterator.map(_ + 1).to(scala.collection.immutable.Set): Set[Int]
15-
xs.iterator.scanLeft(0)((a, b) => a + b).to(scala.collection.immutable.Set): Set[Int]
16-
xs.view.updated(0, 1).to(scala.collection.immutable.Set): Set[Int]
14+
// `IndexedSeqOptimized.zip`
15+
vec.iterator.zip(vec.iterator).toMap: Map[Int, Int]
1716

18-
(xs.iterator ++ xs).to(scala.collection.immutable.Set): Set[Int]
19-
(1 +: xs.view).to(scala.collection.immutable.Set): Set[Int]
20-
(xs.view :+ 1).to(scala.collection.immutable.Set): Set[Int]
21-
(xs ++: xs.view).to(scala.collection.immutable.Set): Set[Int]
17+
// `IterableLike.zip`
18+
seq.iterator.zip(seq.iterator).toMap: Map[Int, Int]
19+
20+
// `IterableLike.zipAll`
21+
seq.iterator.zipAll(seq.iterator, 0, 0).to(scala.Array): Array[(Int, Int)]
22+
23+
// `List ++`
24+
(list.iterator ++ list).to(scala.collection.immutable.Set): Set[Int]
25+
26+
// `List +:`
27+
(1 +: list.view).to(scala.collection.immutable.Set): Set[Int]
28+
29+
// `List.collect`
30+
list.iterator.collect{ case x => x}.to(scala.collection.immutable.Set): Set[Int]
31+
32+
// `List.flatMap`
33+
list.iterator.flatMap(x => List(x)).to(scala.collection.immutable.Set): Set[Int]
34+
35+
// `List.map`
36+
list.iterator.map(x => x).to(scala.collection.immutable.Set): Set[Int]
37+
38+
39+
// `SeqLike.reverseMap`
40+
seq.reverseIterator.map(_ + 1).to(scala.collection.immutable.Set): Set[Int]
41+
42+
// `SeqLike +:`
43+
(1 +: seq.view).to(scala.collection.immutable.List): List[Int]
44+
45+
// `SeqLike :+`
46+
(seq.view :+ 1).to(scala.collection.immutable.List): List[Int]
47+
48+
// `SeqLike.updated`
49+
(seq.view.updated(0, 0)).to(scala.collection.immutable.List): List[Int]
50+
51+
// `SeqLike.union`
52+
seq.iterator.concat(seq).to(scala.collection.immutable.List): List[Int]
2253

23-
xs.iterator.concat(xs).to(scala.collection.immutable.Set): Set[Int]
24-
xs.iterator.zip(xs.iterator).toMap: Map[Int, Int]
25-
xs.iterator.zipAll(xs.iterator, 0, 0).to(scala.Array): Array[(Int, Int)]
26-
}
2754

55+
//`SetLike.map`
56+
Set(1).iterator.map(x => x).to(scala.collection.immutable.List): List[Int]
57+
58+
59+
// `TraversableLike ++`
60+
(ts.iterator ++ ts ).to(scala.collection.immutable.Set): Set[Int]
61+
62+
// `TraversableLike ++:`
63+
(ts ++: ts.view).to(scala.collection.immutable.Set): Set[Int]
64+
65+
// `TraversableLike.collect`
66+
ts.iterator.collect{ case x => x }.to(scala.collection.immutable.Set): Set[Int]
67+
68+
// `TraversableLike.flatMap`
69+
ts.iterator.flatMap(x => List(x)).to(scala.collection.SortedSet): collection.SortedSet[Int]
70+
71+
// `TraversableLike.map`
72+
ts.iterator.map(_ + 1).to(scala.collection.immutable.Set): Set[Int]
73+
74+
// `TraversableLike.scanLeft`
75+
ts.iterator.scanLeft(0)((a, b) => a + b).to(scala.collection.immutable.Set): Set[Int]
76+
77+
78+
// `Vector ++`
79+
(vec.iterator ++ List(1)).to(scala.collection.immutable.List): List[Int]
80+
81+
// `Vector +:`
82+
(1 +: vec.view).to(scala.collection.immutable.List): List[Int]
83+
84+
// `Vector :+`
85+
(vec.view :+ 1).to(scala.collection.immutable.List): List[Int]
86+
87+
// `Vector.updated`
88+
(vec.view.updated(0, 0)).to(scala.collection.immutable.List): List[Int]
89+
90+
// TODO
91+
// Future.sequence(List(Future(1)))(breakOut, global): Future[Seq[Int]]
92+
// Future.traverse(List(1))(x => Future(x))(breakOut, global): Future[Seq[Int]]
93+
}

scalafix/rules/src/main/scala/fix/Stable212Base.scala

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,31 +58,68 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
5858
val breakOut = SymbolMatcher.exact(Symbol("_root_.scala.collection.package.breakOut(Lscala/collection/generic/CanBuildFrom;)Lscala/collection/generic/CanBuildFrom;."))
5959

6060
// infix operators
61+
62+
val `TraversableLike ++` = Symbol("_root_.scala.collection.TraversableLike#`++`(Lscala/collection/GenTraversableOnce;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
63+
val `Vector ++` = Symbol("_root_.scala.collection.immutable.Vector#`++`(Lscala/collection/GenTraversableOnce;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
6164
val `List ++` = Symbol("_root_.scala.collection.immutable.List#`++`(Lscala/collection/GenTraversableOnce;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
65+
66+
val `SeqLike +:` = Symbol("_root_.scala.collection.SeqLike#`+:`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
67+
val `Vector +:` = Symbol("_root_.scala.collection.immutable.Vector#`+:`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
6268
val `List +:` = Symbol("_root_.scala.collection.immutable.List#`+:`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
69+
6370
val `SeqLike :+` = Symbol("_root_.scala.collection.SeqLike#`:+`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
71+
val `Vector :+` = Symbol("_root_.scala.collection.immutable.Vector#`:+`(Ljava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
72+
6473
val `TraversableLike ++:` = Symbol("_root_.scala.collection.TraversableLike#`++:`(Lscala/collection/Traversable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
6574

66-
val operatorsIteratorSymbols = List(`List ++`)
67-
val operatorsViewSymbols = List(`List +:`, `SeqLike :+`, `TraversableLike ++:`)
75+
val operatorsIteratorSymbols = List(`TraversableLike ++`, `List ++`, `Vector ++`)
76+
val operatorsViewSymbols = List(
77+
`SeqLike +:`, `Vector +:`, `List +:`,
78+
`SeqLike :+`, `Vector :+`,
79+
`TraversableLike ++:`
80+
)
81+
6882
val operatorsSymbols = operatorsViewSymbols ++ operatorsIteratorSymbols
6983

7084
val operatorsIterator = SymbolMatcher.exact(operatorsIteratorSymbols: _*)
7185
val operatorsView = SymbolMatcher.exact(operatorsViewSymbols: _*)
7286
val operators = SymbolMatcher.exact(operatorsSymbols: _*)
7387

7488
// select
75-
val `List.collect` = Symbol("_root_.scala.collection.immutable.List#collect(Lscala/PartialFunction;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
76-
val `List.flatMap` = Symbol("_root_.scala.collection.immutable.List#flatMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
77-
val `List.map` = Symbol("_root_.scala.collection.immutable.List#map(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
78-
val `IterableLike.zip` = Symbol("_root_.scala.collection.IterableLike#zip(Lscala/collection/GenIterable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
79-
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;.")
80-
val `SeqLike.union` = Symbol("_root_.scala.collection.SeqLike#union(Lscala/collection/GenSeq;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
81-
val `SeqLike.updated` = Symbol("_root_.scala.collection.SeqLike#updated(ILjava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
82-
val `SeqLike.reverseMap` = Symbol("_root_.scala.collection.SeqLike#reverseMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
83-
84-
val functionsIteratorSymbols = List(`List.collect`, `List.flatMap`, `List.map`, `IterableLike.zip`, `IterableLike.zipAll`, `SeqLike.union`)
85-
val functionsViewSymbols = List(`SeqLike.updated`)
89+
val `List.collect` = Symbol("_root_.scala.collection.immutable.List#collect(Lscala/PartialFunction;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
90+
val `TraversableLike.collect` = Symbol("_root_.scala.collection.TraversableLike#collect(Lscala/PartialFunction;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
91+
92+
val `List.flatMap` = Symbol("_root_.scala.collection.immutable.List#flatMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
93+
val `TraversableLike.flatMap` = Symbol("_root_.scala.collection.TraversableLike#flatMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
94+
95+
val `List.map` = Symbol("_root_.scala.collection.immutable.List#map(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
96+
val `SetLike.map` = Symbol("_root_.scala.collection.SetLike#map(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
97+
val `TraversableLike.map` = Symbol("_root_.scala.collection.TraversableLike#map(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
98+
99+
val `IterableLike.zip` = Symbol("_root_.scala.collection.IterableLike#zip(Lscala/collection/GenIterable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
100+
101+
val `IndexedSeqOptimized.zip` = Symbol("_root_.scala.collection.IndexedSeqOptimized#zip(Lscala/collection/GenIterable;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
102+
103+
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;.")
104+
105+
val `SeqLike.union` = Symbol("_root_.scala.collection.SeqLike#union(Lscala/collection/GenSeq;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
106+
107+
val `SeqLike.updated` = Symbol("_root_.scala.collection.SeqLike#updated(ILjava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
108+
val `Vector.updated` = Symbol("_root_.scala.collection.immutable.Vector#updated(ILjava/lang/Object;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
109+
val `SeqLike.reverseMap` = Symbol("_root_.scala.collection.SeqLike#reverseMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
110+
111+
val functionsZipSymbols = List(
112+
`IterableLike.zip`,
113+
`IndexedSeqOptimized.zip`,
114+
`IterableLike.zipAll`
115+
)
116+
val functionsIteratorSymbols = List(
117+
`List.collect`, `TraversableLike.collect`,
118+
`List.flatMap`, `TraversableLike.flatMap`,
119+
`List.map`, `SetLike.map`, `TraversableLike.map`,
120+
`SeqLike.union`
121+
) ++ functionsZipSymbols
122+
val functionsViewSymbols = List(`SeqLike.updated`, `Vector.updated`)
86123
val functionsReverseIteratorSymbols = List(`SeqLike.reverseMap`)
87124
val functionsSymbols = functionsIteratorSymbols ++ functionsViewSymbols ++ functionsReverseIteratorSymbols
88125

@@ -91,7 +128,7 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
91128
val functionsView = SymbolMatcher.exact(functionsViewSymbols: _*)
92129
val functions = SymbolMatcher.exact(functionsSymbols: _*)
93130

94-
val functionsZip = SymbolMatcher.exact(`IterableLike.zip`, `IterableLike.zipAll`)
131+
val functionsZip = SymbolMatcher.exact(functionsZipSymbols: _*)
95132

96133
// special select
97134

@@ -176,11 +213,10 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
176213
}
177214
}
178215

216+
val breakOutImports = List.newBuilder[Importee]
217+
179218
val rewriteBreakout =
180219
ctx.tree.collect {
181-
case i: Importee if breakOut.matches(i) =>
182-
ctx.removeImportee(i)
183-
184220
case ap0 @ Term.Apply(ap @ Term.ApplyInfix(lhs, operators(op), _, List(rhs)), List(breakOut(bo))) =>
185221
val subject =
186222
if(isLeftAssociative(op)) lhs
@@ -197,7 +233,6 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
197233
fixIt(intermediate, subject, ap, bo, ap0)
198234

199235
case ap0 @ Term.Apply(ap @ Term.Apply(Term.Select(lhs, functions(op)), rhs :: _), List(breakOut(bo))) =>
200-
201236
val intermediateLhs =
202237
op match {
203238
case functionsIterator(_) => "iterator"
@@ -226,10 +261,20 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
226261

227262
case ap0 @ Term.Apply(ap @ Term.Apply(Term.Apply(Term.Select(lhs, `TraversableLike.scanLeft`(op)), _), _), List(breakOut(bo))) =>
228263
fixIt("iterator", lhs, ap, bo, ap0)
264+
265+
case i: Importee if breakOut.matches(i) =>
266+
breakOutImports += i
267+
Patch.empty
268+
229269
}.asPatch
230270

231271
val compatImport =
232-
if(rewriteBreakout.nonEmpty) addCompatImport(ctx)
272+
if(rewriteBreakout.nonEmpty) {
273+
val removeImports = breakOutImports.result().map(i => ctx.removeImportee(i)).asPatch
274+
275+
removeImports +
276+
addCompatImport(ctx)
277+
}
233278
else Patch.empty
234279

235280
rewriteBreakout + compatImport
@@ -387,6 +432,22 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
387432
else Patch.empty
388433
}
389434

435+
var lastPath: Option[String] = None
436+
def trace(in: Any, ctx: RuleCtx): Unit = {
437+
val path =
438+
ctx.input match {
439+
case Input.File(path, _) => path.toString
440+
case Input.VirtualFile(path, _) => path.toString
441+
case _ => "???"
442+
}
443+
444+
if (lastPath != Some(path)) {
445+
println(s"--- $path ---")
446+
lastPath = Some(path)
447+
}
448+
println(in)
449+
}
450+
390451
override def fix(ctx: RuleCtx): Patch = {
391452
replaceSymbols0(ctx) +
392453
replaceCanBuildFrom(ctx) +

0 commit comments

Comments
 (0)