Skip to content

Commit cf7372c

Browse files
Split rules that can be used to cross compile
1 parent 3bcbead commit cf7372c

39 files changed

+581
-549
lines changed

scalafix/build.sbt

+15-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ inScope(Global)(
88
lazy val root = project
99
.in(file("."))
1010
.aggregate(
11-
rules, input, output, tests
11+
rules, input, output212, output213, output213Failure, tests
1212
)
1313

1414
lazy val rules = project.settings(
@@ -20,13 +20,15 @@ lazy val input = project
2020
scalafixSourceroot := sourceDirectory.in(Compile).value
2121
)
2222

23-
lazy val output = project
23+
lazy val output212 = project
24+
25+
lazy val output213 = project
2426
.settings(
2527
resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/",
2628
scalaVersion := "2.13.0-M4"
2729
)
2830

29-
lazy val outputFailure = project.in(file("output-failure"))
31+
lazy val output213Failure = project.in(file("output213-failure"))
3032
.settings(
3133
resolvers += "scala-pr" at "https://scala-ci.typesafe.com/artifactory/scala-integration/",
3234
scalaVersion := "2.13.0-M4"
@@ -39,14 +41,19 @@ lazy val tests = project
3941
buildInfoKeys := Seq[BuildInfoKey](
4042
"inputSourceroot" ->
4143
sourceDirectory.in(input, Compile).value,
42-
"outputSourceroot" ->
43-
sourceDirectory.in(output, Compile).value,
44-
"outputFailureSourceroot" ->
45-
sourceDirectory.in(outputFailure, Compile).value,
44+
"output212Sourceroot" ->
45+
sourceDirectory.in(output212, Compile).value,
46+
"output213Sourceroot" ->
47+
sourceDirectory.in(output213, Compile).value,
48+
"output213FailureSourceroot" ->
49+
sourceDirectory.in(output213Failure, Compile).value,
4650
"inputClassdirectory" ->
4751
classDirectory.in(input, Compile).value
4852
),
49-
test in Test := (test in Test).dependsOn(compile in (output, Compile)).value
53+
test in Test := (test in Test).dependsOn(
54+
compile in (output212, Compile),
55+
compile in (output213, Compile)
56+
).value
5057
)
5158
.dependsOn(input, rules)
5259
.enablePlugins(BuildInfoPlugin)

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable213"
33
*/
44
package fix
55

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable213"
33
*/
44
package fix
55

Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable212"
33
*/
44
package fix
55

66
import scala.collection.mutable
77

88
class CopyToBufferSrc(xs: List[Int], b: mutable.Buffer[Int]) {
9-
109
xs.copyToBuffer(b)
1110
(xs ++ xs).copyToBuffer(b)
12-
1311
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable212"
33
*/
44
package fix
55

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable213"
33
*/
44
package fix
55

66
class IterableSrc(it: Iterable[Int]) {
77
it.sameElements(it)
8-
}
8+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable212"
33
*/
44
package fix
55

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable212"
33
*/
44
package fix
55

@@ -10,4 +10,4 @@ class MutSetMapSrc(map: mutable.Map[Int, Int], set: mutable.Set[Int]) {
1010
map + (2 -> 3)
1111
(set + 2).size
1212
map.updated(1, 3)
13-
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable213"
33
*/
44
package fix
55

@@ -9,4 +9,4 @@ class MethodRenames(xs: Map[Int, Int], ys: Set[Int]) {
99
xs.retain((_, _) => true)
1010
xs.retain{case (x, y) => true}
1111
ys.retain(_ => true)
12-
}
12+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable212"
33
*/
44
package fix
55

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable212"
33
*/
44
package fix
55

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable213"
33
*/
44
package fix
55

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
rule = "scala:fix.Stable"
2+
rule = "scala:fix.Stable213"
33
*/
44
package fix
55

@@ -33,4 +33,4 @@ object Collectionstrawman_v0_Tuple3Zipped {
3333
(List(1, 2, 3), Set(1, 2, 3), Array(1)).zipped
3434
}
3535
def coll(x: Int): List[Int] = ???
36-
}
36+
}

scalafix/output/src/main/scala/fix/CopyToBufferSrc.scala renamed to scalafix/output212/src/main/scala/fix/CopyToBufferSrc.scala

-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ package fix
66
import scala.collection.mutable
77

88
class CopyToBufferSrc(xs: List[Int], b: mutable.Buffer[Int]) {
9-
109
b ++= xs
1110
b ++= xs ++ xs
12-
1311
}

scalafix/output/src/main/scala/fix/IterableSrc.scala renamed to scalafix/output213/src/main/scala/fix/IterableSrc.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ package fix
55

66
class IterableSrc(it: Iterable[Int]) {
77
it.iterator.sameElements(it)
8-
}
8+
}

scalafix/output/src/main/scala/fix/RetainSrc.scala renamed to scalafix/output213/src/main/scala/fix/RetainSrc.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ class MethodRenames(xs: Map[Int, Int], ys: Set[Int]) {
99
xs.filterInPlace{case (_, _) => true}
1010
xs.filterInPlace{case (x, y) => true}
1111
ys.filterInPlace(_ => true)
12-
}
12+
}

scalafix/output/src/main/scala/fix/TupleNZippedSrc.scala renamed to scalafix/output213/src/main/scala/fix/TupleNZippedSrc.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ object Collectionstrawman_v0_Tuple3Zipped {
3333
List(1, 2, 3).lazyZip(Set(1, 2, 3)).lazyZip(Array(1))
3434
}
3535
def coll(x: Int): List[Int] = ???
36-
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
package fix
2+
3+
import scalafix._
4+
import scalafix.syntax._
5+
import scalafix.util._
6+
import scala.meta._
7+
8+
object CanBuildFrom {
9+
def apply(paramss: List[List[Term.Param]],
10+
body: Term,
11+
ctx: RuleCtx,
12+
collectionCanBuildFrom: SymbolMatcher,
13+
nothing: SymbolMatcher)(implicit index: SemanticdbIndex): Patch = {
14+
// CanBuildFrom has def apply() but not CanBuild
15+
def emptyApply(param: Name): Boolean = {
16+
import scala.meta.contrib._
17+
val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get)
18+
body.exists{
19+
case Term.Apply(Term.Select(matchCbf(_), _), Nil) => true
20+
case Term.Apply(matchCbf(_), Nil) => true
21+
case _ => false
22+
}
23+
}
24+
25+
paramss.flatten.collect{
26+
case Term.Param(
27+
List(Mod.Implicit()),
28+
param,
29+
Some(
30+
Type.Apply(
31+
cbf @ collectionCanBuildFrom(_),
32+
List(p1, _, _)
33+
)
34+
),
35+
_
36+
) if !nothing.matches(p1) && !emptyApply(param) => new CanBuildFrom(param, cbf)
37+
}.map(_.toBuildFrom(body, ctx)).asPatch
38+
}
39+
}
40+
41+
// example:
42+
// implicit cbf: collection.generic.CanBuildFrom[C0, Int, CC[Int]]
43+
// param: cbf
44+
// cbf : collection.generic.CanBuildFrom
45+
case class CanBuildFrom(param: Name, cbf: Type) {
46+
def toBuildFrom(body: Term, ctx: RuleCtx)(implicit index: SemanticdbIndex): Patch = {
47+
48+
val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get)
49+
50+
// cbf(x) / cbf.apply(x) => cbf.newBuilder(x)
51+
def replaceNewBuilder(tree: Tree, cbf2: Term, x: Term): Patch =
52+
ctx.replaceTree(
53+
tree,
54+
Term.Apply(Term.Select(cbf2, Term.Name("newBuilder")), List(x)).syntax
55+
)
56+
57+
val cbfCalls =
58+
body.collect {
59+
// cbf.apply(x)
60+
case ap @ Term.Apply(sel @ Term.Select(cbf2 @ matchCbf(_), apply), List(x)) =>
61+
replaceNewBuilder(ap, cbf2, x)
62+
63+
// cbf(x)
64+
case ap @ Term.Apply(cbf2 @ matchCbf(_), List(x)) =>
65+
replaceNewBuilder(ap, cbf2, x)
66+
}.asPatch
67+
68+
val parameterType =
69+
ctx.replaceTree(cbf, "collection.BuildFrom")
70+
71+
parameterType + cbfCalls
72+
}
73+
}
74+
75+
object CanBuildFromNothing {
76+
def apply(paramss: List[List[Term.Param]],
77+
body: Term,
78+
ctx: RuleCtx,
79+
collectionCanBuildFrom: SymbolMatcher,
80+
nothing: SymbolMatcher,
81+
toTpe: SymbolMatcher)(implicit index: SemanticdbIndex): (Patch, Set[Tree]) = {
82+
val handledTo = Set.newBuilder[Tree]
83+
84+
val patches =
85+
paramss.flatten.collect{
86+
case
87+
Term.Param(
88+
List(Mod.Implicit()),
89+
param,
90+
Some(
91+
tpe @ Type.Apply(
92+
collectionCanBuildFrom(_),
93+
List(
94+
nothing(_),
95+
t,
96+
cct @ Type.Apply(
97+
cc,
98+
_
99+
)
100+
)
101+
)
102+
),
103+
_
104+
) => new CanBuildFromNothing(param, tpe, t, cct, cc, body, ctx, toTpe)
105+
}.map{cbf =>
106+
val (ps, ht) = cbf.toFactory
107+
handledTo ++= ht
108+
ps
109+
}.asPatch
110+
111+
(patches, handledTo.result())
112+
}
113+
}
114+
115+
// example:
116+
// implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]]
117+
//
118+
// param: cbf
119+
// tpe : collection.generic.CanBuildFrom[Nothing, Int, CC[Int]]
120+
// cbf : CanBuildFrom
121+
// v : Int
122+
// cct : CC[Int]
123+
// cc : CC
124+
case class CanBuildFromNothing(param: Name,
125+
tpe: Type.Apply,
126+
t: Type,
127+
cct: Type.Apply,
128+
cc: Type,
129+
body: Term,
130+
ctx: RuleCtx,
131+
toTpe: SymbolMatcher) {
132+
def toFactory(implicit index: SemanticdbIndex): (Patch, Set[Tree]) = {
133+
val handledTo = Set.newBuilder[Tree]
134+
135+
val matchCbf = SymbolMatcher.exact(ctx.index.symbol(param).get)
136+
137+
// cbf() / cbf.apply => cbf.newBuilder
138+
def replaceNewBuilder(tree: Tree, cbf2: Term): Patch =
139+
ctx.replaceTree(tree, Term.Select(cbf2, Term.Name("newBuilder")).syntax)
140+
141+
// don't patch cbf.apply twice (cbf.apply and cbf.apply())
142+
val visitedCbfCalls = scala.collection.mutable.Set[Tree]()
143+
144+
val cbfCalls =
145+
body.collect {
146+
// cbf.apply()
147+
case ap @ Term.Apply(sel @ Term.Select(cbf2 @ matchCbf(_), apply), Nil) =>
148+
visitedCbfCalls += sel
149+
replaceNewBuilder(ap, cbf2)
150+
151+
// cbf.apply
152+
case sel @ Term.Select(cbf2 @ matchCbf(_), ap) if (!visitedCbfCalls.contains(sel)) =>
153+
replaceNewBuilder(sel, cbf2)
154+
155+
// cbf()
156+
case ap @ Term.Apply(cbf2 @ matchCbf(_), Nil) =>
157+
replaceNewBuilder(ap, cbf2)
158+
}.asPatch
159+
160+
161+
val matchCC = SymbolMatcher.exact(ctx.index.symbol(cc).get)
162+
163+
// e.to[CC] => e.to(cbf)
164+
val toCalls =
165+
body.collect {
166+
case ap @ Term.ApplyType(Term.Select(_, to @ toTpe(_)), List(cc2 @ matchCC(_))) =>
167+
handledTo += to
168+
169+
// e.to[CC](*cbf*) extract implicit parameter
170+
val synth = ctx.index.synthetics.find(_.position.end == ap.pos.end).get
171+
val Term.Apply(_, List(implicitCbf)) = synth.text.parse[Term].get
172+
173+
// This is a bit unsafe
174+
// https://github.com/scalameta/scalameta/issues/1636
175+
if (implicitCbf.syntax == param.syntax) {
176+
trailingBrackets(to, ctx).map { case (open, close) =>
177+
ctx.replaceTree(cc2, implicitCbf.syntax) +
178+
ctx.replaceToken(open, "(") +
179+
ctx.replaceToken(close, ")")
180+
}.asPatch
181+
} else Patch.empty
182+
183+
}.asPatch
184+
185+
// implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] =>
186+
// implicit cbf: collection.Factory[Int, CC[Int]]
187+
val parameterType =
188+
ctx.replaceTree(
189+
tpe,
190+
Type.Apply(Type.Name("collection.Factory"), List(t, cct)).syntax
191+
)
192+
193+
(parameterType + cbfCalls + toCalls, handledTo.result())
194+
}
195+
}

0 commit comments

Comments
 (0)