    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *        http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.fukurou.taglet;            // 7.4.4.0 (2021/06/30) openGionV8事前準備(taglet2→taglet)
    017
    018import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
    019
    020import jdk.javadoc.doclet.DocletEnvironment      ;
    021// import jdk.javadoc.doclet.Doclet  ;
    022// import jdk.javadoc.doclet.Reporter ;
    023import javax.lang.model.element.Element ;
    024import javax.lang.model.element.Modifier ;
    025import javax.lang.model.element.TypeElement;
    026import javax.lang.model.element.ElementKind     ;
    027import javax.lang.model.element.VariableElement;
    028import javax.lang.model.element.ExecutableElement;
    029// import javax.lang.model.SourceVersion ;
    030import javax.lang.model.type.TypeMirror;
    031import javax.lang.model.type.TypeKind;
    032import javax.lang.model.util.ElementFilter ;
    033import javax.lang.model.util.Elements ;
    034import javax.lang.model.util.Types ;
    035import javax.tools.Diagnostic.Kind ;
    036import com.sun.source.doctree.DocCommentTree ;
    037import com.sun.source.util.DocTrees  ;
    038// import com.sun.source.util.DocSourcePositions ;
    039import com.sun.source.doctree.DocTree  ;
    040
    041// import java.util.Locale ;
    042import java.util.Set;
    043import java.util.List;
    044import java.util.HashSet;
    045import java.util.Arrays;
    046// import java.util.stream.Stream;                                                                              // 6.4.3.4 (2016/03/11)
    047// import java.util.stream.Collectors;                                                                  // 6.4.3.4 (2016/03/11)
    048// import java.util.regex.Pattern;                                                                              // 6.3.9.1 (2015/11/27) final化に伴う整理
    049
    050// import java.io.IOException;
    051// import java.io.File;
    052// import java.io.PrintWriter;
    053import java.util.stream.Stream;                                                                         // 6.4.3.4 (2016/03/11)
    054import java.util.stream.Collectors;                                                                     // 6.4.3.4 (2016/03/11)
    055import java.util.Map;
    056
    057// import org.opengion.fukurou.util.FileUtil;
    058// import org.opengion.fukurou.util.StringUtil;
    059
    060/**
    061 * ソースコメントから、パラメータ情報を取り出す Doclet クラスです。
    062 * og.paramLevel タグと og.cryptography タグを切り出します。
    063 * これらは、ｼｽﾃﾑパラメータとしてGE12ﾃｰﾌﾞﾙに設定される値をクラスより抽出する
    064 * のに使用します。
    065 *
    066 * @version  7.3
    067 * @author      Kazuhiko Hasegawa
    068 * @since        JDK11.0,
    069 */
    070public class DocTreeSpecific extends AbstractDocTree {
    071        private static final String  SELECT_PACKAGE     = "org.opengion" ;
    072        private static final boolean USE_PRIVATE        = false ;
    073
    074        private static final String     OG_FOR_SMPL             = "og.formSample";
    075        private static final String     OG_REV                  = "og.rev";
    076        private static final String     OG_GROUP                = "og.group";
    077        private static final String     DOC_VERSION             = "version";
    078        private static final String     DOC_AUTHOR              = "author";
    079        private static final String     DOC_SINCE               = "since";
    080
    081//      private static final String OG_TAG_NAME         = "og.tag";                             // 6.1.2.0 (2015/01/24) チェック用
    082//      private static final String     DOC_PARAM               = "param";                              // 5.1.9.0 (2010/08/01) チェック用
    083//      private static final String     DOC_RETURN              = "return";                             // 5.1.9.0 (2010/08/01) チェック用
    084
    085        private static final String     CONSTRUCTOR             = "コンストラクタ" ;
    086        private static final String     METHOD                  = "メソッド" ;
    087
    088        private String  version         ;
    089        private String  outfile         ;
    090        private int             debugLevel      ;               // 0:なし 1:最小チェック 2:日本語化 3:体裁 4:Verﾁｪｯｸ 5:taglibﾗﾍﾞﾙ
    091
    092        private final Set<String> mtdClsSet = new HashSet<>();
    093
    094        // 5.1.9.0 (2010/08/01) ソースチェック用(半角文字＋空白文字のみ)
    095//      private static final Pattern PTN = Pattern.compile("[\\w\\s]+");                // 6.3.9.1 (2015/11/27)
    096
    097//      private DocTrees docUtil;
    098//      private Elements eleUtil ;
    099        private Types    typUtil ;
    100
    101        /**
    102         * デフォルトコンストラクター
    103         *
    104         * @og.rev 7.3.0.0 (2021/01/06) PMD refactoring. Each class should declare at least one constructor.
    105         */
    106        public DocTreeSpecific() { super(); }           // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    107
    108        /**
    109         * Doclet のエントリポイントメソッドです(昔の startメソッド)。
    110         *
    111         * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
    112         *
    113         * @param docEnv ドックレットを1回呼び出す操作環境
    114         *
    115         * @return 正常実行時 true
    116         */
    117        @Override
    118        public boolean run( final DocletEnvironment docEnv ) {
    119                try( DocTreeWriter writer = new DocTreeWriter( outfile,ENCODE ) ) {
    120                        writer.printTag( "<?xml version=\"1.0\" encoding=\"", ENCODE , "\" ?>" );
    121                        writer.printTag( "<javadoc>" );
    122                        writer.printTag( "  <version>",version,"</version>" );
    123                        writer.printTag( "  <description></description>" );
    124                        writeContents( docEnv,writer );
    125                        writer.printTag( "</javadoc>" );
    126                }
    127                catch( final Throwable th ) {
    128                        reporter.print(Kind.ERROR, th.getMessage());
    129                }
    130
    131                return true;
    132        }
    133
    134        /**
    135         * DocletEnvironmentよりコンテンツを作成します。
    136         *
    137         * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
    138         * @og.rev 8.0.0.0 (2021/07/31) Avoid instantiating new objects inside loops
    139         * @og.rev 8.0.2.1 (2021/12/10) ｺﾒﾝﾄ分割で『。』と半角の『｡』の両方対応しておく。
    140         *
    141         * @param docEnv        ドックレットの最上位
    142         * @param writer        DocTreeWriterオブジェクト
    143         */
    144        private void writeContents( final DocletEnvironment docEnv, final DocTreeWriter writer ) {
    145//              docUtil = docEnv.getDocTrees();
    146                final DocTrees docUtil = docEnv.getDocTrees();
    147                final Elements eleUtil = docEnv.getElementUtils();
    148                typUtil = docEnv.getTypeUtils();
    149
    150                final StringBuilder modiBuf = new StringBuilder();                      // 8.0.0.0 (2021/07/31) Avoid instantiating new objects inside loops
    151                final StringBuilder buf     = new StringBuilder();                      // 8.0.0.0 (2021/07/31) Avoid instantiating new objects inside loops
    152
    153                // クラス単位にループする。
    154                for( final TypeElement typEle : ElementFilter.typesIn(docEnv.getIncludedElements())) {
    155                        final String fullName   = String.valueOf( typEle.getQualifiedName() ) ;
    156                        writer.setClassName( fullName );
    157
    158                        final String className = String.valueOf( typEle.getSimpleName() );
    159
    160//                      final StringBuilder modiBuf = new StringBuilder();
    161                        modiBuf.setLength( 0 ) ;                                                                // 8.0.0.0 (2021/07/31)
    162                        typEle.getModifiers().forEach( modi -> modiBuf.append( modi ).append( ' ' ) );
    163                        final ElementKind eleKind = typEle.getKind();
    164                        if( ElementKind.CLASS.equals( eleKind ) ) { modiBuf.append( "class" ); }
    165                        final String modifiers = modiBuf.toString().trim();
    166
    167                        final TypeMirror superType      = typEle.getSuperclass();
    168                        final String superClass = TypeKind.NONE.equals( superType.getKind() ) ? "" : superType.toString();
    169
    170                        final String intFase = Stream.of( typEle.getInterfaces() )
    171                                                                                .map( typ -> String.valueOf(typ) )
    172                                                                                .collect( Collectors.joining( "," ) );
    173
    174                        final DocCommentTree docTree = docUtil.getDocCommentTree(typEle);               // ﾄﾞｷｭﾒﾝﾃｰｼｮﾝ･ｺﾒﾝﾄが見つからない場合、null が返る。
    175
    176//                      final List<? extends DocTree> desc      = docTree == null ? EMPTY_LIST : docTree.getFirstSentence();
    177//                      final List<? extends DocTree> cmnt      = docTree == null ? EMPTY_LIST : docTree.getFullBody();
    178                        final String[] cmnts = getTitleCmnt( docTree );                                                 // 8.0.2.1 (2021/12/10)
    179
    180                        final Map<String,List<String>> blkTagMap = blockTagsMap(docTree);
    181                        final String smplTags   = getBlockTag( OG_FOR_SMPL, blkTagMap, ""   );
    182                        final String revTags    = getBlockTag( OG_REV     , blkTagMap, "\n" );
    183                        final String createVer  = getBlockTag( DOC_VERSION, blkTagMap, ""   );
    184                        final String author             = getBlockTag( DOC_AUTHOR , blkTagMap, ""   );
    185                        final String since              = getBlockTag( DOC_SINCE  , blkTagMap, ""   );
    186                        final String grpTags    = getBlockTag( OG_GROUP   , blkTagMap, ","  );
    187
    188                        // 5.7.1.1 (2013/12/13) タグのインデントを止める。
    189                        writer.printTag( "<classDoc>" );
    190                        writer.printTag( "  <fullName>"         ,fullName               ,"</fullName>"          );
    191                        writer.printTag( "  <modifiers>"        ,modifiers              ,"</modifiers>"         );
    192                        writer.printTag( "  <className>"        ,className              ,"</className>"         );
    193                        writer.printTag( "  <superClass>"       ,superClass             ,"</superClass>"        );
    194                        writer.printTag( "  <interface>"        ,intFase                ,"</interface>"         );
    195                        writer.printTag( "  <createVer>"        ,createVer              ,"</createVer>"         );
    196                        writer.printTag( "  <author>"           ,author                 ,"</author>"            );
    197                        writer.printTag( "  <since>"            ,since                  ,"</since>"                     );
    198//                      writer.printTag( "  <description>"      ,desc                   ,"</description>"       );
    199                        writer.printTag( "  <description>"      ,cmnts[0]               ,"</description>"       );              // 8.0.2.1 (2021/12/10)
    200//                      writer.printTag( "  <contents>"         ,cmnt                   ,"</contents>"          );
    201                        writer.printTag( "  <contents>"         ,cmnts[1]               ,"</contents>"          );              // 8.0.2.1 (2021/12/10)
    202                        writer.printTag( "  <classGroup>"       ,grpTags                ,"</classGroup>"        );
    203                        writer.printTag( "  <formSample>"       ,smplTags               ,"</formSample>"        );
    204                        writer.printTag( "  <history>"          ,revTags                ,"</history>"           );
    205
    206                        // 5.1.9.0 (2010/08/01) ソースチェック用(コメントや概要が無い場合。スーパークラスは省く)
    207//                      if( debugLevel >= 2 && ( cmnt.isEmpty() || desc.isEmpty() ) && superClass.isEmpty() ) {
    208                        if( debugLevel >= 2 && ( cmnts[0].isEmpty() || cmnts[1].isEmpty() ) && superClass.isEmpty() ) { // 8.0.2.1 (2021/12/10)
    209        //                      final DocSourcePositions srcPos = docUtil.getSourcePositions();
    210        //                      System.err.println( "警告2:コメントC=\t" + srcPos );
    211                                System.err.println( "②警告2:コメントC=\t" + typEle );
    212                        }
    213
    214                        int extendFlag = 0;             // 0:オリジナル 1:org.opengion関連Extend 2:Java関連Extend
    215
    216                        // 6.4.3.0 (2016/02/05) PMDチェックのDocletでのフォロー。
    217        //              checkPMD( typEle );
    218
    219                        // 5.6.6.0 (2013/07/05) VERSION staticフィールドと、@og.rev コメントの比較チェック
    220                        // while 以下で、fullName と classDoc を順番に上にさかのぼっているので、先にチェックします。
    221        //              checkTag2( typEle );
    222
    223                        mtdClsSet.clear();
    224                        TypeElement loopEle = typEle;
    225                        String superName = fullName;
    226                        while( loopEle != null ) {
    227                                writer.setClassName( superName );
    228
    229                                // 対象クラスの スーパークラスを取得しておく(ﾒｿｯﾄﾞ内で使うのと、上位に上がってく時に使う)
    230                                final TypeMirror spType = loopEle.getSuperclass();
    231
    232                                // AbstractObjectPool<java.sql.Connection> の様な型を削除します。
    233//                              final StringBuilder buf = new StringBuilder().append(spType);
    234                                buf.setLength( 0 ) ;                                                            // 8.0.0.0 (2021/07/31)
    235                                buf.append(spType) ;                                                            // 8.0.0.0 (2021/07/31)
    236
    237                                int st = buf.indexOf("<");
    238                                int ed = buf.indexOf(">",st);
    239                                while( st > 0 ) {
    240                                        buf.delete(st,ed+1);
    241                                        st = buf.indexOf("<");
    242                                        ed = buf.indexOf(">",st);
    243                                }
    244                                superName = buf.toString();
    245                //              superName = String.valueOf( spType );
    246
    247                                final String extClass   = ( extendFlag == 0 ) ? "" : superName ;
    248
    249                                // コンストラクタのみフィルタリングして取得する
    250                                for( final ExecutableElement exEle : ElementFilter.constructorsIn(loopEle.getEnclosedElements()) ) {
    251                                        final DocCommentTree dct = docUtil.getDocCommentTree(exEle);            // ﾄﾞｷｭﾒﾝﾃｰｼｮﾝ･ｺﾒﾝﾄが見つからない場合、null が返る。
    252                                        if( dct != null && isAction( exEle,extendFlag ) ) {
    253                //                              checkTag( exEle,dct );                                                                                          // 5.5.4.1 (2012/07/06)  チェックを分離
    254                                                menberTag( exEle,dct,CONSTRUCTOR,writer,extendFlag,extClass );
    255                                        }
    256                                }
    257
    258                                // メソッドのみフィルタリングして取得する
    259                                for( final ExecutableElement exEle : ElementFilter.methodsIn(loopEle.getEnclosedElements())) {
    260                                        final DocCommentTree dct = docUtil.getDocCommentTree(exEle);            // ﾄﾞｷｭﾒﾝﾃｰｼｮﾝ･ｺﾒﾝﾄが見つからない場合、null が返る。
    261                                        if( dct != null && isAction( exEle,extendFlag ) ) {
    262                //                              checkTag( exEle,dct );
    263                                                menberTag( exEle,dct,METHOD,writer,extendFlag,extClass );
    264                                        }
    265                                }
    266
    267                                // 対象クラス(オリジナル)から、上に上がっていく。
    268                                if( superName.startsWith( SELECT_PACKAGE ) ) {
    269                                        extendFlag = 1;
    270                                }
    271                                else {
    272                                        break;
    273                                }
    274
    275                                loopEle = eleUtil.getTypeElement(superName);
    276                        }
    277                        writer.printTag( "</classDoc>" );
    278                }
    279        }
    280
    281        /**
    282         * メンバークラスのXML化を行うかどうか[true/false]を判定します。
    283         *
    284         * 以下の条件に合致する場合は、処理を行いません。(false を返します。)
    285         *
    286         * １．同一クラスを処理中にEXTENDで継承元をさかのぼる場合、すでに同じシグネチャのメソッドが
    287         *     存在している。
    288         * ２．USE_PRIVATE が true の時の private メソッド
    289         * ３．extendFlag が 0以上(1,2)の時の private メソッド
    290         * ４．メソッド名におかしな記号(&lt;など)が含まれている場合
    291         *
    292         * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
    293         *
    294         * @param       menber ExecutableMemberDocオブジェクト
    295         * @param       extendFlag      継承状態 [0:オリジナル/1:org.opengion関連Extend/2:Java関連Extend]
    296         *
    297         * @return      XML化を行うかどうか[true/false]
    298         */
    299        private boolean isAction( final ExecutableElement menber,final int extendFlag ) {
    300//              final String menberName = String.valueOf( menber.getSimpleName() ) ;
    301                final boolean isPrivate   = menber.getModifiers().contains( Modifier.PRIVATE );
    302                final boolean isTypeParam = ! menber.getTypeParameters().isEmpty();
    303                final boolean rtn = ! mtdClsSet.add( String.valueOf( menber ) )         // 5.5.4.1 (2012/07/06) メソッドの重複処理判定は、クラス名も含めて行う
    304                                                ||      USE_PRIVATE    && isPrivate
    305                                                ||      extendFlag > 0 && isPrivate
    306                                                ||      isTypeParam;                                                                    // PMD Useless parentheses.
    307
    308                return ! rtn ;
    309        }
    310
    311//      /**
    312//       * param,return 等の整合性をチェックします。
    313//       *
    314//       * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
    315//       *
    316//       * @param exEle ExecutableElementオブジェクト
    317//       * @param menber DocCommentTreeオブジェクト
    318//       */
    319//      private void checkTag( final ExecutableElement exEle , final DocCommentTree menber ) {
    320//              // 未実装
    321//      }
    322
    323//      /**
    324//       * PMDで、チェックしている処理のうち、Docletでフォローできる分をチェックします。
    325//       *
    326//       * ※ このチェックは、警告レベル5 のみ集約していますので、呼出元で、制限します。
    327//       *
    328//       * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
    329//       *
    330//       * @param typEle TypeElementオブジェクト
    331//       */
    332//      private void checkTag2( final TypeElement typEle ) {
    333//              String cnstVar = null ;         // 初期値
    334//              String seriUID = null ;
    335//              final String src = "\tsrc/" + String.valueOf(typEle).replace('.','/') + ".java:100" ;                   // 行が判らないので、100行目 決め打ち
    336//
    337//              // フィールドのみフィルタリングして取得する
    338//              for( final VariableElement varEle : ElementFilter.fieldsIn(typEle.getEnclosedElements())) {             // フィールドだけに絞る
    339//                      final String key = String.valueOf(varEle);
    340//                      if( "VERSION".equals( key ) ) {
    341//                              cnstVar = String.valueOf( varEle.getConstantValue() );
    342//                      }
    343//                      else if( "serialVersionUID".equals( key ) ) {
    344//                              seriUID = String.valueOf( varEle.getConstantValue() ) + "L";                    // 旧JavaDocと違い、"L" まで取ってこれないみたい
    345//                      }
    346//              }
    347//
    348//              if( cnstVar == null ) { return; }                               // VERSION が未定義のクラスは処理しない
    349//
    350//              String maxRev = cnstVar ;                                               // 5.7.1.1 (2013/12/13) 初期値
    351//              boolean isChange = false;                                               // max が入れ替わったら、true
    352//
    353//              // メソッドのみフィルタリングして取得する
    354//              for( final ExecutableElement exEle : ElementFilter.methodsIn(typEle.getEnclosedElements())) {
    355//                      final DocCommentTree dct = docUtil.getDocCommentTree(exEle);            // ﾄﾞｷｭﾒﾝﾃｰｼｮﾝ･ｺﾒﾝﾄが見つからない場合、null が返る。
    356//                      final Map<String,List<String>> blkTagMap = blockTagsMap(dct);
    357//                      final List<String> revTags = blkTagMap.get("og.rev");
    358//
    359//                      if( revTags != null ) {
    360//                              for( final String tag :revTags ) {                                                              // 複数存在しているはず
    361//                                      final int idx = tag.indexOf( ' ' );                                                     // 最初のスペース
    362//                                      if( idx > 0 ) {
    363//                                              final String rev = tag.substring( 0,idx ).trim();
    364//                                              if( maxRev.compareTo( rev ) < 0 ) {                                             // revTags の og.rev が大きい場合
    365//                                                      maxRev = rev ;
    366//                                                      isChange = true;
    367//                                              }
    368//                                      }
    369//                              }
    370//                      }
    371//              }
    372//
    373//              // VERSION 文字列 の定義があり、かつ、max の入れ替えが発生した場合のみ、警告4:VERSIONが古い
    374//              if( isChange ) {                        // 5.7.1.1 (2013/12/13) 入れ替えが発生した場合
    375//                      System.err.println( "警告4:VERSIONが古い=\t" + cnstVar + " ⇒ " + maxRev + src );
    376//              }
    377//
    378//              // serialVersionUID の定義がある。
    379//              if( seriUID != null ) {
    380//                      final StringBuilder buf = new StringBuilder();
    381//                      // maxRev は、最大の Revか、初期のVERSION文字列 例:5.6.6.0 (2013/07/05)
    382//                      for( int i=0; i<maxRev.length(); i++ ) {        //
    383//                              final char ch = maxRev.charAt( i );
    384//                              if( ch >= '0' && ch <= '9' ) { buf.append( ch ); }      // 数字だけ取り出す。 例:566020130705
    385//                      }
    386//                      buf.append( 'L' );      // 強制的に、L を追加する。
    387//                      final String maxSeriUID = buf.toString() ;
    388//
    389//                      // 5.7.1.1 (2013/12/13) 値の取出し。Long型を表す "L" も含まれている。
    390//                      if( !maxSeriUID.equals( seriUID ) ) {   // 一致しない
    391//                              System.err.println( "警告4:serialVersionUIDが古い=\t" + seriUID + " ⇒ " + maxSeriUID + src );
    392//                      }
    393//              }
    394//      }
    395
    396//      /**
    397//       * PMDで、チェックしている処理のうち、Docletでフォローできる分をチェックします。
    398//       *
    399//       * ※ このチェックは、警告レベル5 のみ集約していますので、呼出元で、制限します。
    400//       *
    401//       * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
    402//       *
    403//       * @param typEle TypeElementオブジェクト
    404//       */
    405//      private void checkPMD( final TypeElement typEle ) {
    406//              // 未実装
    407//      }
    408
    409        /**
    410         * メンバークラス(コンストラクタ、メソッド)をXML化します。
    411         *
    412         * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
    413         * @og.rev 8.0.2.1 (2021/12/10) ｺﾒﾝﾄ分割で『。』と半角の『｡』の両方対応しておく。
    414         *
    415         * @param       menber          ExecutableElementオブジェクト
    416         * @param       docTree         DocCommentTreeオブジェクト
    417         * @param       menberType      メンバータイプ(コンストラクタ、メソッド)
    418         * @param       writer          Tagを書き出すWriterオブジェクト
    419         * @param       extendFlag      継承状態 [0:オリジナル/1::org.opengion関連Extend/2:Java関連Extend]
    420         * @param       extClass        継承クラス(オリジナルの場合は、空文字列)
    421         */
    422        private void menberTag( final ExecutableElement menber,
    423                                                        final DocCommentTree docTree ,
    424                                                        final String menberType,
    425                                                        final DocTreeWriter writer,
    426                                                        final int extendFlag ,
    427                                                        final String extClass ) {
    428
    429                final String modifiers ;
    430
    431                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    432                menber.getModifiers().forEach( modi -> buf.append( modi ).append( ' ' ) );
    433                if( ElementKind.METHOD.equals( menber.getKind() ) ) {           // メソッドの処理。コンストラクタの場合は、返り値がないので処理しない。
    434                        buf.append( menber.getReturnType() );
    435                }
    436                modifiers = buf.toString();
    437
    438                final String menberName = String.valueOf( menber.getSimpleName() );                     // コンストラクタの場合は、<init> が返る。
    439
    440                final StringBuilder sigBuf = new StringBuilder().append( menberName ).append( '(' ) ;
    441                boolean flag = false;
    442                for( final VariableElement valEle : menber.getParameters() ) {
    443                        flag = true;
    444                        final Element ele = typUtil.asElement( valEle.asType() );               // 型が対応する要素を持たない場合はnullを返します。
    445                        final String key = ele == null                                                                  // 配列や、プリミティブ型の場合は、null になっている。
    446                                                                        ? String.valueOf( valEle.asType() )
    447                                                                        : String.valueOf( ele.getSimpleName() );
    448
    449                        sigBuf.append( key ).append( ' ' )
    450                                        .append( valEle.getSimpleName() ).append( ',' );
    451                }
    452
    453                if( flag ) { sigBuf.deleteCharAt( sigBuf.length()-1 ); }
    454                sigBuf.append( ')' );
    455                final String signature = sigBuf.toString();
    456//              final String signature = String.valueOf( menber );
    457
    458//              final List<? extends DocTree> desc      = docTree == null ? EMPTY_LIST : docTree.getFirstSentence();
    459//              final List<? extends DocTree> cmnt      = docTree == null ? EMPTY_LIST : docTree.getFullBody();
    460                final String[] cmnts = getTitleCmnt( docTree );                                                 // 8.0.2.1 (2021/12/10)
    461
    462                final Map<String,List<String>> blkTagMap = blockTagsMap(docTree);
    463                final String revTags = getBlockTag( OG_REV, blkTagMap, "\n" );
    464
    465                // tags は、OG_REV 以外のすべてで、かつ、ｷｰﾜｰﾄﾞも含む。
    466                final StringBuilder tagBuf = new StringBuilder();
    467                if( docTree != null ) {
    468                        for( final DocTree dt : docTree.getBlockTags() ) {
    469                                final String tag = String.valueOf(dt).trim();
    470                                if( !tag.contains( OG_REV ) ) { tagBuf.append( tag ).append( '\n' ); }
    471                        }
    472                }
    473                final String tags = tagBuf.toString().trim();
    474
    475//              final StringBuilder tagBuf = new StringBuilder();
    476//              final StringBuilder revBuf = new StringBuilder();
    477//              if( docTree != null ) {
    478//                      for( final DocTree dt : docTree.getBlockTags() ) {
    479//                              final String tag = String.valueOf(dt).trim();
    480//                              if( tag.contains( OG_REV ) ) { revBuf.append( cutTag( tag,OG_REV ) ).append( '\n' ); }
    481//                              else { tagBuf.append( tag ).append( '\n' ); }
    482//                      }
    483//              }
    484//              final String revTags = revBuf.toString().trim();
    485//              final String tags    = tagBuf.toString().trim();
    486
    487                final String    extend  = String.valueOf( extendFlag );
    488
    489        //      final DocSourcePositions srcPos = docUtil.getSourcePositions();
    490        //      final String    position = String.valueOf( srcPos.getStartPosition( null,docTree,null ) );
    491                final String    position = "";
    492
    493                writer.printTag( "  <menber>" );
    494                writer.printTag( "    <type>"           ,menberType     ,"</type>"                      );
    495                writer.printTag( "    <name>"           ,menberName     ,"</name>"                      );
    496                writer.printTag( "    <modifiers>"      ,modifiers      ,"</modifiers>"         );
    497                writer.printTag( "    <signature>"      ,signature      ,"</signature>"         );
    498                writer.printTag( "    <position>"       ,position       ,"</position>"          );
    499                writer.printTag( "    <extendClass>",extClass   ,"</extendClass>"       );
    500                writer.printTag( "    <extendFlag>"     ,extend         ,"</extendFlag>"        );
    501//              writer.printTag( "    <description>",desc               ,"</description>"       );
    502                writer.printTag( "    <description>",cmnts[0]   ,"</description>"       );              // 8.0.2.1 (2021/12/10)
    503//              writer.printTag( "    <contents>"       ,cmnt           ,"</contents>"          );
    504                writer.printTag( "    <contents>"       ,cmnts[1]       ,"</contents>"          );              // 8.0.2.1 (2021/12/10)
    505                writer.printTag( "    <tagText>"        ,tags           ,"</tagText>"           );
    506                writer.printTag( "    <history>"        ,revTags        ,"</history>"           );
    507                writer.printTag( "  </menber>");
    508        }
    509
    510        /**
    511         * サポートされているすべてのオプションを返します。
    512         *
    513         * @return サポートされているすべてのオプションを含むセット、存在しない場合は空のセット
    514         */
    515        @Override
    516        public Set<? extends Option> getSupportedOptions() {
    517                final Option[] options = {
    518                        new AbstractOption( "-outfile", "-version", "-debugLevel" ) {
    519
    520                                /**
    521                                 * 必要に応じてオプションと引数を処理します。
    522                                 *
    523                                 * @param  opt オプション名
    524                                 * @param  arguments 引数をカプセル化したリスト
    525                                 * @return 操作が成功した場合はtrue、そうでない場合はfalse
    526                                 */
    527                                @Override
    528                                public boolean process(final String opt, final List<String> arguments) {
    529                                        if( "-outfile".equalsIgnoreCase(opt) ) {
    530                                                outfile = arguments.get(0);
    531                                        }
    532                                        else if( "-version".equalsIgnoreCase(opt) ) {
    533                                                version = arguments.get(0);
    534                                        }
    535                                        else if( "-debugLevel".equalsIgnoreCase(opt) ) {
    536                                                debugLevel = Integer.parseInt( arguments.get(0) );
    537                                        }
    538                                        return true;
    539                                }
    540                        }
    541                };
    542                return new HashSet<>(Arrays.asList(options));
    543        }
    544}