8214738: javadoc should honor styles in doc-files
authorpmuthuswamy
Tue, 08 Jan 2019 11:16:32 +0530
changeset 53164 f2140eebd91b
parent 53163 76f7dbf458fe
child 53177 2692d1bfe83a
8214738: javadoc should honor styles in doc-files Reviewed-by: jjg
src/jdk.compiler/share/classes/com/sun/tools/doclint/HtmlTag.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java
test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/HtmlTag.java	Mon Jan 07 18:48:39 2019 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/HtmlTag.java	Tue Jan 08 11:16:32 2019 +0530
@@ -305,6 +305,8 @@
     STRONG(BlockType.INLINE, EndKind.REQUIRED,
             EnumSet.of(Flag.EXPECT_CONTENT)),
 
+    STYLE(BlockType.OTHER, EndKind.REQUIRED),
+
     SUB(BlockType.INLINE, EndKind.REQUIRED,
             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java	Mon Jan 07 18:48:39 2019 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java	Tue Jan 08 11:16:32 2019 +0530
@@ -31,6 +31,7 @@
 import com.sun.source.doctree.EndElementTree;
 import com.sun.source.doctree.StartElementTree;
 import com.sun.source.doctree.TextTree;
+import com.sun.source.util.DocTreeFactory;
 import com.sun.source.util.SimpleDocTreeVisitor;
 import com.sun.tools.doclint.HtmlTag;
 import com.sun.tools.doclint.HtmlTag.Attr;
@@ -43,6 +44,7 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 
 import javax.lang.model.element.Element;
@@ -51,6 +53,7 @@
 import javax.tools.FileObject;
 import javax.tools.JavaFileManager.Location;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -140,13 +143,12 @@
                             srcfile.getPath(), dstdir.getPath());
                 } else {
                     if (Utils.toLowerCase(srcfile.getPath()).endsWith(".html")) {
-                        if (handleHtmlFile(srcfile, dstDocPath)) {
-                            continue;
-                        }
+                        handleHtmlFile(srcfile, dstDocPath);
+                    } else {
+                        configuration.messages.notice("doclet.Copying_File_0_To_Dir_1",
+                                srcfile.getPath(), dstdir.getPath());
+                        destfile.copyFile(srcfile);
                     }
-                    configuration.messages.notice("doclet.Copying_File_0_To_Dir_1",
-                            srcfile.getPath(), dstdir.getPath());
-                    destfile.copyFile(srcfile);
                 }
             } else if (srcfile.isDirectory()) {
                 if (configuration.copydocfilesubdirs
@@ -158,19 +160,18 @@
         }
     }
 
-    private boolean handleHtmlFile(DocFile srcfile, DocPath dstPath) throws DocFileIOException {
+    private void handleHtmlFile(DocFile srcfile, DocPath dstPath) throws DocFileIOException {
         Utils utils = configuration.utils;
         FileObject fileObject = srcfile.getFileObject();
         DocFileElement dfElement = new DocFileElement(element, fileObject);
 
-        if (shouldPassThrough(utils.getPreamble(dfElement))) {
-            return false;
-        }
-
         DocPath dfilePath = dstPath.resolve(srcfile.getName());
         HtmlDocletWriter docletWriter = new DocFileWriter(configuration, dfilePath, element);
         configuration.messages.notice("doclet.Generating_0", docletWriter.filename.getPath());
 
+        List<? extends DocTree> localTags = getLocalHeaderTags(utils.getPreamble(dfElement));
+        Content localTagsContent = docletWriter.commentTagsToContent(null, dfElement, localTags, false);
+
         String title = getWindowTitle(docletWriter, dfElement).trim();
         HtmlTree htmlContent = docletWriter.getBody(true, title);
         docletWriter.addTop(htmlContent);
@@ -193,70 +194,61 @@
         navBar.setUserFooter(docletWriter.getUserHeaderFooter(false));
         htmlContent.addContent(navBar.getContent(false));
         docletWriter.addBottom(htmlContent);
-        docletWriter.printHtmlDocument(Collections.emptyList(), false, htmlContent);
-        return true;
+        docletWriter.printHtmlDocument(Collections.emptyList(), false, localTagsContent, htmlContent);
     }
 
 
-    private boolean shouldPassThrough(List<? extends DocTree> dtrees) {
-        SimpleDocTreeVisitor<Boolean, Boolean> check = new SimpleDocTreeVisitor<Boolean, Boolean>() {
-            @Override
-            public Boolean visitStartElement(StartElementTree node, Boolean p) {
-                if (Utils.toLowerCase(node.getName().toString()).equals((Attr.STYLE.getText()))) {
-                    return true;
-                }
-                if (Utils.toLowerCase(node.getName().toString()).equals(HtmlTag.LINK.getText())) {
-                    for (DocTree dt : node.getAttributes()) {
-                        if (this.visit(dt, true))
-                            return true;
+    private List<? extends DocTree> getLocalHeaderTags(List<? extends DocTree> dtrees) {
+        List<DocTree> localTags = new ArrayList<>();
+        DocTreeFactory docTreeFactory = configuration.docEnv.getDocTrees().getDocTreeFactory();
+        boolean inHead = false;
+        boolean inTitle = false;
+        loop:
+        for (DocTree dt : dtrees) {
+            switch (dt.getKind()) {
+                case START_ELEMENT:
+                    StartElementTree startElem = (StartElementTree)dt;
+                    switch (HtmlTag.get(startElem.getName())) {
+                        case HEAD:
+                            inHead = true;
+                            break;
+                        case META:
+                            break;
+                        case TITLE:
+                            inTitle = true;
+                            break;
+                        default:
+                            if (inHead) {
+                                localTags.add(startElem);
+                                localTags.add(docTreeFactory.newTextTree(DocletConstants.NL));
+                            }
                     }
-                }
-                return false;
+                    break;
+                case END_ELEMENT:
+                    EndElementTree endElem = (EndElementTree)dt;
+                    switch (HtmlTag.get(endElem.getName())) {
+                        case HEAD:
+                            inHead = false;
+                            break loop;
+                        case TITLE:
+                            inTitle = false;
+                            break;
+                        default:
+                            if (inHead) {
+                                localTags.add(endElem);
+                                localTags.add(docTreeFactory.newTextTree(DocletConstants.NL));
+                            }
+                    }
+                    break;
+                case ENTITY:
+                case TEXT:
+                    if (inHead && !inTitle) {
+                        localTags.add(dt);
+                    }
+                    break;
             }
-
-            @Override
-            public Boolean visitAttribute(AttributeTree node, Boolean p) {
-                if (p == null || p == false) {
-                    return false;
-                }
-                if (Utils.toLowerCase(node.getName().toString()).equals("rel")) {
-                    for (DocTree dt :  node.getValue()) {
-                        Boolean found = new SimpleDocTreeVisitor<Boolean, ValueKind>() {
-
-                            @Override
-                            public Boolean visitText(TextTree node, ValueKind valueKind) {
-                                switch (valueKind) {
-                                    case EMPTY:
-                                        return false;
-                                    default:
-                                        return Utils.toLowerCase(node.getBody()).equals("stylesheet");
-                                }
-                            }
-
-                            @Override
-                            protected Boolean defaultAction(DocTree node, ValueKind valueKind) {
-                                return false;
-                            }
-
-                        }.visit(dt, node.getValueKind());
-
-                        if (found)
-                            return true;
-                    }
-                }
-                return false;
-            }
-
-            @Override
-            protected Boolean defaultAction(DocTree node, Boolean p) {
-                return false;
-            }
-        };
-        for (DocTree dt : dtrees) {
-            if (check.visit(dt, false))
-                return true;
         }
-        return false;
+        return localTags;
     }
 
     private String getWindowTitle(HtmlDocletWriter docletWriter, Element element) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Mon Jan 07 18:48:39 2019 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Tue Jan 08 11:16:32 2019 +0530
@@ -427,7 +427,24 @@
      * @throws DocFileIOException if there is a problem writing the file
      */
     public void printHtmlDocument(List<String> metakeywords, boolean includeScript,
-            Content body) throws DocFileIOException {
+                                  Content body) throws DocFileIOException {
+        printHtmlDocument(metakeywords, includeScript, new ContentBuilder(), body);
+    }
+
+    /**
+     * Generates the HTML document tree and prints it out.
+     *
+     * @param metakeywords Array of String keywords for META tag. Each element
+     *                     of the array is assigned to a separate META tag.
+     *                     Pass in null for no array
+     * @param includeScript true if printing windowtitle script
+     *                      false for files that appear in the left-hand frames
+     * @param extraContent any additional content to be included in the HEAD element
+     * @param body the body htmltree to be included in the document
+     * @throws DocFileIOException if there is a problem writing the file
+     */
+    public void printHtmlDocument(List<String> metakeywords, boolean includeScript, Content extraContent,
+                                  Content body) throws DocFileIOException {
         DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
         Content htmlComment = contents.newPage;
         Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
@@ -437,7 +454,8 @@
                 .addKeywords(metakeywords)
                 .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets())
                 .setUseModuleDirectories(configuration.useModuleDirectories)
-                .setIndex(configuration.createindex, mainBodyScript);
+                .setIndex(configuration.createindex, mainBodyScript)
+                .addContent(extraContent);
 
         Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), head.toContent(), body);
         HtmlDocument htmlDocument = new HtmlDocument(htmlDocType, htmlComment, htmlTree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java	Mon Jan 07 18:48:39 2019 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java	Tue Jan 08 11:16:32 2019 +0530
@@ -254,10 +254,6 @@
             tree.addContent(HtmlTree.META("keywords", k));
         }
 
-        for (Content c : extraContent) {
-            tree.addContent(c);
-        }
-
         if (canonicalLink != null) {
             HtmlTree link = new HtmlTree(HtmlTag.LINK);
             link.addAttr(HtmlAttr.REL, "canonical");
@@ -267,6 +263,7 @@
 
         addStylesheets(tree);
         addScripts(tree);
+        extraContent.forEach(tree::addContent);
 
         return tree;
     }
--- a/test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java	Mon Jan 07 18:48:39 2019 -0800
+++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java	Tue Jan 08 11:16:32 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug  8157349 8185985 8194953
+ * @bug  8157349 8185985 8194953 8214738
  * @summary  test copy of doc-files, and its contents for HTML meta content.
  * @library  ../../lib
  * @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -268,9 +268,22 @@
                 "-sourcepath", testSrc("packages"),
                 "p2");
         checkExit(Exit.OK);
-        checkOutput("p2/doc-files/case1.html", true, "<!-- Generated by javadoc");
-        checkOutput("p2/doc-files/case2.html", false, "<!-- Generated by javadoc");
-        checkOutput("p2/doc-files/case3.html", false, "<!-- Generated by javadoc");
-        checkOutput("p2/doc-files/case4.html", false, "<!-- Generated by javadoc");
+        checkOutput("p2/doc-files/case2.html", true,
+                "<!-- Generated by javadoc",
+                "<style type=\"text/css\">\n"
+                + "body {\n"
+                + "        font-family: Helvetica, Arial, sans-serif;\n"
+                + "        font-size: 14px;\n"
+                + "      }\n"
+                + "    </style>");
+        checkOutput("p2/doc-files/case3.html", true,
+                "<!-- Generated by javadoc",
+                "<style>\n"
+                + "h1 {color:red;}\n"
+                + "        p {color:blue;}\n"
+                + "      </style>");
+        checkOutput("p2/doc-files/case4.html", true,
+                "<!-- Generated by javadoc",
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"theme.css\">");
     }
 }