Skip to content

Commit 5445d64

Browse files
authored
Merge pull request #111 from MasseGuillaume/future-deprecated
Rewrite Future.{onFailure, onSuccess} => onComplete (fix #94)
2 parents c2bbd2d + 089dbdb commit 5445d64

File tree

5 files changed

+103
-7
lines changed

5 files changed

+103
-7
lines changed

build.sbt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,19 @@ lazy val scalafixRules = project
7777

7878
// == Scalafix Test Setup ==
7979

80+
lazy val sharedScalafixSettings = Seq(
81+
scalacOptions ++= Seq(
82+
"-deprecation",
83+
"-encoding",
84+
"UTF-8",
85+
"-feature",
86+
"-unchecked"
87+
)
88+
)
89+
8090
lazy val scalafixInput = project
8191
.in(file("scalafix/input"))
92+
.settings(sharedScalafixSettings)
8293
.settings(dontPublish)
8394
.settings(
8495
scalaVersion := scalafixScala212,
@@ -88,22 +99,26 @@ lazy val scalafixInput = project
8899

89100
lazy val scalafixOutput212 = project
90101
.in(file("scalafix/output212"))
102+
.settings(sharedScalafixSettings)
91103
.settings(scalaVersion := scalafixScala212)
92104
.settings(dontPublish)
93105
.dependsOn(compatJVM)
94106

95107
lazy val scalafixOutput213 = project
96108
.in(file("scalafix/output213"))
109+
.settings(sharedScalafixSettings)
97110
.settings(scala213Settings)
98111
.settings(dontPublish)
99112

100113
lazy val scalafixOutput213Failure = project
101114
.in(file("scalafix/output213-failure"))
115+
.settings(sharedScalafixSettings)
102116
.settings(scala213Settings)
103117
.settings(dontPublish)
104118

105119
lazy val scalafixTests = project
106120
.in(file("scalafix/tests"))
121+
.settings(sharedScalafixSettings)
107122
.settings(dontPublish)
108123
.settings(
109124
scalaVersion := scalafixScala212,
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
rule = "scala:fix.CrossCompat"
3+
*/
4+
package fix
5+
6+
import scala.concurrent.{Future, ExecutionContext}
7+
import java.lang.Throwable
8+
9+
class FutureSrc(fs: Future[Int])(implicit ec: ExecutionContext){
10+
class E1 extends Throwable
11+
case class E2(v: Int) extends Throwable
12+
case object E3 extends Throwable
13+
14+
fs.onFailure {
15+
case _: E1 => println("type pattern")
16+
case E2(_) => println("constructor pattern")
17+
case E3 => println("singleton pattern")
18+
}
19+
20+
fs.onSuccess {
21+
case x if x > 0 => println("x > 0")
22+
case x if x < 0 => println("x < 0")
23+
}(ec)
24+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
3+
4+
package fix
5+
6+
import scala.concurrent.{Future, ExecutionContext}
7+
import java.lang.Throwable
8+
9+
class FutureSrc(fs: Future[Int])(implicit ec: ExecutionContext){
10+
class E1 extends Throwable
11+
case class E2(v: Int) extends Throwable
12+
case object E3 extends Throwable
13+
14+
fs.onComplete {
15+
case scala.util.Failure(_: E1) => println("type pattern")
16+
case scala.util.Failure(E2(_)) => println("constructor pattern")
17+
case scala.util.Failure(E3) => println("singleton pattern")
18+
case _ => ()
19+
}
20+
21+
fs.onComplete {
22+
case scala.util.Success(x) if x > 0 => println("x > 0")
23+
case scala.util.Success(x) if x < 0 => println("x < 0")
24+
case _ => ()
25+
}(ec)
26+
}

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

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import scala.meta._
66

77
import scala.collection.mutable
88

9+
import System.{lineSeparator => nl}
10+
911
trait CrossCompatibility {
1012
def isCrossCompatible: Boolean
1113
}
@@ -26,6 +28,9 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
2628
normalized(s"_root_.scala.collection.TraversableOnce.`$op`.")
2729
}
2830

31+
val foldLeftSymbol = foldSymbol(isLeft = true)
32+
val foldRightSymbol = foldSymbol(isLeft = false)
33+
2934
val iterator = normalized("_root_.scala.collection.TraversableLike.toIterator.")
3035
val toTpe = normalized("_root_.scala.collection.TraversableLike.to.")
3136
val copyToBuffer = normalized("_root_.scala.collection.TraversableOnce.copyToBuffer.")
@@ -39,8 +44,8 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
3944
val mutSetPlus = exact("_root_.scala.collection.mutable.SetLike#`+`(Ljava/lang/Object;)Lscala/collection/mutable/Set;.")
4045
val mutMapPlus = exact("_root_.scala.collection.mutable.MapLike#`+`(Lscala/Tuple2;)Lscala/collection/mutable/Map;.")
4146
val mutMapUpdate = exact("_root_.scala.collection.mutable.MapLike#updated(Ljava/lang/Object;Ljava/lang/Object;)Lscala/collection/mutable/Map;.")
42-
val foldLeftSymbol = foldSymbol(isLeft = true)
43-
val foldRightSymbol = foldSymbol(isLeft = false)
47+
val `Future.onFailure` = exact("_root_.scala.concurrent.Future#onFailure(Lscala/PartialFunction;Lscala/concurrent/ExecutionContext;)V.")
48+
val `Future.onSuccess` = exact("_root_.scala.concurrent.Future#onSuccess(Lscala/PartialFunction;Lscala/concurrent/ExecutionContext;)V.")
4449

4550
val traversable = exact(
4651
"_root_.scala.package.Traversable#",
@@ -262,6 +267,29 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
262267
compatImport + replaceToIterator + replaceTo
263268
}
264269

270+
def replaceFuture(ctx: RuleCtx): Patch = {
271+
272+
def toOnCompletePF(f: Tree, cases: List[Tree], tryApply: String): Patch = {
273+
val indent = " " * cases.head.pos.startColumn
274+
275+
ctx.replaceTree(f, "onComplete") +
276+
cases.map{ case Case(c, _, _) =>
277+
ctx.addLeft(c, tryApply +"(") +
278+
ctx.addRight(c, ")")
279+
}.asPatch +
280+
ctx.addRight(cases.last, nl + indent + "case _ => ()" )
281+
}
282+
283+
ctx.tree.collect {
284+
case Term.Apply(Term.Select(_, f @ `Future.onFailure`(_)), List(Term.PartialFunction(cases))) =>
285+
toOnCompletePF(f, cases, "scala.util.Failure")
286+
287+
case Term.Apply(Term.Select(_, f @ `Future.onSuccess`(_)), List(Term.PartialFunction(cases))) =>
288+
toOnCompletePF(f, cases, "scala.util.Success")
289+
290+
}.asPatch
291+
}
292+
265293
private val compatImportAdded = mutable.Set[Input]()
266294

267295
def addCompatImport(ctx: RuleCtx): Patch = {
@@ -284,7 +312,7 @@ trait Stable212Base extends CrossCompatibility { self: SemanticRule =>
284312
replaceMutMapUpdated(ctx) +
285313
replaceArrayBuilderMake(ctx) +
286314
replaceIterableSameElements(ctx) +
287-
replaceBreakout(ctx)
315+
replaceBreakout(ctx) +
316+
replaceFuture(ctx)
288317
}
289-
290318
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ package object fix {
1616
close <- ctx.matchingParens.close(open)
1717
} yield (open, close)
1818

19-
def startsWithParens(tree: Tree): Boolean =
20-
tree.tokens.headOption.map(_.is[Token.LeftParen]).getOrElse(false)
21-
2219
def trailingParens(tree: Tree, ctx: RuleCtx): Option[(Token.LeftParen, Token.RightParen)] =
2320
for {
2421
end <- tree.tokens.lastOption
2522
open <- ctx.tokenList.find(end)(_.is[Token.LeftParen]).map(_.asInstanceOf[Token.LeftParen])
2623
close <- ctx.matchingParens.close(open)
2724
} yield (open, close)
25+
26+
def trailingApply(tree: Tree, ctx: RuleCtx): Option[(Token, Token)] =
27+
trailingParens(tree, ctx).orElse(trailingBrackets(tree, ctx))
28+
29+
def startsWithParens(tree: Tree): Boolean =
30+
tree.tokens.headOption.map(_.is[Token.LeftParen]).getOrElse(false)
2831
}

0 commit comments

Comments
 (0)