langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java
changeset 33919 e9fccc09cfc6
child 35351 2c8aa590f3d5
equal deleted inserted replaced
33918:6d7a40b2a54b 33919:e9fccc09cfc6
       
     1 /*
       
     2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package sampleapi.generator;
       
    25 
       
    26 import java.io.File;
       
    27 import java.io.BufferedInputStream;
       
    28 import java.io.IOException;
       
    29 import java.util.Set;
       
    30 import javax.lang.model.element.Modifier;
       
    31 
       
    32 import com.sun.tools.javac.tree.JCTree;
       
    33 import com.sun.tools.javac.tree.JCTree.*;
       
    34 import com.sun.tools.javac.util.List;
       
    35 
       
    36 class DocCommentGenerator {
       
    37 
       
    38     public enum Text {
       
    39         BROWNFOX(BROWNFOX_TEXT),
       
    40         NOWISTHETIME(NOWISTHETIME_TEXT),
       
    41         THISPANGRAM(THISPANGRAM_TEXT),
       
    42         LOREMIPSUM(LOREMIPSUM_TEXT),
       
    43         LIEUROPANLINGUES(LIEUROPANLINGUES_TEXT),
       
    44         CODE(CODE_TEXT);
       
    45 
       
    46         String commentText;
       
    47 
       
    48         Text(String text) {
       
    49             commentText = text;
       
    50         }
       
    51 
       
    52         @Override
       
    53         public String toString() {
       
    54             return commentText;
       
    55         }
       
    56     }
       
    57 
       
    58     public enum Tag {
       
    59         AUTHOR("@author", "Cody J. Writer"),
       
    60         PARAM("@param", ""),
       
    61         RETURN("@return", Text.NOWISTHETIME.toString()),
       
    62         SINCE("@since", "1.0"),
       
    63         THROWS("@throws", "If problem detected"),
       
    64         EXCEPTION("@exception", "If problem detected"),
       
    65         SERIAL("@serial", ""),
       
    66         SERIALDATA("@serialData", "The types and order of data could be here."),
       
    67         SERIALFIELD("@serialField", "\n        Serial field in special array"),
       
    68         FX_PROPSETTER("@propertySetter", "Set the property"),
       
    69         FX_PROPGETTER("@propertyGetter", "Get the property"),
       
    70         FX_PROPDESC("@propertyDescription", ""),
       
    71         FX_DEFVALUE("@defaultValue", ""),
       
    72         FX_TREATASPRIVATE("@treatAsPrivate", "");
       
    73 
       
    74         String tagName;
       
    75         String tagValue;
       
    76 
       
    77         Tag(String tagName, String tagValue) {
       
    78             this.tagName = tagName;
       
    79             this.tagValue = tagValue;
       
    80         }
       
    81 
       
    82         public String toString() {
       
    83             return value("", "");
       
    84         }
       
    85 
       
    86         public String value(String value) {
       
    87             return value(value, "");
       
    88         }
       
    89 
       
    90         public String value(String value, String extra) {
       
    91             return tagName
       
    92                    + ((value.length() != 0) ? " " + value : "")
       
    93                    + ((tagValue.length() != 0) ? " " + tagValue : "")
       
    94                    + ((extra.length() != 0) ? " " + extra : "");
       
    95         }
       
    96     }
       
    97 
       
    98     public enum InlineTag {
       
    99         LITERAL("@literal", "Use < and > brackets instead of &lt; and &gt; escapes."),
       
   100         CODE("@code", "(i) -> new Abc<Object>((i > 0) ? (i << 1) : 0)"),
       
   101         LINK("@link", ""),
       
   102         VALUE("@value", "");
       
   103 
       
   104         String tagName;
       
   105         String tagValue;
       
   106 
       
   107         InlineTag(String tagName, String tagValue) {
       
   108             this.tagName = tagName;
       
   109             this.tagValue = tagValue;
       
   110         }
       
   111 
       
   112         public String toString() {
       
   113             return value("");
       
   114         }
       
   115 
       
   116         public String value(String value) {
       
   117             return "{" + tagName
       
   118                    + ((tagValue.length() != 0) ? " " + tagValue : "")
       
   119                    + ((value.length() != 0) ? " " + value : "")
       
   120                    + "}";
       
   121         }
       
   122     }
       
   123 
       
   124     public static class LinkTag {
       
   125 
       
   126         static String[] links = new String[] {
       
   127             "Boolean",
       
   128             "Boolean#TRUE",
       
   129             "Boolean#Boolean(boolean)",
       
   130             "Boolean#Boolean(String s)",
       
   131             "Boolean#compare(boolean, boolean)",
       
   132             "Boolean#compareTo(Boolean b)",
       
   133             "java.util.Vector",
       
   134             "java.util.Vector#elementCount",
       
   135             "java.util.Vector#Vector(int)",
       
   136             "java.util.Vector#Vector(int initialCapacity, int capacityIncrement)",
       
   137             "java.util.Vector#indexOf(Object)",
       
   138             "java.util.Vector#indexOf(Object o, int index)",
       
   139             "java.lang.annotation" };
       
   140 
       
   141         static int index = 0;
       
   142 
       
   143         public static String nextSee() {
       
   144             String next = "@see " + links[index];
       
   145             index = (index + 1) % links.length;
       
   146             return next;
       
   147         }
       
   148 
       
   149         public static String nextLink() {
       
   150             String next = "Also check "
       
   151                           + (((index % 2) == 0) ? "{@link " : "{@linkplain ")
       
   152                           + links[index]
       
   153                           + "} for details.\n";
       
   154             index = (index + 1) % links.length;
       
   155             return next;
       
   156         }
       
   157     }
       
   158 
       
   159     public static class VersionTag {
       
   160 
       
   161         static String[] versions = new String[] {
       
   162             "1.5, 09/01/04",
       
   163             "1.6, 12/11/06",
       
   164             "1.7, 07/28/11",
       
   165             "1.8, 04/19/14",
       
   166             "1.9, 06/03/16" };
       
   167 
       
   168         static int index = 0;
       
   169 
       
   170         public static String nextVersion() {
       
   171             String next = "@version " + versions[index];
       
   172             index = (index + 1) % versions.length;
       
   173             return next;
       
   174         }
       
   175     }
       
   176 
       
   177     //
       
   178     // getters (build comments for entities)
       
   179     //
       
   180 
       
   181     public String getPackageComment() {
       
   182         return Text.LOREMIPSUM
       
   183                + "\n <p>" + Text.LIEUROPANLINGUES
       
   184                + "\n" + Text.CODE
       
   185                + "\n" + LinkTag.nextLink()
       
   186                + "\n" + LinkTag.nextSee()
       
   187                + "\n" + Tag.SINCE;
       
   188     }
       
   189 
       
   190     String[] serialVals = new String[] { "include", "exclude" };
       
   191     // static index to roll over "include/exclude"
       
   192     static int serialValIdx = 0;
       
   193 
       
   194     public String getBaseComment(JCClassDecl baseDecl, boolean toplevel) {
       
   195         String buildComment = Text.LIEUROPANLINGUES + "\n";
       
   196 
       
   197         buildComment += "<p>It is possible to see inlined code:\n"
       
   198                         + InlineTag.CODE
       
   199                         + " is the example.\n\n";
       
   200 
       
   201         buildComment += "<p>Literal use example.\n"
       
   202                         + InlineTag.LITERAL + "\n\n";
       
   203 
       
   204         buildComment += "<p>" + Text.THISPANGRAM + "\n"; // make comment longer
       
   205 
       
   206         buildComment += "<p>" + LinkTag.nextLink() + "\n";
       
   207 
       
   208         if (toplevel)
       
   209             buildComment += "\n" + VersionTag.nextVersion() + "\n";
       
   210 
       
   211         // @param for type params
       
   212         List<JCTypeParameter> params = baseDecl.getTypeParameters();
       
   213         int paramIndex = 0;
       
   214         for (JCTypeParameter paramDecl : params) {
       
   215             buildComment += Tag.PARAM.value(
       
   216                                 "<" + paramDecl.getName().toString() + ">",
       
   217                                 "the type of value set #" + paramIndex++)
       
   218                             + "\n";
       
   219         }
       
   220 
       
   221         buildComment += "\n" + LinkTag.nextSee();
       
   222 
       
   223         buildComment += "\n";
       
   224 
       
   225         if (toplevel)
       
   226             buildComment += Tag.AUTHOR + "\n";
       
   227 
       
   228         buildComment += Tag.SINCE + "\n";
       
   229 
       
   230         // for serial; currently no need to dig too deep
       
   231         if (isSerializable(baseDecl) || isErrorOrException(baseDecl)) {
       
   232             buildComment += "\n" + Tag.SERIAL.value(serialVals[serialValIdx]);
       
   233             serialValIdx = (serialValIdx + 1) % 2;
       
   234         }
       
   235 
       
   236         return buildComment;
       
   237     }
       
   238 
       
   239     public String getConstComment() {
       
   240         String buildComment = Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n";
       
   241 
       
   242         buildComment += LinkTag.nextLink() + "\n";
       
   243         buildComment += LinkTag.nextSee() + "\n";
       
   244         buildComment += Tag.SINCE + "\n";
       
   245 
       
   246         return buildComment;
       
   247     }
       
   248 
       
   249     public String getFieldComment(JCClassDecl baseDecl,
       
   250                                   JCVariableDecl varDecl,
       
   251                                   boolean isFxStyle) {
       
   252         String buildComment = Text.BROWNFOX + "<p>" + Text.NOWISTHETIME + "\n";
       
   253 
       
   254         Set<Modifier> mods = varDecl.getModifiers().getFlags();
       
   255         String varName = varDecl.getName().toString();
       
   256 
       
   257         if (mods.contains(Modifier.STATIC) && mods.contains(Modifier.FINAL)) {
       
   258             JCExpression init = varDecl.getInitializer();
       
   259             if (init != null
       
   260                 && !"null".equals(init.toString())
       
   261                 && !"serialPersistentFields".equals(varName))
       
   262                 buildComment += "<p>The value of this constant is "
       
   263                                 + InlineTag.VALUE
       
   264                                 + ".\n";
       
   265         }
       
   266 
       
   267         buildComment += "<p>" + LinkTag.nextLink() + "\n";
       
   268 
       
   269         if (isSerializable(baseDecl)) {
       
   270             if (isErrorOrException(baseDecl)) {
       
   271                 buildComment += Tag.SERIAL + "\n";
       
   272             } else if ("serialPersistentFields".equals(varName)) {
       
   273                 JCNewArray sfList = (JCNewArray)varDecl.getInitializer();
       
   274                 for (JCExpression sf : sfList.getInitializers()) {
       
   275                     List<JCExpression> args = ((JCNewClass)sf).getArguments();
       
   276                     String sfName = ((JCLiteral)args.get(0)).getValue().toString();
       
   277                     String sfClass = ((JCIdent)args.get(1)).getName().toString();
       
   278                     String sfType = sfClass.substring(0, sfClass.indexOf(".class"));
       
   279 
       
   280                     buildComment += Tag.SERIALFIELD.value(sfName + "    " + sfType)
       
   281                                     + "\n";
       
   282                 }
       
   283             } else {
       
   284                 buildComment += Tag.SERIAL.value("Very important value.") + "\n";
       
   285             }
       
   286         }
       
   287 
       
   288         if (isFxStyle) {
       
   289             // set default value
       
   290             String varType = varDecl.getType().toString();
       
   291             buildComment += Tag.FX_DEFVALUE.value(defValue(varType)) + "\n";
       
   292         }
       
   293 
       
   294         buildComment += LinkTag.nextSee() + "\n";
       
   295 
       
   296         return buildComment;
       
   297     }
       
   298 
       
   299     public String getMethodComment(JCClassDecl baseDecl,
       
   300                                    JCMethodDecl methodDecl,
       
   301                                    boolean isFxStyle) {
       
   302         String buildComment = Text.BROWNFOX + "\n<p>" + Text.THISPANGRAM + "\n";
       
   303 
       
   304         buildComment += "<p>" + LinkTag.nextLink() + "\n";
       
   305 
       
   306         buildComment += "<p>Literal use example.\n"
       
   307                         + InlineTag.LITERAL + "\n\n";
       
   308 
       
   309         // @param for type params
       
   310         List<JCTypeParameter> tparams = methodDecl.getTypeParameters();
       
   311         int tparamIndex = 0;
       
   312         for (JCTypeParameter paramDecl : tparams) {
       
   313             String paramDeclString = paramDecl.getName().toString();
       
   314             // simplify it (could contain 'extend'/'super' clauses
       
   315             int spacePos = paramDeclString.indexOf(' ');
       
   316             if (spacePos != -1)
       
   317                 paramDeclString = paramDeclString.substring(0, spacePos);
       
   318             buildComment += Tag.PARAM.value(
       
   319                                 "<" + paramDeclString + ">",
       
   320                                 "the type of value set #" + tparamIndex++)
       
   321                             + "\n";
       
   322         }
       
   323 
       
   324         // @param
       
   325         List<JCVariableDecl> params =  methodDecl.getParameters();
       
   326         int paramIndex = 0;
       
   327         for (JCVariableDecl paramDecl : params) {
       
   328             buildComment += Tag.PARAM.value(
       
   329                                 paramDecl.getName().toString(),
       
   330                                 "an income parameter #" + paramIndex++)
       
   331                             + "\n";
       
   332         }
       
   333 
       
   334         // @return
       
   335         JCTree retType = methodDecl.getReturnType(); // null for constructors
       
   336         if (retType != null && !"void".equals(retType.toString()))
       
   337             buildComment += Tag.RETURN + "\n";
       
   338 
       
   339         // @throws/@exception
       
   340         Tag t = isDerived(baseDecl) ? Tag.EXCEPTION : Tag.THROWS;
       
   341         List<JCExpression> throwTypes = methodDecl.getThrows();
       
   342         for (JCExpression throwsExp : throwTypes) {
       
   343             buildComment += t.value(throwsExp.toString()) + "\n";
       
   344         }
       
   345 
       
   346         if (isSerializable(baseDecl)) {
       
   347             switch (methodDecl.getName().toString()) {
       
   348                 case "writeObject":
       
   349                 case "readObject":
       
   350                 case "writeExternal":
       
   351                 case "readExternal":
       
   352                 case "writeReplace":
       
   353                 case "readResolve":
       
   354                     buildComment += Tag.SERIALDATA + "\n";
       
   355                     break;
       
   356                 default:
       
   357             }
       
   358         }
       
   359 
       
   360         if (isFxStyle) {
       
   361             // @propertySetter/Getter + Description
       
   362             if ("void".equals(retType.toString())) {
       
   363                 buildComment += Tag.FX_PROPSETTER + "\n";
       
   364             } else {
       
   365                 buildComment += Tag.FX_PROPGETTER + "\n";
       
   366                 buildComment += Tag.FX_DEFVALUE.value(defValue(retType.toString()))
       
   367                                 + "\n";
       
   368             }
       
   369             buildComment += Tag.FX_PROPDESC.value(Text.BROWNFOX.toString()) + "\n";
       
   370 
       
   371             // @treatAsPrivate
       
   372             if (methodDecl.getModifiers().getFlags().contains(Modifier.PUBLIC))
       
   373                 buildComment += Tag.FX_TREATASPRIVATE + "\n";
       
   374         }
       
   375 
       
   376         // @see
       
   377         buildComment += LinkTag.nextSee() + "\n";
       
   378 
       
   379         // @since
       
   380         buildComment += Tag.SINCE + "\n";
       
   381 
       
   382         return buildComment;
       
   383     }
       
   384 
       
   385     //
       
   386     // util methods
       
   387     //
       
   388 
       
   389     private boolean isErrorOrException(JCClassDecl baseDecl) {
       
   390         JCExpression ext = baseDecl.getExtendsClause();
       
   391         if (ext != null) {
       
   392             String extClassName = ext.toString();
       
   393             if (extClassName.contains("Error") || extClassName.contains("Exception"))
       
   394                 return true;
       
   395         }
       
   396         return false;
       
   397     }
       
   398 
       
   399     private boolean isSerializable(JCClassDecl baseDecl) {
       
   400         List<JCExpression> impls = baseDecl.getImplementsClause();
       
   401         for (JCExpression impl : impls) {
       
   402             if (impl.toString().contains("Serializable"))
       
   403                 return true;
       
   404         }
       
   405         return false;
       
   406     }
       
   407 
       
   408     private boolean isDerived(JCClassDecl baseDecl) {
       
   409         return (baseDecl.getExtendsClause() == null) ? false : true;
       
   410     }
       
   411 
       
   412     private String defValue(String type) {
       
   413         switch (type) {
       
   414             case "boolean":
       
   415                 return "true";
       
   416             case "byte": case "char": case "int": case "long":
       
   417             case "Integer": case "Long":
       
   418                 return "1";
       
   419             case "float": case "double": case "Float": case "Double":
       
   420                 return "1.0";
       
   421             case "String":
       
   422                 return "string";
       
   423             default:
       
   424                 return "null";
       
   425         }
       
   426     }
       
   427 
       
   428     private static final String BROWNFOX_TEXT =
       
   429         "The quick brown fox jumps over the lazy dog.\n";
       
   430     private static final String NOWISTHETIME_TEXT =
       
   431         "Now is the time for all good men to come to the aid of the party.\n";
       
   432     private static final String THISPANGRAM_TEXT =
       
   433         "This pangram contains four a's, one b, two c's, one d, thirty e's,\n" +
       
   434         "six f's, five g's, seven h's, eleven i's, one j, one k, two l's,\n" +
       
   435         "two m's, eighteen n's, fifteen o's, two p's, one q, five r's,\n" +
       
   436         "twenty-seven s's, eighteen t's, two u's, seven v's, eight w's,\n" +
       
   437         "two x's, three y's, &amp; one z.";
       
   438     private static final String LOREMIPSUM_TEXT =
       
   439         "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\n" +
       
   440         "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut\n" +
       
   441         "enim ad minim veniam, quis nostrud exercitation ullamco laboris\n" +
       
   442         "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor\n" +
       
   443         "in reprehenderit in voluptate velit esse cillum dolore eu fugiat\n" +
       
   444         "nulla pariatur. Excepteur sint occaecat cupidatat non proident,\n" +
       
   445         "sunt in culpa qui officia deserunt mollit anim id est laborum.\n";
       
   446     private static final String LIEUROPANLINGUES_TEXT =
       
   447         "Li Europan lingues es membres del sam familie. Lor separat existentie\n" +
       
   448         "es un myth. Por scientie, musica, sport etc, litot Europa usa li sam\n" +
       
   449         "vocabular. Li lingues differe solmen in li grammatica, li pronunciation\n" +
       
   450         "e li plu commun vocabules. Omnicos directe al desirabilite de un nov\n" +
       
   451         "lingua franca: On refusa continuar payar custosi traductores.\n" +
       
   452         "\n" +
       
   453         "<p>At solmen va esser necessi far uniform grammatica, pronunciation\n" +
       
   454         "e plu commun paroles. Ma quande lingues coalesce, li grammatica del\n" +
       
   455         "resultant lingue es plu simplic e regulari quam ti del coalescent\n" +
       
   456         "lingues. Li nov lingua franca va esser plu simplic e regulari quam\n" +
       
   457         "li existent Europan lingues. It va esser tam simplic quam Occidental\n" +
       
   458         "in fact, it va esser Occidental. A un Angleso it va semblar un simplificat\n" +
       
   459         "Angles, quam un skeptic Cambridge amico dit me que Occidental es.\n";
       
   460     private static final String CODE_TEXT =
       
   461         "<pre>\n" +
       
   462         "public void checkLanguage(Language lang) throws Exception {\n" +
       
   463         "    if (lang.getName().equals(\"Java\")) {\n" +
       
   464         "        System.out.println(\"Warning! Hot!\");\n" +
       
   465         "    else {\n" +
       
   466         "        throw new LooserException();\n" +
       
   467         "    }\n" +
       
   468         "}\n" +
       
   469         "</pre>\n";
       
   470 }