2016-07-29 8 views
2

コンパイル時にいくつかのクラスに汎用フィールドを追加したいと思います。この目的のために、私はdocumentationという公式に従って独自のASTアノテーションとトランスフォーメーションクラスを実装し、ASTアノテーションで目的のクラスにアノテーションを付けました。GroovyASTコンパイル時に汎用フィールドを追加する

org.codehaus.groovy.control.MultipleCompilationErrorsException:起動に失敗しました: /home/.../groovy/Sample.groovy:-1

しかし、私はコンパイル時にこのエラーを取得しています:変換では、フィールドxに対して直接ClassNode java.util.HashSetを含むジェネリックを使用しました。あなたはこれをするべきではありません。古いClassNodeを参照する新しいClassNodeを作成し、古いClassNodeの代わりに新しいClassNodeを使用してください。そうしないと、コンパイラは誤った記述子を作成し、OpenJDKのTypeResolverでNullPointerExceptionが発生する可能性があります。これが自分自身でない場合は、このバグを変換の作者に報告してください。 @行-1、列-1

私は間違いをしましたか?例えば

サンプルコード

、私はMyASTアノテーションで注釈され、すべてのクラスに、xという名前HashSet<Long>フィールドを追加するとします。

マイAST注釈クラス:

@Retention(RetentionPolicy.SOURCE) 
@Target(ElementType.TYPE) 
@GroovyASTTransformationClass(classes = [MyASTTransformation.class]) 
public @interface MyAST { 
} 

マイAST変換クラス:

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

@Override 
public void visit(ASTNode[] nodes, SourceUnit sourceUnit) { 
    ClassNode clazz = (ClassNode) nodes[1]; 
    ClassNode longHashSetClass = new ClassNode(HashSet.class); 
    longHashSetClass.setGenericsTypes([new GenericsType(new ClassNode(Long.class))] as GenericsType[]); 
    FieldNode field = new FieldNode("x", FieldNode.ACC_PRIVATE, longHashSetClass, clazz, new ConstantExpression(null)); 
    clazz.addField(field); 
} 
} 

サンプル注釈付きクラス:

@MyAST 
public class Sample { 
} 

longHashSetClass.setGenericsTypes([new GenericsType(new ClassNode(Long.class))] as GenericsType[]);行を削除すると、すべてがOKですが、xのタイプは、実行時にHashSet<Long>の代わりにHashSetになります。

答えて

2

あなたはClassNodeを作成するためにClassHelperまたはGenericUtilsを使用する必要があります。

import static org.codehaus.groovy.ast.ClassHelper.make 
import static org.codehaus.groovy.ast.tools.GenericsUtils.makeClassSafeWithGenerics 

... 

ClassNode hashSet = makeClassSafeWithGenerics(HashSet, make(Long)) 
+0

ありがとうございました。それは動作しますが、 'make(HashSet)'を 'new ClassNode(HashSet)'に変更するとエラーになります。彼らの違いは何ですか? – vahidreza

+0

正直なところ、わかりませんが、ClassNodeを直接インスタンス化するべきではありません。これらのメソッドは、バイトコードを生成するときに必要なキャッシング、エイリアシングなどを処理します。 –

関連する問題