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

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

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

mercurial