groovy 最小化gradle多项目构建,包括全局AST转换

dldeef67  于 6个月前  发布在  其他
关注(0)|答案(1)|浏览(59)

我正在尝试创建一个gradle项目,该项目将项目A中定义的全局AST转换应用于项目B中定义的类。我一直在按照本指南中的说明操作,但没有成功:
https://groovy-lang.org/metaprogramming.html#transforms-global
我的项目结构是:

|- project-root
   |- settings.gradle
   |- A
      |-- build.gradle 
      |-- src
      └── main
          ├── groovy
          │   ├── gep
          │       └── WithLoggingASTTransformation.groovy
          └── resources
              └── META-INF
                  └── services
                      └── org.codehaus.groovy.transform.ASTTransformation
   |- B
      ├── build.gradle
      └── src
          └── main
              └── groovy
                  └── package1
                      └── Application.groovy

字符串
根项目的settings. gradle:

rootProject.name = 'test-global-ast'
include 'A'
include 'B'


项目A的build. gradle

plugins {
    id 'groovy'
}

dependencies {
    implementation platform('org.apache.groovy:groovy-bom:4.0.5')
    implementation 'org.apache.groovy:groovy'
}


项目B的build. gradle

plugins {
    id 'groovy'
    id 'application'
}

mainClassName = 'project1.App'

configurations { astTransformation }

dependencies {
    implementation platform('org.apache.groovy:groovy-bom:4.0.5')
    implementation 'org.apache.groovy:groovy'
    astTransformation project(':A')
}

tasks.withType(GroovyCompile).configureEach {
    astTransformationClasspath.from(configurations.astTransformation)
}


B/gep/WithLoggingAST转换. groovy

package gep

import groovy.transform.CompileStatic
import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.expr.ArgumentListExpression
import org.codehaus.groovy.ast.expr.ConstantExpression
import org.codehaus.groovy.ast.expr.MethodCallExpression
import org.codehaus.groovy.ast.expr.VariableExpression
import org.codehaus.groovy.ast.stmt.BlockStatement
import org.codehaus.groovy.ast.stmt.ExpressionStatement
import org.codehaus.groovy.ast.stmt.Statement
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.transform.ASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformation

@CompileStatic
@GroovyASTTransformation(phase= CompilePhase.SEMANTIC_ANALYSIS)
class WithLoggingASTTransformation implements ASTTransformation {

    @Override
    void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
        def methods = sourceUnit.AST.methods
        methods.each { method ->
            def startMessage = createPrintlnAst("Starting $method.name")
            def endMessage = createPrintlnAst("Ending $method.name")

            def existingStatements = ((BlockStatement)method.code).statements
            existingStatements.add(0, startMessage)
            existingStatements.add(endMessage)
        }
    }

    private static Statement createPrintlnAst(String message) {
        new ExpressionStatement(
                new MethodCallExpression(
                        new VariableExpression("this"),
                        new ConstantExpression("println"),
                        new ArgumentListExpression(
                                new ConstantExpression(message)
                        )
                )
        )
    }
}


A/src/main/resources/META-INF/service/org. codehaus. groovy. transform. AST转换

gep.WithLoggingASTTransformation


B/package1/Application. groovy

package package1

class Application {

    def x() {
        println "x"
    }

    static void main(args) {
        println "hi"
        def a = new Application()
        a.x()
    }
}


如果我运行./gradlew :B:compileGroovy,一切都会编译。但是,当我使用./gradlew :B:run运行时,如果应用了AST,我希望看到
启动主
开始打印

结束println
起始x
开始打印
X
结束println
结束X
终端干线
然而,我却看到:

X
这使我相信全局AST没有被应用。我如何调整我的多项目构建,以便在项目'A'中定义的全局AST成功应用于项目'B'中的类?

更新1

我能够应用全局AST,
1.使用./gradlew :A:jar将项目A打包为一个示例
1.更改到B目录cd B
1.使用groovyc -cp A.jar:src/main/groovy/package1/ src/main/groovy/package1/Application.groovy编译项目B
1.使用java -cp groovy-4.0.13.jar:A.jar:. package1.Application运行编译后的类
我还修改了package1.Application,以更好地匹配www.example.com中的示例:
B/package1/Application. groovy

package package1

def x() {
    println "x"
}

x()


通过这些更改,应用了全局AST,但我仍在努力让它在多项目构建中工作。

of1yzvn4

of1yzvn41#

事情看起来比我谷歌搜索的建议要简单。需要改变的主要事情是:
1.将对astTransformation配置的引用替换为implementation,并删除配置GroovyCompile AST类路径的块
B/构建.gradle

plugins {
    id 'groovy'
    id 'application'
}

mainClassName = 'project1.App'

dependencies {
    implementation platform('org.apache.groovy:groovy-bom:4.0.5')
    implementation 'org.apache.groovy:groovy'
    implementation project(':A')
}

字符串
1.将AST应用于示例中使用的相同代码(没有 Package 类/main方法):

package package1

def x() {
    println "x"
}

x()


之所以需要2.,是因为由WithLoggingASTTransformation定义的AST转换应用于sourceUnit.AST.methods,它引用顶级方法,而不是类中的方法。
通过这些更改,./gradlew :B:run生成转换后的输出:
起始x
X
结束x

相关问题