public
Created

  • Download Gist
gistfile1.scala
Scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
import tools.nsc.plugins.{Plugin, PluginComponent}
import tools.nsc.Global
import tools.nsc.transform.{TypingTransformers, InfoTransform, Transform}
import tools.nsc.symtab.Flags
 
 
class MyPlugin(val global: Global) extends Plugin {
val name = "annotations-inject-implicit"
val description = "generates code which adds an implicit parameter of type BindingModule when an AutoInjectable trait is mixed in"
val components = List[PluginComponent](AnnotationsInjectComponent)
 
private object AnnotationsInjectComponent extends PluginComponent with Transform with TypingTransformers {
val global: MyPlugin.this.global.type = MyPlugin.this.global
import global._
 
val runsAfter = List[String]("parser")
override val runsBefore = List[String]("namer")
val phaseName = MyPlugin.this.name
 
def newTransformer(unit: CompilationUnit) = new AnnotationsInjectTransformer (unit)
 
val autoInjectable = "Serializable"
val bindingModule = "bindingModule"
val constructorMethod = "<init>"
 
val bindingModuleType = Select(Select(Ident(newTermName("_root_")),newTermName("app")),newTermName("Module"))
 
class AnnotationsInjectTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
def preTransform(tree: Tree): Tree = {
 
import Flags._
 
tree match {
case cd @ ClassDef(modifiers, name, tparams, classBody)
if !classBody.parents.map(_.toString).contains(autoInjectable) => {
 
log("AutoInjecting class %s".format(name))
val newParents = classBody.parents
 
val body = classBody.body.map {
 
case item @ DefDef(modifiers, termname, tparams, vparamss, tpt, rhs)
if termname.toString != constructorMethod =>
 
val newMods = Modifiers(IMPLICIT | PARAM | PARAMACCESSOR)
val newImplicit = new ValDef(newMods, bindingModule, bindingModuleType, EmptyTree)
val newParams = vparamss ::: List(List(newImplicit))
val newTree = treeCopy.DefDef(item, modifiers, termname, tparams, newParams, tpt, rhs)
newTree
 
case t => t
}
 
val newImpVal = ValDef(Modifiers(IMPLICIT | PARAMACCESSOR), bindingModule, bindingModuleType, EmptyTree)
 
treeCopy.ClassDef(cd, modifiers, name, tparams, Template(newParents, classBody.self, newImpVal :: body))
 
}
case t => t
}
}
 
override def transform (tree:Tree):Tree = {
val t = preTransform(tree)
super.transform(t)
}
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.