src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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

@@ -21,20 +21,29 @@
  * 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.builders;
+package jdk.javadoc.internal.doclets.toolkit.builders;
 
 import java.io.*;
 import java.util.*;
 
-import com.sun.javadoc.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-import com.sun.tools.javac.util.StringUtils;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
 
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.SerialFieldTree;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter;
+import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
+import jdk.javadoc.internal.doclets.toolkit.util.Utils;
+
 /**
  * Builds the serialized form.
  *
  *  <p><b>This is NOT part of any supported API.
  *  If you write code that depends on this, you do so at your own risk.

@@ -70,26 +79,27 @@
     /**
      * The header for the serial version UID.  Save the string
      * here instead of the properties file because we do not want
      * this string to be localized.
      */
-    private static final String SERIAL_VERSION_UID_HEADER = "serialVersionUID:";
+    private static final String SERIAL_VERSION_UID = "serialVersionUID";
+    private static final String SERIAL_VERSION_UID_HEADER = SERIAL_VERSION_UID + ":";
 
     /**
      * The current package being documented.
      */
-    private PackageDoc currentPackage;
+    private PackageElement currentPackage;
 
     /**
      * The current class being documented.
      */
-    private ClassDoc currentClass;
+    private TypeElement currentTypeElement;
 
     /**
      * The current member being documented.
      */
-    protected MemberDoc currentMember;
+    protected Element currentMember;
 
     /**
      * The content that will be added to the serialized form documentation tree.
      */
     private Content contentTree;

@@ -113,11 +123,13 @@
 
     /**
      * Build the serialized form.
      */
     public void build() throws IOException {
-        if (! serialClassFoundToDocument(configuration.root.classes())) {
+        SortedSet<TypeElement> rootclasses = new TreeSet<>(utils.makeGeneralPurposeComparator());
+        rootclasses.addAll(configuration.root.getIncludedClasses());
+        if (!serialClassFoundToDocument(rootclasses)) {
             //Nothing to document.
             return;
         }
         try {
             writer = configuration.getWriterFactory().getSerializedFormWriter();

@@ -160,11 +172,11 @@
      * @param node the XML element that specifies which components to document
      * @param serializedTree content tree to which the documentation will be added
      */
     public void buildSerializedFormSummaries(XMLNode node, Content serializedTree) {
         Content serializedSummariesTree = writer.getSerializedSummariesHeader();
-        for (PackageDoc pkg : configuration.packages) {
+        for (PackageElement pkg : configuration.packages) {
             currentPackage = pkg;
             buildChildren(node, serializedSummariesTree);
         }
         serializedTree.addContent(writer.getSerializedContent(
                 serializedSummariesTree));

@@ -176,16 +188,15 @@
      * @param node the XML element that specifies which components to document
      * @param serializedSummariesTree content tree to which the documentation will be added
      */
     public void buildPackageSerializedForm(XMLNode node, Content serializedSummariesTree) {
         Content packageSerializedTree = writer.getPackageSerializedHeader();
-        String foo = currentPackage.name();
-        ClassDoc[] classes = currentPackage.allClasses(false);
-        if (classes == null || classes.length == 0) {
+        SortedSet<TypeElement> classes = utils.getAllClassesUnfiltered(currentPackage);
+        if (classes.isEmpty()) {
             return;
         }
-        if (!serialInclude(currentPackage)) {
+        if (!serialInclude(utils, currentPackage)) {
             return;
         }
         if (!serialClassFoundToDocument(classes)) {
             return;
         }

@@ -210,21 +221,20 @@
      * @param node the XML element that specifies which components to document
      * @param packageSerializedTree content tree to which the documentation will be added
      */
     public void buildClassSerializedForm(XMLNode node, Content packageSerializedTree) {
         Content classSerializedTree = writer.getClassSerializedHeader();
-        ClassDoc[] classes = currentPackage.allClasses(false);
-        Arrays.sort(classes);
-        for (ClassDoc classDoc : classes) {
-            currentClass = classDoc;
-            fieldWriter = writer.getSerialFieldWriter(currentClass);
-            methodWriter = writer.getSerialMethodWriter(currentClass);
-            if (currentClass.isClass() && currentClass.isSerializable()) {
-                if (!serialClassInclude(currentClass)) {
+        SortedSet<TypeElement> typeElements = utils.getAllClassesUnfiltered(currentPackage);
+        for (TypeElement typeElement : typeElements) {
+            currentTypeElement = typeElement;
+            fieldWriter = writer.getSerialFieldWriter(currentTypeElement);
+            methodWriter = writer.getSerialMethodWriter(currentTypeElement);
+            if (utils.isClass(currentTypeElement) && utils.isSerializable(currentTypeElement)) {
+                if (!serialClassInclude(utils, currentTypeElement)) {
                     continue;
                 }
-                Content classTree = writer.getClassHeader(currentClass);
+                Content classTree = writer.getClassHeader(currentTypeElement);
                 buildChildren(node, classTree);
                 classSerializedTree.addContent(classTree);
             }
         }
         packageSerializedTree.addContent(classSerializedTree);

@@ -236,15 +246,16 @@
      * @param node the XML element that specifies which components to document
      * @param classTree content tree to which the serial UID information will be added
      */
     public void buildSerialUIDInfo(XMLNode node, Content classTree) {
         Content serialUidTree = writer.getSerialUIDInfoHeader();
-        for (FieldDoc field : currentClass.fields(false)) {
-            if (field.name().equals("serialVersionUID") &&
-                field.constantValueExpression() != null) {
+        for (Element e : utils.getFieldsUnfiltered(currentTypeElement)) {
+            VariableElement field = (VariableElement)e;
+            if (field.getSimpleName().toString().compareTo(SERIAL_VERSION_UID) == 0 &&
+                field.getConstantValue() != null) {
                 writer.addSerialUIDInfo(SERIAL_VERSION_UID_HEADER,
-                                        field.constantValueExpression(), serialUidTree);
+                                        utils.constantValueExpresion(field), serialUidTree);
                 break;
             }
         }
         classTree.addContent(serialUidTree);
     }

@@ -268,30 +279,28 @@
      * @param node the XML element that specifies which components to document
      * @param classContentTree content tree to which the documentation will be added
      */
     public void buildSerializableMethods(XMLNode node, Content classContentTree) {
         Content serializableMethodTree = methodWriter.getSerializableMethodsHeader();
-        MemberDoc[] members = currentClass.serializationMethods();
-        int membersLength = members.length;
-        if (membersLength > 0) {
-            for (int i = 0; i < membersLength; i++) {
-                currentMember = members[i];
+        SortedSet<ExecutableElement> members = utils.serializationMethods(currentTypeElement);
+        if (!members.isEmpty()) {
+            for (ExecutableElement member : members) {
+                currentMember = member;
                 Content methodsContentTree = methodWriter.getMethodsContentHeader(
-                        (i == membersLength - 1));
+                        currentMember == members.last());
                 buildChildren(node, methodsContentTree);
                 serializableMethodTree.addContent(methodsContentTree);
             }
         }
-        if (currentClass.serializationMethods().length > 0) {
+        if (!utils.serializationMethods(currentTypeElement).isEmpty()) {
             classContentTree.addContent(methodWriter.getSerializableMethods(
                     configuration.getText("doclet.Serialized_Form_methods"),
                     serializableMethodTree));
-            if (currentClass.isSerializable() && !currentClass.isExternalizable()) {
-                if (currentClass.serializationMethods().length == 0) {
+            if (utils.isSerializable(currentTypeElement) && !utils.isExternalizable(currentTypeElement)) {
+                if (utils.serializationMethods(currentTypeElement).isEmpty()) {
                     Content noCustomizationMsg = methodWriter.getNoCustomizationMsg(
-                            configuration.getText(
-                            "doclet.Serializable_no_customization"));
+                            configuration.getText("doclet.Serializable_no_customization"));
                     classContentTree.addContent(methodWriter.getSerializableMethods(
                     configuration.getText("doclet.Serialized_Form_methods"),
                     noCustomizationMsg));
                 }
             }

@@ -303,21 +312,21 @@
      *
      * @param node the XML element that specifies which components to document
      * @param methodsContentTree content tree to which the documentation will be added
      */
     public void buildMethodSubHeader(XMLNode node, Content methodsContentTree)  {
-        methodWriter.addMemberHeader((MethodDoc)currentMember, methodsContentTree);
+        methodWriter.addMemberHeader((ExecutableElement)currentMember, methodsContentTree);
     }
 
     /**
      * Build the deprecated method description.
      *
      * @param node the XML element that specifies which components to document
      * @param methodsContentTree content tree to which the documentation will be added
      */
     public void buildDeprecatedMethodInfo(XMLNode node, Content methodsContentTree) {
-        methodWriter.addDeprecatedMemberInfo((MethodDoc) currentMember, methodsContentTree);
+        methodWriter.addDeprecatedMemberInfo((ExecutableElement)currentMember, methodsContentTree);
     }
 
     /**
      * Build the information for the method.
      *

@@ -336,28 +345,29 @@
      *
      * @param node the XML element that specifies which components to document
      * @param methodsContentTree content tree to which the documentation will be added
      */
     public void buildMethodDescription(XMLNode node, Content methodsContentTree) {
-        methodWriter.addMemberDescription((MethodDoc) currentMember, methodsContentTree);
+        methodWriter.addMemberDescription((ExecutableElement)currentMember, methodsContentTree);
     }
 
     /**
      * Build the method tags.
      *
      * @param node the XML element that specifies which components to document
      * @param methodsContentTree content tree to which the documentation will be added
      */
     public void buildMethodTags(XMLNode node, Content methodsContentTree) {
-        methodWriter.addMemberTags((MethodDoc) currentMember, methodsContentTree);
-        MethodDoc method = (MethodDoc)currentMember;
-        if (method.name().compareTo("writeExternal") == 0
-                && method.tags("serialData").length == 0) {
+        methodWriter.addMemberTags((ExecutableElement)currentMember, methodsContentTree);
+        ExecutableElement method = (ExecutableElement)currentMember;
+        if (method.getSimpleName().toString().compareTo("writeExternal") == 0
+                && utils.getSerialDataTrees(method).isEmpty()) {
             if (configuration.serialwarn) {
-                configuration.getDocletSpecificMsg().warning(
-                        currentMember.position(), "doclet.MissingSerialDataTag",
-                        method.containingClass().qualifiedName(), method.name());
+                TypeElement encl  = (TypeElement) method.getEnclosingElement();
+                configuration.getDocletSpecificMsg().warning(currentMember,
+                        "doclet.MissingSerialDataTag", encl.getQualifiedName().toString(),
+                        method.getSimpleName().toString());
             }
         }
     }
 
     /**

@@ -365,36 +375,33 @@
      *
      * @param node the XML element that specifies which components to document
      * @param classContentTree content tree to which the documentation will be added
      */
     public void buildFieldHeader(XMLNode node, Content classContentTree) {
-        if (currentClass.serializableFields().length > 0) {
-            buildFieldSerializationOverview(currentClass, classContentTree);
+        if (!utils.serializableFields(currentTypeElement).isEmpty()) {
+            buildFieldSerializationOverview(currentTypeElement, classContentTree);
         }
     }
 
     /**
      * Build the serialization overview for the given class.
      *
-     * @param classDoc the class to print the overview for.
+     * @param typeElement the class to print the overview for.
      * @param classContentTree content tree to which the documentation will be added
      */
-    public void buildFieldSerializationOverview(ClassDoc classDoc, Content classContentTree) {
-        if (classDoc.definesSerializableFields()) {
-            FieldDoc serialPersistentField = classDoc.serializableFields()[0];
+    public void buildFieldSerializationOverview(TypeElement typeElement, Content classContentTree) {
+        if (utils.definesSerializableFields(typeElement)) {
+            VariableElement ve = utils.serializableFields(typeElement).first();
             // Check to see if there are inline comments, tags or deprecation
             // information to be printed.
-            if (fieldWriter.shouldPrintOverview(serialPersistentField)) {
+            if (fieldWriter.shouldPrintOverview(ve)) {
                 Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader();
                 Content fieldsOverviewContentTree = fieldWriter.getFieldsContentHeader(true);
-                fieldWriter.addMemberDeprecatedInfo(serialPersistentField,
-                        fieldsOverviewContentTree);
+                fieldWriter.addMemberDeprecatedInfo(ve, fieldsOverviewContentTree);
                 if (!configuration.nocomment) {
-                    fieldWriter.addMemberDescription(serialPersistentField,
-                            fieldsOverviewContentTree);
-                    fieldWriter.addMemberTags(serialPersistentField,
-                            fieldsOverviewContentTree);
+                    fieldWriter.addMemberDescription(ve, fieldsOverviewContentTree);
+                    fieldWriter.addMemberTags(ve, fieldsOverviewContentTree);
                 }
                 serializableFieldsTree.addContent(fieldsOverviewContentTree);
                 classContentTree.addContent(fieldWriter.getSerializableFields(
                         configuration.getText("doclet.Serialized_Form_class"),
                         serializableFieldsTree));

@@ -407,23 +414,21 @@
      *
      * @param node the XML element that specifies which components to document
      * @param classContentTree content tree to which the documentation will be added
      */
     public void buildSerializableFields(XMLNode node, Content classContentTree) {
-        MemberDoc[] members = currentClass.serializableFields();
-        int membersLength = members.length;
-        if (membersLength > 0) {
+        SortedSet<VariableElement> members = utils.serializableFields(currentTypeElement);
+        if (!members.isEmpty()) {
             Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader();
-            for (int i = 0; i < membersLength; i++) {
-                currentMember = members[i];
-                if (!currentClass.definesSerializableFields()) {
+            for (VariableElement ve : members) {
+                currentMember = ve;
+                if (!utils.definesSerializableFields(currentTypeElement)) {
                     Content fieldsContentTree = fieldWriter.getFieldsContentHeader(
-                            (i == membersLength - 1));
+                            currentMember == members.last());
                     buildChildren(node, fieldsContentTree);
                     serializableFieldsTree.addContent(fieldsContentTree);
-                }
-                else {
+                } else {
                     buildSerialFieldTagsInfo(serializableFieldsTree);
                 }
             }
             classContentTree.addContent(fieldWriter.getSerializableFields(
                     configuration.getText("doclet.Serialized_Form_fields"),

@@ -436,14 +441,15 @@
      *
      * @param node the XML element that specifies which components to document
      * @param fieldsContentTree content tree to which the documentation will be added
      */
     public void buildFieldSubHeader(XMLNode node, Content fieldsContentTree) {
-        if (!currentClass.definesSerializableFields()) {
-            FieldDoc field = (FieldDoc) currentMember;
-            fieldWriter.addMemberHeader(field.type().asClassDoc(),
-                    field.type().typeName(), field.type().dimension(), field.name(),
+        if (!utils.definesSerializableFields(currentTypeElement)) {
+            VariableElement field = (VariableElement) currentMember;
+            fieldWriter.addMemberHeader(utils.asTypeElement(field.asType()),
+                    utils.getTypeName(field.asType(), false), utils.getDimension(field.asType()),
+                    utils.getSimpleName(field),
                     fieldsContentTree);
         }
     }
 
     /**

@@ -451,13 +457,13 @@
      *
      * @param node the XML element that specifies which components to document
      * @param fieldsContentTree content tree to which the documentation will be added
      */
     public void buildFieldDeprecationInfo(XMLNode node, Content fieldsContentTree) {
-        if (!currentClass.definesSerializableFields()) {
-            FieldDoc field = (FieldDoc)currentMember;
-            fieldWriter.addMemberDeprecatedInfo(field, fieldsContentTree);
+        if (!utils.definesSerializableFields(currentTypeElement)) {
+            fieldWriter.addMemberDeprecatedInfo((VariableElement)currentMember,
+                    fieldsContentTree);
         }
     }
 
     /**
      * Build the serial field tags information.

@@ -466,26 +472,44 @@
      */
     public void buildSerialFieldTagsInfo(Content serializableFieldsTree) {
         if(configuration.nocomment){
             return;
         }
-        FieldDoc field = (FieldDoc)currentMember;
+        VariableElement field = (VariableElement)currentMember;
         // Process Serializable Fields specified as array of
         // ObjectStreamFields. Print a member for each serialField tag.
         // (There should be one serialField tag per ObjectStreamField
         // element.)
-        SerialFieldTag[] tags = field.serialFieldTags();
-        Arrays.sort(tags);
-        int tagsLength = tags.length;
-        for (int i = 0; i < tagsLength; i++) {
-            if (tags[i].fieldName() == null || tags[i].fieldType() == null) // ignore malformed @serialField tags
+        SortedSet<SerialFieldTree> tags = new TreeSet<>(utils.makeSerialFieldTreeComparator());
+        // sort the elements
+        for (DocTree dt : utils.getSerialFieldTrees(field)) {
+            SerialFieldTree st = (SerialFieldTree) dt;
+            tags.add(st);
+        }
+
+        CommentHelper ch = utils.getCommentHelper(field);
+        for (SerialFieldTree tag : tags) {
+            if (tag.getName() == null || tag.getType() == null)  // ignore malformed @serialField tags
                 continue;
-            Content fieldsContentTree = fieldWriter.getFieldsContentHeader(
-                    (i == tagsLength - 1));
-            fieldWriter.addMemberHeader(tags[i].fieldTypeDoc(),
-                    tags[i].fieldType(), "", tags[i].fieldName(), fieldsContentTree);
-            fieldWriter.addMemberDescription(tags[i], fieldsContentTree);
+            Content fieldsContentTree = fieldWriter.getFieldsContentHeader(tag.equals(tags.last()));
+            TypeElement te = ch.getReferencedClass(configuration, tag);
+            String fieldType = ch.getReferencedMemberName(tag);
+            if (te != null && utils.isPrimitive(te.asType())) {
+                fieldType = utils.getTypeName(te.asType(), false);
+                te = null;
+            }
+            String refSignature = ch.getReferencedSignature(tag);
+            // TODO: Print the signature directly, if it is an array, the
+            // current DocTree APIs makes it very hard to distinguish
+            // an as these are returned back as "Array" a DeclaredType.
+            if (refSignature.endsWith("[]")) {
+                te = null;
+                fieldType = refSignature;
+            }
+            fieldWriter.addMemberHeader(te, fieldType, "",
+                    tag.getName().getName().toString(), fieldsContentTree);
+            fieldWriter.addMemberDescription(field, tag, fieldsContentTree);
             serializableFieldsTree.addContent(fieldsContentTree);
         }
     }
 
     /**

@@ -496,79 +520,74 @@
      */
     public void buildFieldInfo(XMLNode node, Content fieldsContentTree) {
         if(configuration.nocomment){
             return;
         }
-        FieldDoc field = (FieldDoc)currentMember;
-        ClassDoc cd = field.containingClass();
+        VariableElement field = (VariableElement)currentMember;
+        TypeElement te = utils.getEnclosingTypeElement(currentMember);
         // Process default Serializable field.
-        if ((field.tags("serial").length == 0) && ! field.isSynthetic()
+        if ((utils.getSerialTrees(field).isEmpty()) /*&& ! field.isSynthetic()*/
                 && configuration.serialwarn) {
-            configuration.message.warning(field.position(),
-                    "doclet.MissingSerialTag", cd.qualifiedName(),
-                    field.name());
+            configuration.message.warning(field,
+                    "doclet.MissingSerialTag", utils.getFullyQualifiedName(te),
+                    utils.getSimpleName(field));
         }
         fieldWriter.addMemberDescription(field, fieldsContentTree);
         fieldWriter.addMemberTags(field, fieldsContentTree);
     }
 
     /**
-     * Return true if the given Doc should be included
+     * Return true if the given Element should be included
      * in the serialized form.
      *
-     * @param doc the Doc object to check for serializability.
+     * @param element the Element object to check for serializability.
      */
-    public static boolean serialInclude(Doc doc) {
-        if (doc == null) {
+    public static boolean serialInclude(Utils utils, Element element) {
+        if (element == null) {
             return false;
         }
-        return doc.isClass() ?
-            serialClassInclude((ClassDoc)doc) :
-            serialDocInclude(doc);
+        return utils.isClass(element)
+                ? serialClassInclude(utils, (TypeElement)element)
+                : serialDocInclude(utils, element);
     }
 
     /**
-     * Return true if the given ClassDoc should be included
+     * Return true if the given TypeElement should be included
      * in the serialized form.
      *
-     * @param cd the ClassDoc object to check for serializability.
+     * @param te the TypeElement object to check for serializability.
      */
-    private static boolean serialClassInclude(ClassDoc cd) {
-        if (cd.isEnum()) {
+    private static boolean serialClassInclude(Utils utils, TypeElement te) {
+        if (utils.isEnum(te)) {
             return false;
         }
-        try {
-            cd.superclassType();
-        } catch (NullPointerException e) {
-            //Workaround for null pointer bug in ClassDoc.superclassType().
-            return false;
-        }
-        if (cd.isSerializable()) {
-            if (cd.tags("serial").length > 0) {
-                return serialDocInclude(cd);
-            } else if (cd.isPublic() || cd.isProtected()) {
+        if (utils.isSerializable(te)) {
+            if (!utils.getSerialTrees(te).isEmpty()) {
+                return serialDocInclude(utils, te);
+            } else if (utils.isPublic(te) || utils.isProtected(te)) {
                 return true;
             } else {
                 return false;
             }
         }
         return false;
     }
 
     /**
-     * Return true if the given Doc should be included
+     * Return true if the given Element should be included
      * in the serialized form.
      *
-     * @param doc the Doc object to check for serializability.
+     * @param element the Element to check for serializability.
      */
-    private static boolean serialDocInclude(Doc doc) {
-        if (doc.isEnum()) {
+    private static boolean serialDocInclude(Utils utils, Element element) {
+        if (utils.isEnum(element)) {
             return false;
         }
-        Tag[] serial = doc.tags("serial");
-        if (serial.length > 0) {
-            String serialtext = StringUtils.toLowerCase(serial[0].text());
+        List<? extends DocTree> serial = utils.getSerialTrees(element);
+        if (!serial.isEmpty()) {
+            CommentHelper ch = utils.getCommentHelper(element);
+            String serialtext = Utils.toLowerCase(ch.getText(serial.get(0)));
             if (serialtext.contains("exclude")) {
                 return false;
             } else if (serialtext.contains("include")) {
                 return true;
             }

@@ -575,18 +594,18 @@
         }
         return true;
     }
 
     /**
-     * Return true if any of the given classes have a @serialinclude tag.
+     * Return true if any of the given typeElements have a @serialinclude tag.
      *
-     * @param classes the classes to check.
-     * @return true if any of the given classes have a @serialinclude tag.
+     * @param classes the typeElements to check.
+     * @return true if any of the given typeElements have a @serialinclude tag.
      */
-    private boolean serialClassFoundToDocument(ClassDoc[] classes) {
-        for (ClassDoc aClass : classes) {
-            if (serialClassInclude(aClass)) {
+    private boolean serialClassFoundToDocument(SortedSet<TypeElement> classes) {
+        for (TypeElement aClass : classes) {
+            if (serialClassInclude(utils, aClass)) {
                 return true;
             }
         }
         return false;
     }