8223805: DocCommentParser should allow for <main> and </main>
authorjjg
Tue, 04 Jun 2019 11:29:29 -0700
changeset 55204 0289438c1286
parent 55203 8e31e083fe3c
child 55205 ef23ea332077
8223805: DocCommentParser should allow for <main> and </main> Reviewed-by: hannesw
src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java
test/langtools/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java
test/langtools/tools/javac/doctree/dcapi/overview8.html
test/langtools/tools/javac/doctree/dcapi/overview8.html.out
test/langtools/tools/javac/doctree/dcapi/overview9.html
test/langtools/tools/javac/doctree/dcapi/overview9.html.out
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java	Tue Jun 04 13:26:20 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java	Tue Jun 04 11:29:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -188,7 +188,7 @@
                     if (isFileContent) {
                         switch (phase) {
                             case PREAMBLE:
-                                if (peek("body")) {
+                                if (isEndPreamble()) {
                                     trees.add(html());
                                     if (textStart == -1) {
                                         textStart = bp;
@@ -200,7 +200,7 @@
                                 }
                                 break;
                             case BODY:
-                                if (peek("/body")) {
+                                if (isEndBody()) {
                                     addPendingText(trees, lastNonWhite);
                                     break loop;
                                 }
@@ -787,6 +787,94 @@
         }
     }
 
+    /**
+     * Returns whether this is the end of the preamble of an HTML file.
+     * The preamble ends with start of {@code body} element followed by
+     * possible whitespace and the start of a {@code main} element.
+     *
+     * @return whether this is the end of the preamble
+     */
+    boolean isEndPreamble() {
+        final int savedpos = bp;
+        try {
+            if (ch == '<')
+                nextChar();
+
+            if (isIdentifierStart(ch)) {
+                String name = StringUtils.toLowerCase(readIdentifier().toString());
+                switch (name) {
+                    case "body":
+                        // Check if also followed by <main>
+                        // 1. skip rest of <body>
+                        while (ch != -1 && ch != '>') {
+                            nextChar();
+                        }
+                        if (ch == '>') {
+                            nextChar();
+                        }
+                        // 2. skip any whitespce
+                        while (ch != -1 && Character.isWhitespace(ch)) {
+                            nextChar();
+                        }
+                        // 3. check if looking at "<main..."
+                        if (ch == '<') {
+                            nextChar();
+                            if (isIdentifierStart(ch)) {
+                                name = StringUtils.toLowerCase(readIdentifier().toString());
+                                if (name.equals("main")) {
+                                    return false;
+                                }
+                            }
+                        }
+                        // if <body> is _not_ followed by <main> then this is the
+                        // end of the preamble
+                        return true;
+
+                    case "main":
+                        // <main> is unconditionally the end of the preamble
+                        return true;
+                }
+            }
+            return false;
+        } finally {
+            bp = savedpos;
+            ch = buf[bp];
+        }
+    }
+
+    /**
+     * Returns whether this is the end of the main body of the content in a standalone
+     * HTML file.
+     * The content ends with the closing tag for a {@code main} or {@code body} element.
+     *
+     * @return whether this is the end of the main body of the content
+     */
+    boolean isEndBody() {
+        final int savedpos = bp;
+        try {
+            if (ch == '<')
+                nextChar();
+
+            if (ch == '/') {
+                nextChar();
+                if (isIdentifierStart(ch)) {
+                    String name = StringUtils.toLowerCase(readIdentifier().toString());
+                    switch (name) {
+                        case "body":
+                        case "main":
+                            return true;
+                    }
+                }
+            }
+
+            return false;
+        } finally {
+            bp = savedpos;
+            ch = buf[bp];
+        }
+
+    }
+
     boolean peek(String s) {
         final int savedpos = bp;
         try {
--- a/test/langtools/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java	Tue Jun 04 13:26:20 2019 -0400
+++ b/test/langtools/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java	Tue Jun 04 11:29:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -39,6 +39,7 @@
 import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.StringWriter;
+import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.text.BreakIterator;
@@ -98,14 +99,14 @@
             test.runDocTreePath("Anchor.java", "package.html");
 
             // test for correct parsing using valid and some invalid html tags
-            test.runFileObjectTest("overview0.html");
-            test.runFileObjectTest("overview1.html");
-            test.runFileObjectTest("overview2.html");
-            test.runFileObjectTest("overview3.html");
-            test.runFileObjectTest("overview4.html");
-            test.runFileObjectTest("overview5.html");
-            test.runFileObjectTest("overview6.html");
-            test.runFileObjectTest("overview7.html");
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(Path.of(testSrc))) {
+                for (Path entry: ds) {
+                    String name = entry.getFileName().toString();
+                    if (name.matches("overview[0-9]+\\.html")) {
+                        test.runFileObjectTest(name);
+                    }
+                }
+            }
 
         } finally {
             test.status();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/doctree/dcapi/overview8.html	Tue Jun 04 11:29:29 2019 -0700
@@ -0,0 +1,9 @@
+<!-- /nodynamiccopyright/ -->
+<HTML>
+<HEAD>
+</HEAD>
+<BODY><MAIN>
+This is the content.
+@since 1.0
+</MAIN></BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/doctree/dcapi/overview8.html.out	Tue Jun 04 11:29:29 2019 -0700
@@ -0,0 +1,35 @@
+EXPECT_START
+DocComment[DOC_COMMENT, pos:0
+  preamble: 6
+    Comment[COMMENT, pos:0, <!--_/nodynamiccopyright/_-->]
+    StartElement[START_ELEMENT, pos:30
+      name:HTML
+      attributes: empty
+    ]
+    StartElement[START_ELEMENT, pos:37
+      name:HEAD
+      attributes: empty
+    ]
+    EndElement[END_ELEMENT, pos:44, HEAD]
+    StartElement[START_ELEMENT, pos:52
+      name:BODY
+      attributes: empty
+    ]
+    StartElement[START_ELEMENT, pos:58
+      name:MAIN
+      attributes: empty
+    ]
+  firstSentence: 1
+    Text[TEXT, pos:65, This_is_the_content.]
+  body: empty
+  block tags: 1
+    Since[SINCE, pos:86
+      body: 1
+        Text[TEXT, pos:93, 1.0]
+    ]
+  postamble: 3
+    EndElement[END_ELEMENT, pos:97, MAIN]
+    EndElement[END_ELEMENT, pos:104, BODY]
+    EndElement[END_ELEMENT, pos:112, HTML]
+]
+EXPECT_END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/doctree/dcapi/overview9.html	Tue Jun 04 11:29:29 2019 -0700
@@ -0,0 +1,10 @@
+<!-- /nodynamiccopyright/ -->
+<HTML>
+<HEAD>
+</HEAD>
+<BODY lang="en">
+<main role="main">
+This is the content.
+@since 1.0
+</main></BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/doctree/dcapi/overview9.html.out	Tue Jun 04 11:29:29 2019 -0700
@@ -0,0 +1,47 @@
+EXPECT_START
+DocComment[DOC_COMMENT, pos:0
+  preamble: 6
+    Comment[COMMENT, pos:0, <!--_/nodynamiccopyright/_-->]
+    StartElement[START_ELEMENT, pos:30
+      name:HTML
+      attributes: empty
+    ]
+    StartElement[START_ELEMENT, pos:37
+      name:HEAD
+      attributes: empty
+    ]
+    EndElement[END_ELEMENT, pos:44, HEAD]
+    StartElement[START_ELEMENT, pos:52
+      name:BODY
+      attributes: 1
+        Attribute[ATTRIBUTE, pos:58
+          name: lang
+          vkind: DOUBLE
+          value: 1
+            Text[TEXT, pos:64, en]
+        ]
+    ]
+    StartElement[START_ELEMENT, pos:69
+      name:main
+      attributes: 1
+        Attribute[ATTRIBUTE, pos:75
+          name: role
+          vkind: DOUBLE
+          value: 1
+            Text[TEXT, pos:81, main]
+        ]
+    ]
+  firstSentence: 1
+    Text[TEXT, pos:88, This_is_the_content.]
+  body: empty
+  block tags: 1
+    Since[SINCE, pos:109
+      body: 1
+        Text[TEXT, pos:116, 1.0]
+    ]
+  postamble: 3
+    EndElement[END_ELEMENT, pos:120, main]
+    EndElement[END_ELEMENT, pos:127, BODY]
+    EndElement[END_ELEMENT, pos:135, HTML]
+]
+EXPECT_END