#author("2021-12-14T02:32:37+00:00","","")
// 下階層用テンプレート
#topicpath
----
//ここにコンテンツを記述します。
#contents

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

#ref(abstract.png)
 List<AbstractTypeDeclaration> CompilationUnit#types();
を呼び出すことでCompilationUnitに記述されている型情報を取得することができます。戻り値がListになっているのは、一つのUnit((=ファイル?))に複数のクラスが書いてある場合があるからですね。ちなみに、[[あるソースコードに書かれているクラス名を全て取得する>Eclipse/プラグイン開発のTIPS集/ソースコードを解析するパーサASTParser/TypeDeclaration#f465918b]] これを使ってもソース内のクラス名などは取得可能です。あちらは
 ICompilationUnit =element; <-パッケージエクスプローラなどから取得する
 IType[] types = element.getTypes();
といってITypeインタフェースを経由して型情報にアクセスできますね((そもそも、なんで2通りのやり方があるのかはよくわからんです))。。

**Annotationにアクセスしてみる [#s6a7f75d]
対象の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形式でアクセスができそうです。


----
この記事は
#vote(おもしろかった[1],そうでもない[0])
#vote(おもしろかった[2],そうでもない[0])

#comment
#topicpath


SIZE(10){現在のアクセス:&counter;}

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS