Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
olafurpg committed Dec 13, 2016
1 parent 40caaa3 commit 13935bf
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 1 deletion.
2 changes: 1 addition & 1 deletion core/src/main/scala/scalafix/rewrite/Rewrite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object Rewrite {
}

val syntaxRewrites: Seq[Rewrite] = Seq(ProcedureSyntax, VolatileLazyVal)
val semanticRewrites: Seq[Rewrite] = Seq(ExplicitImplicit)
val semanticRewrites: Seq[Rewrite] = Seq(ExplicitImplicit, Xor2Either)
val allRewrites: Seq[Rewrite] = syntaxRewrites ++ semanticRewrites
val name2rewrite: Map[String, Rewrite] =
allRewrites.map(x => x.toString -> x).toMap
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/scala/scalafix/rewrite/SemanticApi.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package scalafix.rewrite

import scala.meta.Defn
import scala.meta.Tree
import scala.meta.Type
import scala.meta.parsers.Parse

/** A custom semantic api for scalafix rewrites.
*
Expand All @@ -18,4 +20,6 @@ trait SemanticApi {

/** Returns the type annotation for given val/def. */
def typeSignature(defn: Defn): Option[Type]

def desugared[A <: Tree](tree: A)(implicit parse: Parse[A]): Option[A]
}
24 changes: 24 additions & 0 deletions core/src/main/scala/scalafix/rewrite/Xor2Either.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package scalafix.rewrite

import scala.{meta => m}
import scalafix.util.Patch
import scalafix.util.Whitespace
import scalafix.util.logger

case object Xor2Either extends Rewrite {
override def rewrite(ast: m.Tree, ctx: RewriteCtx): Seq[Patch] = {
import scala.meta._
val semantic = getSemanticApi(ctx)
ast.collect {
case t: m.Type.Ref
if semantic
.desugared(t: m.Type)(m.parsers.Parse.parseType)
.exists(_.syntax.contains("Xor")) =>
logger.elem(t.syntax, semantic.desugared(t: Type))
val tok = t.tokens.head
Seq(
Patch(tok, tok, tok.syntax + "BANANA")
)
}.flatten
}
}
10 changes: 10 additions & 0 deletions core/src/test/resources/Xor/basic.source
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
rewrites = [Xor2Either]
<<< ONLY xor 1
import cats.data.Xor
trait A {
val r: Xor[Int, String]
}
>>>
trait A {
val r: Either[Int, String]
}
32 changes: 32 additions & 0 deletions scalafix-nsc/src/main/scala/scalafix/nsc/NscSemanticApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package scalafix.nsc

import scala.collection.mutable
import scala.meta.Dialect
import scala.meta.Tree
import scala.meta.Type
import scala.meta.parsers.Parse
import scala.reflect.internal.util.SourceFile
import scala.{meta => m}
import scalafix.Fixed
Expand Down Expand Up @@ -97,6 +99,18 @@ trait NscSemanticApi extends ReflectToolkit {
builder
}

private def collect[T](gtree: g.Tree)(
pf: PartialFunction[g.Tree, T]): Seq[T] = {
val builder = Seq.newBuilder[T]
val f = pf.lift
def iter(gtree: g.Tree): Unit = {
f(gtree).foreach(builder += _)
gtree.children.foreach(iter)
}
iter(gtree)
builder.result()
}

private def getSemanticApi(unit: g.CompilationUnit,
config: ScalafixConfig): SemanticApi = {
val offsets = offsetToType(unit.body, config.dialect)
Expand All @@ -111,6 +125,24 @@ trait NscSemanticApi extends ReflectToolkit {
None
}
}

override def desugared[T <: Tree](tree: T)(
implicit parse: Parse[T]): Option[T] = {
logger.elem(tree, unit.body)
val result = collect[Option[T]](unit.body) {
case t
if t.pos.isDefined &&
t.pos.start == tree.pos.start.offset =>
import scala.meta._
parse(m.Input.String(t.toString()), config.dialect) match {
case Parsed.Success(x) => Some(x)
case _ => None
}
case t if { logger.elem(t.toString(), g.showRaw(t)); false } => None
}.flatten
logger.elem(result)
result.headOption
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions scalafix-nsc/src/test/scala/cats/data/Xor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cats.data

sealed abstract class Xor[+A, +B] extends Product with Serializable

object Xor {
final case class Left[+A](a: A) extends (A Xor Nothing)
final case class Right[+B](b: B) extends (Nothing Xor B)
}

0 comments on commit 13935bf

Please sign in to comment.