- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Non-monolithic compiler plugins
Wed, 2011-10-26, 14:47
My plugin is getting too big to fit comfortably in a single class and a single source file. I'd like to split it up, but I'm struggling.
Here's a simple example to illustrate the problem I'm hitting. The following monolithic (but small :-) plugin compiles just fine:
> class TestComponent(plugin: TestPlugin, val global: Global) extends PluginComponent {
> import global._
>
> val runsAfter = List[String]("typer")
> val phaseName = "testphase"
>
> def newPhase(prev: Phase) = new StdPhase(prev) {
> def apply(unit: CompilationUnit) {
> new ForeachTreeTraverser(findAnnotations).traverse(unit.body)
> }
> }
>
> def findAnnotations(tree: Tree) {
> tree match {
> case ClassDef(_, _, _, _) if tree.hasSymbol => handleAnnotations(tree.symbol)
> case _ =>
> }
> }
>
> def handleAnnotations(sym: Symbol) {
> for (AnnotationInfo(atp, _, _) <- sym.annotations)
> doSomethingWithAnnotation(sym, atp)
> }
>
> def doSomethingWithAnnotation(sym: Symbol, atp: Type) {
> log("found "+ atp.typeSymbol +" annotation on "+ sym.name)
> }
> }
But imagine that I want to split the annotation-handling code out into a separate class. Here's my attempt to do so:
> class AnnotationHandler(global: Global) {
> import global._
>
> def apply(tree: Tree) {
> tree match {
> case ClassDef(_, _, _, _) if tree.hasSymbol => handleAnnotations(tree.symbol)
> case _ =>
> }
> }
>
> def handleAnnotations(sym: Symbol) {
> for (AnnotationInfo(atp, _, _) <- sym.annotations)
> doSomethingWithAnnotation(sym, atp)
> }
>
> def doSomethingWithAnnotation(sym: Symbol, atp: Type) {
> log("found "+ atp.typeSymbol +" annotation on "+ sym.name)
> }
> }
And I modify findAnnotations to look like:
> def findAnnotations(tree: Tree) {
> new AnnotationHandler(global)(tree)
> }
When I compile, I get:
> [error] /Users/paul/scala/foo/src/main/scala/TestPlugin.scala:31: type mismatch;
> [error] found : TestComponent.this.global.Tree
> [error] required: _1.global.Tree where val _1: com.example.AnnotationHandler
> [error] new AnnotationHandler(global)(tree)
> [error] ^
> [error] one error found
I assume because the "global" in AnnotationHandler is distinct from the one in TestComponent?
What is the correct way for me to structure things?
--
paul.butcher->msgCount++
Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?
http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: paul@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
Wed, 2011-10-26, 15:27
#2
Re: Non-monolithic compiler plugins
On Wednesday 26 October 2011 14:47:18 Paul Butcher wrote:
> What is the correct way for me to structure things?
See this SO question:
http://stackoverflow.com/questions/5629127/splitting-scalac-plugin-into-
multiple-files/5632536
Hope this helps,
Mirko
Wed, 2011-10-26, 15:47
#3
Re: Non-monolithic compiler plugins
Mirko, Lukas,
Many thanks - I think that that's given me what I need to find an appropriate solution for my case :-)
On 26 Oct 2011, at 15:18, Mirko Stocker wrote:
> On Wednesday 26 October 2011 14:47:18 Paul Butcher wrote:
>> What is the correct way for me to structure things?
>
> See this SO question:
>
> http://stackoverflow.com/questions/5629127/splitting-scalac-plugin-into-
> multiple-files/5632536
>
> Hope this helps,
>
> Mirko
>
https://github.com/soundrabbit/effects/blob/master/src/main/scala/scala/tools/nsc/effects/EffectChecker.scala https://github.com/soundrabbit/effects/blob/master/src/main/scala/scala/tools/nsc/effects/ExternalEffects.scala
Lukas
On Wed, Oct 26, 2011 at 15:47, Paul Butcher <paul@paulbutcher.com> wrote: