src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java

Thu, 29 Aug 2013 11:41:20 -0700

author
jjg
date
Thu, 29 Aug 2013 11:41:20 -0700
changeset 1985
0e6577980181
parent 1963
a76dc1b4c299
child 2413
fe033d997ddf
permissions
-rw-r--r--

8001669: javadoc internal DocletAbortException should set cause when appropriate
Reviewed-by: darcy

     1 /*
     2  * Copyright (c) 1999, 2013, 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.doclets.internal.toolkit.util;
    28 import java.io.*;
    29 import java.lang.annotation.ElementType;
    30 import java.util.*;
    32 import com.sun.javadoc.*;
    33 import com.sun.javadoc.AnnotationDesc.ElementValuePair;
    34 import com.sun.tools.doclets.internal.toolkit.*;
    35 import javax.tools.StandardLocation;
    37 /**
    38  * Utilities Class for Doclets.
    39  *
    40  *  <p><b>This is NOT part of any supported API.
    41  *  If you write code that depends on this, you do so at your own risk.
    42  *  This code and its internal interfaces are subject to change or
    43  *  deletion without notice.</b>
    44  *
    45  * @author Atul M Dambalkar
    46  * @author Jamie Ho
    47  */
    48 public class Util {
    50     /**
    51      * Return array of class members whose documentation is to be generated.
    52      * If the member is deprecated do not include such a member in the
    53      * returned array.
    54      *
    55      * @param  members             Array of members to choose from.
    56      * @return ProgramElementDoc[] Array of eligible members for whom
    57      *                             documentation is getting generated.
    58      */
    59     public static ProgramElementDoc[] excludeDeprecatedMembers(
    60         ProgramElementDoc[] members) {
    61         return
    62             toProgramElementDocArray(excludeDeprecatedMembersAsList(members));
    63     }
    65     /**
    66      * Return array of class members whose documentation is to be generated.
    67      * If the member is deprecated do not include such a member in the
    68      * returned array.
    69      *
    70      * @param  members    Array of members to choose from.
    71      * @return List       List of eligible members for whom
    72      *                    documentation is getting generated.
    73      */
    74     public static List<ProgramElementDoc> excludeDeprecatedMembersAsList(
    75         ProgramElementDoc[] members) {
    76         List<ProgramElementDoc> list = new ArrayList<ProgramElementDoc>();
    77         for (int i = 0; i < members.length; i++) {
    78             if (members[i].tags("deprecated").length == 0) {
    79                 list.add(members[i]);
    80             }
    81         }
    82         Collections.sort(list);
    83         return list;
    84     }
    86     /**
    87      * Return the list of ProgramElementDoc objects as Array.
    88      */
    89     public static ProgramElementDoc[] toProgramElementDocArray(List<ProgramElementDoc> list) {
    90         ProgramElementDoc[] pgmarr = new ProgramElementDoc[list.size()];
    91         for (int i = 0; i < list.size(); i++) {
    92             pgmarr[i] = list.get(i);
    93         }
    94         return pgmarr;
    95     }
    97     /**
    98      * Return true if a non-public member found in the given array.
    99      *
   100      * @param  members Array of members to look into.
   101      * @return boolean True if non-public member found, false otherwise.
   102      */
   103     public static boolean nonPublicMemberFound(ProgramElementDoc[] members) {
   104         for (int i = 0; i < members.length; i++) {
   105             if (!members[i].isPublic()) {
   106                 return true;
   107             }
   108         }
   109         return false;
   110     }
   112     /**
   113      * Search for the given method in the given class.
   114      *
   115      * @param  cd        Class to search into.
   116      * @param  method    Method to be searched.
   117      * @return MethodDoc Method found, null otherwise.
   118      */
   119     public static MethodDoc findMethod(ClassDoc cd, MethodDoc method) {
   120         MethodDoc[] methods = cd.methods();
   121         for (int i = 0; i < methods.length; i++) {
   122             if (executableMembersEqual(method, methods[i])) {
   123                 return methods[i];
   125             }
   126         }
   127         return null;
   128     }
   130     /**
   131      * @param member1 the first method to compare.
   132      * @param member2 the second method to compare.
   133      * @return true if member1 overrides/hides or is overriden/hidden by member2.
   134      */
   135     public static boolean executableMembersEqual(ExecutableMemberDoc member1,
   136             ExecutableMemberDoc member2) {
   137         if (! (member1 instanceof MethodDoc && member2 instanceof MethodDoc))
   138             return false;
   140         MethodDoc method1 = (MethodDoc) member1;
   141         MethodDoc method2 = (MethodDoc) member2;
   142         if (method1.isStatic() && method2.isStatic()) {
   143             Parameter[] targetParams = method1.parameters();
   144             Parameter[] currentParams;
   145             if (method1.name().equals(method2.name()) &&
   146                    (currentParams = method2.parameters()).length ==
   147                 targetParams.length) {
   148                 int j;
   149                 for (j = 0; j < targetParams.length; j++) {
   150                     if (! (targetParams[j].typeName().equals(
   151                               currentParams[j].typeName()) ||
   152                                    currentParams[j].type() instanceof TypeVariable ||
   153                                    targetParams[j].type() instanceof TypeVariable)) {
   154                         break;
   155                     }
   156                 }
   157                 if (j == targetParams.length) {
   158                     return true;
   159                 }
   160             }
   161             return false;
   162         } else {
   163                 return method1.overrides(method2) ||
   164                 method2.overrides(method1) ||
   165                                 member1 == member2;
   166         }
   167     }
   169     /**
   170      * According to
   171      * <cite>The Java&trade; Language Specification</cite>,
   172      * all the outer classes and static inner classes are core classes.
   173      */
   174     public static boolean isCoreClass(ClassDoc cd) {
   175         return cd.containingClass() == null || cd.isStatic();
   176     }
   178     public static boolean matches(ProgramElementDoc doc1,
   179             ProgramElementDoc doc2) {
   180         if (doc1 instanceof ExecutableMemberDoc &&
   181             doc2 instanceof ExecutableMemberDoc) {
   182             ExecutableMemberDoc ed1 = (ExecutableMemberDoc)doc1;
   183             ExecutableMemberDoc ed2 = (ExecutableMemberDoc)doc2;
   184             return executableMembersEqual(ed1, ed2);
   185         } else {
   186             return doc1.name().equals(doc2.name());
   187         }
   188     }
   190     /**
   191      * Copy the given directory contents from the source package directory
   192      * to the generated documentation directory. For example for a package
   193      * java.lang this method find out the source location of the package using
   194      * {@link SourcePath} and if given directory is found in the source
   195      * directory structure, copy the entire directory, to the generated
   196      * documentation hierarchy.
   197      *
   198      * @param configuration The configuration of the current doclet.
   199      * @param path The relative path to the directory to be copied.
   200      * @param dir The original directory name to copy from.
   201      * @param overwrite Overwrite files if true.
   202      */
   203     public static void copyDocFiles(Configuration configuration, PackageDoc pd) {
   204         copyDocFiles(configuration, DocPath.forPackage(pd).resolve(DocPaths.DOC_FILES));
   205     }
   207     public static void copyDocFiles(Configuration configuration, DocPath dir) {
   208         try {
   209             boolean first = true;
   210             for (DocFile f : DocFile.list(configuration, StandardLocation.SOURCE_PATH, dir)) {
   211                 if (!f.isDirectory()) {
   212                     continue;
   213                 }
   214                 DocFile srcdir = f;
   215                 DocFile destdir = DocFile.createFileForOutput(configuration, dir);
   216                 if (srcdir.isSameFile(destdir)) {
   217                     continue;
   218                 }
   220                 for (DocFile srcfile: srcdir.list()) {
   221                     DocFile destfile = destdir.resolve(srcfile.getName());
   222                     if (srcfile.isFile()) {
   223                         if (destfile.exists() && !first) {
   224                             configuration.message.warning((SourcePosition) null,
   225                                     "doclet.Copy_Overwrite_warning",
   226                                     srcfile.getPath(), destdir.getPath());
   227                         } else {
   228                             configuration.message.notice(
   229                                     "doclet.Copying_File_0_To_Dir_1",
   230                                     srcfile.getPath(), destdir.getPath());
   231                             destfile.copyFile(srcfile);
   232                         }
   233                     } else if (srcfile.isDirectory()) {
   234                         if (configuration.copydocfilesubdirs
   235                                 && !configuration.shouldExcludeDocFileDir(srcfile.getName())) {
   236                             copyDocFiles(configuration, dir.resolve(srcfile.getName()));
   237                         }
   238                     }
   239                 }
   241                 first = false;
   242             }
   243         } catch (SecurityException exc) {
   244             throw new DocletAbortException(exc);
   245         } catch (IOException exc) {
   246             throw new DocletAbortException(exc);
   247         }
   248     }
   250     /**
   251      * We want the list of types in alphabetical order.  However, types are not
   252      * comparable.  We need a comparator for now.
   253      */
   254     private static class TypeComparator implements Comparator<Type> {
   255         public int compare(Type type1, Type type2) {
   256             return type1.qualifiedTypeName().toLowerCase().compareTo(
   257                 type2.qualifiedTypeName().toLowerCase());
   258         }
   259     }
   261     /**
   262      * For the class return all implemented interfaces including the
   263      * superinterfaces of the implementing interfaces, also iterate over for
   264      * all the superclasses. For interface return all the extended interfaces
   265      * as well as superinterfaces for those extended interfaces.
   266      *
   267      * @param  type       type whose implemented or
   268      *                    super interfaces are sought.
   269      * @param  configuration the current configuration of the doclet.
   270      * @param  sort if true, return list of interfaces sorted alphabetically.
   271      * @return List of all the required interfaces.
   272      */
   273     public static List<Type> getAllInterfaces(Type type,
   274             Configuration configuration, boolean sort) {
   275         Map<ClassDoc,Type> results = sort ? new TreeMap<ClassDoc,Type>() : new LinkedHashMap<ClassDoc,Type>();
   276         Type[] interfaceTypes = null;
   277         Type superType = null;
   278         if (type instanceof ParameterizedType) {
   279             interfaceTypes = ((ParameterizedType) type).interfaceTypes();
   280             superType = ((ParameterizedType) type).superclassType();
   281         } else if (type instanceof ClassDoc) {
   282             interfaceTypes = ((ClassDoc) type).interfaceTypes();
   283             superType = ((ClassDoc) type).superclassType();
   284         } else {
   285             interfaceTypes = type.asClassDoc().interfaceTypes();
   286             superType = type.asClassDoc().superclassType();
   287         }
   289         for (int i = 0; i < interfaceTypes.length; i++) {
   290             Type interfaceType = interfaceTypes[i];
   291             ClassDoc interfaceClassDoc = interfaceType.asClassDoc();
   292             if (! (interfaceClassDoc.isPublic() ||
   293                 (configuration == null ||
   294                 isLinkable(interfaceClassDoc, configuration)))) {
   295                 continue;
   296             }
   297             results.put(interfaceClassDoc, interfaceType);
   298             List<Type> superInterfaces = getAllInterfaces(interfaceType, configuration, sort);
   299             for (Iterator<Type> iter = superInterfaces.iterator(); iter.hasNext(); ) {
   300                 Type t = iter.next();
   301                 results.put(t.asClassDoc(), t);
   302             }
   303         }
   304         if (superType == null)
   305             return new ArrayList<Type>(results.values());
   306         //Try walking the tree.
   307         addAllInterfaceTypes(results,
   308             superType,
   309             interfaceTypesOf(superType),
   310             false, configuration);
   311         List<Type> resultsList = new ArrayList<Type>(results.values());
   312         if (sort) {
   313                 Collections.sort(resultsList, new TypeComparator());
   314         }
   315         return resultsList;
   316     }
   318     private static Type[] interfaceTypesOf(Type type) {
   319         if (type instanceof AnnotatedType)
   320             type = ((AnnotatedType)type).underlyingType();
   321         return type instanceof ClassDoc ?
   322                 ((ClassDoc)type).interfaceTypes() :
   323                 ((ParameterizedType)type).interfaceTypes();
   324     }
   326     public static List<Type> getAllInterfaces(Type type, Configuration configuration) {
   327         return getAllInterfaces(type, configuration, true);
   328     }
   330     private static void findAllInterfaceTypes(Map<ClassDoc,Type> results, ClassDoc c, boolean raw,
   331             Configuration configuration) {
   332         Type superType = c.superclassType();
   333         if (superType == null)
   334             return;
   335         addAllInterfaceTypes(results, superType,
   336                 interfaceTypesOf(superType),
   337                 raw, configuration);
   338     }
   340     private static void findAllInterfaceTypes(Map<ClassDoc,Type> results, ParameterizedType p,
   341             Configuration configuration) {
   342         Type superType = p.superclassType();
   343         if (superType == null)
   344             return;
   345         addAllInterfaceTypes(results, superType,
   346                 interfaceTypesOf(superType),
   347                 false, configuration);
   348     }
   350     private static void addAllInterfaceTypes(Map<ClassDoc,Type> results, Type type,
   351             Type[] interfaceTypes, boolean raw,
   352             Configuration configuration) {
   353         for (int i = 0; i < interfaceTypes.length; i++) {
   354             Type interfaceType = interfaceTypes[i];
   355             ClassDoc interfaceClassDoc = interfaceType.asClassDoc();
   356             if (! (interfaceClassDoc.isPublic() ||
   357                 (configuration != null &&
   358                 isLinkable(interfaceClassDoc, configuration)))) {
   359                 continue;
   360             }
   361             if (raw)
   362                 interfaceType = interfaceType.asClassDoc();
   363             results.put(interfaceClassDoc, interfaceType);
   364             List<Type> superInterfaces = getAllInterfaces(interfaceType, configuration);
   365             for (Iterator<Type> iter = superInterfaces.iterator(); iter.hasNext(); ) {
   366                 Type superInterface = iter.next();
   367                 results.put(superInterface.asClassDoc(), superInterface);
   368             }
   369         }
   370         if (type instanceof AnnotatedType)
   371             type = ((AnnotatedType)type).underlyingType();
   373         if (type instanceof ParameterizedType)
   374             findAllInterfaceTypes(results, (ParameterizedType) type, configuration);
   375         else if (((ClassDoc) type).typeParameters().length == 0)
   376             findAllInterfaceTypes(results, (ClassDoc) type, raw, configuration);
   377         else
   378             findAllInterfaceTypes(results, (ClassDoc) type, true, configuration);
   379     }
   381     /**
   382      * Enclose in quotes, used for paths and filenames that contains spaces
   383      */
   384     public static String quote(String filepath) {
   385         return ("\"" + filepath + "\"");
   386     }
   388     /**
   389      * Given a package, return its name.
   390      * @param packageDoc the package to check.
   391      * @return the name of the given package.
   392      */
   393     public static String getPackageName(PackageDoc packageDoc) {
   394         return packageDoc == null || packageDoc.name().length() == 0 ?
   395             DocletConstants.DEFAULT_PACKAGE_NAME : packageDoc.name();
   396     }
   398     /**
   399      * Given a package, return its file name without the extension.
   400      * @param packageDoc the package to check.
   401      * @return the file name of the given package.
   402      */
   403     public static String getPackageFileHeadName(PackageDoc packageDoc) {
   404         return packageDoc == null || packageDoc.name().length() == 0 ?
   405             DocletConstants.DEFAULT_PACKAGE_FILE_NAME : packageDoc.name();
   406     }
   408     /**
   409      * Given a string, replace all occurrences of 'newStr' with 'oldStr'.
   410      * @param originalStr the string to modify.
   411      * @param oldStr the string to replace.
   412      * @param newStr the string to insert in place of the old string.
   413      */
   414     public static String replaceText(String originalStr, String oldStr,
   415             String newStr) {
   416         if (oldStr == null || newStr == null || oldStr.equals(newStr)) {
   417             return originalStr;
   418         }
   419         return originalStr.replace(oldStr, newStr);
   420     }
   422     /**
   423      * Given an annotation, return true if it should be documented and false
   424      * otherwise.
   425      *
   426      * @param annotationDoc the annotation to check.
   427      *
   428      * @return true return true if it should be documented and false otherwise.
   429      */
   430     public static boolean isDocumentedAnnotation(AnnotationTypeDoc annotationDoc) {
   431         AnnotationDesc[] annotationDescList = annotationDoc.annotations();
   432         for (int i = 0; i < annotationDescList.length; i++) {
   433             if (annotationDescList[i].annotationType().qualifiedName().equals(
   434                    java.lang.annotation.Documented.class.getName())){
   435                 return true;
   436             }
   437         }
   438         return false;
   439     }
   441     private static boolean isDeclarationTarget(AnnotationDesc targetAnno) {
   442         // The error recovery steps here are analogous to TypeAnnotations
   443         ElementValuePair[] elems = targetAnno.elementValues();
   444         if (elems == null
   445             || elems.length != 1
   446             || !"value".equals(elems[0].element().name())
   447             || !(elems[0].value().value() instanceof AnnotationValue[]))
   448             return true;    // error recovery
   450         AnnotationValue[] values = (AnnotationValue[])elems[0].value().value();
   451         for (int i = 0; i < values.length; i++) {
   452             Object value = values[i].value();
   453             if (!(value instanceof FieldDoc))
   454                 return true; // error recovery
   456             FieldDoc eValue = (FieldDoc)value;
   457             if (Util.isJava5DeclarationElementType(eValue)) {
   458                 return true;
   459             }
   460         }
   462         return false;
   463     }
   465     /**
   466      * Returns true if the {@code annotationDoc} is to be treated
   467      * as a declaration annotation, when targeting the
   468      * {@code elemType} element type.
   469      *
   470      * @param annotationDoc the annotationDoc to check
   471      * @param elemType  the targeted elemType
   472      * @return true if annotationDoc is a declaration annotation
   473      */
   474     public static boolean isDeclarationAnnotation(AnnotationTypeDoc annotationDoc,
   475             boolean isJava5DeclarationLocation) {
   476         if (!isJava5DeclarationLocation)
   477             return false;
   478         AnnotationDesc[] annotationDescList = annotationDoc.annotations();
   479         // Annotations with no target are treated as declaration as well
   480         if (annotationDescList.length==0)
   481             return true;
   482         for (int i = 0; i < annotationDescList.length; i++) {
   483             if (annotationDescList[i].annotationType().qualifiedName().equals(
   484                     java.lang.annotation.Target.class.getName())) {
   485                 if (isDeclarationTarget(annotationDescList[i]))
   486                     return true;
   487             }
   488         }
   489         return false;
   490     }
   492     /**
   493      * Return true if this class is linkable and false if we can't link to the
   494      * desired class.
   495      * <br>
   496      * <b>NOTE:</b>  You can only link to external classes if they are public or
   497      * protected.
   498      *
   499      * @param classDoc the class to check.
   500      * @param configuration the current configuration of the doclet.
   501      *
   502      * @return true if this class is linkable and false if we can't link to the
   503      * desired class.
   504      */
   505     public static boolean isLinkable(ClassDoc classDoc,
   506             Configuration configuration) {
   507         return
   508             ((classDoc.isIncluded() && configuration.isGeneratedDoc(classDoc))) ||
   509             (configuration.extern.isExternal(classDoc) &&
   510                 (classDoc.isPublic() || classDoc.isProtected()));
   511     }
   513     /**
   514      * Given a class, return the closest visible super class.
   515      *
   516      * @param classDoc the class we are searching the parent for.
   517      * @param configuration the current configuration of the doclet.
   518      * @return the closest visible super class.  Return null if it cannot
   519      *         be found (i.e. classDoc is java.lang.Object).
   520      */
   521     public static Type getFirstVisibleSuperClass(ClassDoc classDoc,
   522             Configuration configuration) {
   523         if (classDoc == null) {
   524             return null;
   525         }
   526         Type sup = classDoc.superclassType();
   527         ClassDoc supClassDoc = classDoc.superclass();
   528         while (sup != null &&
   529                   (! (supClassDoc.isPublic() ||
   530                               isLinkable(supClassDoc, configuration))) ) {
   531             if (supClassDoc.superclass().qualifiedName().equals(supClassDoc.qualifiedName()))
   532                 break;
   533             sup = supClassDoc.superclassType();
   534             supClassDoc = supClassDoc.superclass();
   535         }
   536         if (classDoc.equals(supClassDoc)) {
   537             return null;
   538         }
   539         return sup;
   540     }
   542     /**
   543      * Given a class, return the closest visible super class.
   544      *
   545      * @param classDoc the class we are searching the parent for.
   546      * @param configuration the current configuration of the doclet.
   547      * @return the closest visible super class.  Return null if it cannot
   548      *         be found (i.e. classDoc is java.lang.Object).
   549      */
   550     public static ClassDoc getFirstVisibleSuperClassCD(ClassDoc classDoc,
   551             Configuration configuration) {
   552         if (classDoc == null) {
   553             return null;
   554         }
   555         ClassDoc supClassDoc = classDoc.superclass();
   556         while (supClassDoc != null &&
   557                   (! (supClassDoc.isPublic() ||
   558                               isLinkable(supClassDoc, configuration))) ) {
   559             supClassDoc = supClassDoc.superclass();
   560         }
   561         if (classDoc.equals(supClassDoc)) {
   562             return null;
   563         }
   564         return supClassDoc;
   565     }
   567     /**
   568      * Given a ClassDoc, return the name of its type (Class, Interface, etc.).
   569      *
   570      * @param cd the ClassDoc to check.
   571      * @param lowerCaseOnly true if you want the name returned in lower case.
   572      *                      If false, the first letter of the name is capitalized.
   573      * @return
   574      */
   575     public static String getTypeName(Configuration config,
   576         ClassDoc cd, boolean lowerCaseOnly) {
   577         String typeName = "";
   578         if (cd.isOrdinaryClass()) {
   579             typeName = "doclet.Class";
   580         } else if (cd.isInterface()) {
   581             typeName = "doclet.Interface";
   582         } else if (cd.isException()) {
   583             typeName = "doclet.Exception";
   584         } else if (cd.isError()) {
   585             typeName = "doclet.Error";
   586         } else if (cd.isAnnotationType()) {
   587             typeName = "doclet.AnnotationType";
   588         } else if (cd.isEnum()) {
   589             typeName = "doclet.Enum";
   590         }
   591         return config.getText(
   592             lowerCaseOnly ? typeName.toLowerCase() : typeName);
   593     }
   595     /**
   596      * Replace all tabs in a string with the appropriate number of spaces.
   597      * The string may be a multi-line string.
   598      * @param configuration the doclet configuration defining the setting for the
   599      *                      tab length.
   600      * @param text the text for which the tabs should be expanded
   601      * @return the text with all tabs expanded
   602      */
   603     public static String replaceTabs(Configuration configuration, String text) {
   604         if (text.indexOf("\t") == -1)
   605             return text;
   607         final int tabLength = configuration.sourcetab;
   608         final String whitespace = configuration.tabSpaces;
   609         final int textLength = text.length();
   610         StringBuilder result = new StringBuilder(textLength);
   611         int pos = 0;
   612         int lineLength = 0;
   613         for (int i = 0; i < textLength; i++) {
   614             char ch = text.charAt(i);
   615             switch (ch) {
   616                 case '\n': case '\r':
   617                     lineLength = 0;
   618                     break;
   619                 case '\t':
   620                     result.append(text, pos, i);
   621                     int spaceCount = tabLength - lineLength % tabLength;
   622                     result.append(whitespace, 0, spaceCount);
   623                     lineLength += spaceCount;
   624                     pos = i + 1;
   625                     break;
   626                 default:
   627                     lineLength++;
   628             }
   629         }
   630         result.append(text, pos, textLength);
   631         return result.toString();
   632     }
   634     public static String normalizeNewlines(String text) {
   635         StringBuilder sb = new StringBuilder();
   636         final int textLength = text.length();
   637         final String NL = DocletConstants.NL;
   638         int pos = 0;
   639         for (int i = 0; i < textLength; i++) {
   640             char ch = text.charAt(i);
   641             switch (ch) {
   642                 case '\n':
   643                     sb.append(text, pos, i);
   644                     sb.append(NL);
   645                     pos = i + 1;
   646                     break;
   647                 case '\r':
   648                     sb.append(text, pos, i);
   649                     sb.append(NL);
   650                     if (i + 1 < textLength && text.charAt(i + 1) == '\n')
   651                         i++;
   652                     pos = i + 1;
   653                     break;
   654             }
   655         }
   656         sb.append(text, pos, textLength);
   657         return sb.toString();
   658     }
   660     /**
   661      * The documentation for values() and valueOf() in Enums are set by the
   662      * doclet.
   663      */
   664     public static void setEnumDocumentation(Configuration configuration,
   665             ClassDoc classDoc) {
   666         MethodDoc[] methods = classDoc.methods();
   667         for (int j = 0; j < methods.length; j++) {
   668             MethodDoc currentMethod = methods[j];
   669             if (currentMethod.name().equals("values") &&
   670                     currentMethod.parameters().length == 0) {
   671                 StringBuilder sb = new StringBuilder();
   672                 sb.append(configuration.getText("doclet.enum_values_doc.main", classDoc.name()));
   673                 sb.append("\n@return ");
   674                 sb.append(configuration.getText("doclet.enum_values_doc.return"));
   675                 currentMethod.setRawCommentText(sb.toString());
   676             } else if (currentMethod.name().equals("valueOf") &&
   677                     currentMethod.parameters().length == 1) {
   678                 Type paramType = currentMethod.parameters()[0].type();
   679                 if (paramType != null &&
   680                         paramType.qualifiedTypeName().equals(String.class.getName())) {
   681                 StringBuilder sb = new StringBuilder();
   682                 sb.append(configuration.getText("doclet.enum_valueof_doc.main", classDoc.name()));
   683                 sb.append("\n@param name ");
   684                 sb.append(configuration.getText("doclet.enum_valueof_doc.param_name"));
   685                 sb.append("\n@return ");
   686                 sb.append(configuration.getText("doclet.enum_valueof_doc.return"));
   687                 sb.append("\n@throws IllegalArgumentException ");
   688                 sb.append(configuration.getText("doclet.enum_valueof_doc.throws_ila"));
   689                 sb.append("\n@throws NullPointerException ");
   690                 sb.append(configuration.getText("doclet.enum_valueof_doc.throws_npe"));
   691                 currentMethod.setRawCommentText(sb.toString());
   692                 }
   693             }
   694         }
   695     }
   697     /**
   698      *  Return true if the given Doc is deprecated.
   699      *
   700      * @param doc the Doc to check.
   701      * @return true if the given Doc is deprecated.
   702      */
   703     public static boolean isDeprecated(Doc doc) {
   704         if (doc.tags("deprecated").length > 0) {
   705             return true;
   706         }
   707         AnnotationDesc[] annotationDescList;
   708         if (doc instanceof PackageDoc)
   709             annotationDescList = ((PackageDoc)doc).annotations();
   710         else
   711             annotationDescList = ((ProgramElementDoc)doc).annotations();
   712         for (int i = 0; i < annotationDescList.length; i++) {
   713             if (annotationDescList[i].annotationType().qualifiedName().equals(
   714                    java.lang.Deprecated.class.getName())){
   715                 return true;
   716             }
   717         }
   718         return false;
   719     }
   721     /**
   722      * A convenience method to get property name from the name of the
   723      * getter or setter method.
   724      * @param name name of the getter or setter method.
   725      * @return the name of the property of the given setter of getter.
   726      */
   727     public static String propertyNameFromMethodName(String name) {
   728         String propertyName = null;
   729         if (name.startsWith("get") || name.startsWith("set")) {
   730             propertyName = name.substring(3);
   731         } else if (name.startsWith("is")) {
   732             propertyName = name.substring(2);
   733         }
   734         if ((propertyName == null) || propertyName.isEmpty()){
   735             return "";
   736         }
   737         return propertyName.substring(0, 1).toLowerCase()
   738                 + propertyName.substring(1);
   739     }
   741     /**
   742      * In case of JavaFX mode on, filters out classes that are private,
   743      * package private or having the @treatAsPrivate annotation. Those are not
   744      * documented in JavaFX mode.
   745      *
   746      * @param classes array of classes to be filtered.
   747      * @param javafx set to true if in JavaFX mode.
   748      * @return list of filtered classes.
   749      */
   750     public static ClassDoc[] filterOutPrivateClasses(final ClassDoc[] classes,
   751                                                      boolean javafx) {
   752         if (!javafx) {
   753             return classes;
   754         }
   755         final List<ClassDoc> filteredOutClasses =
   756                 new ArrayList<ClassDoc>(classes.length);
   757         for (ClassDoc classDoc : classes) {
   758             if (classDoc.isPrivate() || classDoc.isPackagePrivate()) {
   759                 continue;
   760             }
   761             Tag[] aspTags = classDoc.tags("treatAsPrivate");
   762             if (aspTags != null && aspTags.length > 0) {
   763                 continue;
   764             }
   765             filteredOutClasses.add(classDoc);
   766         }
   768         return filteredOutClasses.toArray(new ClassDoc[0]);
   769     }
   771     /**
   772      * Test whether the given FieldDoc is one of the declaration annotation ElementTypes
   773      * defined in Java 5.
   774      * Instead of testing for one of the new enum constants added in Java 8, test for
   775      * the old constants. This prevents bootstrapping problems.
   776      *
   777      * @param elt The FieldDoc to test
   778      * @return true, iff the given ElementType is one of the constants defined in Java 5
   779      * @since 1.8
   780      */
   781     public static boolean isJava5DeclarationElementType(FieldDoc elt) {
   782         return elt.name().contentEquals(ElementType.ANNOTATION_TYPE.name()) ||
   783                 elt.name().contentEquals(ElementType.CONSTRUCTOR.name()) ||
   784                 elt.name().contentEquals(ElementType.FIELD.name()) ||
   785                 elt.name().contentEquals(ElementType.LOCAL_VARIABLE.name()) ||
   786                 elt.name().contentEquals(ElementType.METHOD.name()) ||
   787                 elt.name().contentEquals(ElementType.PACKAGE.name()) ||
   788                 elt.name().contentEquals(ElementType.PARAMETER.name()) ||
   789                 elt.name().contentEquals(ElementType.TYPE.name());
   790     }
   791 }

mercurial