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形式でアクセスができそうです。
この記事は
現在のアクセス:10001