changeset 56963:caf2e374095c records-and-sealed

initial (basic) support for permitted subtypes
author jjg
date Fri, 02 Aug 2019 11:21:38 -0700
parents d0d29c0bc571
children 9a1e6004ac08 f71ddaa59037
files src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java
diffstat 4 files changed, 135 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Wed Jul 31 13:54:15 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Fri Aug 02 11:21:38 2019 -0700
@@ -1096,7 +1096,7 @@
                             if (tree.sym.isAnonymous()) {
                                 log.error(sealedParentPair.snd, Errors.CantInheritFromSealed(sealedParentPair.fst.tsym));
                             } else {
-                                sealedParentPair.fst.permitted = sealedParentPair.fst.permitted.prepend(tree.sym.type);
+                                sealedParentPair.fst.permitted = sealedParentPair.fst.permitted.append(tree.sym.type);
                             }
                         } else if (!dontErrorIfSealedExtended) {
                             log.error(sealedParentPair.snd, Errors.CantInheritFromSealed(sealedParentPair.fst.tsym));
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Wed Jul 31 13:54:15 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Fri Aug 02 11:21:38 2019 -0700
@@ -263,6 +263,28 @@
                 pre.add(link);
             }
         }
+        List<? extends TypeMirror> permits = typeElement.getPermittedSubtypes();
+        if (!permits.isEmpty()) {
+            boolean isFirst = true;
+            for (TypeMirror type : permits) {
+                TypeElement tDoc = utils.asTypeElement(type);
+                if (!(utils.isPublic(tDoc) || utils.isLinkable(tDoc))) {
+                    continue;
+                }
+                if (isFirst) {
+                    pre.add(DocletConstants.NL);
+                    pre.add("permits ");
+                    isFirst = false;
+                } else {
+                    pre.add(", ");
+                }
+                Content link = getLink(new LinkInfoImpl(configuration,
+                        LinkInfoImpl.Kind.PERMITTED_SUBTYPES,
+                        type));
+                pre.add(link);
+            }
+
+        }
         classInfoTree.add(pre);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java	Wed Jul 31 13:54:15 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java	Fri Aug 02 11:21:38 2019 -0700
@@ -168,6 +168,11 @@
         CLASS_SIGNATURE_PARENT_NAME,
 
         /**
+         * Permitted subtypes of a sealed type.
+         */
+        PERMITTED_SUBTYPES,
+
+        /**
          * The header for method documentation copied from parent.
          */
         EXECUTABLE_ELEMENT_COPY,
@@ -375,6 +380,7 @@
             case CLASS_TREE_PARENT:
             case TREE:
             case CLASS_SIGNATURE_PARENT_NAME:
+            case PERMITTED_SUBTYPES:
                 excludeTypeParameterLinks = true;
                 excludeTypeBounds = true;
                 includeTypeInClassLinkLabel = false;
--- a/test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java	Wed Jul 31 13:54:15 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testSealedTypes/TestSealedTypes.java	Fri Aug 02 11:21:38 2019 -0700
@@ -153,4 +153,110 @@
                 "public sealed interface <span class=\"typeNameLabel\">B</span>");
     }
 
+    @Test
+    public void testSinglePermits(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B { }",
+                "package p; public class B extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"typeNameLabel\">A</span>\n"
+                + "extends java.lang.Object\n"
+                + "permits <a href=\"B.html\" title=\"class in p\">B</a></pre>");
+    }
+
+    @Test
+    public void testMultiplePermits(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B,C,D { }",
+                "package p; public class B extends A { }",
+                "package p; public class C extends A { }",
+                "package p; public class D extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"typeNameLabel\">A</span>\n"
+                        + "extends java.lang.Object\n"
+                        + "permits <a href=\"B.html\" title=\"class in p\">B</a>, "
+                        + "<a href=\"C.html\" title=\"class in p\">C</a>, "
+                        + "<a href=\"D.html\" title=\"class in p\">D</a></pre>");
+    }
+
+    @Test
+    public void testPartialMultiplePermits(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A permits B,C,D { }",
+                "package p; public class B extends A { }",
+                "package p; public class C extends A { }",
+                "package p;        class D extends A { }");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"typeNameLabel\">A</span>\n"
+                        + "extends java.lang.Object\n"
+                        + "permits <a href=\"B.html\" title=\"class in p\">B</a>, "
+                        + "<a href=\"C.html\" title=\"class in p\">C</a></pre>");
+    }
+
+    @Test
+    public void testImplicitPermitsAuxiliary(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A { }\n"
+                + "class B extends A { }\n"
+                + "class C extends A { }\n"
+                + "class D extends A { }\n");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "-package",
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"typeNameLabel\">A</span>\n"
+                        + "extends java.lang.Object\n"
+                        + "permits <a href=\"B.html\" title=\"class in p\">B</a>, "
+                        + "<a href=\"C.html\" title=\"class in p\">C</a>, "
+                        + "<a href=\"D.html\" title=\"class in p\">D</a></pre>");
+    }
+
+    @Test
+    public void testImplicitPermitsNested(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package p; public sealed class A {\n"
+                        + "  public static class B extends A { }\n"
+                        + "  public static class C extends A { }\n"
+                        + "  public static class D extends A { }\n"
+                        + "}");
+
+        javadoc("-d", base.resolve("out").toString(),
+                "--source-path", src.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/A.html", true,
+                "<pre>public sealed class <span class=\"typeNameLabel\">A</span>\n"
+                        + "extends java.lang.Object\n"
+                        + "permits <a href=\"A.B.html\" title=\"class in p\">A.B</a>, "
+                        + "<a href=\"A.C.html\" title=\"class in p\">A.C</a>, "
+                        + "<a href=\"A.D.html\" title=\"class in p\">A.D</a></pre>");
+    }
 }