Skip to content

Commit 2bbfd40

Browse files
Rewrite for strict reverseMap and filterKeys (fix scala#85)
1 parent d18fe86 commit 2bbfd40

File tree

10 files changed

+131
-79
lines changed

10 files changed

+131
-79
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
rule = "scala:fix.Roughly"
3+
Roughly.strictMapValues = true
4+
Roughly.strictFilterKeys = true
5+
Roughly.strictReverseMap = true
6+
*/
7+
package fix
8+
9+
class Roughly212Src(map: Map[Int, Int], seq: Seq[Int]) {
10+
map.mapValues(_ + 1): Map[Int, Int]
11+
map.filterKeys(_ > 1): Map[Int, Int]
12+
seq.reverseMap(_ + 1): Seq[Int]
13+
}

scalafix/input/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala renamed to scalafix/input/src/main/scala/fix/Roughly213Src.scala

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
/*
2-
rule = "scala:fix.RoughlyStreamToLazyList"
2+
rule = "scala:fix.Roughly"
3+
Roughly = {
4+
withLazyAppendedAll = true
5+
withLazyList = true
6+
}
37
*/
48
package fix
59

6-
class RoughlyStreamToLazyListSrc() {
10+
class Roughly213Src() {
711
val s = Stream(1, 2, 3)
812
s.append(List(4, 5, 6))
913
1 #:: 2 #:: 3 #:: Stream.Empty

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

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
3+
4+
package fix
5+
6+
class Roughly212Src(map: Map[Int, Int], seq: Seq[Int]) {
7+
map.mapValues(_ + 1).toMap: Map[Int, Int]
8+
map.filterKeys(_ > 1).toMap: Map[Int, Int]
9+
seq.reverseMap(_ + 1).toSeq: Seq[Int]
10+
}

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

-8
This file was deleted.

scalafix/output213/src/main/scala/fix/RoughlyStreamToLazyListSrc.scala renamed to scalafix/output213/src/main/scala/fix/Roughly213Src.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
package fix
55

6-
class RoughlyStreamToLazyListSrc() {
6+
class Roughly213Src() {
77
val s = LazyList(1, 2, 3)
88
s.lazyAppendedAll(List(4, 5, 6))
99
1 #:: 2 #:: 3 #:: LazyList.Empty
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package fix
2+
3+
import scalafix._
4+
import scalafix.util._
5+
import scala.meta._
6+
7+
import metaconfig.{ConfDecoder, Conf, Configured}
8+
import metaconfig.annotation.Description
9+
import metaconfig.annotation.ExampleValue
10+
import metaconfig.generic
11+
import metaconfig.generic.Surface
12+
13+
/* 2.12 Cross-Compatible
14+
*
15+
* This rules is *roughly* correct, they compile but might have a different runtime semantic
16+
*
17+
* Map.{mapValues, filterKeys}, Seq.reverseMap were lazy but with a strict interface
18+
* (ex returning Map where they should return MapView).
19+
*
20+
* LazyList has a lazy head, were Stream has a strict head
21+
*
22+
*/
23+
final case class Roughly(index: SemanticdbIndex, config: RoughlyConfig) extends SemanticRule(index, "Roughly") {
24+
def this(index: SemanticdbIndex) = this(index, RoughlyConfig.default)
25+
26+
val mapValues =
27+
SymbolMatcher.exact(
28+
Symbol("_root_.scala.collection.immutable.MapLike#mapValues(Lscala/Function1;)Lscala/collection/immutable/Map;.")
29+
)
30+
31+
val reverseMap =
32+
SymbolMatcher.exact(
33+
Symbol("_root_.scala.collection.SeqLike#reverseMap(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;.")
34+
)
35+
36+
val filterKeys =
37+
SymbolMatcher.exact(
38+
Symbol("_root_.scala.collection.immutable.MapLike#filterKeys(Lscala/Function1;)Lscala/collection/immutable/Map;.")
39+
)
40+
41+
val streamAppend = SymbolMatcher.normalized(
42+
Symbol("_root_.scala.collection.immutable.Stream.append.")
43+
)
44+
45+
def replaceSymbols(ctx: RuleCtx): Patch = {
46+
if (config.withLazyList) {
47+
ctx.replaceSymbols(
48+
"scala.Stream" -> "scala.LazyList",
49+
"scala.collection.immutable.Stream" -> "scala.collection.immutable.LazyList"
50+
)
51+
} else Patch.empty
52+
}
53+
54+
override def description: String = ""
55+
56+
override def init(config: Conf): Configured[Rule] =
57+
config
58+
.getOrElse("roughly", "Roughly")(RoughlyConfig.default)
59+
.map(Roughly(index, _))
60+
61+
override def fix(ctx: RuleCtx): Patch = {
62+
import config._
63+
64+
val collectFixes =
65+
ctx.tree.collect {
66+
case ap @ Term.Apply(Term.Select(_, mapValues(_)), List(_)) if strictMapValues =>
67+
ctx.addRight(ap, ".toMap")
68+
69+
case ap @ Term.Apply(Term.Select(_, filterKeys(_)), List(_)) if strictFilterKeys =>
70+
ctx.addRight(ap, ".toMap")
71+
72+
case ap @ Term.Apply(Term.Select(_, reverseMap(_)), List(_)) if strictReverseMap =>
73+
ctx.addRight(ap, ".toSeq")
74+
75+
case streamAppend(t: Name) if withLazyAppendedAll =>
76+
ctx.replaceTree(t, "lazyAppendedAll")
77+
78+
case ap @ Term.Apply(Term.Select(_, op), List(_)) =>
79+
println(ctx.index.symbol(op))
80+
Patch.empty
81+
82+
}.asPatch
83+
84+
collectFixes + replaceSymbols(ctx)
85+
}
86+
}
87+
88+
case class RoughlyConfig(
89+
strictMapValues: Boolean = false,
90+
strictFilterKeys: Boolean = false,
91+
strictReverseMap: Boolean = false,
92+
withLazyAppendedAll: Boolean = false,
93+
withLazyList: Boolean = false
94+
)
95+
96+
object RoughlyConfig {
97+
val default: RoughlyConfig = RoughlyConfig()
98+
implicit val surface: Surface[RoughlyConfig] = generic.deriveSurface[RoughlyConfig]
99+
implicit val decoder: ConfDecoder[RoughlyConfig] = generic.deriveDecoder[RoughlyConfig](default)
100+
}

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

-24
This file was deleted.

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

-35
This file was deleted.

scalafix/tests/src/test/scala/fix/ScalafixTests.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ class ScalafixTests
1717

1818
runAllTests()
1919
// to run only one test:
20-
// testsToRun.filter(_.filename.toNIO.getFileName.toString == "IterableSrc.scala" ).foreach(runOn)
20+
// testsToRun.filter(_.filename.toNIO.getFileName.toString == "Playground.scala" ).foreach(runOn)
2121
}

0 commit comments

Comments
 (0)