Groovy AST语义分析重复类定义

Groovy AST语义分析重复类定义,groovy,metaprogramming,transformation,abstract-syntax-tree,Groovy,Metaprogramming,Transformation,Abstract Syntax Tree,我有一个类,它实现了ASTTransformation,并为每个标记有特定注释的字段创建了getter和setter方法: @GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS) public class Rewriter implements ASTTransformation { public void visit(ASTNode[] nodes, SourceUnit source) { List fields

我有一个类,它实现了ASTTransformation,并为每个标记有特定注释的字段创建了getter和setter方法:

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)
public class Rewriter implements ASTTransformation {
public void visit(ASTNode[] nodes, SourceUnit source) {
    List fields = nodes.findAll { it instanceof FieldNode }
    fields.each {
        MethodNode get = createGetter(it)
        MethodNode set = createSetter(it)
        source.getAST().addMethod(get)
        source.getAST().addMethod(set)
    }
}

private MethodNode createGetter(FieldNode f) {
    Parameter[] parameters = []
    ClassNode[] exceptions = []
    Statement state = new AstBuilder().buildFromString("return ${f.name}").get(0)
    return new MethodNode("get" + f.name.capitalize(), Opcodes.ACC_PUBLIC, ClassHelper.make(f.getType().name), parameters, exceptions, state)
}

private MethodNode createSetter(FieldNode f) {
    Parameter[] parameters = [
        new Parameter(ClassHelper.make(f.getType().name), f.name)
    ]
    ClassNode[] exceptions = []
    Statement state = new AstBuilder().buildFromString("this.${f.name} = ${f.name}").get(0)
    return new MethodNode("set" + f.name.capitalize(), Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, parameters, exceptions, state)
    }
}
运行以下测试类

class Main {
    @Accessors
    int counter = 5

    public static void main(String[] args) {
            println getCounter()
    }
}
产生以下错误:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
User\groovy\meta\src\Main.groovy: -1: Invalid duplicate class definition of class Main : The source User\groovy\meta\src\Main.groovy contains at least two definitions of the class Main.
One of the classes is an explicit generated class using the class statement, the other is a class generated from the script body based on the file name. Solutions are to change the file name or to change the class name.
@ line -1, column -1.
1 error
这是什么原因?它似乎创建了这些方法并将它们添加到源代码的AST中。
我正在使用GroovyEclipse4.3

您很快就可以进行AST转换了。下面是我在查看和测试您的代码时所做的一些观察

  • visit
    方法中

    source.getAST().addMethod(...)
    
    似乎是您看到的
    多重编译错误异常的根源。换成

    it.declaringClass.addMethod(...)
    
  • 另外,在
    Main
    类中,您需要在
    static Main
    方法中创建一个实例:
    println new Main()。getCounter()
    应该是关键

  • get和set方法与groovy提供的默认get和set方法相同。即使您以后想更改它,现在也很难进行测试,因为无法知道使用的是AST转换还是groovy提供的方法。因此,您至少应该暂时将行为更改为“非标准”(或更改方法名称)。我通过在getter的返回值中插入“+1”来测试代码

  • 最后一个注意事项,可能是品味的问题:我认为如果注释和AST转换有“匹配”的名称,则更清楚。也就是说,我会将
    重写器
    重命名为
    访问器ASTTransformation