diff options
Diffstat (limited to 'docs')
8 files changed, 122 insertions, 43 deletions
diff --git a/docs/examples/plugintemplate/doc/README b/docs/examples/plugintemplate/doc/README index f3b9e15e97..958f71282b 100644 --- a/docs/examples/plugintemplate/doc/README +++ b/docs/examples/plugintemplate/doc/README @@ -34,6 +34,32 @@ in the Java Build Path: Right-Click the project and select "Properties". Then go to "Java Build Path" -> "Libraries" and add the jar file "eclipse/plugins/ch.epfl.lamp.sdt.core[..]/lib/scala-compiler.jar". +Traverse, Transform, Check +-------------------------- +There are several pre-defined components that can be used to code +the behavior of a plugin: +- TemplateTraverseComponent: a template for tree traversers. Used + to analyze and collect data about compiler trees. + -> implement the "check" method + +- TemplateTransformComponent: a template for tree transformers. + -> implement "preTransform" and / or "postTransform" + +- TemplateInfoTransformComponent: also a tree transformer, which + additionally is an InfoTransformer. Allows changing the type + of some symbols for later phases. + -> implement "preTransform" and / or "postTransform", and the + "apply" method of the "infoTransformer". + +- TemplateAnnotationChecker: a plugin for the typechecker, useful + for pluggable type systems. Computes the subtyping between two + annotated types, and allows providing inferred type information. + -> implement "annotationsConform" and optionally "addAnnotations" + +- TemplateComponent: the most general component. Can do anything it + likes with the CompilationUnits. + -> implement the "run" method + Ant tasks --------- "build.xml" defines Ant tasks for building, testing and packing a diff --git a/docs/examples/plugintemplate/src/plugintemplate/TemplateAnnotationChecker.scala b/docs/examples/plugintemplate/src/plugintemplate/TemplateAnnotationChecker.scala new file mode 100644 index 0000000000..6cd3472675 --- /dev/null +++ b/docs/examples/plugintemplate/src/plugintemplate/TemplateAnnotationChecker.scala @@ -0,0 +1,20 @@ +package plugintemplate + +import scala.tools.nsc.Global + +abstract class TemplateAnnotationChecker { + val global: Global + import global._ + + object checker extends AnnotationChecker { + def annotationsConform(tpe1: Type, tpe2: Type): Boolean = { + println("checking: "+ tpe1 +" <: "+ tpe2) + true + } + + override def addAnnotations(tree: Tree, tpe: Type): Type = { + println("adding annot to "+ tree.symbol) + tpe + } + } +} diff --git a/docs/examples/plugintemplate/src/plugintemplate/TemplateInfoTransformComponent.scala b/docs/examples/plugintemplate/src/plugintemplate/TemplateInfoTransformComponent.scala index 7185717e6d..60f56ba30a 100644 --- a/docs/examples/plugintemplate/src/plugintemplate/TemplateInfoTransformComponent.scala +++ b/docs/examples/plugintemplate/src/plugintemplate/TemplateInfoTransformComponent.scala @@ -28,17 +28,23 @@ class TemplateInfoTransformComponent(val global: Global) extends PluginComponent */ val phaseName = "plugintemplateinfotransform" - def transformInfo(sym: Symbol, tp: Type): Type = infoTransformer(tp) + def transformInfo(sym: Symbol, tp: Type): Type = infoTransformer.mapOver(tp) def newTransformer(unit: CompilationUnit) = new TemplateTransformer - /** The type transformation applied by this component + /** The type transformation applied by this component. The trait InfoTransform + * will create an instance of InfoTransformer applying this TypeMap. The type + * map will be applied when computing a symbol's type in all phases + * <em>after</em> "plugintemplateinfotransform". * * @todo Implement. */ private val infoTransformer = new TypeMap { def apply(tp: Type): Type = tp match { - case _ => tp + case MethodType(pts, rt) => + println("methodType (_, _, ..) => "+ rt) + tp + case _ => mapOver(tp) } } @@ -53,6 +59,9 @@ class TemplateInfoTransformComponent(val global: Global) extends PluginComponent * visited before its children. */ def preTransform(tree: Tree): Tree = tree match { + case ValDef(_, name, _, _) => + println("pre-info-transforming valdef "+ name) + tree case _ => tree } diff --git a/docs/examples/plugintemplate/src/plugintemplate/TemplatePlugin.scala b/docs/examples/plugintemplate/src/plugintemplate/TemplatePlugin.scala index 5c4780d247..658b38e58e 100644 --- a/docs/examples/plugintemplate/src/plugintemplate/TemplatePlugin.scala +++ b/docs/examples/plugintemplate/src/plugintemplate/TemplatePlugin.scala @@ -12,33 +12,31 @@ class TemplatePlugin(val global: Global) extends Plugin { /** The name of this plugin. Extracted from the properties file. */ val name = PluginProperties.pluginName + val runsAfter = "refchecks" + /** A short description of the plugin, read from the properties file */ val description = PluginProperties.pluginDescription + /** @todo A description of the plugin's options */ + override val optionsHelp = Some( + " -P:"+ name +":option sets some option for this plugin") + + /** @todo Implement parsing of plugin options */ + override def processOptions(options: List[String], error: String => Unit) { + super.processOptions(options, error) + } + /** The compiler components that will be applied when running * this plugin * * @todo Adapt to the plugin being implemented */ val components = TemplatePlugin.components(global) - val runsAfter = "refchecks" - /* TODO: include annotationChecker - import global._ - - println("adding annotationchecker...") - addAnnotationChecker(new AnnotationChecker { - def annotationsConform(tpe1: Type, tpe2: Type): Boolean = { - println("checking: "+ tpe1 +" <: "+ tpe2) - true - } - - override def addAnnotations(tree: Tree, tpe: Type): Type = { - //println("adding annot to "+ tree.symbol) - tpe - } - }) - */ + val checker = new TemplateAnnotationChecker { + val global: TemplatePlugin.this.global.type = TemplatePlugin.this.global + } + global.addAnnotationChecker(checker.checker) } object TemplatePlugin { @@ -48,6 +46,7 @@ object TemplatePlugin { */ def components(global: Global) = List(new TemplateComponent(global), + new TemplateTraverseComponent(global), new TemplateTransformComponent(global), new TemplateInfoTransformComponent(global)) } diff --git a/docs/examples/plugintemplate/src/plugintemplate/TemplateTransformComponent.scala b/docs/examples/plugintemplate/src/plugintemplate/TemplateTransformComponent.scala index 4156f262ee..06afedad97 100644 --- a/docs/examples/plugintemplate/src/plugintemplate/TemplateTransformComponent.scala +++ b/docs/examples/plugintemplate/src/plugintemplate/TemplateTransformComponent.scala @@ -45,6 +45,9 @@ class TemplateTransformComponent(val global: Global) extends PluginComponent * visited after its children. */ def postTransform(tree: Tree): Tree = tree match { + case New(tpt) => + println("post-transforming new "+ tpt) + tree case _ => tree } diff --git a/docs/examples/plugintemplate/src/plugintemplate/TemplateTraverseComponent.scala b/docs/examples/plugintemplate/src/plugintemplate/TemplateTraverseComponent.scala new file mode 100644 index 0000000000..e87d4d18b0 --- /dev/null +++ b/docs/examples/plugintemplate/src/plugintemplate/TemplateTraverseComponent.scala @@ -0,0 +1,32 @@ +package plugintemplate + +import scala.tools.nsc._ +import scala.tools.nsc.plugins.PluginComponent + +/** This class implements a plugin component using a tree + * traverser */ +class TemplateTraverseComponent (val global: Global) extends PluginComponent { + import global._ + import global.definitions._ + + val runsAfter = "refchecks" + /** The phase name of the compiler plugin + * @todo Adapt to specific plugin. + */ + val phaseName = "plugintemplatetraverse" + + def newPhase(prev: Phase): Phase = new TraverserPhase(prev) + class TraverserPhase(prev: Phase) extends StdPhase(prev) { + def apply(unit: CompilationUnit) { + newTraverser().traverse(unit.body) + } + } + + def newTraverser(): Traverser = new ForeachTreeTraverser(check) + + def check(tree: Tree): Unit = tree match { + case Apply(fun, args) => + println("traversing application of "+ fun) + case _ => () + } +} diff --git a/docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala b/docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala index 6eec249ed7..042409c000 100644 --- a/docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala +++ b/docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala @@ -4,6 +4,11 @@ import scala.tools.nsc.CompilerCommand import scala.tools.nsc.Settings /** An object for running the plugin as standalone application. + * + * @todo: print, parse and apply plugin options !!! + * ideally re-use the TemplatePlugin (-> runsAfter, optionsHelp, + * processOptions, components, annotationChecker) instead of + * duplicating it here and in PluginRunner. */ object Main { def main(args: Array[String]) { diff --git a/docs/examples/plugintemplate/src/plugintemplate/standalone/PluginRunner.scala b/docs/examples/plugintemplate/src/plugintemplate/standalone/PluginRunner.scala index a4481829c5..16b6ce2259 100644 --- a/docs/examples/plugintemplate/src/plugintemplate/standalone/PluginRunner.scala +++ b/docs/examples/plugintemplate/src/plugintemplate/standalone/PluginRunner.scala @@ -10,30 +10,15 @@ class PluginRunner(settings: Settings, reporter: Reporter) extends Global(settings, reporter) { def this(settings: Settings) = this(settings, new ConsoleReporter(settings)) - /* TODO: include AnnotationChecker - println("adding annotationchecker...") - addAnnotationChecker(new AnnotationChecker { - def annotationsConform(tpe1: Type, tpe2: Type): Boolean = { - def getAnnTpe(t: Type) = t match { - case AnnotatedType(attrs, underlying, selfsym) => - attrs match { - case x :: xs => Some(x.atp) - case _ => None - } - case _ => None - } - val ta1 = getAnnTpe(tpe1) - val ta2 = getAnnTpe(tpe2) - ta1 == ta2 - } - - override def addAnnotations(tree: Tree, tpe: Type): Type = { - //println("adding annot to "+ tree.symbol) - tpe - } - }) - */ + val annotChecker = new TemplateAnnotationChecker { + val global: PluginRunner.this.type = PluginRunner.this + } + addAnnotationChecker(annotChecker.checker) + /** The phases to be run. + * + * @todo: Adapt to specific plugin implementation + */ override def phaseDescriptors: List[SubComponent] = List( analyzer.namerFactory, analyzer.typerFactory, |