AbstractTypeDeclaration? は型(クラスやインタフェース)やEnum,Annotationを表現する抽象クラスです。
List<AbstractTypeDeclaration> CompilationUnit#types();
を呼び出すことでCompilationUnit?に記述されている型情報を取得することができます。戻り値がListになっているのは、一つのUnit*1に複数のクラスが書いてある場合があるからですね。ちなみに、あるソースコードに書かれているクラス名を全て取得する これを使ってもソース内のクラス名などは取得可能です。あちらは
ICompilationUnit =element; <-パッケージエクスプローラなどから取得する IType[] types = element.getTypes();
といってITypeインタフェースを経由して型情報にアクセスできますね*2。。
対象のCompilationUnit?がAnnotationだった場合に、正しくアクセスできるか試してみました。
対象のコードはこんな感じ
package nu.mine.kino.annotations; @Inherited @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface Service { boolean singleton() default false; }
上のコードを解析するソースはこんな感じです
ASTParser parser = ASTParser.newParser(AST.JLS3); // parser.setResolveBindings(true); parser.setSource(unit); parser.setKind(ASTParser.K_COMPILATION_UNIT); // parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);// やったら↓これはNG CompilationUnit root = (CompilationUnit) parser .createAST(new NullProgressMonitor()); List<AbstractTypeDeclaration> types = (List<AbstractTypeDeclaration>) root .types(); for (AbstractTypeDeclaration type : types) { System.out.println("タイプのクラス名: " + type.getClass().getName()); System.out.println("クラス名: " + type.getName()); // System.out.println("TypeのValue: " + type); System.out.println("---------"); // そのクラス自体がAnnotationかどうか。 if (type instanceof AnnotationTypeDeclaration) { System.out.println("Annotationです"); } }
実行結果です
タイプのクラス名: org.eclipse.jdt.core.dom.AnnotationTypeDeclaration クラス名: Service --------- Annotationです
まだAnnotationらしいデータにはアクセスしてないですが、Annotationだってこと自体は確認できました。
次はその型のModifierやAnnotationにアクセスしてみます。Modifierとはいわゆる
public protected private static abstract final native synchronized transient volatile strictfp
などの修飾子のことですね。AnnotationはまさにAnnotationですね。先の型@Serviceはそれ自体もAnnotationですが、
@Inherited @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface Service { ...
などとAnnotationが付与されているため、それらの値も取得できそうです。
実際にModiferやAnnotationにアクセスするメソッドは
List<IExtendedModifier> modifiers = type.modifiers();
です。実際にコードは以下の通りです。
// http://dev.eclipse.org/newslists/news.eclipse.tools.jdt/msg19931.html List<IExtendedModifier> modifiers = type.modifiers(); // ただし↑は、 @inheritedされて継承されたAnnotationはModifiersとしては返却されないようだ。。 for (IExtendedModifier modifier : modifiers) { System.out.println("modifier: " + modifier); if (modifier.isAnnotation()) { System.out.println("isAnnotation"); Annotation annoModifier = (Annotation) modifier; if (annoModifier.isSingleMemberAnnotation()) { System.out.println("isSingleMemberAnnotation"); Expression value = ((SingleMemberAnnotation) annoModifier) .getValue(); // このクラスにAnnoされている値。 System.out.println(value); } else if (annoModifier.isMarkerAnnotation()) { System.out.println("isMarkerAnnotation"); } else if (annoModifier.isNormalAnnotation()) { System.out.println("isNormalAnnotation"); List<MemberValuePair> list = ((NormalAnnotation) annoModifier) .values(); for (MemberValuePair pair : list) { System.out.println("Annotationされている情報: " + pair.getName() + "=" + pair.getValue()); } } } else { Modifier normalModifier = (Modifier) modifier; System.out.println(normalModifier.getKeyword()); } }
結果は以下の通り
modifier: @Inherited isAnnotation isMarkerAnnotation <- マーカー modifier: @Target(ElementType.TYPE) isAnnotation isSingleMemberAnnotation <-SingleMember ElementType.TYPE <-そのValue modifier: @Retention(RetentionPolicy.SOURCE) isAnnotation isSingleMemberAnnotation <-SingleMember RetentionPolicy.SOURCE <-そのValue modifier: public public
SingleMember?じゃないAnnotationはなかったので表示されませんでしたが、NormalAnnotation?の場合は
List<MemberValuePair> list = ((NormalAnnotation) annoModifier).values(); for (MemberValuePair pair : list) { System.out.println("Annotationされている情報: " + pair.getName() + "=" + pair.getValue()); }
などとKey/Value形式でアクセスができそうです。
この記事は
現在のアクセス:9317