Skip to content

Commit 190b7b3

Browse files
Rewrite for strict filterKeys (fix #85)
1 parent d18fe86 commit 190b7b3

File tree

10 files changed

+189
-79
lines changed

10 files changed

+189
-79
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
rule = "scala:fix.Roughly"
3+
Roughly = {
4+
strictMapValues = true
5+
strictFilterKeys = true
6+
}
7+
*/
8+
package fix
9+
10+
import scala.{collection => c}
11+
import scala.collection.{immutable => i, mutable => m}
12+
13+
object Roughly212Src {
14+
15+
def id[T](x: T): T = x
16+
def f[T](x: T): Boolean = true
17+
def f2[T](x: T): Int = 1
18+
val props = new scala.sys.SystemProperties()
19+
val d = 1 -> 1
20+
val d2 = 1L -> 1
21+
val multi = new m.HashMap[Int, m.Set[Int]] with m.MultiMap[Int, Int]
22+
23+
// i.SortedMap(d).mapValues(id): i.SortedMap[Int, Int]
24+
// m.SortedMap(d).mapValues(id): c.SortedMap[Int, Int]
25+
i.IntMap(d).mapValues(f2) : i.Map[Int, Int]
26+
i.LongMap(d2).mapValues(f2) : i.Map[Long, Int]
27+
i.Map(d).mapValues(id) : i.Map[Int, Int]
28+
m.LongMap(d2).mapValues(f2) : c.Map[Long, Int]
29+
m.Map(d).mapValues(id) : c.Map[Int, Int]
30+
m.OpenHashMap(d).mapValues(id) : c.Map[Int, Int]
31+
multi.mapValues(f2) : c.Map[Int, Int]
32+
props.mapValues(id) : c.Map[String, String]
33+
34+
// i.SortedMap(d).filterKeys(f): i.SortedMap[Int, Int]
35+
// m.SortedMap(d).filterKeys(f): c.SortedMap[Int, Int]
36+
i.IntMap(d).filterKeys(f) : i.Map[Int, Int]
37+
i.LongMap(d2).filterKeys(f) : i.Map[Long, Int]
38+
i.Map(d).filterKeys(f) : i.Map[Int, Int]
39+
m.LongMap(d2).filterKeys(f) : c.Map[Long, Int]
40+
m.Map(d).filterKeys(f) : c.Map[Int, Int]
41+
m.Map(d).filterKeys(f) : c.Map[Int, Int]
42+
multi.filterKeys(f) : c.Map[Int, m.Set[Int]]
43+
props.filterKeys(f) : c.Map[String, String]
44+
45+
}

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,41 @@
1+
2+
3+
4+
package fix
5+
6+
import scala.{collection => c}
7+
import scala.collection.{immutable => i, mutable => m}
8+
9+
object Roughly212Src {
10+
11+
def id[T](x: T): T = x
12+
def f[T](x: T): Boolean = true
13+
def f2[T](x: T): Int = 1
14+
val props = new scala.sys.SystemProperties()
15+
val d = 1 -> 1
16+
val d2 = 1L -> 1
17+
val multi = new m.HashMap[Int, m.Set[Int]] with m.MultiMap[Int, Int]
18+
19+
// i.SortedMap(d).mapValues(id): i.SortedMap[Int, Int]
20+
// m.SortedMap(d).mapValues(id): c.SortedMap[Int, Int]
21+
i.IntMap(d).mapValues(f2).toMap : i.Map[Int, Int]
22+
i.LongMap(d2).mapValues(f2).toMap : i.Map[Long, Int]
23+
i.Map(d).mapValues(id).toMap : i.Map[Int, Int]
24+
m.LongMap(d2).mapValues(f2).toMap : c.Map[Long, Int]
25+
m.Map(d).mapValues(id).toMap : c.Map[Int, Int]
26+
m.OpenHashMap(d).mapValues(id).toMap : c.Map[Int, Int]
27+
multi.mapValues(f2).toMap : c.Map[Int, Int]
28+
props.mapValues(id).toMap : c.Map[String, String]
29+
30+
// i.SortedMap(d).filterKeys(f): i.SortedMap[Int, Int]
31+
// m.SortedMap(d).filterKeys(f): c.SortedMap[Int, Int]
32+
i.IntMap(d).filterKeys(f).toMap : i.Map[Int, Int]
33+
i.LongMap(d2).filterKeys(f).toMap : i.Map[Long, Int]
34+
i.Map(d).filterKeys(f).toMap : i.Map[Int, Int]
35+
m.LongMap(d2).filterKeys(f).toMap : c.Map[Long, Int]
36+
m.Map(d).filterKeys(f).toMap : c.Map[Int, Int]
37+
m.Map(d).filterKeys(f).toMap : c.Map[Int, Int]
38+
multi.filterKeys(f).toMap : c.Map[Int, m.Set[Int]]
39+
props.filterKeys(f).toMap : c.Map[String, String]
40+
41+
}

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,95 @@
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+
Symbol("_root_.scala.collection.MapLike#filterKeys(Lscala/Function1;)Lscala/collection/Map;.")
30+
)
31+
32+
val filterKeys =
33+
SymbolMatcher.exact(
34+
Symbol("_root_.scala.collection.immutable.MapLike#filterKeys(Lscala/Function1;)Lscala/collection/immutable/Map;."),
35+
Symbol("_root_.scala.collection.MapLike#mapValues(Lscala/Function1;)Lscala/collection/Map;.")
36+
)
37+
38+
// Not supported: SortedMap
39+
// Symbol("_root_.scala.collection.immutable.SortedMap#mapValues(Lscala/Function1;)Lscala/collection/immutable/SortedMap;."),
40+
// Symbol("_root_.scala.collection.SortedMapLike#mapValues(Lscala/Function1;)Lscala/collection/SortedMap;.")
41+
// Symbol("_root_.scala.collection.immutable.SortedMap#filterKeys(Lscala/Function1;)Lscala/collection/immutable/SortedMap;.")
42+
// Symbol("_root_.scala.collection.SortedMapLike#filterKeys(Lscala/Function1;)Lscala/collection/SortedMap;.")
43+
44+
val streamAppend = SymbolMatcher.normalized(
45+
Symbol("_root_.scala.collection.immutable.Stream.append.")
46+
)
47+
48+
def replaceSymbols(ctx: RuleCtx): Patch = {
49+
if (config.withLazyList) {
50+
ctx.replaceSymbols(
51+
"scala.Stream" -> "scala.LazyList",
52+
"scala.collection.immutable.Stream" -> "scala.collection.immutable.LazyList"
53+
)
54+
} else Patch.empty
55+
}
56+
57+
override def description: String = ""
58+
59+
override def init(config: Conf): Configured[Rule] =
60+
config
61+
.getOrElse("roughly", "Roughly")(RoughlyConfig.default)
62+
.map(Roughly(index, _))
63+
64+
override def fix(ctx: RuleCtx): Patch = {
65+
import config._
66+
67+
val collectFixes =
68+
ctx.tree.collect {
69+
case ap @ Term.Apply(Term.Select(_, mapValues(_)), List(_)) if strictMapValues =>
70+
ctx.addRight(ap, ".toMap")
71+
72+
case ap @ Term.Apply(Term.Select(_, filterKeys(_)), List(_)) if strictFilterKeys =>
73+
ctx.addRight(ap, ".toMap")
74+
75+
case streamAppend(t: Name) if withLazyAppendedAll =>
76+
ctx.replaceTree(t, "lazyAppendedAll")
77+
78+
}.asPatch
79+
80+
collectFixes + replaceSymbols(ctx)
81+
}
82+
}
83+
84+
case class RoughlyConfig(
85+
strictMapValues: Boolean = false,
86+
strictFilterKeys: Boolean = false,
87+
withLazyAppendedAll: Boolean = false,
88+
withLazyList: Boolean = false
89+
)
90+
91+
object RoughlyConfig {
92+
val default: RoughlyConfig = RoughlyConfig()
93+
implicit val surface: Surface[RoughlyConfig] = generic.deriveSurface[RoughlyConfig]
94+
implicit val decoder: ConfDecoder[RoughlyConfig] = generic.deriveDecoder[RoughlyConfig](default)
95+
}

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)