changeset 4264:d39d31cff220

support "requires transitive"
author jjg
date Mon, 22 Aug 2016 19:13:59 -0700
parents 983bd135b79d
children 77cd200ee6ed
files src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java src/jdk.compiler/share/classes/module-info.java src/jdk.javadoc/share/classes/module-info.java src/jdk.jshell/share/classes/module-info.java test/tools/javac/classfiles/attributes/Module/ModuleTest.java test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java test/tools/javac/modules/AutomaticModules.java test/tools/javac/modules/GraphsTest.java test/tools/javac/modules/ModuleInfoTest.java test/tools/javac/modules/RequiresPublicTest.java test/tools/javac/modules/RequiresStaticTest.java test/tools/javac/modules/RequiresTransitiveTest.java test/tools/jdeps/lib/ModuleMetaData.java test/tools/jdeps/modules/CheckModuleTest.java test/tools/jdeps/modules/ModuleTest.java test/tools/jdeps/modules/src/m2/module-info.java test/tools/jdeps/modules/src/m3/module-info.java test/tools/jdeps/modules/src/m4/module-info.java test/tools/jdeps/modules/src/m5/module-info.java test/tools/lib/toolbox/ModuleBuilder.java
diffstat 24 files changed, 311 insertions(+), 295 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java	Mon Aug 22 19:13:59 2016 -0700
@@ -127,10 +127,10 @@
      */
     interface RequiresDirective extends Directive {
         /**
-         * Returns whether or not this is a public dependency.
-         * @return whether or not this is a public dependency
+         * Returns whether or not this is a transitive dependency.
+         * @return whether or not this is a transitive dependency
          */
-        boolean isPublic();
+        boolean isTransitive();
 
         /**
          * Returns the module that is required
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java	Mon Aug 22 19:13:59 2016 -0700
@@ -209,7 +209,7 @@
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public boolean isPublic() {
+        public boolean isTransitive() {
             return flags.contains(RequiresFlag.TRANSITIVE);
         }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Mon Aug 22 19:13:59 2016 -0700
@@ -1109,7 +1109,7 @@
                     Assert.checkNonNull(current.requires, () -> current + ".requires == null; " + msym);
                     requires = current.requires;
                     for (RequiresDirective rd : requires) {
-                        if (rd.isPublic())
+                        if (rd.isTransitive())
                             todo = todo.prepend(rd.module);
                     }
                 } else {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Aug 22 19:13:59 2016 -0700
@@ -3209,16 +3209,31 @@
             int pos = token.pos;
             if (token.name() == names.requires) {
                 nextToken();
+                boolean isPublic = false;
                 boolean isTransitive = false;
                 boolean isStaticPhase = false;
             loop:
                 while (true) {
                     switch (token.kind) {
-                        case PUBLIC:
-                            if (isTransitive) {
+                        case IDENTIFIER:
+                            if (token.name() == names.transitive && !isTransitive) {
+                                Token t1 = S.token(1);
+                                if (t1.kind == SEMI || t1.kind == DOT) {
+                                    break loop;
+                                }
+                                if (isPublic || isTransitive) {
+                                    error(token.pos, "repeated.modifier");
+                                }
+                                isTransitive = true;
+                                break;
+                            } else {
+                                break loop;
+                            }
+                        case PUBLIC: // temporary
+                            if (isPublic || isTransitive) {
                                 error(token.pos, "repeated.modifier");
                             }
-                            isTransitive = true;
+                            isPublic = isTransitive = true;
                             break;
                         case STATIC:
                             if (isStaticPhase) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Mon Aug 22 19:13:59 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -69,6 +69,7 @@
     public final Name provides;
     public final Name requires;
     public final Name to;
+    public final Name transitive;
     public final Name uses;
     public final Name with;
 
@@ -226,6 +227,7 @@
         provides = fromString("provides");
         requires = fromString("requires");
         to = fromString("to");
+        transitive = fromString("transitive");
         uses = fromString("uses");
         with = fromString("with");
 
--- a/src/jdk.compiler/share/classes/module-info.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/src/jdk.compiler/share/classes/module-info.java	Mon Aug 22 19:13:59 2016 -0700
@@ -24,7 +24,7 @@
  */
 
 module jdk.compiler {
-    requires public java.compiler;
+    requires transitive java.compiler;
 
     exports com.sun.source.doctree;
     exports com.sun.source.tree;
--- a/src/jdk.javadoc/share/classes/module-info.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/src/jdk.javadoc/share/classes/module-info.java	Mon Aug 22 19:13:59 2016 -0700
@@ -24,8 +24,8 @@
  */
 
 module jdk.javadoc {
-    requires public java.compiler;
-    requires public jdk.compiler;
+    requires transitive java.compiler;
+    requires transitive jdk.compiler;
     requires java.xml;
 
     exports com.sun.javadoc;
--- a/src/jdk.jshell/share/classes/module-info.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/src/jdk.jshell/share/classes/module-info.java	Mon Aug 22 19:13:59 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -29,7 +29,7 @@
  * Read-Eval-Print Loops (REPLs).
  */
 module jdk.jshell {
-    requires public java.compiler;
+    requires transitive java.compiler;
     requires java.desktop;
     requires java.prefs;
     requires jdk.compiler;
--- a/test/tools/javac/classfiles/attributes/Module/ModuleTest.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/javac/classfiles/attributes/Module/ModuleTest.java	Mon Aug 22 19:13:59 2016 -0700
@@ -140,9 +140,9 @@
     }
 
     @Test
-    public void testRequiresPublic(Path base) throws Exception {
+    public void testRequiresTransitive(Path base) throws Exception {
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
-                .requires("jdk.jdeps", RequiresFlag.PUBLIC)
+                .requires("jdk.jdeps", RequiresFlag.TRANSITIVE)
                 .write(base);
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
@@ -160,12 +160,12 @@
     @Test
     public void testSeveralRequires(Path base) throws Exception {
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
-                .requires("jdk.jdeps", RequiresFlag.PUBLIC)
+                .requires("jdk.jdeps", RequiresFlag.TRANSITIVE)
                 .requires("jdk.compiler")
                 .requires("m2", RequiresFlag.STATIC)
                 .requires("m3")
-                .requires("m4", RequiresFlag.PUBLIC)
-                .requires("m5", RequiresFlag.STATIC, RequiresFlag.PUBLIC)
+                .requires("m4", RequiresFlag.TRANSITIVE)
+                .requires("m5", RequiresFlag.STATIC, RequiresFlag.TRANSITIVE)
                 .write(base.resolve("m1"));
         tb.writeJavaFiles(base.resolve("m2"), "module m2 { }");
         tb.writeJavaFiles(base.resolve("m3"), "module m3 { }");
@@ -230,16 +230,16 @@
                 .exportsTo("packTo1", "m2")
                 .exportsTo("packTo3", "m3", ExportFlag.DYNAMIC)
                 .requires("jdk.compiler")
-                .requires("m2", RequiresFlag.PUBLIC)
+                .requires("m2", RequiresFlag.TRANSITIVE)
                 .requires("m3", RequiresFlag.STATIC)
-                .requires("m4", RequiresFlag.PUBLIC, RequiresFlag.STATIC)
+                .requires("m4", RequiresFlag.TRANSITIVE, RequiresFlag.STATIC)
                 .provides("java.util.List", "pack1.C")
                 .uses("java.util.List")
                 .uses("java.nio.file.Path")
                 .provides("java.util.List", "pack2.D")
-                .requires("jdk.jdeps", RequiresFlag.STATIC, RequiresFlag.PUBLIC)
+                .requires("jdk.jdeps", RequiresFlag.STATIC, RequiresFlag.TRANSITIVE)
                 .requires("m5", RequiresFlag.STATIC)
-                .requires("m6", RequiresFlag.PUBLIC)
+                .requires("m6", RequiresFlag.TRANSITIVE)
                 .requires("java.compiler")
                 .exportsTo("packTo4", "java.compiler", ExportFlag.DYNAMIC)
                 .exportsTo("packTo2", "java.compiler")
--- a/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java	Mon Aug 22 19:13:59 2016 -0700
@@ -152,7 +152,7 @@
     }
 
     enum RequiresFlag implements Mask {
-        PUBLIC("public", Module_attribute.ACC_TRANSITIVE),
+        TRANSITIVE("transitive", Module_attribute.ACC_TRANSITIVE),
         STATIC("static", Module_attribute.ACC_STATIC_PHASE);
 
         private final String token;
--- a/test/tools/javac/modules/AutomaticModules.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/javac/modules/AutomaticModules.java	Mon Aug 22 19:13:59 2016 -0700
@@ -193,7 +193,7 @@
         Files.createDirectories(depClasses);
 
         tb.writeJavaFiles(depSrc,
-                          "module m1 { requires public automatic; }",
+                          "module m1 { requires transitive automatic; }",
                           "package dep; public class Dep { api.Api api; }");
 
         new JavacTask(tb)
--- a/test/tools/javac/modules/GraphsTest.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/javac/modules/GraphsTest.java	Mon Aug 22 19:13:59 2016 -0700
@@ -55,19 +55,19 @@
 
     /**
      * Tests diamond graph with an automatic module added in.
-     * +-------------+          +--------------------+         +------------------+
-     * | module M    |          | module N           |         | module O         |
-     * |             | ----->   |                    | --->    |                  |  --> J.jar
-     * | require N   |          | requires public  O |         |                  |
-     * | require L   |          |                    |         +------------------+
-     * +-------------+          +--------------------+                  ^
+     * +-------------+          +-----------------------+         +------------------+
+     * | module M    |          | module N              |         | module O         |
+     * |             | ----->   |                       | --->    |                  |  --> J.jar
+     * | require N   |          | requires transitive O |         |                  |
+     * | require L   |          |                       |         +------------------+
+     * +-------------+          +-----------------------+                  ^
      *       |                                                          |
-     *       |                  +--------------------+                  |
-     *       ------------------>| module L           |                  |
-     *                          |                    |------------------
-     *                          | requires public O  |
-     *                          |                    |
-     *                          +--------------------+
+     *       |                  +-----------------------+                  |
+     *       ------------------>| module L              |                  |
+     *                          |                       |------------------
+     *                          | requires transitive O |
+     *                          |                       |
+     *                          +-----------------------+
      *
      */
     @Test
@@ -92,18 +92,18 @@
 
         new ModuleBuilder(tb, "O")
                 .exports("openO")
-                .requiresPublic("J", jarModules)
+                .requiresTransitive("J", jarModules)
                 .classes("package openO; public class O { openJ.J j; }")
                 .classes("package closedO; public class O { }")
                 .build(modSrc, modules);
         new ModuleBuilder(tb, "N")
-                .requiresPublic("O", modules, jarModules)
+                .requiresTransitive("O", modules, jarModules)
                 .exports("openN")
                 .classes("package openN; public class N { }")
                 .classes("package closedN; public class N { }")
                 .build(modSrc, modules);
         new ModuleBuilder(tb, "L")
-                .requiresPublic("O", modules, jarModules)
+                .requiresTransitive("O", modules, jarModules)
                 .exports("openL")
                 .classes("package openL; public class L { }")
                 .classes("package closedL; public class L { }")
@@ -171,18 +171,18 @@
     /**
      * Tests graph where module M reexport package of N, but N export the package only to M.
      *
-    +-------------+        +--------------------+        +---------------+
-    | module L    |        | module M           |        | module N      |
-    |             | -----> |                    | -----> |               |
-    |  requires M |        |  requires public N |        | exports P to M|
-    +-------------+        |                    |        +---------------+
-                           +--------------------+
+    +-------------+        +------------------------+        +---------------+
+    | module L    |        | module M               |        | module N      |
+    |             | -----> |                        | -----> |               |
+    |  requires M |        |  requires transitive N |        | exports P to M|
+    +-------------+        |                        |        +---------------+
+                           +------------------------+
     */
     @Test
     public void reexportOfQualifiedExport(Path base) throws Exception {
         Path modSrc = base.resolve("modSrc");
         new ModuleBuilder(tb, "M")
-                .requiresPublic("N")
+                .requiresTransitive("N")
                 .write(modSrc);
         new ModuleBuilder(tb, "N")
                 .exportsTo("pack", "M")
--- a/test/tools/javac/modules/ModuleInfoTest.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/javac/modules/ModuleInfoTest.java	Mon Aug 22 19:13:59 2016 -0700
@@ -228,12 +228,12 @@
      * Verify that a multi-module loop is detected.
      */
     @Test
-    public void testRequiresPublicLoop(Path base) throws Exception {
+    public void testRequiresTransitiveLoop(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }");
         Path src_m2 = src.resolve("m2");
-        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires public m3; }");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires transitive m3; }");
         Path src_m3 = src.resolve("m3");
         tb.writeFile(src_m3.resolve("module-info.java"), "module m3 { requires m1; }");
 
@@ -248,7 +248,7 @@
                 .writeAll()
                 .getOutput(Task.OutputKind.DIRECT);
 
-        if (!log.contains("module-info.java:1:29: compiler.err.cyclic.requires: m3"))
+        if (!log.contains("module-info.java:1:33: compiler.err.cyclic.requires: m3"))
             throw new Exception("expected output not found");
     }
 
@@ -282,12 +282,12 @@
      * Verify that duplicate requires are detected.
      */
     @Test
-    public void testDuplicateRequiresPublicStatic(Path base) throws Exception {
+    public void testDuplicateRequiresTransitiveStatic(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
         Path src_m2 = src.resolve("m2");
-        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires public m1; requires static m1; }");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires transitive m1; requires static m1; }");
 
         Path classes = base.resolve("classes");
         Files.createDirectories(classes);
@@ -300,7 +300,7 @@
                 .writeAll()
                 .getOutput(Task.OutputKind.DIRECT);
 
-        if (!log.contains("module-info.java:1:49: compiler.err.duplicate.requires: m1"))
+        if (!log.contains("module-info.java:1:53: compiler.err.duplicate.requires: m1"))
             throw new Exception("expected output not found");
     }
 
--- a/test/tools/javac/modules/RequiresPublicTest.java	Sat Aug 20 20:29:41 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary tests for "requires public"
- * @library /tools/lib
- * @modules
- *      jdk.compiler/com.sun.tools.javac.api
- *      jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
- * @run main RequiresPublicTest
- */
-
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-import toolbox.JavacTask;
-import toolbox.Task;
-import toolbox.ToolBox;
-
-public class RequiresPublicTest extends ModuleTestBase {
-
-    public static void main(String... args) throws Exception {
-        RequiresPublicTest t = new RequiresPublicTest();
-        t.runTests();
-    }
-
-    @Test
-    public void testJavaSE_OK(Path base) throws Exception {
-        Path src = base.resolve("src");
-        tb.writeJavaFiles(src,
-                "module m { requires java.se; }",
-                "import java.awt.Frame;\n"  // in java.se
-                + "class Test {\n"
-                + "    Frame f;\n"
-                + "}");
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        new JavacTask(tb, Task.Mode.CMDLINE)
-                .files(findJavaFiles(src))
-                .outdir(classes)
-                .run()
-                .writeAll();
-    }
-
-    @Test
-    public void testJavaSE_Fail(Path base) throws Exception {
-        Path src = base.resolve("src");
-        tb.writeJavaFiles(src,
-                "module m { requires java.se; }",
-                "import com.sun.source.tree.Tree;\n" // not in java.se (in jdk.compiler)
-                + "class Test {\n"
-                + "    Tree t;\n"
-                + "}");
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb, Task.Mode.CMDLINE)
-                .options("-XDrawDiagnostics")
-                .files(findJavaFiles(src))
-                .outdir(classes)
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-
-        if (!log.contains("Test.java:1:27: compiler.err.doesnt.exist: com.sun.source.tree"))
-            throw new Exception("expected output not found");
-    }
-
-    @Test
-    public void testComplex_OK(Path base) throws Exception {
-        Path src = getComplexSrc(base, "", "");
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        new JavacTask(tb, Task.Mode.CMDLINE)
-                .options("--module-source-path", src.toString())
-                .files(findJavaFiles(src))
-                .outdir(classes)
-                .run()
-                .writeAll();
-    }
-
-    @Test
-    public void testComplex_Fail(Path base) throws Exception {
-        Path src = getComplexSrc(base,
-                "import p5.C5; import p6.C6; import p7.C7;\n",
-                "C5 c5; C6 c6; C7 c7;\n");
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb, Task.Mode.CMDLINE)
-                .options("-XDrawDiagnostics",
-                        "--module-source-path", src.toString())
-                .files(findJavaFiles(src))
-                .outdir(classes)
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-
-        String[] expect = {
-            "C1.java:5:10: compiler.err.not.def.access.package.cant.access: p5.C5, p5",
-            "C1.java:5:24: compiler.err.not.def.access.package.cant.access: p6.C6, p6",
-            "C1.java:5:38: compiler.err.not.def.access.package.cant.access: p7.C7, p7",
-            "C1.java:8:1: compiler.err.cant.resolve.location: kindname.class, C5, , , "
-                + "(compiler.misc.location: kindname.class, p1.C1, null)",
-            "C1.java:8:8: compiler.err.cant.resolve.location: kindname.class, C6, , , "
-                + "(compiler.misc.location: kindname.class, p1.C1, null)",
-            "C1.java:8:15: compiler.err.cant.resolve.location: kindname.class, C7, , , "
-                + "(compiler.misc.location: kindname.class, p1.C1, null)"
-        };
-
-        for (String e: expect) {
-            if (!log.contains(e))
-                throw new Exception("expected output not found: " + e);
-        }
-    }
-
-    /*
-     * Set up the following module graph
-     *     m1 -> m2 => m3 => m4 -> m5
-     *              -> m6 => m7
-     * where -> is requires, => is requires public
-     */
-    Path getComplexSrc(Path base, String m1_extraImports, String m1_extraUses) throws Exception {
-        Path src = base.resolve("src");
-
-        Path src_m1 = src.resolve("m1");
-        tb.writeJavaFiles(src_m1,
-                "module m1 { requires m2; }",
-                "package p1;\n"
-                + "import p2.C2;\n"
-                + "import p3.C3;\n"
-                + "import p4.C4;\n"
-                + m1_extraImports
-                + "class C1 {\n"
-                + "  C2 c2; C3 c3; C4 c4;\n"
-                + m1_extraUses
-                + "}\n");
-
-        Path src_m2 = src.resolve("m2");
-        tb.writeJavaFiles(src_m2,
-                "module m2 {\n"
-                + "  requires public m3;\n"
-                + "  requires        m6;\n"
-                + "  exports p2;\n"
-                + "}",
-                "package p2;\n"
-                + "public class C2 { }\n");
-
-        Path src_m3 = src.resolve("m3");
-        tb.writeJavaFiles(src_m3,
-                "module m3 { requires public m4; exports p3; }",
-                "package p3;\n"
-                + "public class C3 { }\n");
-
-        Path src_m4 = src.resolve("m4");
-        tb.writeJavaFiles(src_m4,
-                "module m4 { requires m5; exports p4; }",
-                "package p4;\n"
-                + "public class C4 { }\n");
-
-        Path src_m5 = src.resolve("m5");
-        tb.writeJavaFiles(src_m5,
-                "module m5 { exports p5; }",
-                "package p5;\n"
-                + "public class C5 { }\n");
-
-        Path src_m6 = src.resolve("m6");
-        tb.writeJavaFiles(src_m6,
-                "module m6 { requires public m7; exports p6; }",
-                "package p6;\n"
-                + "public class C6 { }\n");
-
-        Path src_m7 = src.resolve("m7");
-        tb.writeJavaFiles(src_m7,
-                "module m7 { exports p7; }",
-                "package p7;\n"
-                + "public class C7 { }\n");
-
-        return src;
-    }
-}
--- a/test/tools/javac/modules/RequiresStaticTest.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/javac/modules/RequiresStaticTest.java	Mon Aug 22 19:13:59 2016 -0700
@@ -151,7 +151,7 @@
      *              \       /
      *                v   v
      *                  m6 => m7 --> m8
-     * where -> is requires, => is requires public, --> is requires static, -=-> is requires public static
+     * where -> is requires, => is requires transitive, --> is requires static, -=-> is requires transitive static
      */
     Path getComplexSrc(Path base, String m1_extraImports, String m1_extraUses) throws Exception {
         Path src = base.resolve("src");
@@ -172,7 +172,7 @@
         Path src_m2 = src.resolve("m2");
         tb.writeJavaFiles(src_m2,
                 "module m2 {\n"
-                + "  requires public m3;\n"
+                + "  requires transitive m3;\n"
                 + "  requires static m6;\n"
                 + "  exports p2;\n"
                 + "}",
@@ -181,7 +181,7 @@
 
         Path src_m3 = src.resolve("m3");
         tb.writeJavaFiles(src_m3,
-                "module m3 { requires public static m4; exports p3; }",
+                "module m3 { requires transitive static m4; exports p3; }",
                 "package p3;\n"
                 + "public class C3 { }\n");
 
@@ -199,7 +199,7 @@
 
         Path src_m6 = src.resolve("m6");
         tb.writeJavaFiles(src_m6,
-                "module m6 { requires public m7; exports p6; }",
+                "module m6 { requires transitive m7; exports p6; }",
                 "package p6;\n"
                 + "public class C6 { p7.C7 c7; }\n");
 
@@ -280,7 +280,7 @@
     }
 
     @Test
-    public void testRequiresPublicStatic(Path base) throws Exception {
+    public void testRequiresTransitiveStatic(Path base) throws Exception {
         Path src = base.resolve("src");
         Path m1 = src.resolve("m1");
         tb.writeJavaFiles(m1,
@@ -300,7 +300,7 @@
 
         Path m2 = src.resolve("m2");
         tb.writeJavaFiles(m2,
-                "module m2 { requires public static m1; }");
+                "module m2 { requires transitive static m1; }");
 
         Path m2Classes = classes.resolve("m2");
         Files.createDirectories(m2Classes);
@@ -356,7 +356,7 @@
     }
 
     @Test
-    public void testRequiresStaticPublic(Path base) throws Exception {
+    public void testRequiresStaticTransitive(Path base) throws Exception {
         Path src = base.resolve("src");
         Path m1 = src.resolve("m1");
         tb.writeJavaFiles(m1,
@@ -376,7 +376,7 @@
 
         Path m2 = src.resolve("m2");
         tb.writeJavaFiles(m2,
-                "module m2 { requires public static m1; }");
+                "module m2 { requires transitive static m1; }");
 
         Path m2Classes = classes.resolve("m2");
         Files.createDirectories(m2Classes);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/RequiresTransitiveTest.java	Mon Aug 22 19:13:59 2016 -0700
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2015, 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary tests for "requires transitive"
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @run main RequiresTransitiveTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class RequiresTransitiveTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        RequiresTransitiveTest t = new RequiresTransitiveTest();
+        t.runTests();
+    }
+
+    @Test
+    public void testJavaSE_OK(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires java.se; }",
+                "import java.awt.Frame;\n"  // in java.se
+                + "class Test {\n"
+                + "    Frame f;\n"
+                + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testJavaSE_Fail(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires java.se; }",
+                "import com.sun.source.tree.Tree;\n" // not in java.se (in jdk.compiler)
+                + "class Test {\n"
+                + "    Tree t;\n"
+                + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.contains("Test.java:1:27: compiler.err.doesnt.exist: com.sun.source.tree"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    public void testComplex_OK(Path base) throws Exception {
+        Path src = getComplexSrc(base, "", "");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString())
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testComplex_Fail(Path base) throws Exception {
+        Path src = getComplexSrc(base,
+                "import p5.C5; import p6.C6; import p7.C7;\n",
+                "C5 c5; C6 c6; C7 c7;\n");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "--module-source-path", src.toString())
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        String[] expect = {
+            "C1.java:5:10: compiler.err.not.def.access.package.cant.access: p5.C5, p5",
+            "C1.java:5:24: compiler.err.not.def.access.package.cant.access: p6.C6, p6",
+            "C1.java:5:38: compiler.err.not.def.access.package.cant.access: p7.C7, p7",
+            "C1.java:8:1: compiler.err.cant.resolve.location: kindname.class, C5, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)",
+            "C1.java:8:8: compiler.err.cant.resolve.location: kindname.class, C6, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)",
+            "C1.java:8:15: compiler.err.cant.resolve.location: kindname.class, C7, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)"
+        };
+
+        for (String e: expect) {
+            if (!log.contains(e))
+                throw new Exception("expected output not found: " + e);
+        }
+    }
+
+    /*
+     * Set up the following module graph
+     *     m1 -> m2 => m3 => m4 -> m5
+     *              -> m6 => m7
+     * where -> is requires, => is requires transitive
+     */
+    Path getComplexSrc(Path base, String m1_extraImports, String m1_extraUses) throws Exception {
+        Path src = base.resolve("src");
+
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                "module m1 { requires m2; }",
+                "package p1;\n"
+                + "import p2.C2;\n"
+                + "import p3.C3;\n"
+                + "import p4.C4;\n"
+                + m1_extraImports
+                + "class C1 {\n"
+                + "  C2 c2; C3 c3; C4 c4;\n"
+                + m1_extraUses
+                + "}\n");
+
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                "module m2 {\n"
+                + "  requires transitive m3;\n"
+                + "  requires        m6;\n"
+                + "  exports p2;\n"
+                + "}",
+                "package p2;\n"
+                + "public class C2 { }\n");
+
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                "module m3 { requires transitive m4; exports p3; }",
+                "package p3;\n"
+                + "public class C3 { }\n");
+
+        Path src_m4 = src.resolve("m4");
+        tb.writeJavaFiles(src_m4,
+                "module m4 { requires m5; exports p4; }",
+                "package p4;\n"
+                + "public class C4 { }\n");
+
+        Path src_m5 = src.resolve("m5");
+        tb.writeJavaFiles(src_m5,
+                "module m5 { exports p5; }",
+                "package p5;\n"
+                + "public class C5 { }\n");
+
+        Path src_m6 = src.resolve("m6");
+        tb.writeJavaFiles(src_m6,
+                "module m6 { requires transitive m7; exports p6; }",
+                "package p6;\n"
+                + "public class C6 { }\n");
+
+        Path src_m7 = src.resolve("m7");
+        tb.writeJavaFiles(src_m7,
+                "module m7 { exports p7; }",
+                "package p7;\n"
+                + "public class C7 { }\n");
+
+        return src;
+    }
+}
--- a/test/tools/jdeps/lib/ModuleMetaData.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/jdeps/lib/ModuleMetaData.java	Mon Aug 22 19:13:59 2016 -0700
@@ -70,7 +70,7 @@
         return this;
     }
 
-    ModuleMetaData requiresPublic(String name) {
+    ModuleMetaData requiresTransitive(String name) {
         requires.put(name, new ModuleRequires(name, TRANSITIVE));
         return this;
     }
--- a/test/tools/jdeps/modules/CheckModuleTest.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/jdeps/modules/CheckModuleTest.java	Mon Aug 22 19:13:59 2016 -0700
@@ -100,7 +100,7 @@
             { "m4", new ModuleMetaData[] {
                         // original
                         new ModuleMetaData("m4")
-                            .requiresPublic("java.compiler")
+                            .requiresTransitive("java.compiler")
                             .requires("java.logging")
                             // unnused exports
                             .exports("p4.internal", Set.of("m6", "m7")),
@@ -115,21 +115,21 @@
             { "m5", new ModuleMetaData[] {
                         // original
                         new ModuleMetaData("m5")
-                            .requiresPublic("java.compiler")
-                            .requiresPublic("java.logging")
+                            .requiresTransitive("java.compiler")
+                            .requiresTransitive("java.logging")
                             .requires("java.sql")
-                            .requiresPublic("m4"),
+                            .requiresTransitive("m4"),
                         // suggested version
                         new ModuleMetaData("m5")
-                            .requiresPublic("java.compiler")
+                            .requiresTransitive("java.compiler")
                             .requires("java.logging")
-                            .requiresPublic("java.sql")
-                            .requiresPublic("m4"),
+                            .requiresTransitive("java.sql")
+                            .requiresTransitive("m4"),
                         // reduced version
                         new ModuleMetaData("m5")
-                            .requiresPublic("java.compiler")
-                            .requiresPublic("java.sql")
-                            .requiresPublic("m4"),
+                            .requiresTransitive("java.compiler")
+                            .requiresTransitive("java.sql")
+                            .requiresTransitive("m4"),
                     }
             },
         };
--- a/test/tools/jdeps/modules/ModuleTest.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/jdeps/modules/ModuleTest.java	Mon Aug 22 19:13:59 2016 -0700
@@ -80,10 +80,10 @@
     @DataProvider(name = "modules")
     public Object[][] expected() {
         return new Object[][]{
-                { "m3", new ModuleMetaData("m3").requiresPublic("java.sql")
-                            .requiresPublic("m2")
+                { "m3", new ModuleMetaData("m3").requiresTransitive("java.sql")
+                            .requiresTransitive("m2")
                             .requires("java.logging")
-                            .requiresPublic("m1")
+                            .requiresTransitive("m1")
                             .reference("p3", "java.lang", "java.base")
                             .reference("p3", "java.sql", "java.sql")
                             .reference("p3", "java.util.logging", "java.logging")
@@ -91,7 +91,7 @@
                             .reference("p3", "p2", "m2")
                             .qualified("p3", "p2.internal", "m2")
                 },
-                { "m2", new ModuleMetaData("m2").requiresPublic("m1")
+                { "m2", new ModuleMetaData("m2").requiresTransitive("m1")
                             .reference("p2", "java.lang", "java.base")
                             .reference("p2", "p1", "m1")
                             .reference("p2.internal", "java.lang", "java.base")
--- a/test/tools/jdeps/modules/src/m2/module-info.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/jdeps/modules/src/m2/module-info.java	Mon Aug 22 19:13:59 2016 -0700
@@ -22,7 +22,7 @@
  */
 
 module m2 {
-    requires public m1;
+    requires transitive m1;
     exports p2;
     exports p2.internal to m3;
 }
--- a/test/tools/jdeps/modules/src/m3/module-info.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/jdeps/modules/src/m3/module-info.java	Mon Aug 22 19:13:59 2016 -0700
@@ -22,9 +22,9 @@
  */
 
 module m3 {
-    requires public java.sql;
-    requires public m2;
+    requires transitive java.sql;
+    requires transitive m2;
     requires java.logging;   // TODO: --gen-module-info to do transitive reduction
-    requires public m1;
+    requires transitive m1;
     exports p3;
 }
--- a/test/tools/jdeps/modules/src/m4/module-info.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/jdeps/modules/src/m4/module-info.java	Mon Aug 22 19:13:59 2016 -0700
@@ -23,7 +23,7 @@
 
 module m4 {
     // not used in signature
-    requires public java.compiler;
+    requires transitive java.compiler;
 
     // unused dependence
     requires java.logging;
--- a/test/tools/jdeps/modules/src/m5/module-info.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/jdeps/modules/src/m5/module-info.java	Mon Aug 22 19:13:59 2016 -0700
@@ -22,15 +22,15 @@
  */
 
 module m5 {
-    // m4 requires public java.compiler
-    requires public m4;
-    requires public java.compiler;
+    // m4 requires transitive java.compiler
+    requires transitive m4;
+    requires transitive java.compiler;
 
-    // java.sql should be requires public
+    // java.sql should be requires transitive
     requires java.sql;
 
     // java.logging is used for implementation only
-    requires public java.logging;
+    requires transitive java.logging;
 
     exports p5;
 
--- a/test/tools/lib/toolbox/ModuleBuilder.java	Sat Aug 20 20:29:41 2016 +0100
+++ b/test/tools/lib/toolbox/ModuleBuilder.java	Mon Aug 22 19:13:59 2016 -0700
@@ -72,14 +72,14 @@
     }
 
     /**
-     * Adds a "requires public" directive to the declaration.
+     * Adds a "requires transitive" directive to the declaration.
      * @param requires the name of the module that is required
      * @param modulePath a path in which to locate the modules
      *    if the declaration is compiled
      * @return this builder
      */
-    public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
-        this.requires.add("requires public " + requires + ";");
+    public ModuleBuilder requiresTransitive(String requires, Path... modulePath) {
+        this.requires.add("requires transitive " + requires + ";");
         this.modulePath.addAll(Arrays.asList(modulePath));
         return this;
     }
@@ -111,7 +111,6 @@
     /**
      * Adds an unqualified "exports" directive to the declaration.
      * @param pkg the name of the package to be exported
-     * @param module the name of the module to which it is to be exported
      * @return this builder
      */
     public ModuleBuilder exports(String pkg) {