如何在Grails插件中实现Groovy全局AST转换?

如何在Grails插件中实现Groovy全局AST转换?,grails,groovy,grails-plugin,Grails,Groovy,Grails Plugin,我想在编译时修改一些Grails域类。我最初认为这是Groovy全局ASTTransformation的工作,因为我不想注释我的域类(本地转换器需要)。最好的方法是什么 我还尝试模仿DefaultGrailDomainClassInjector.java,在同一个包中创建自己的类,实现相同的接口,但我可能不知道如何将其打包到正确的位置,因为我从未看到调用我的方法 另一方面,我能够手动创建一个JAR,其中包含一个已编译的AST转换类,以及普通Groovy全局转换所需的META-INF/servic

我想在编译时修改一些Grails域类。我最初认为这是Groovy全局ASTTransformation的工作,因为我不想注释我的域类(本地转换器需要)。最好的方法是什么

我还尝试模仿DefaultGrailDomainClassInjector.java,在同一个包中创建自己的类,实现相同的接口,但我可能不知道如何将其打包到正确的位置,因为我从未看到调用我的方法

另一方面,我能够手动创建一个JAR,其中包含一个已编译的AST转换类,以及普通Groovy全局转换所需的META-INF/services工件。我将该JAR放入项目的“lib”目录中,成功地调用了visit()。显然,这是一项草率的工作,因为我希望将AST转换的源代码放在Grails插件中,如果不需要的话,也不需要单独的JAR工件,而且我无法通过将JAR放在Grails插件的“lib”中来实现这种方法,而是必须将其放在Grails应用程序的“lib”中


这篇文章也帮了一点忙:

关于全局转换的事情编译开始时,转换代码应该是可用的。把变压器放在罐子里是我首先做的!但正如你所说,这是一份草率的工作。 您要做的是在其他人进入编译阶段之前编译ast转换类。这就是你要做的

准备变压器 在
src
文件夹中创建一个名为
precompiled
的目录!并使用正确的打包结构在此目录中添加transformer使用的转换类和类(如注释)

precompiled
--amanu
----LoggingASTTransformation.groovy
--META-INF
----services
------org.codehaus.groovy.transform.ASTTransformation
然后在called
precompiled/META-INF/services
中创建一个名为
org.codehaus.groovy.transform.ASTTransformation
的文件,您将拥有以下结构

precompiled
--amanu
----LoggingASTTransformation.groovy
--META-INF
----services
------org.codehaus.groovy.transform.ASTTransformation
然后在
org.codehaus.groovy.transform.ASTTransformation
文件中写入转换器的完全限定名,因为上面的示例中,完全限定名是
amanu.LoggingASTTransformation

实施 汇编 在实现了这一点之后,您可以通过两种方式进行操作!第一种方法是像你一样把它放在罐子里!另一种是使用groovy脚本在其他脚本之前编译它。为了在grails中实现这一点,我们使用
\u Events.groovy
脚本

您可以从插件或主项目中执行此操作,这并不重要。如果不存在,请创建一个名为
\u Events.groovy的文件,并添加以下内容

代码经过修改后从中复制

eventCompileStart = {target ->  
    ...
    compileAST(pluginBasedir, classesDirPath)  
    ...
  }  
  def compileAST(def srcBaseDir, def destDir) {  
   ant.sequential {  
      echo "Precompiling AST Transformations ..."  
      echo "src ${srcBaseDir} ${destDir}"  
      path id: "grails.compile.classpath", compileClasspath  
      def classpathId = "grails.compile.classpath"  
      mkdir dir: destDir  
      groovyc(destdir: destDir,  
          srcDir: "$srcBaseDir/src/precompiled",  
          classpathref: classpathId,  
          stacktrace: "yes",  
          encoding: "UTF-8")
     copy(toDir:"$destDir/META-INF"){
        fileset(dir:"$srcBaseDir/src/precompiled/META-INF")
     }  
      echo "done precompiling AST Transformations"  
    }  
}  
前面的脚本将在编译其他脚本之前编译转换器!这使转换器可用于转换域类

别忘了 如果您使用除类路径中添加的类以外的任何类,那么您也必须预编译这些类。上面的脚本将编译
precompiled
目录中的所有内容,您还可以添加不需要ast但该目录中需要的类

如果要在转换中使用域类,可能需要在
evencileend
块中进行预编译!但这会让事情变得更慢

更新 @道格拉斯·门德斯(Douglas Mendes)提到,有一种简单的方法可以引起预编译。这更简洁

eventCompileStart = { 
   target -> projectCompiler.srcDirectories.add(0, "./src/precompiled") 
}

还有一种更简单的方法可以首先使用_Events.groovy编译AST源文件夹:
eventCompileStart={target->projectCompiler.srcDirectories.add(0,“./src/precompiled”)}
链接是死的,活的: