diff -r 000000000000 -r 959103a6100f src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Wed Apr 27 01:34:52 2016 +0800 @@ -0,0 +1,792 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.internal.toolkit.util; + +import java.io.*; +import java.lang.annotation.ElementType; +import java.util.*; +import javax.tools.StandardLocation; + +import com.sun.javadoc.*; +import com.sun.javadoc.AnnotationDesc.ElementValuePair; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.javac.util.StringUtils; + +/** + * Utilities Class for Doclets. + * + *
This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.
+ *
+ * @author Atul M Dambalkar
+ * @author Jamie Ho
+ */
+public class Util {
+
+ /**
+ * Return array of class members whose documentation is to be generated.
+ * If the member is deprecated do not include such a member in the
+ * returned array.
+ *
+ * @param members Array of members to choose from.
+ * @return ProgramElementDoc[] Array of eligible members for whom
+ * documentation is getting generated.
+ */
+ public static ProgramElementDoc[] excludeDeprecatedMembers(
+ ProgramElementDoc[] members) {
+ return
+ toProgramElementDocArray(excludeDeprecatedMembersAsList(members));
+ }
+
+ /**
+ * Return array of class members whose documentation is to be generated.
+ * If the member is deprecated do not include such a member in the
+ * returned array.
+ *
+ * @param members Array of members to choose from.
+ * @return List List of eligible members for whom
+ * documentation is getting generated.
+ */
+ public static List
+ * NOTE: You can only link to external classes if they are public or
+ * protected.
+ *
+ * @param classDoc the class to check.
+ * @param configuration the current configuration of the doclet.
+ *
+ * @return true if this class is linkable and false if we can't link to the
+ * desired class.
+ */
+ public static boolean isLinkable(ClassDoc classDoc,
+ Configuration configuration) {
+ return
+ ((classDoc.isIncluded() && configuration.isGeneratedDoc(classDoc))) ||
+ (configuration.extern.isExternal(classDoc) &&
+ (classDoc.isPublic() || classDoc.isProtected()));
+ }
+
+ /**
+ * Given a class, return the closest visible super class.
+ *
+ * @param classDoc the class we are searching the parent for.
+ * @param configuration the current configuration of the doclet.
+ * @return the closest visible super class. Return null if it cannot
+ * be found (i.e. classDoc is java.lang.Object).
+ */
+ public static Type getFirstVisibleSuperClass(ClassDoc classDoc,
+ Configuration configuration) {
+ if (classDoc == null) {
+ return null;
+ }
+ Type sup = classDoc.superclassType();
+ ClassDoc supClassDoc = classDoc.superclass();
+ while (sup != null &&
+ (! (supClassDoc.isPublic() ||
+ isLinkable(supClassDoc, configuration))) ) {
+ if (supClassDoc.superclass().qualifiedName().equals(supClassDoc.qualifiedName()))
+ break;
+ sup = supClassDoc.superclassType();
+ supClassDoc = supClassDoc.superclass();
+ }
+ if (classDoc.equals(supClassDoc)) {
+ return null;
+ }
+ return sup;
+ }
+
+ /**
+ * Given a class, return the closest visible super class.
+ *
+ * @param classDoc the class we are searching the parent for.
+ * @param configuration the current configuration of the doclet.
+ * @return the closest visible super class. Return null if it cannot
+ * be found (i.e. classDoc is java.lang.Object).
+ */
+ public static ClassDoc getFirstVisibleSuperClassCD(ClassDoc classDoc,
+ Configuration configuration) {
+ if (classDoc == null) {
+ return null;
+ }
+ ClassDoc supClassDoc = classDoc.superclass();
+ while (supClassDoc != null &&
+ (! (supClassDoc.isPublic() ||
+ isLinkable(supClassDoc, configuration))) ) {
+ supClassDoc = supClassDoc.superclass();
+ }
+ if (classDoc.equals(supClassDoc)) {
+ return null;
+ }
+ return supClassDoc;
+ }
+
+ /**
+ * Given a ClassDoc, return the name of its type (Class, Interface, etc.).
+ *
+ * @param cd the ClassDoc to check.
+ * @param lowerCaseOnly true if you want the name returned in lower case.
+ * If false, the first letter of the name is capitalized.
+ * @return
+ */
+ public static String getTypeName(Configuration config,
+ ClassDoc cd, boolean lowerCaseOnly) {
+ String typeName = "";
+ if (cd.isOrdinaryClass()) {
+ typeName = "doclet.Class";
+ } else if (cd.isInterface()) {
+ typeName = "doclet.Interface";
+ } else if (cd.isException()) {
+ typeName = "doclet.Exception";
+ } else if (cd.isError()) {
+ typeName = "doclet.Error";
+ } else if (cd.isAnnotationType()) {
+ typeName = "doclet.AnnotationType";
+ } else if (cd.isEnum()) {
+ typeName = "doclet.Enum";
+ }
+ return config.getText(
+ lowerCaseOnly ? StringUtils.toLowerCase(typeName) : typeName);
+ }
+
+ /**
+ * Replace all tabs in a string with the appropriate number of spaces.
+ * The string may be a multi-line string.
+ * @param configuration the doclet configuration defining the setting for the
+ * tab length.
+ * @param text the text for which the tabs should be expanded
+ * @return the text with all tabs expanded
+ */
+ public static String replaceTabs(Configuration configuration, String text) {
+ if (text.indexOf("\t") == -1)
+ return text;
+
+ final int tabLength = configuration.sourcetab;
+ final String whitespace = configuration.tabSpaces;
+ final int textLength = text.length();
+ StringBuilder result = new StringBuilder(textLength);
+ int pos = 0;
+ int lineLength = 0;
+ for (int i = 0; i < textLength; i++) {
+ char ch = text.charAt(i);
+ switch (ch) {
+ case '\n': case '\r':
+ lineLength = 0;
+ break;
+ case '\t':
+ result.append(text, pos, i);
+ int spaceCount = tabLength - lineLength % tabLength;
+ result.append(whitespace, 0, spaceCount);
+ lineLength += spaceCount;
+ pos = i + 1;
+ break;
+ default:
+ lineLength++;
+ }
+ }
+ result.append(text, pos, textLength);
+ return result.toString();
+ }
+
+ public static String normalizeNewlines(String text) {
+ StringBuilder sb = new StringBuilder();
+ final int textLength = text.length();
+ final String NL = DocletConstants.NL;
+ int pos = 0;
+ for (int i = 0; i < textLength; i++) {
+ char ch = text.charAt(i);
+ switch (ch) {
+ case '\n':
+ sb.append(text, pos, i);
+ sb.append(NL);
+ pos = i + 1;
+ break;
+ case '\r':
+ sb.append(text, pos, i);
+ sb.append(NL);
+ if (i + 1 < textLength && text.charAt(i + 1) == '\n')
+ i++;
+ pos = i + 1;
+ break;
+ }
+ }
+ sb.append(text, pos, textLength);
+ return sb.toString();
+ }
+
+ /**
+ * The documentation for values() and valueOf() in Enums are set by the
+ * doclet.
+ */
+ public static void setEnumDocumentation(Configuration configuration,
+ ClassDoc classDoc) {
+ MethodDoc[] methods = classDoc.methods();
+ for (int j = 0; j < methods.length; j++) {
+ MethodDoc currentMethod = methods[j];
+ if (currentMethod.name().equals("values") &&
+ currentMethod.parameters().length == 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(configuration.getText("doclet.enum_values_doc.main", classDoc.name()));
+ sb.append("\n@return ");
+ sb.append(configuration.getText("doclet.enum_values_doc.return"));
+ currentMethod.setRawCommentText(sb.toString());
+ } else if (currentMethod.name().equals("valueOf") &&
+ currentMethod.parameters().length == 1) {
+ Type paramType = currentMethod.parameters()[0].type();
+ if (paramType != null &&
+ paramType.qualifiedTypeName().equals(String.class.getName())) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(configuration.getText("doclet.enum_valueof_doc.main", classDoc.name()));
+ sb.append("\n@param name ");
+ sb.append(configuration.getText("doclet.enum_valueof_doc.param_name"));
+ sb.append("\n@return ");
+ sb.append(configuration.getText("doclet.enum_valueof_doc.return"));
+ sb.append("\n@throws IllegalArgumentException ");
+ sb.append(configuration.getText("doclet.enum_valueof_doc.throws_ila"));
+ sb.append("\n@throws NullPointerException ");
+ sb.append(configuration.getText("doclet.enum_valueof_doc.throws_npe"));
+ currentMethod.setRawCommentText(sb.toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * Return true if the given Doc is deprecated.
+ *
+ * @param doc the Doc to check.
+ * @return true if the given Doc is deprecated.
+ */
+ public static boolean isDeprecated(Doc doc) {
+ if (doc.tags("deprecated").length > 0) {
+ return true;
+ }
+ AnnotationDesc[] annotationDescList;
+ if (doc instanceof PackageDoc)
+ annotationDescList = ((PackageDoc)doc).annotations();
+ else
+ annotationDescList = ((ProgramElementDoc)doc).annotations();
+ for (int i = 0; i < annotationDescList.length; i++) {
+ if (annotationDescList[i].annotationType().qualifiedName().equals(
+ java.lang.Deprecated.class.getName())){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A convenience method to get property name from the name of the
+ * getter or setter method.
+ * @param name name of the getter or setter method.
+ * @return the name of the property of the given setter of getter.
+ */
+ public static String propertyNameFromMethodName(Configuration configuration, String name) {
+ String propertyName = null;
+ if (name.startsWith("get") || name.startsWith("set")) {
+ propertyName = name.substring(3);
+ } else if (name.startsWith("is")) {
+ propertyName = name.substring(2);
+ }
+ if ((propertyName == null) || propertyName.isEmpty()){
+ return "";
+ }
+ return propertyName.substring(0, 1).toLowerCase(configuration.getLocale())
+ + propertyName.substring(1);
+ }
+
+ /**
+ * In case of JavaFX mode on, filters out classes that are private,
+ * package private or having the @treatAsPrivate annotation. Those are not
+ * documented in JavaFX mode.
+ *
+ * @param classes array of classes to be filtered.
+ * @param javafx set to true if in JavaFX mode.
+ * @return list of filtered classes.
+ */
+ public static ClassDoc[] filterOutPrivateClasses(final ClassDoc[] classes,
+ boolean javafx) {
+ if (!javafx) {
+ return classes;
+ }
+ final List