Skip to content

Commit cde493f

Browse files
committed
add KindProjector
1 parent dc34675 commit cde493f

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

build.sbt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ val commonSettings = Def.settings(
1717
},
1818
scalacOptions ++= Seq(
1919
"-deprecation",
20+
"-language:higherKinds",
21+
"-feature",
2022
),
2123
pomExtra := (
2224
<developers>
@@ -102,6 +104,13 @@ lazy val rules = projectMatrix
102104

103105
lazy val inputOutputCommon = Def.settings(
104106
libraryDependencies += "org.scala-lang.modules" %% "scala-collection-compat" % "2.6.0",
107+
libraryDependencies ++= {
108+
if (scalaBinaryVersion.value != "3") {
109+
Seq(compilerPlugin("org.typelevel" %% "kind-projector" % "0.13.2" cross CrossVersion.full))
110+
} else {
111+
Nil
112+
}
113+
},
105114
libraryDependencies ++= {
106115
if (scalaBinaryVersion.value == "2.13") {
107116
Seq("io.circe" %% "circe-generic-extras" % "0.14.1")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
rule = KindProjector
3+
*/
4+
package fix
5+
6+
import cats.data.Validated
7+
8+
trait KindProjectorTest {
9+
def f1: Functor[String Either *]
10+
def f2: Functor[Int Validated *]
11+
}
12+
13+
trait Functor[F[_]]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package fix
2+
3+
import cats.data.Validated
4+
5+
trait KindProjectorTest {
6+
def f1: Functor[Either[String, *]]
7+
def f2: Functor[Validated[Int, *]]
8+
}
9+
10+
trait Functor[F[_]]
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package fix
2+
3+
import metaconfig.ConfDecoder
4+
import metaconfig.Configured
5+
import metaconfig.generic.Surface
6+
import scalafix.Patch
7+
import scalafix.v1.Configuration
8+
import scalafix.v1.Rule
9+
import scalafix.v1.SyntacticDocument
10+
import scalafix.v1.SyntacticRule
11+
import scala.meta.Type
12+
13+
case class KindProjectorConfig(
14+
rewriteInfixTypes: Set[String]
15+
)
16+
17+
object KindProjectorConfig {
18+
val default: KindProjectorConfig = KindProjectorConfig(
19+
rewriteInfixTypes = Set.empty
20+
)
21+
22+
implicit val surface: Surface[KindProjectorConfig] =
23+
metaconfig.generic.deriveSurface[KindProjectorConfig]
24+
25+
implicit val decoder: ConfDecoder[KindProjectorConfig] =
26+
metaconfig.generic.deriveDecoder(default)
27+
}
28+
29+
/**
30+
* [[https://github.com/lampepfl/dotty-feature-requests/issues/117]]
31+
*/
32+
class KindProjector(config: KindProjectorConfig) extends SyntacticRule("KindProjector") {
33+
def this() = this(KindProjectorConfig.default)
34+
35+
override def withConfiguration(config: Configuration): Configured[Rule] = {
36+
config.conf.getOrElse("KindProjector")(this.config).map(newConfig => new KindProjector(newConfig))
37+
}
38+
39+
private[this] object InfixOpExtractor {
40+
def unapply(name: Type.Name): Option[String] = {
41+
if (config.rewriteInfixTypes.isEmpty) {
42+
// rewrite all if config isEmpty
43+
Some(name.value)
44+
} else if (config.rewriteInfixTypes(name.value)) {
45+
Some(name.value)
46+
} else {
47+
None
48+
}
49+
}
50+
}
51+
52+
override def fix(implicit doc: SyntacticDocument): Patch = {
53+
doc.tree.collect { case t @ Type.ApplyInfix(left, InfixOpExtractor(opName), Type.Name("*")) =>
54+
Patch.replaceTree(t, s"${opName}[${left}, *]")
55+
}.asPatch
56+
}
57+
}

0 commit comments

Comments
 (0)