AbstractTypeDeclaration? は型(クラスやインタフェース)やEnum,Annotationを表現する抽象クラスです。

abstract.png
List<AbstractTypeDeclaration> CompilationUnit#types();

を呼び出すことでCompilationUnit?に記述されている型情報を取得することができます。戻り値がListになっているのは、一つのUnit*1に複数のクラスが書いてある場合があるからですね。ちなみに、あるソースコードに書かれているクラス名を全て取得する これを使ってもソース内のクラス名などは取得可能です。あちらは

ICompilationUnit =element; <-パッケージエクスプローラなどから取得する
IType[] types = element.getTypes();

といってITypeインタフェースを経由して型情報にアクセスできますね*2。。

Annotationにアクセスしてみる

対象のCompilationUnit?がAnnotationだった場合に、正しくアクセスできるか試してみました。

対象のコードはこんな感じ

  • nu.mine.kino.annotations.Service
    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形式でアクセスができそうです。


この記事は

選択肢 投票
おもしろかった 2  
そうでもない 0  

現在のアクセス:9307


*1 =ファイル?
*2 そもそも、なんで2通りのやり方があるのかはよくわからんです

添付ファイル: fileabstract.png 943件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-12-14 (火) 11:32:37 (858d)