2011-04-12 6 views
6

Me gustaría dividir mi scalac plugin en varios archivos. Esto parece fácil, pero no he logrado llevarlo a cabo debido a problemas de tipo dependientes de la ruta que provienen de la línea import global._.Splitting scalac plugin en varios archivos

Aquí es plugin de muestra de Lex Cuchara:

package localhost 

import scala.tools.nsc 
import nsc.Global 
import nsc.Phase 
import nsc.plugins.Plugin 
import nsc.plugins.PluginComponent 

class DivByZero(val global: Global) extends Plugin { 
    import global._ 

    val name = "divbyzero" 
    val description = "checks for division by zero" 
    val components = List[PluginComponent](Component) 

    private object Component extends PluginComponent { 
    val global: DivByZero.this.global.type = DivByZero.this.global 
    val runsAfter = "refchecks" 
    // Using the Scala Compiler 2.8.x the runsAfter should be written as below 
    // val runsAfter = List[String]("refchecks"); 
    val phaseName = DivByZero.this.name 
    def newPhase(_prev: Phase) = new DivByZeroPhase(_prev)  

    class DivByZeroPhase(prev: Phase) extends StdPhase(prev) { 
     override def name = DivByZero.this.name 
     def apply(unit: CompilationUnit) { 
     for (tree @ Apply(Select(rcvr, nme.DIV), List(Literal(Constant(0)))) <- unit.body; 
      if rcvr.tpe <:< definitions.IntClass.tpe) 
      { 
      unit.error(tree.pos, "definitely division by zero") 
      } 
     } 
    } 
    } 
} 

¿Cómo puedo poner Component y DivByZeroPhase en sus propios archivos sin tener la import global._ en su alcance?

Respuesta

2

Puede crear una clase separada para su componente y pasar global en:

class TemplateComponent(val global: Global) extends PluginComponent { 

    import global._ 

    val runsAfter = List[String]("refchecks") 

    val phaseName = "plugintemplate" 

    def newPhase(prev: Phase) = new StdPhase(prev) { 

    override def name = phaseName 

    def apply(unit:CompilationUnit) = { 
    }  
    } 
} 
3

En la biblioteca Scala Refactoring, lo resolví por tener un CompilerAccess rasgo:

trait CompilerAccess { 
    val global: tools.nsc.Global 
} 

Ahora todo el otros rasgos que necesitan acceder global solo declarar CompilerAccess como una dependencia:

trait TreeTraverser { 
    this: CompilerAccess => 
    import global._ 

    ... 
} 

y luego hay una clase que mezcla en todos estos rasgos y proporciona una instancia del mundial:

trait SomeRefactoring extends TreeTraverser with OtherTrait with MoreTraits { 
    val global = //wherever you get your global from 
} 

Este esquema funcionó bastante bien para mí.