我正在尝试创建一个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,但我仍在努力让它在多项目构建中工作。
1条答案
按热度按时间of1yzvn41#
事情看起来比我谷歌搜索的建议要简单。需要改变的主要事情是:
1.将对
astTransformation
配置的引用替换为implementation
,并删除配置GroovyCompile AST类路径的块B/构建.gradle
字符串
1.将AST应用于示例中使用的相同代码(没有 Package 类/main方法):
型
之所以需要2.,是因为由WithLoggingASTTransformation定义的AST转换应用于
sourceUnit.AST.methods
,它引用顶级方法,而不是类中的方法。通过这些更改,
./gradlew :B:run
生成转换后的输出:起始x
X
结束x