有没有办法测试scala编译器插件?
我正在尝试为我正在开发的scala编译器插件设置测试 根据这种类似的方法,可以通过编程方式调用插件。然而,当我尝试这样做时,程序找不到我的插件有没有办法测试scala编译器插件?,scala,plugins,compiler-construction,Scala,Plugins,Compiler Construction,我正在尝试为我正在开发的scala编译器插件设置测试 根据这种类似的方法,可以通过编程方式调用插件。然而,当我尝试这样做时,程序找不到我的插件 Error:(34, 25) not found: type GetFileFromAnnotation for (phase <- new GetFileFromAnnotation(this).components) 两个文件都在同一个包中 下面是试图测试从上述问题中提取的插件的代码,注释掉的代码是上面代码的替代代码,并抛出相同的
Error:(34, 25) not found: type GetFileFromAnnotation
for (phase <- new GetFileFromAnnotation(this).components)
两个文件都在同一个包中
下面是试图测试从上述问题中提取的插件的代码,注释掉的代码是上面代码的替代代码,并抛出相同的错误:
package compilerPlugin
import scala.reflect.internal.util.BatchSourceFile
import scala.tools.nsc.io.VirtualDirectory
import scala.tools.nsc.reporters.ConsoleReporter
import scala.tools.nsc.{Global, Settings}
object AnnotationFinderTest extends App {
// prepare the code you want to compile
val code =
"""
|class Typestate(filename:String) extends scala.annotation.StaticAnnotation
|
|@Typestate(filename = "MyProtocol.txt")
|class Cat{
| def comeAlive(): Unit = println("The cat is alive")
|}
|
|object Main extends App {
| val cat = new Cat()
| cat.comeAlive()
|}""".stripMargin
val sources = List(new BatchSourceFile("<test>", code))
println("sources "+sources)
val settings = new Settings
settings.usejavacp.value = true
settings.outputDirs.setSingleOutput(new VirtualDirectory("(memory)", None))
val compiler = new Global(settings, new ConsoleReporter(settings)) {
override protected def computeInternalPhases () {
super.computeInternalPhases
for (phase <- new GetFileFromAnnotation(this).components)
phasesSet += phase
}
}
new compiler.Run() compileSources (sources)
}
GetFileFromAnnotation插件的代码为:
package compilerPlugin
import java.io.{FileNotFoundException, IOException}
import scala.tools.nsc
import nsc.Global
import nsc.Phase
import nsc.plugins.Plugin
import nsc.plugins.PluginComponent
import scala.io.BufferedSource
import scala.io.Source._
class GetFileFromAnnotation(val global: Global) extends Plugin {
import global._
val name = "GetFileFromAnnotation"
val description = "gets file from typestate annotation"
val components: List[PluginComponent] = List[PluginComponent](Component)
private object Component extends PluginComponent {
val global: GetFileFromAnnotation.this.global.type = GetFileFromAnnotation.this.global
val runsAfter: List[String] = List[String]("parser")
val phaseName: String = GetFileFromAnnotation.this.name
def newPhase(_prev: Phase) = new GetFileFromAnnotationPhase(_prev)
class GetFileFromAnnotationPhase(prev: Phase) extends StdPhase(prev) {
override def name: String = GetFileFromAnnotation.this.name
def printFile(filename: String): Unit ={
val source = fromFile(filename)
try {
val it = source.getLines()
while (it.hasNext)
println(it.next())
}
catch{
case e: IOException => println(s"Had an IOException trying to use file $filename")
} finally {
source.close
}
}
def getFilenameFromAnnotation(annotation: Apply): Option[String] ={
annotation match{
case Apply(Select(New(Ident(TypeName("Typestate"))), con),List(NamedArg(Ident(TermName("filename")), Literal(Constant(filename))))) => Some(filename.toString)
case Apply(Select(New(Ident(TypeName("Typestate"))), con),List(Literal(Constant(filename)))) => Some(filename.toString)
case _ => None
}
}
def apply(unit: CompilationUnit): Unit = {
for (tree@q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" <- unit.body) {
val annotations = mods.annotations
for(annotation@Apply(arg1,arg2) <- annotations){
getFilenameFromAnnotation(annotation) match{
case Some(filename) => printFile(filename)
case None => println("Not a Typestate annotation")
}
}
}
}
}
}
}
使用这种方法测试插件是否可行,或者使用模拟是唯一的方法?有没有其他方法可以完全做到这一点
更新:
感谢您的评论和github示例。
它最终与上面编辑的测试代码一起工作良好,并按预期打印出协议文件。我不知道为什么它以前不工作。无法复制。如果我在IDE中运行AnnotationFinderTest,它的行为与预期的一样:它打印源列表aaa bbb aaa bbb是MyProtocol.txt中的行。如果我尝试在sbt shell中运行AnnotationFinderTest,则加载对象时出错,编译器镜像中缺少依赖项“类scala.native”,scala.reflect.internal.MissingRequirementError:未找到编译器镜像中的对象scala.annotation.StaticAnnotation。。。。。。但是对getClass.getClassLoader.asInstanceOf[URLClassLoader]from的修复对我不起作用:java.lang.ClassCastException:sbt.internal.LayeredClassLoader不能强制转换为scala.reflect.internal.util.ScalaClassLoader$URLClassLoader。无法复制。如果我在IDE中运行AnnotationFinderTest,它的行为与预期的一样:它打印源列表aaa bbb aaa bbb是MyProtocol.txt中的行。如果我尝试在sbt shell中运行AnnotationFinderTest,则加载对象时出错,编译器镜像中缺少依赖项“类scala.native”,scala.reflect.internal.MissingRequirementError:未找到编译器镜像中的对象scala.annotation.StaticAnnotation。。。。。。但是使用getClass.getClassLoader.asInstanceOf[URLClassLoader]from的修复对我不起作用:java.lang.ClassCastException:sbt.internal.LayeredClassLoader不能强制转换为scala.reflect.internal.util.ScalaClassLoader$URLClassLoader。