Skip to content

Instantly share code, notes, and snippets.

@martijnhoekstra
Last active May 24, 2018 02:57
Show Gist options
  • Save martijnhoekstra/a804d062740ee2a42973060782991334 to your computer and use it in GitHub Desktop.
Save martijnhoekstra/a804d062740ee2a42973060782991334 to your computer and use it in GitHub Desktop.
a scalafix for viewbounds
package fix
import scalafix._
import scala.meta._
case object Viewbounds_v1_0 extends Rule("Viewbounds_v1_0") {
def eliminateViewBound(defn: Defn.Def): Option[Defn.Def] = {
def makeimplicit(i: Int, from: Name, to: Type): Term.Param = {
val funname = s"viewbound_$i"
val expr = s"implicit viewbound_$i: $from => $to"
expr.parse[Term.Param].get
}
def isImplParameterList(params: List[Term.Param]): Boolean = params.exists {
case Term.Param(mods, _, _, _) => mods.exists(_.is[Mod.Implicit])
}
defn match {
case Defn.Def(x, name, typeparams, parameterlists, ascription, body) => {
val (regular, impl) = parameterlists.span(pl => !isImplParameterList(pl))
val (nobounds, names, bounds) = typeparams.map {
case Type.Param(mods, name, tparams, typebounds, viewbounds, contextbounds) => (Type.Param(mods, name, tparams, typebounds, Nil, contextbounds), name, viewbounds)
}.unzip3
val b = names.zip(bounds).flatMap{
case (name, targets) => targets.map(to => (name, to))
}
val convertedparams = b.zipWithIndex.map{ case ((from, to), i) => makeimplicit(i, from, to)}
if (convertedparams.nonEmpty) {
val totalimplicits = impl.flatten ::: convertedparams
val paramlists = regular :+ totalimplicits
Some(Defn.Def(x, name, nobounds, paramlists, ascription, body))
} else None
}
}
}
override def description: String =
"Rewrite that replaces viewbounds with an implicit conversion parameter"
override def fix(ctx: RuleCtx): Patch = {
ctx.tree.collect {
case defn: Defn.Def => {
val replacement = eliminateViewBound(defn)
replacement.map(repl => ctx.replaceTree(defn, repl.toString)).getOrElse(Patch.empty)
}
}.asPatch
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment