1 /*
   2  * Copyright (c) 1997, 2019, 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.formats.html;
  27 
  28 import java.util.Collection;
  29 import java.util.List;
  30 import java.util.Set;
  31 import java.util.SortedSet;
  32 import java.util.TreeSet;
  33 
  34 import javax.lang.model.element.AnnotationMirror;
  35 import javax.lang.model.element.Element;
  36 import javax.lang.model.element.ModuleElement;
  37 import javax.lang.model.element.PackageElement;
  38 import javax.lang.model.element.RecordComponentElement;
  39 import javax.lang.model.element.TypeElement;
  40 import javax.lang.model.type.TypeMirror;
  41 import javax.lang.model.util.SimpleElementVisitor8;
  42 
  43 import com.sun.source.doctree.DocTree;
  44 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
  45 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
  46 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
  47 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  48 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  49 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
  50 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
  51 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
  52 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  53 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
  54 import jdk.javadoc.internal.doclets.toolkit.Content;
  55 import jdk.javadoc.internal.doclets.toolkit.taglets.ParamTaglet;
  56 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
  57 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
  58 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
  59 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  60 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
  61 
  62 /**
  63  * Generate the Class Information Page.
  64  *
  65  *  <p><b>This is NOT part of any supported API.
  66  *  If you write code that depends on this, you do so at your own risk.
  67  *  This code and its internal interfaces are subject to change or
  68  *  deletion without notice.</b>
  69  *
  70  * @see javax.lang.model.element.TypeElement
  71  * @see java.util.Collections
  72  * @see java.util.List
  73  * @see java.util.ArrayList
  74  * @see java.util.HashMap
  75  */
  76 public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter {
  77 
  78     private static final Set<String> suppressSubtypesSet
  79             = Set.of("java.lang.Object",
  80                      "org.omg.CORBA.Object");
  81 
  82     private static final Set<String> suppressImplementingSet
  83             = Set.of( "java.lang.Cloneable",
  84                     "java.lang.constant.Constable",
  85                     "java.lang.constant.ConstantDesc",
  86                     "java.io.Serializable");
  87 
  88     protected final TypeElement typeElement;
  89 
  90     protected final ClassTree classtree;
  91 
  92     private final Navigation navBar;
  93 
  94     /**
  95      * @param configuration the configuration data for the doclet
  96      * @param typeElement the class being documented.
  97      * @param classTree the class tree for the given class.
  98      */
  99     public ClassWriterImpl(HtmlConfiguration configuration, TypeElement typeElement,
 100                            ClassTree classTree) {
 101         super(configuration, configuration.docPaths.forClass(typeElement));
 102         this.typeElement = typeElement;
 103         configuration.currentTypeElement = typeElement;
 104         this.classtree = classTree;
 105         this.navBar = new Navigation(typeElement, configuration, PageMode.CLASS, path);
 106     }
 107 
 108     /**
 109      * {@inheritDoc}
 110      */
 111     @Override
 112     public Content getHeader(String header) {
 113         HtmlTree bodyTree = getBody(getWindowTitle(utils.getSimpleName(typeElement)));
 114         Content headerContent = new ContentBuilder();
 115         addTop(headerContent);
 116         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
 117                 contents.moduleLabel);
 118         navBar.setNavLinkModule(linkContent);
 119         navBar.setMemberSummaryBuilder(configuration.getBuilderFactory().getMemberSummaryBuilder(this));
 120         navBar.setUserHeader(getUserHeaderFooter(true));
 121         headerContent.add(navBar.getContent(true));
 122         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 123         div.setStyle(HtmlStyle.header);
 124         if (configuration.showModules) {
 125             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement);
 126             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel);
 127             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
 128             moduleNameDiv.add(Entity.NO_BREAK_SPACE);
 129             moduleNameDiv.add(getModuleLink(mdle,
 130                     new StringContent(mdle.getQualifiedName())));
 131             div.add(moduleNameDiv);
 132         }
 133         PackageElement pkg = utils.containingPackage(typeElement);
 134         if (!pkg.isUnnamed()) {
 135             Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInType, contents.packageLabel);
 136             Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
 137             pkgNameDiv.add(Entity.NO_BREAK_SPACE);
 138             Content pkgNameContent = getPackageLink(pkg,
 139                     new StringContent(utils.getPackageName(pkg)));
 140             pkgNameDiv.add(pkgNameContent);
 141             div.add(pkgNameDiv);
 142         }
 143         LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
 144                 LinkInfoImpl.Kind.CLASS_HEADER, typeElement);
 145         //Let's not link to ourselves in the header.
 146         linkInfo.linkToSelf = false;
 147         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
 148                 HtmlStyle.title, new StringContent(header));
 149         heading.add(getTypeParameterLinks(linkInfo));
 150         div.add(heading);
 151         bodyContents.setHeader(headerContent)
 152                 .addMainContent(MarkerComments.START_OF_CLASS_DATA)
 153                 .addMainContent(div);
 154         return bodyTree;
 155     }
 156 
 157     /**
 158      * {@inheritDoc}
 159      */
 160     @Override
 161     public Content getClassContentHeader() {
 162         return getContentHeader();
 163     }
 164 
 165     /**
 166      * {@inheritDoc}
 167      */
 168     @Override
 169     public void addFooter() {
 170         bodyContents.addMainContent(MarkerComments.END_OF_CLASS_DATA);
 171         Content htmlTree = HtmlTree.FOOTER();
 172         navBar.setUserFooter(getUserHeaderFooter(false));
 173         htmlTree.add(navBar.getContent(false));
 174         addBottom(htmlTree);
 175         bodyContents.setFooter(htmlTree);
 176     }
 177 
 178     /**
 179      * {@inheritDoc}
 180      */
 181     @Override
 182     public void printDocument(Content contentTree) throws DocFileIOException {
 183         String description = getDescription("declaration", typeElement);
 184         PackageElement pkg = utils.containingPackage(typeElement);
 185         List<DocPath> localStylesheets = getLocalStylesheets(pkg);
 186         contentTree.add(bodyContents.toContent());
 187         printHtmlDocument(configuration.metakeywords.getMetaKeywords(typeElement),
 188                 description, localStylesheets, contentTree);
 189     }
 190 
 191     /**
 192      * {@inheritDoc}
 193      */
 194     @Override
 195     public Content getClassInfoTreeHeader() {
 196         return getMemberTreeHeader();
 197     }
 198 
 199     /**
 200      * {@inheritDoc}
 201      */
 202     @Override
 203     public Content getClassInfo(Content classInfoTree) {
 204         return getMemberTree(HtmlStyle.description, classInfoTree);
 205     }
 206 
 207     /**
 208      * {@inheritDoc}
 209      */
 210     @Override
 211     protected TypeElement getCurrentPageElement() {
 212         return typeElement;
 213     }
 214 
 215     /**
 216      * {@inheritDoc}
 217      */
 218     @Override @SuppressWarnings("preview")
 219     public void addClassSignature(String modifiers, Content classInfoTree) {
 220         Content hr = new HtmlTree(HtmlTag.HR);
 221         classInfoTree.add(hr);
 222         Content pre = new HtmlTree(HtmlTag.PRE);
 223         addAnnotationInfo(typeElement, pre);
 224         pre.add(modifiers);
 225         LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
 226                 LinkInfoImpl.Kind.CLASS_SIGNATURE, typeElement);
 227         //Let's not link to ourselves in the signature.
 228         linkInfo.linkToSelf = false;
 229         Content className = new StringContent(utils.getSimpleName(typeElement));
 230         Content parameterLinks = getTypeParameterLinks(linkInfo);
 231         if (configuration.getOptions().linkSource) {
 232             addSrcLink(typeElement, className, pre);
 233             pre.add(parameterLinks);
 234         } else {
 235             Content span = HtmlTree.SPAN(HtmlStyle.typeNameLabel, className);
 236             span.add(parameterLinks);
 237             pre.add(span);
 238         }
 239         if (utils.isRecord(typeElement)) {
 240             pre.add(getRecordComponents(typeElement));
 241         }
 242         if (!utils.isInterface(typeElement)) {
 243             TypeMirror superclass = utils.getFirstVisibleSuperClass(typeElement);
 244             if (superclass != null) {
 245                 pre.add(DocletConstants.NL);
 246                 pre.add("extends ");
 247                 Content link = getLink(new LinkInfoImpl(configuration,
 248                         LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME,
 249                         superclass));
 250                 pre.add(link);
 251             }
 252         }
 253         List<? extends TypeMirror> interfaces = typeElement.getInterfaces();
 254         if (!interfaces.isEmpty()) {
 255             boolean isFirst = true;
 256             for (TypeMirror type : interfaces) {
 257                 TypeElement tDoc = utils.asTypeElement(type);
 258                 if (!(utils.isPublic(tDoc) || utils.isLinkable(tDoc))) {
 259                     continue;
 260                 }
 261                 if (isFirst) {
 262                     pre.add(DocletConstants.NL);
 263                     pre.add(utils.isInterface(typeElement) ? "extends " : "implements ");
 264                     isFirst = false;
 265                 } else {
 266                     pre.add(", ");
 267                 }
 268                 Content link = getLink(new LinkInfoImpl(configuration,
 269                                                         LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME,
 270                                                         type));
 271                 pre.add(link);
 272             }
 273         }
 274         classInfoTree.add(pre);
 275     }
 276 
 277     @SuppressWarnings("preview")
 278     private Content getRecordComponents(TypeElement typeElem) {
 279         Content content = new ContentBuilder();
 280         content.add("(");
 281         String sep = "";
 282         for (RecordComponentElement e : typeElement.getRecordComponents()) {
 283             content.add(sep);
 284             getAnnotations(e.getAnnotationMirrors(), false).stream()
 285                     .forEach(a -> { content.add(a); content.add(" "); });
 286             Content link = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.RECORD_COMPONENT,
 287                     e.asType()));
 288             content.add(link);
 289             content.add(Entity.NO_BREAK_SPACE);
 290             content.add(e.getSimpleName());
 291             sep = ", ";
 292         }
 293         content.add(")");
 294         return content;
 295     }
 296 
 297     /**
 298      * {@inheritDoc}
 299      */
 300     @Override
 301     public void addClassDescription(Content classInfoTree) {
 302         if(!configuration.getOptions().noComment) {
 303             // generate documentation for the class.
 304             if (!utils.getFullBody(typeElement).isEmpty()) {
 305                 addInlineComment(typeElement, classInfoTree);
 306             }
 307         }
 308     }
 309 
 310     /**
 311      * {@inheritDoc}
 312      */
 313     @Override
 314     public void addClassTagInfo(Content classInfoTree) {
 315         if(!configuration.getOptions().noComment) {
 316             // Print Information about all the tags here
 317             addTagsInfo(typeElement, classInfoTree);
 318         }
 319     }
 320 
 321     /**
 322      * Get the class hierarchy tree for the given class.
 323      *
 324      * @param type the class to print the hierarchy for
 325      * @return a content tree for class inheritance
 326      */
 327     private Content getClassInheritanceTree(TypeMirror type) {
 328         TypeMirror sup;
 329         HtmlTree classTree = null;
 330         do {
 331             sup = utils.getFirstVisibleSuperClass(type);
 332             HtmlTree htmlElement = HtmlTree.DIV(HtmlStyle.inheritance, getTreeForClassHelper(type));
 333             if (classTree != null)
 334                 htmlElement.add(classTree);
 335             classTree = htmlElement;
 336             type = sup;
 337         } while (sup != null);
 338         classTree.put(HtmlAttr.TITLE, contents.getContent("doclet.Inheritance_Tree").toString());
 339         return classTree;
 340     }
 341 
 342     /**
 343      * Get the class helper tree for the given class.
 344      *
 345      * @param type the class to print the helper for
 346      * @return a content tree for class helper
 347      */
 348     private Content getTreeForClassHelper(TypeMirror type) {
 349         Content content = new ContentBuilder();
 350         if (type.equals(typeElement.asType())) {
 351             Content typeParameters = getTypeParameterLinks(
 352                     new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE,
 353                     typeElement));
 354             if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) {
 355                 content.add(utils.asTypeElement(type).getSimpleName());
 356                 content.add(typeParameters);
 357             } else {
 358                 content.add(utils.asTypeElement(type).getQualifiedName());
 359                 content.add(typeParameters);
 360             }
 361         } else {
 362             Content link = getLink(new LinkInfoImpl(configuration,
 363                     LinkInfoImpl.Kind.CLASS_TREE_PARENT, type)
 364                     .label(configuration.getClassName(utils.asTypeElement(type))));
 365             content.add(link);
 366         }
 367         return content;
 368     }
 369 
 370     /**
 371      * {@inheritDoc}
 372      */
 373     @Override
 374     public void addClassTree(Content classContentTree) {
 375         if (!utils.isClass(typeElement)) {
 376             return;
 377         }
 378         classContentTree.add(getClassInheritanceTree(typeElement.asType()));
 379     }
 380 
 381     /**
 382      * {@inheritDoc}
 383      */
 384     @Override
 385     public void addParamInfo(Content classInfoTree) {
 386         if (utils.hasBlockTag(typeElement, DocTree.Kind.PARAM)) {
 387             Content paramInfo = (new ParamTaglet()).getTagletOutput(typeElement,
 388                     getTagletWriterInstance(false));
 389             if (!paramInfo.isEmpty()) {
 390                 classInfoTree.add(HtmlTree.DL(paramInfo));
 391             }
 392         }
 393     }
 394 
 395     /**
 396      * {@inheritDoc}
 397      */
 398     @Override
 399     public void addSubClassInfo(Content classInfoTree) {
 400         if (utils.isClass(typeElement)) {
 401             for (String s : suppressSubtypesSet) {
 402                 if (typeElement.getQualifiedName().contentEquals(s)) {
 403                     return;    // Don't generate the list, too huge
 404                 }
 405             }
 406             Set<TypeElement> subclasses = classtree.directSubClasses(typeElement, false);
 407             if (!subclasses.isEmpty()) {
 408                 Content label = contents.subclassesLabel;
 409                 Content dt = HtmlTree.DT(label);
 410                 Content dl = HtmlTree.DL(dt);
 411                 dl.add(getClassLinks(LinkInfoImpl.Kind.SUBCLASSES,
 412                         subclasses));
 413                 classInfoTree.add(dl);
 414             }
 415         }
 416     }
 417 
 418     /**
 419      * {@inheritDoc}
 420      */
 421     @Override
 422     public void addSubInterfacesInfo(Content classInfoTree) {
 423         if (utils.isInterface(typeElement)) {
 424             Set<TypeElement> subInterfaces = classtree.allSubClasses(typeElement, false);
 425             if (!subInterfaces.isEmpty()) {
 426                 Content label = contents.subinterfacesLabel;
 427                 Content dt = HtmlTree.DT(label);
 428                 Content dl = HtmlTree.DL(dt);
 429                 dl.add(getClassLinks(LinkInfoImpl.Kind.SUBINTERFACES,
 430                         subInterfaces));
 431                 classInfoTree.add(dl);
 432             }
 433         }
 434     }
 435 
 436     /**
 437      * {@inheritDoc}
 438      */
 439     @Override
 440     public void addInterfaceUsageInfo (Content classInfoTree) {
 441         if (!utils.isInterface(typeElement)) {
 442             return;
 443         }
 444         for (String s : suppressImplementingSet) {
 445             if (typeElement.getQualifiedName().contentEquals(s)) {
 446                 return;    // Don't generate the list, too huge
 447             }
 448         }
 449         Set<TypeElement> implcl = classtree.implementingClasses(typeElement);
 450         if (!implcl.isEmpty()) {
 451             Content label = contents.implementingClassesLabel;
 452             Content dt = HtmlTree.DT(label);
 453             Content dl = HtmlTree.DL(dt);
 454             dl.add(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_CLASSES,
 455                     implcl));
 456             classInfoTree.add(dl);
 457         }
 458     }
 459 
 460     /**
 461      * {@inheritDoc}
 462      */
 463     @Override
 464     public void addImplementedInterfacesInfo(Content classInfoTree) {
 465         SortedSet<TypeMirror> interfaces = new TreeSet<>(utils.makeTypeMirrorClassUseComparator());
 466         interfaces.addAll(utils.getAllInterfaces(typeElement));
 467         if (utils.isClass(typeElement) && !interfaces.isEmpty()) {
 468             Content label = contents.allImplementedInterfacesLabel;
 469             Content dt = HtmlTree.DT(label);
 470             Content dl = HtmlTree.DL(dt);
 471             dl.add(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_INTERFACES, interfaces));
 472             classInfoTree.add(dl);
 473         }
 474     }
 475 
 476     /**
 477      * {@inheritDoc}
 478      */
 479     @Override
 480     public void addSuperInterfacesInfo(Content classInfoTree) {
 481         SortedSet<TypeMirror> interfaces =
 482                 new TreeSet<>(utils.makeTypeMirrorIndexUseComparator());
 483         interfaces.addAll(utils.getAllInterfaces(typeElement));
 484 
 485         if (utils.isInterface(typeElement) && !interfaces.isEmpty()) {
 486             Content label = contents.allSuperinterfacesLabel;
 487             Content dt = HtmlTree.DT(label);
 488             Content dl = HtmlTree.DL(dt);
 489             dl.add(getClassLinks(LinkInfoImpl.Kind.SUPER_INTERFACES, interfaces));
 490             classInfoTree.add(dl);
 491         }
 492     }
 493 
 494     /**
 495      * {@inheritDoc}
 496      */
 497     @Override
 498     public void addNestedClassInfo(final Content classInfoTree) {
 499         Element outerClass = typeElement.getEnclosingElement();
 500         if (outerClass == null)
 501             return;
 502         new SimpleElementVisitor8<Void, Void>() {
 503             @Override
 504             public Void visitType(TypeElement e, Void p) {
 505                 Content label = utils.isInterface(e)
 506                         ? contents.enclosingInterfaceLabel
 507                         : contents.enclosingClassLabel;
 508                 Content dt = HtmlTree.DT(label);
 509                 Content dl = HtmlTree.DL(dt);
 510                 Content dd = new HtmlTree(HtmlTag.DD);
 511                 dd.add(getLink(new LinkInfoImpl(configuration,
 512                         LinkInfoImpl.Kind.CLASS, e)));
 513                 dl.add(dd);
 514                 classInfoTree.add(dl);
 515                 return null;
 516             }
 517         }.visit(outerClass);
 518     }
 519 
 520     /**
 521      * {@inheritDoc}
 522      */
 523     @Override
 524     public void addFunctionalInterfaceInfo (Content classInfoTree) {
 525         if (isFunctionalInterface()) {
 526             Content dt = HtmlTree.DT(contents.functionalInterface);
 527             Content dl = HtmlTree.DL(dt);
 528             Content dd = new HtmlTree(HtmlTag.DD);
 529             dd.add(contents.functionalInterfaceMessage);
 530             dl.add(dd);
 531             classInfoTree.add(dl);
 532         }
 533     }
 534 
 535     public boolean isFunctionalInterface() {
 536         List<? extends AnnotationMirror> annotationMirrors = ((Element) typeElement).getAnnotationMirrors();
 537         for (AnnotationMirror anno : annotationMirrors) {
 538             if (utils.isFunctionalInterface(anno)) {
 539                 return true;
 540             }
 541         }
 542         return false;
 543     }
 544 
 545 
 546     /**
 547      * {@inheritDoc}
 548      */
 549     @Override
 550     public void addClassDeprecationInfo(Content classInfoTree) {
 551         List<? extends DocTree> deprs = utils.getBlockTags(typeElement, DocTree.Kind.DEPRECATED);
 552         if (utils.isDeprecated(typeElement)) {
 553             Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(typeElement));
 554             Content div = HtmlTree.DIV(HtmlStyle.deprecationBlock, deprLabel);
 555             if (!deprs.isEmpty()) {
 556                 CommentHelper ch = utils.getCommentHelper(typeElement);
 557                 DocTree dt = deprs.get(0);
 558                 List<? extends DocTree> commentTags = ch.getBody(configuration, dt);
 559                 if (!commentTags.isEmpty()) {
 560                     addInlineDeprecatedComment(typeElement, deprs.get(0), div);
 561                 }
 562             }
 563             classInfoTree.add(div);
 564         }
 565     }
 566 
 567     /**
 568      * Get links to the given classes.
 569      *
 570      * @param context the id of the context where the link will be printed
 571      * @param list the list of classes
 572      * @return a content tree for the class list
 573      */
 574     private Content getClassLinks(LinkInfoImpl.Kind context, Collection<?> list) {
 575         Content dd = new HtmlTree(HtmlTag.DD);
 576         boolean isFirst = true;
 577         for (Object type : list) {
 578             if (!isFirst) {
 579                 Content separator = new StringContent(", ");
 580                 dd.add(separator);
 581             } else {
 582                 isFirst = false;
 583             }
 584             // TODO: should we simply split this method up to avoid instanceof ?
 585             if (type instanceof TypeElement) {
 586                 Content link = getLink(
 587                         new LinkInfoImpl(configuration, context, (TypeElement)(type)));
 588                 dd.add(HtmlTree.CODE(link));
 589             } else {
 590                 Content link = getLink(
 591                         new LinkInfoImpl(configuration, context, ((TypeMirror)type)));
 592                 dd.add(HtmlTree.CODE(link));
 593             }
 594         }
 595         return dd;
 596     }
 597 
 598     /**
 599      * Return the TypeElement being documented.
 600      *
 601      * @return the TypeElement being documented.
 602      */
 603     @Override
 604     public TypeElement getTypeElement() {
 605         return typeElement;
 606     }
 607 }