src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java

Print this page


   1 /*
   2  * Copyright (c) 2003, 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  */
  25 
  26 package com.sun.tools.doclets.internal.toolkit.util.links;
  27 
  28 import com.sun.javadoc.*;
  29 import com.sun.tools.doclets.internal.toolkit.Content;
  30 

















  31 /**
  32  * A factory that constructs links from given link information.
  33  *
  34  *  <p><b>This is NOT part of any supported API.
  35  *  If you write code that depends on this, you do so at your own risk.
  36  *  This code and its internal interfaces are subject to change or
  37  *  deletion without notice.</b>
  38  *
  39  * @author Jamie Ho
  40  * @since 1.5
  41  */
  42 public abstract class LinkFactory {
  43 
  44     /**
  45      * Return an empty instance of a content object.
  46      *
  47      * @return an empty instance of a content object.
  48      */
  49     protected abstract Content newContent();
  50 
  51     /**
  52      * Constructs a link from the given link information.
  53      *
  54      * @param linkInfo the information about the link.
  55      * @return the output of the link.
  56      */
  57     public Content getLink(LinkInfo linkInfo) {

  58         if (linkInfo.type != null) {
  59             Type type = linkInfo.type;



  60             Content link = newContent();
  61             if (type.isPrimitive()) {
  62                 //Just a primitive.
  63                 link.addContent(type.typeName());
  64             } else if (type.asAnnotatedType() != null && type.dimension().length() == 0) {
















  65                 link.addContent(getTypeAnnotationLinks(linkInfo));
  66                 linkInfo.type = type.asAnnotatedType().underlyingType();
  67                 link.addContent(getLink(linkInfo));





  68                 return link;
  69             } else if (type.asWildcardType() != null) {
  70                 //Wildcard type.


  71                 linkInfo.isTypeBound = true;
  72                 link.addContent("?");
  73                 WildcardType wildcardType = type.asWildcardType();
  74                 Type[] extendsBounds = wildcardType.extendsBounds();
  75                 for (int i = 0; i < extendsBounds.length; i++) {
  76                     link.addContent(i > 0 ? ", " : " extends ");
  77                     setBoundsLinkInfo(linkInfo, extendsBounds[i]);
  78                     link.addContent(getLink(linkInfo));
  79                 }
  80                 Type[] superBounds = wildcardType.superBounds();
  81                 for (int i = 0; i < superBounds.length; i++) {
  82                     link.addContent(i > 0 ? ", " : " super ");
  83                     setBoundsLinkInfo(linkInfo, superBounds[i]);
  84                     link.addContent(getLink(linkInfo));
  85                 }
  86             } else if (type.asTypeVariable()!= null) {




  87                 link.addContent(getTypeAnnotationLinks(linkInfo));
  88                 linkInfo.isTypeBound = true;
  89                 //A type variable.
  90                 Doc owner = type.asTypeVariable().owner();
  91                 if ((! linkInfo.excludeTypeParameterLinks) &&
  92                         owner instanceof ClassDoc) {
  93                     linkInfo.classDoc = (ClassDoc) owner;

  94                     Content label = newContent();
  95                     label.addContent(type.typeName());
  96                     linkInfo.label = label;
  97                     link.addContent(getClassLink(linkInfo));
  98                 } else {
  99                     //No need to link method type parameters.
 100                     link.addContent(type.typeName());
 101                 }
 102 
 103                 Type[] bounds = type.asTypeVariable().bounds();
 104                 if (! linkInfo.excludeTypeBounds) {
 105                     linkInfo.excludeTypeBounds = true;
 106                     for (int i = 0; i < bounds.length; i++) {
 107                         link.addContent(i > 0 ? " & " : " extends ");
 108                         setBoundsLinkInfo(linkInfo, bounds[i]);










 109                         link.addContent(getLink(linkInfo));

 110                     }
 111                 }
 112             } else if (type.asClassDoc() != null) {
 113                 //A class type.
 114                 if (linkInfo.isTypeBound &&
 115                         linkInfo.excludeTypeBoundsLinks) {
 116                     //Since we are excluding type parameter links, we should not
 117                     //be linking to the type bound.
 118                     link.addContent(type.typeName());


 119                     link.addContent(getTypeParameterLinks(linkInfo));
 120                     return link;
 121                 } else {
 122                     linkInfo.classDoc = type.asClassDoc();
 123                     link = newContent();


 124                     link.addContent(getClassLink(linkInfo));
 125                     if (linkInfo.includeTypeAsSepLink) {
 126                         link.addContent(getTypeParameterLinks(linkInfo, false));
 127                     }
 128                 }
 129             }
 130 
 131             if (linkInfo.isVarArg) {
 132                 if (type.dimension().length() > 2) {
 133                     //Javadoc returns var args as array.
 134                     //Strip out the first [] from the var arg.
 135                     link.addContent(type.dimension().substring(2));
 136                 }
 137                 link.addContent("...");
 138             } else {
 139                 while (type != null && type.dimension().length() > 0) {
 140                     if (type.asAnnotatedType() != null) {
 141                         linkInfo.type = type;
 142                         link.addContent(" ");
 143                         link.addContent(getTypeAnnotationLinks(linkInfo));
 144                         link.addContent("[]");
 145                         type = type.asAnnotatedType().underlyingType().getElementType();
 146                     } else {
 147                         link.addContent("[]");
 148                         type = type.getElementType();
 149                     }
 150                 }
 151                 linkInfo.type = type;
 152                 Content newLink = newContent();
 153                 newLink.addContent(getTypeAnnotationLinks(linkInfo));
 154                 newLink.addContent(link);
 155                 link = newLink;
 156             }
 157             return link;
 158         } else if (linkInfo.classDoc != null) {
 159             //Just a class link


 160             Content link = newContent();
 161             link.addContent(getClassLink(linkInfo));
 162             if (linkInfo.includeTypeAsSepLink) {
 163                 link.addContent(getTypeParameterLinks(linkInfo, false));
 164             }
 165             return link;
 166         } else {
 167             return null;
 168         }
 169     }
 170 
 171     private void setBoundsLinkInfo(LinkInfo linkInfo, Type bound) {
 172         linkInfo.classDoc = null;
 173         linkInfo.label = null;
 174         linkInfo.type = bound;
 175     }
 176 
 177     /**
 178      * Return the link to the given class.
 179      *
 180      * @param linkInfo the information about the link to construct.
 181      *
 182      * @return the link for the given class.
 183      */
 184     protected abstract Content getClassLink(LinkInfo linkInfo);
 185 
 186     /**
 187      * Return the link to the given type parameter.
 188      *
 189      * @param linkInfo     the information about the link to construct.
 190      * @param typeParam the type parameter to link to.
 191      */
 192     protected abstract Content getTypeParameterLink(LinkInfo linkInfo,
 193         Type typeParam);
 194 
 195     protected abstract Content getTypeAnnotationLink(LinkInfo linkInfo,
 196             AnnotationDesc annotation);
 197 
 198     /**
 199      * Return the links to the type parameters.
 200      *
 201      * @param linkInfo     the information about the link to construct.
 202      * @return the links to the type parameters.
 203      */
 204     public Content getTypeParameterLinks(LinkInfo linkInfo) {
 205         return getTypeParameterLinks(linkInfo, true);
 206     }
 207 
 208     /**
 209      * Return the links to the type parameters.
 210      *
 211      * @param linkInfo     the information about the link to construct.
 212      * @param isClassLabel true if this is a class label.  False if it is
 213      *                     the type parameters portion of the link.
 214      * @return the links to the type parameters.
 215      */
 216     public Content getTypeParameterLinks(LinkInfo linkInfo, boolean isClassLabel) {

 217         Content links = newContent();
 218         Type[] vars;
 219         if (linkInfo.executableMemberDoc != null) {
 220             vars = linkInfo.executableMemberDoc.typeParameters();
 221         } else if (linkInfo.type != null &&
 222                 linkInfo.type.asParameterizedType() != null){
 223             vars =  linkInfo.type.asParameterizedType().typeArguments();
 224         } else if (linkInfo.classDoc != null){
 225             vars = linkInfo.classDoc.typeParameters();












 226         } else {
 227             //Nothing to document.
 228             return links;
 229         }
 230         if (((linkInfo.includeTypeInClassLinkLabel && isClassLabel) ||
 231              (linkInfo.includeTypeAsSepLink && ! isClassLabel)
 232               )
 233             && vars.length > 0) {
 234             links.addContent("<");
 235             for (int i = 0; i < vars.length; i++) {
 236                 if (i > 0) {

 237                     links.addContent(",");
 238                 }
 239                 links.addContent(getTypeParameterLink(linkInfo, vars[i]));

 240             }
 241             links.addContent(">");
 242         }
 243         return links;
 244     }
 245 
 246     public Content getTypeAnnotationLinks(LinkInfo linkInfo) {

 247         Content links = newContent();
 248         if (linkInfo.type.asAnnotatedType() == null)
 249             return links;
 250         AnnotationDesc[] annotations = linkInfo.type.asAnnotatedType().annotations();
 251         for (int i = 0; i < annotations.length; i++) {
 252             if (i > 0) {


 253                 links.addContent(" ");
 254             }
 255             links.addContent(getTypeAnnotationLink(linkInfo, annotations[i]));

 256         }
 257 
 258         links.addContent(" ");
 259         return links;
 260     }
 261 }
   1 /*
   2  * Copyright (c) 2003, 2016, 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  */
  25 
  26 package jdk.javadoc.internal.doclets.toolkit.util.links;
  27 
  28 import java.util.ArrayList;
  29 import java.util.List;
  30 
  31 import javax.lang.model.element.AnnotationMirror;
  32 import javax.lang.model.element.Element;
  33 import javax.lang.model.element.TypeElement;
  34 import javax.lang.model.element.TypeParameterElement;
  35 import javax.lang.model.type.ArrayType;
  36 import javax.lang.model.type.DeclaredType;
  37 import javax.lang.model.type.TypeMirror;
  38 import javax.lang.model.type.TypeVariable;
  39 import javax.lang.model.type.WildcardType;
  40 import javax.lang.model.util.SimpleTypeVisitor9;
  41 
  42 import jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl;
  43 import jdk.javadoc.internal.doclets.toolkit.Content;
  44 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
  45 import com.sun.tools.javac.util.DefinedBy;
  46 import com.sun.tools.javac.util.DefinedBy.Api;
  47 
  48 /**
  49  * A factory that constructs links from given link information.
  50  *
  51  *  <p><b>This is NOT part of any supported API.
  52  *  If you write code that depends on this, you do so at your own risk.
  53  *  This code and its internal interfaces are subject to change or
  54  *  deletion without notice.</b>
  55  *
  56  * @author Jamie Ho
  57  * @since 1.5
  58  */
  59 public abstract class LinkFactory {
  60 
  61     /**
  62      * Return an empty instance of a content object.
  63      *
  64      * @return an empty instance of a content object.
  65      */
  66     protected abstract Content newContent();
  67 
  68     /**
  69      * Constructs a link from the given link information.
  70      *
  71      * @param linkInfo the information about the link.
  72      * @return the output of the link.
  73      */
  74     public Content getLink(LinkInfo linkInfo) {
  75         Utils utils = ((LinkInfoImpl) linkInfo).configuration.utils;
  76         if (linkInfo.type != null) {
  77             SimpleTypeVisitor9<Content, LinkInfo> linkVisitor =
  78                     new SimpleTypeVisitor9<Content, LinkInfo>() {
  79 
  80                 TypeMirror componentType = utils.getComponentType(linkInfo.type);
  81                 Content link = newContent();
  82 
  83                 // handles primitives, no types and error types
  84                 @Override @DefinedBy(Api.LANGUAGE_MODEL)
  85                 protected Content defaultAction(TypeMirror type, LinkInfo linkInfo) {
  86                     link.addContent(utils.getTypeName(type, false));
  87                     return link;
  88                 }
  89 
  90                 int currentDepth = 0;
  91                 @Override @DefinedBy(Api.LANGUAGE_MODEL)
  92                 public Content visitArray(ArrayType type, LinkInfo linkInfo) {
  93                     // keep track of the dimension depth and replace the last dimension
  94                     // specifier with vararags, when the stack is fully unwound.
  95                     currentDepth++;
  96                     linkInfo.type = type.getComponentType();
  97                     visit(linkInfo.type, linkInfo);
  98                     currentDepth--;
  99                     if (utils.isAnnotated(type)) {
 100                         linkInfo.type = type;
 101                         link.addContent(" ");
 102                         link.addContent(getTypeAnnotationLinks(linkInfo));
 103                     }
 104                     // use vararg if required
 105                     if (linkInfo.isVarArg && currentDepth == 0) {
 106                         link.addContent("...");
 107                     } else {
 108                         link.addContent("[]");
 109                     }
 110                     return link;
 111                 }
 112 
 113                 @Override @DefinedBy(Api.LANGUAGE_MODEL)
 114                 public Content visitWildcard(WildcardType type, LinkInfo linkInfo) {
 115                     linkInfo.isTypeBound = true;
 116                     link.addContent("?");
 117                     TypeMirror extendsBound = type.getExtendsBound();
 118                     if (extendsBound != null) {
 119                         link.addContent(" extends ");
 120                         setBoundsLinkInfo(linkInfo, extendsBound);

 121                         link.addContent(getLink(linkInfo));
 122                     }
 123                     TypeMirror superBound = type.getSuperBound();
 124                     if (superBound != null) {
 125                         link.addContent(" super ");
 126                         setBoundsLinkInfo(linkInfo, superBound);
 127                         link.addContent(getLink(linkInfo));
 128                     }
 129                     return link;
 130                 }
 131 
 132                 @Override @DefinedBy(Api.LANGUAGE_MODEL)
 133                 public Content visitTypeVariable(TypeVariable type, LinkInfo linkInfo) {
 134                     link.addContent(getTypeAnnotationLinks(linkInfo));
 135                     linkInfo.isTypeBound = true;
 136                     TypeVariable typevariable = (utils.isArrayType(type))
 137                             ? (TypeVariable) componentType
 138                             : type;
 139                     Element owner = typevariable.asElement().getEnclosingElement();
 140                     if ((!linkInfo.excludeTypeParameterLinks) && utils.isTypeElement(owner)) {
 141                         linkInfo.typeElement = (TypeElement) owner;
 142                         Content label = newContent();
 143                         label.addContent(utils.getTypeName(type, false));
 144                         linkInfo.label = label;
 145                         link.addContent(getClassLink(linkInfo));
 146                     } else {
 147                         // No need to link method type parameters.
 148                         link.addContent(utils.getTypeName(typevariable, false));
 149                     }
 150 
 151                     if (!linkInfo.excludeTypeBounds) {

 152                         linkInfo.excludeTypeBounds = true;
 153                         TypeParameterElement tpe = ((TypeParameterElement) typevariable.asElement());
 154                         boolean more = false;
 155                         List<? extends TypeMirror> bounds = utils.getBounds(tpe);
 156                         for (TypeMirror bound : bounds) {
 157                             // we get everything as extends java.lang.Object we suppress
 158                             // all of them except those that have multiple extends
 159                             if (bounds.size() == 1 &&
 160                                     bound.equals(utils.getObjectType()) &&
 161                                     !utils.isAnnotated(bound)) {
 162                                 continue;
 163                             }
 164                             link.addContent(more ? " & " : " extends ");
 165                             setBoundsLinkInfo(linkInfo, bound);
 166                             link.addContent(getLink(linkInfo));
 167                             more = true;
 168                         }
 169                     }
 170                     return link;
 171                 }
 172 
 173                 @Override @DefinedBy(Api.LANGUAGE_MODEL)
 174                 public Content visitDeclared(DeclaredType type, LinkInfo linkInfo) {
 175                     if (linkInfo.isTypeBound && linkInfo.excludeTypeBoundsLinks) {
 176                         // Since we are excluding type parameter links, we should not
 177                         // be linking to the type bound.
 178                         link.addContent(utils.getTypeName(type, false));
 179                         link.addContent(getTypeParameterLinks(linkInfo));
 180                         return link;
 181                     } else {

 182                         link = newContent();
 183                         link.addContent(getTypeAnnotationLinks(linkInfo));
 184                         linkInfo.typeElement = utils.asTypeElement(type);
 185                         link.addContent(getClassLink(linkInfo));
 186                         if (linkInfo.includeTypeAsSepLink) {
 187                             link.addContent(getTypeParameterLinks(linkInfo, false));
 188                         }
 189                     }




























 190                     return link;
 191                 }
 192             };
 193             return linkVisitor.visit(linkInfo.type, linkInfo);
 194         } else if (linkInfo.typeElement != null) {
 195             Content link = newContent();
 196             link.addContent(getClassLink(linkInfo));
 197             if (linkInfo.includeTypeAsSepLink) {
 198                 link.addContent(getTypeParameterLinks(linkInfo, false));
 199             }
 200             return link;
 201         } else {
 202             return null;
 203         }
 204     }
 205 
 206     private void setBoundsLinkInfo(LinkInfo linkInfo, TypeMirror bound) {
 207         linkInfo.typeElement = null;
 208         linkInfo.label = null;
 209         linkInfo.type = bound;
 210     }
 211 
 212     /**
 213      * Return the link to the given class.
 214      *
 215      * @param linkInfo the information about the link to construct.
 216      *
 217      * @return the link for the given class.
 218      */
 219     protected abstract Content getClassLink(LinkInfo linkInfo);
 220 
 221     /**
 222      * Return the link to the given type parameter.
 223      *
 224      * @param linkInfo     the information about the link to construct.
 225      * @param typeParam the type parameter to link to.
 226      */
 227     protected abstract Content getTypeParameterLink(LinkInfo linkInfo, TypeMirror typeParam);

 228 
 229     protected abstract Content getTypeAnnotationLink(LinkInfo linkInfo, AnnotationMirror annotation);

 230 
 231     /**
 232      * Return the links to the type parameters.
 233      *
 234      * @param linkInfo     the information about the link to construct.
 235      * @return the links to the type parameters.
 236      */
 237     public Content getTypeParameterLinks(LinkInfo linkInfo) {
 238         return getTypeParameterLinks(linkInfo, true);
 239     }
 240 
 241     /**
 242      * Return the links to the type parameters.
 243      *
 244      * @param linkInfo     the information about the link to construct.
 245      * @param isClassLabel true if this is a class label.  False if it is
 246      *                     the type parameters portion of the link.
 247      * @return the links to the type parameters.
 248      */
 249     public Content getTypeParameterLinks(LinkInfo linkInfo, boolean isClassLabel) {
 250         Utils utils = ((LinkInfoImpl)linkInfo).utils;
 251         Content links = newContent();
 252         List<TypeMirror> vars = new ArrayList<>();
 253         TypeMirror ctype = linkInfo.type != null
 254                 ? utils.getComponentType(linkInfo.type)
 255                 : null;
 256         if (linkInfo.executableElement != null) {
 257             linkInfo.executableElement.getTypeParameters().stream().forEach((t) -> {
 258                 vars.add(t.asType());
 259             });
 260         } else if (linkInfo.type != null && utils.isDeclaredType(linkInfo.type)) {
 261             ((DeclaredType)linkInfo.type).getTypeArguments().stream().forEach((t) -> {
 262                 vars.add(t);
 263             });
 264         } else if (ctype != null && utils.isDeclaredType(ctype)) {
 265             ((DeclaredType)ctype).getTypeArguments().stream().forEach((t) -> {
 266                 vars.add(t);
 267             });
 268         } else if (linkInfo.typeElement != null) {
 269             linkInfo.typeElement.getTypeParameters().stream().forEach((t) -> {
 270                 vars.add(t.asType());
 271             });
 272         } else {
 273             // Nothing to document.
 274             return links;
 275         }
 276         if (((linkInfo.includeTypeInClassLinkLabel && isClassLabel)
 277                 || (linkInfo.includeTypeAsSepLink && !isClassLabel)) && !vars.isEmpty()) {


 278             links.addContent("<");
 279             boolean many = false;
 280             for (TypeMirror t : vars) {
 281                 if (many) {
 282                     links.addContent(",");
 283                 }
 284                 links.addContent(getTypeParameterLink(linkInfo, t));
 285                 many = true;
 286             }
 287             links.addContent(">");
 288         }
 289         return links;
 290     }
 291 
 292     public Content getTypeAnnotationLinks(LinkInfo linkInfo) {
 293         Utils utils = ((LinkInfoImpl)linkInfo).utils;
 294         Content links = newContent();
 295         if (!utils.isAnnotated(linkInfo.type))
 296             return links;
 297 
 298         List<? extends AnnotationMirror> annotations = linkInfo.type.getAnnotationMirrors();
 299         boolean needSpace = false;
 300         for (AnnotationMirror anno : annotations) {
 301             if (needSpace) {
 302                 links.addContent(" ");
 303             }
 304             links.addContent(getTypeAnnotationLink(linkInfo, anno));
 305             needSpace = true;
 306         }
 307 
 308         links.addContent(" ");
 309         return links;
 310     }
 311 }