Separation of plugins-plugins into several files

I would like to split my scalac plugin into several files. It sounds simple, but I was not able to remove it due to path-specific issues related to the import global._ line.

Here's an example of a Lex Spoon trial plugin:

 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") } } } } } 

How can I put Component and DivByZeroPhase in my own files without having import global._ in scope?

+6
source share
3 answers

Here is a really old project where I did the same:

https://github.com/jsuereth/osgi-scalac-plugin/blob/master/src/main/scala/scala/osgi/compiler/OsgiPlugin.scala

If you don’t need to pass path-dependent types from the global, don’t worry about saving the appropriate “this.global” parts.

+4
source

In the Scala refactoring library, I solved it using the CompilerAccess property:

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

Now all the other traits that need to access global just declare CompilerAccess as a dependency:

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

and then there is a class that mixes up in all of these ways and provides an instance of global:

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

This circuit worked for me well.

+3
source

You can create a separate class for your component and pass a global value:

 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) = { } } } 
+2
source

Source: https://habr.com/ru/post/885692/


All Articles