langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
changeset 36500 d31e4986dc8b
parent 36038 39c5445924b9
child 36526 3b41f1c69604
equal deleted inserted replaced
36499:9d823cc0fe98 36500:d31e4986dc8b
   163      * To check whether the container annotations is documented or not.
   163      * To check whether the container annotations is documented or not.
   164      */
   164      */
   165     private boolean isContainerDocumented = false;
   165     private boolean isContainerDocumented = false;
   166 
   166 
   167     HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV);
   167     HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV);
       
   168 
       
   169     final static Pattern IMPROPER_HTML_CHARS = Pattern.compile(".*[&<>].*");
   168 
   170 
   169     /**
   171     /**
   170      * Constructor to construct the HtmlStandardWriter object.
   172      * Constructor to construct the HtmlStandardWriter object.
   171      *
   173      *
   172      * @param path File to be generated.
   174      * @param path File to be generated.
   943      * @return package name content
   945      * @return package name content
   944      */
   946      */
   945     public Content getPackageName(PackageElement packageElement) {
   947     public Content getPackageName(PackageElement packageElement) {
   946         return packageElement == null || packageElement.isUnnamed()
   948         return packageElement == null || packageElement.isUnnamed()
   947                 ? defaultPackageLabel
   949                 ? defaultPackageLabel
   948                 : getPackageLabel(packageElement.getQualifiedName().toString());
   950                 : getPackageLabel(packageElement.getQualifiedName());
   949     }
   951     }
   950 
   952 
   951     /**
   953     /**
   952      * Returns a package name label.
   954      * Returns a package name label.
   953      *
   955      *
   954      * @param packageName the package name
   956      * @param packageName the package name
   955      * @return the package name content
   957      * @return the package name content
   956      */
   958      */
   957     public Content getPackageLabel(String packageName) {
   959     public Content getPackageLabel(CharSequence packageName) {
   958         return new StringContent(packageName);
   960         return new StringContent(packageName);
   959     }
   961     }
   960 
   962 
   961     /**
   963     /**
   962      * Add package deprecation information to the documentation tree
   964      * Add package deprecation information to the documentation tree
  1036      *
  1038      *
  1037      * @param packageElement the package to link to.
  1039      * @param packageElement the package to link to.
  1038      * @param label the label for the link.
  1040      * @param label the label for the link.
  1039      * @return a content tree for the package link.
  1041      * @return a content tree for the package link.
  1040      */
  1042      */
  1041     public Content getPackageLink(PackageElement packageElement, String label) {
  1043     public Content getPackageLink(PackageElement packageElement, CharSequence label) {
  1042         return getPackageLink(packageElement, new StringContent(label));
  1044         return getPackageLink(packageElement, new StringContent(label));
  1043     }
  1045     }
  1044 
  1046 
  1045     public Content getPackageLink(PackageElement packageElement) {
  1047     public Content getPackageLink(PackageElement packageElement) {
  1046         StringContent content =  packageElement.isUnnamed()
  1048         StringContent content =  packageElement.isUnnamed()
  1079         }
  1081         }
  1080     }
  1082     }
  1081 
  1083 
  1082     public Content interfaceName(TypeElement typeElement, boolean qual) {
  1084     public Content interfaceName(TypeElement typeElement, boolean qual) {
  1083         Content name = new StringContent((qual)
  1085         Content name = new StringContent((qual)
  1084                 ? typeElement.getQualifiedName().toString()
  1086                 ? typeElement.getQualifiedName()
  1085                 : utils.getSimpleName(typeElement));
  1087                 : utils.getSimpleName(typeElement));
  1086         return (utils.isInterface(typeElement)) ?  HtmlTree.SPAN(HtmlStyle.interfaceName, name) : name;
  1088         return (utils.isInterface(typeElement)) ?  HtmlTree.SPAN(HtmlStyle.interfaceName, name) : name;
  1087     }
  1089     }
  1088 
  1090 
  1089     /**
  1091     /**
  1277      * @param context the id of the context where the link will be added
  1279      * @param context the id of the context where the link will be added
  1278      * @param element the member being linked to
  1280      * @param element the member being linked to
  1279      * @param label the label for the link
  1281      * @param label the label for the link
  1280      * @return a content tree for the element link
  1282      * @return a content tree for the element link
  1281      */
  1283      */
  1282     public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label) {
  1284     public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label) {
  1283         return getDocLink(context, utils.getEnclosingTypeElement(element), element,
  1285         return getDocLink(context, utils.getEnclosingTypeElement(element), element,
  1284                 new StringContent(label));
  1286                 new StringContent(label));
  1285     }
  1287     }
  1286 
  1288 
  1287     /**
  1289     /**
  1291      * @param element the member being linked to.
  1293      * @param element the member being linked to.
  1292      * @param label the label for the link.
  1294      * @param label the label for the link.
  1293      * @param strong true if the link should be strong.
  1295      * @param strong true if the link should be strong.
  1294      * @return the link for the given member.
  1296      * @return the link for the given member.
  1295      */
  1297      */
  1296     public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label,
  1298     public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label,
  1297             boolean strong) {
  1299             boolean strong) {
  1298         return getDocLink(context, utils.getEnclosingTypeElement(element), element, label, strong);
  1300         return getDocLink(context, utils.getEnclosingTypeElement(element), element, label, strong);
  1299     }
  1301     }
  1300 
  1302 
  1301     /**
  1303     /**
  1309      * @param label the label for the link.
  1311      * @param label the label for the link.
  1310      * @param strong true if the link should be strong.
  1312      * @param strong true if the link should be strong.
  1311      * @return the link for the given member.
  1313      * @return the link for the given member.
  1312      */
  1314      */
  1313     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
  1315     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
  1314             String label, boolean strong) {
  1316             CharSequence label, boolean strong) {
  1315         return getDocLink(context, typeElement, element, label, strong, false);
  1317         return getDocLink(context, typeElement, element, label, strong, false);
  1316     }
  1318     }
  1317 
  1319 
  1318     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
  1320     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
  1319             Content label, boolean strong) {
  1321             Content label, boolean strong) {
  1332      * @param strong true if the link should be strong.
  1334      * @param strong true if the link should be strong.
  1333      * @param isProperty true if the element parameter is a JavaFX property.
  1335      * @param isProperty true if the element parameter is a JavaFX property.
  1334      * @return the link for the given member.
  1336      * @return the link for the given member.
  1335      */
  1337      */
  1336     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
  1338     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
  1337             String label, boolean strong, boolean isProperty) {
  1339             CharSequence label, boolean strong, boolean isProperty) {
  1338         return getDocLink(context, typeElement, element, new StringContent(check(label)), strong, isProperty);
  1340         return getDocLink(context, typeElement, element, new StringContent(check(label)), strong, isProperty);
  1339     }
  1341     }
  1340 
  1342 
  1341     String check(String s) {
  1343     CharSequence check(CharSequence s) {
  1342         if (s.matches(".*[&<>].*")) {
  1344         Matcher m = IMPROPER_HTML_CHARS.matcher(s);
  1343             throw new IllegalArgumentException(s);
  1345         if (m.matches()) {
       
  1346             throw new IllegalArgumentException(s.toString());
  1344         }
  1347         }
  1345         return s;
  1348         return s;
  1346     }
  1349     }
  1347 
  1350 
  1348     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
  1351     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
  1424             return new ContentBuilder();
  1427             return new ContentBuilder();
  1425         }
  1428         }
  1426 
  1429 
  1427         CommentHelper ch = utils.getCommentHelper(element);
  1430         CommentHelper ch = utils.getCommentHelper(element);
  1428         String tagName = ch.getTagName(see);
  1431         String tagName = ch.getTagName(see);
  1429         String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see)));
  1432         String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see)).toString());
  1430         // Check if @see is an href or "string"
  1433         // Check if @see is an href or "string"
  1431         if (seetext.startsWith("<") || seetext.startsWith("\"")) {
  1434         if (seetext.startsWith("<") || seetext.startsWith("\"")) {
  1432             return new RawHtml(seetext);
  1435             return new RawHtml(seetext);
  1433         }
  1436         }
  1434         boolean isLinkPlain = kind == LINK_PLAIN;
  1437         boolean isLinkPlain = kind == LINK_PLAIN;
  1450             PackageElement refPackage = ch.getReferencedPackage(configuration, see);
  1453             PackageElement refPackage = ch.getReferencedPackage(configuration, see);
  1451             if (refPackage != null && utils.isIncluded(refPackage)) {
  1454             if (refPackage != null && utils.isIncluded(refPackage)) {
  1452                 //@see is referencing an included package
  1455                 //@see is referencing an included package
  1453                 if (label.isEmpty())
  1456                 if (label.isEmpty())
  1454                     label = plainOrCode(isLinkPlain,
  1457                     label = plainOrCode(isLinkPlain,
  1455                             new StringContent(refPackage.getQualifiedName().toString()));
  1458                             new StringContent(refPackage.getQualifiedName()));
  1456                 return getPackageLink(refPackage, label);
  1459                 return getPackageLink(refPackage, label);
  1457             } else {
  1460             } else {
  1458                 // @see is not referencing an included class or package.  Check for cross links.
  1461                 // @see is not referencing an included class or package.  Check for cross links.
  1459                 Content classCrossLink;
  1462                 Content classCrossLink;
  1460                 DocLink packageCrossLink = getCrossPackageLink(refClassName);
  1463                 DocLink packageCrossLink = getCrossPackageLink(refClassName);
  1693     public Content commentTagsToContent(DocTree holderTag, Element element,
  1696     public Content commentTagsToContent(DocTree holderTag, Element element,
  1694             List<? extends DocTree> tags, boolean isFirstSentence) {
  1697             List<? extends DocTree> tags, boolean isFirstSentence) {
  1695 
  1698 
  1696         final Content result = new ContentBuilder() {
  1699         final Content result = new ContentBuilder() {
  1697             @Override
  1700             @Override
  1698             public void addContent(String text) {
  1701             public void addContent(CharSequence text) {
  1699                 super.addContent(utils.normalizeNewlines(text));
  1702                 super.addContent(utils.normalizeNewlines(text));
  1700             }
  1703             }
  1701         };
  1704         };
  1702         CommentHelper ch = utils.getCommentHelper(element);
  1705         CommentHelper ch = utils.getCommentHelper(element);
  1703         // Array of all possible inline tags for this javadoc run
  1706         // Array of all possible inline tags for this javadoc run
  1739 
  1742 
  1740                 @Override @DefinedBy(Api.COMPILER_TREE)
  1743                 @Override @DefinedBy(Api.COMPILER_TREE)
  1741                 public Boolean visitAttribute(AttributeTree node, Content c) {
  1744                 public Boolean visitAttribute(AttributeTree node, Content c) {
  1742                     StringBuilder sb = new StringBuilder(SPACER).append(node.getName());
  1745                     StringBuilder sb = new StringBuilder(SPACER).append(node.getName());
  1743                     if (node.getValueKind() == ValueKind.EMPTY) {
  1746                     if (node.getValueKind() == ValueKind.EMPTY) {
  1744                         result.addContent(sb.toString());
  1747                         result.addContent(sb);
  1745                         return false;
  1748                         return false;
  1746                     }
  1749                     }
  1747                     sb.append("=");
  1750                     sb.append("=");
  1748                     String quote;
  1751                     String quote;
  1749                     switch (node.getValueKind()) {
  1752                     switch (node.getValueKind()) {
  1756                         default:
  1759                         default:
  1757                             quote = "";
  1760                             quote = "";
  1758                             break;
  1761                             break;
  1759                     }
  1762                     }
  1760                     sb.append(quote);
  1763                     sb.append(quote);
  1761                     result.addContent(sb.toString());
  1764                     result.addContent(sb);
  1762                     Content docRootContent = new ContentBuilder();
  1765                     Content docRootContent = new ContentBuilder();
  1763 
  1766 
  1764                     for (DocTree dt : node.getValue()) {
  1767                     for (DocTree dt : node.getValue()) {
  1765                         if (utils.isText(dt) && inAnAtag()) {
  1768                         if (utils.isText(dt) && inAnAtag()) {
  1766                             String text = ((TextTree) dt).getBody();
  1769                             String text = ((TextTree) dt).getBody();
  1767                             if (text.startsWith("/..") && !configuration.docrootparent.isEmpty()) {
  1770                             if (text.startsWith("/..") && !configuration.docrootparent.isEmpty()) {
  1768                                 result.addContent(configuration.docrootparent);
  1771                                 result.addContent(configuration.docrootparent);
  1769                                 docRootContent = new ContentBuilder();
  1772                                 docRootContent = new ContentBuilder();
  1770                                 text = textCleanup(text.substring(3), isLast(node));
  1773                                 result.addContent(textCleanup(text.substring(3), isLast(node)));
  1771                             } else {
  1774                             } else {
  1772                                 if (!docRootContent.isEmpty()) {
  1775                                 if (!docRootContent.isEmpty()) {
  1773                                     docRootContent = copyDocRootContent(docRootContent);
  1776                                     docRootContent = copyDocRootContent(docRootContent);
  1774                                 } else {
  1777                                 } else {
  1775                                     text = redirectRelativeLinks(element, (TextTree) dt);
  1778                                     text = redirectRelativeLinks(element, (TextTree) dt);
  1776                                 }
  1779                                 }
  1777                                 text = textCleanup(text, isLast(node));
  1780                                 result.addContent(textCleanup(text, isLast(node)));
  1778                             }
  1781                             }
  1779                             result.addContent(text);
       
  1780                         } else {
  1782                         } else {
  1781                             docRootContent = copyDocRootContent(docRootContent);
  1783                             docRootContent = copyDocRootContent(docRootContent);
  1782                             dt.accept(this, docRootContent);
  1784                             dt.accept(this, docRootContent);
  1783                         }
  1785                         }
  1784                     }
  1786                     }
  1887                 }
  1889                 }
  1888 
  1890 
  1889                 @Override @DefinedBy(Api.COMPILER_TREE)
  1891                 @Override @DefinedBy(Api.COMPILER_TREE)
  1890                 public Boolean visitStartElement(StartElementTree node, Content c) {
  1892                 public Boolean visitStartElement(StartElementTree node, Content c) {
  1891                     String text = "<" + node.getName();
  1893                     String text = "<" + node.getName();
  1892                     text = utils.normalizeNewlines(text);
  1894                     RawHtml rawHtml = new RawHtml(utils.normalizeNewlines(text));
  1893                     RawHtml rawHtml = new RawHtml(text);
       
  1894                     result.addContent(rawHtml);
  1895                     result.addContent(rawHtml);
  1895 
  1896 
  1896                     for (DocTree dt : node.getAttributes()) {
  1897                     for (DocTree dt : node.getAttributes()) {
  1897                         dt.accept(this, null);
  1898                         dt.accept(this, null);
  1898                     }
  1899                     }
  1899                     result.addContent(new RawHtml(node.isSelfClosing() ? "/>" : ">"));
  1900                     result.addContent(new RawHtml(node.isSelfClosing() ? "/>" : ">"));
  1900                     return false;
  1901                     return false;
  1901                 }
  1902                 }
  1902 
  1903 
  1903                 private String textCleanup(String text, boolean isLast) {
  1904                 private CharSequence textCleanup(String text, boolean isLast) {
  1904                     return textCleanup(text, isLast, false);
  1905                     return textCleanup(text, isLast, false);
  1905                 }
  1906                 }
  1906 
  1907 
  1907                 private String textCleanup(String text, boolean isLast, boolean trimLeader) {
  1908                 private CharSequence textCleanup(String text, boolean isLast, boolean trimLeader) {
  1908                     if (trimLeader) {
  1909                     if (trimLeader) {
  1909                         text = removeLeadingWhitespace(text);
  1910                         text = removeLeadingWhitespace(text);
  1910                     }
  1911                     }
  1911                     if (isFirstSentence && isLast) {
  1912                     if (isFirstSentence && isLast) {
  1912                         text = removeTrailingWhitespace(text);
  1913                         text = removeTrailingWhitespace(text);
  1913                     }
  1914                     }
  1914                     text = utils.replaceTabs(text);
  1915                     text = utils.replaceTabs(text);
  1915                     text = utils.normalizeNewlines(text);
  1916                     return utils.normalizeNewlines(text);
  1916                     return text;
       
  1917                 }
  1917                 }
  1918 
  1918 
  1919                 @Override @DefinedBy(Api.COMPILER_TREE)
  1919                 @Override @DefinedBy(Api.COMPILER_TREE)
  1920                 public Boolean visitText(TextTree node, Content c) {
  1920                 public Boolean visitText(TextTree node, Content c) {
  1921                     String text = node.getBody();
  1921                     String text = node.getBody();
  1922                     text = textCleanup(text, isLast(node), commentRemoved);
  1922                     result.addContent(new RawHtml(textCleanup(text, isLast(node), commentRemoved)));
  1923                     commentRemoved = false;
  1923                     commentRemoved = false;
  1924                     result.addContent(new RawHtml(text));
       
  1925                     return false;
  1924                     return false;
  1926                 }
  1925                 }
  1927 
  1926 
  1928                 @Override @DefinedBy(Api.COMPILER_TREE)
  1927                 @Override @DefinedBy(Api.COMPILER_TREE)
  1929                 protected Boolean defaultAction(DocTree node, Content c) {
  1928                 protected Boolean defaultAction(DocTree node, Content c) {
  2356      * @param linkBreak if true, add new line between each member value
  2355      * @param linkBreak if true, add new line between each member value
  2357      */
  2356      */
  2358     private void addAnnotations(TypeElement annotationDoc, LinkInfoImpl linkInfo,
  2357     private void addAnnotations(TypeElement annotationDoc, LinkInfoImpl linkInfo,
  2359         ContentBuilder annotation, Map<? extends ExecutableElement,? extends AnnotationValue>map,
  2358         ContentBuilder annotation, Map<? extends ExecutableElement,? extends AnnotationValue>map,
  2360         int indent, boolean linkBreak) {
  2359         int indent, boolean linkBreak) {
  2361         linkInfo.label = new StringContent("@" + annotationDoc.getSimpleName().toString());
  2360         linkInfo.label = new StringContent("@");
       
  2361         linkInfo.label.addContent(annotationDoc.getSimpleName());
  2362         annotation.addContent(getLink(linkInfo));
  2362         annotation.addContent(getLink(linkInfo));
  2363         if (!map.isEmpty()) {
  2363         if (!map.isEmpty()) {
  2364             annotation.addContent("(");
  2364             annotation.addContent("(");
  2365             boolean isFirst = true;
  2365             boolean isFirst = true;
  2366             Set<? extends ExecutableElement> keys = map.keySet();
  2366             Set<? extends ExecutableElement> keys = map.keySet();
  2370                     isFirst = false;
  2370                     isFirst = false;
  2371                 } else {
  2371                 } else {
  2372                     annotation.addContent(",");
  2372                     annotation.addContent(",");
  2373                     if (linkBreak) {
  2373                     if (linkBreak) {
  2374                         annotation.addContent(DocletConstants.NL);
  2374                         annotation.addContent(DocletConstants.NL);
  2375                         int spaces = annotationDoc.getSimpleName().toString().length() + 2;
  2375                         int spaces = annotationDoc.getSimpleName().length() + 2;
  2376                         for (int k = 0; k < (spaces + indent); k++) {
  2376                         for (int k = 0; k < (spaces + indent); k++) {
  2377                             annotation.addContent(" ");
  2377                             annotation.addContent(" ");
  2378                         }
  2378                         }
  2379                     }
  2379                     }
  2380                 }
  2380                 }
  2494                 return buf;
  2494                 return buf;
  2495             }
  2495             }
  2496             @Override @DefinedBy(Api.LANGUAGE_MODEL)
  2496             @Override @DefinedBy(Api.LANGUAGE_MODEL)
  2497             public Content visitEnumConstant(VariableElement c, Void p) {
  2497             public Content visitEnumConstant(VariableElement c, Void p) {
  2498                 return getDocLink(LinkInfoImpl.Kind.ANNOTATION,
  2498                 return getDocLink(LinkInfoImpl.Kind.ANNOTATION,
  2499                         c, c.getSimpleName().toString(), false);
  2499                         c, c.getSimpleName(), false);
  2500             }
  2500             }
  2501             @Override @DefinedBy(Api.LANGUAGE_MODEL)
  2501             @Override @DefinedBy(Api.LANGUAGE_MODEL)
  2502             public Content visitArray(List<? extends AnnotationValue> vals, Void p) {
  2502             public Content visitArray(List<? extends AnnotationValue> vals, Void p) {
  2503                 ContentBuilder buf = new ContentBuilder();
  2503                 ContentBuilder buf = new ContentBuilder();
  2504                 String sep = "";
  2504                 String sep = "";