changeset 4911:e570a50f29d5

Merge
author alanb
date Thu, 27 Apr 2017 17:16:25 +0100
parents 4d2852920d34 7e0ac3c3eaba
children 3abaf27917da
files .hgtags src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java src/java.compiler/share/classes/javax/tools/JavaFileManager.java src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css test/ProblemList.txt test/TEST.ROOT test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java test/jdk/javadoc/doclet/testModules/TestModules.java test/jdk/jshell/CompletionSuggestionTest.java test/jdk/jshell/MergedTabShiftTabTest.java test/tools/javac/api/TestClientCodeWrapper.java test/tools/javac/modules/T8158224/T8158224.out test/tools/lib/toolbox/ModuleBuilder.java
diffstat 53 files changed, 1803 insertions(+), 536 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Apr 26 21:09:20 2017 +0100
+++ b/.hgtags	Thu Apr 27 17:16:25 2017 +0100
@@ -412,3 +412,4 @@
 ff80ebf4ace699497bf9c3688e34e0c42d07ca13 jpms-pr2
 98108b7d4cb6078773e2d27ad8471dc25d4d6124 jdk-9+165
 2a8b403a623320479705aad04ed8d78396661eb7 jdk-9+166
+f260f1a2acf616509a4ee5a29bc7f2acca3853e3 jdk-9+167
--- a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java	Thu Apr 27 17:16:25 2017 +0100
@@ -278,14 +278,14 @@
      * <dd><code>*</code>
      *
      * <dt><i>ModulePrefix:</i>
-     * <dd><i>TypeName</i> <code>/</code>
+     * <dd><i>ModuleName</i> <code>/</code>
      *
      * <dt><i>DotStar:</i>
      * <dd><code>.</code> <code>*</code>
      * </dl>
      * </blockquote>
      *
-     * where <i>TypeName</i> is as defined in
+     * where <i>TypeName</i> and <i>ModuleName</i> are as defined in
      * <cite>The Java&trade; Language Specification</cite>.
      *
      * @apiNote When running in an environment which supports modules,
@@ -299,7 +299,7 @@
      * @return the names of the annotation types supported by this processor
      * @see javax.annotation.processing.SupportedAnnotationTypes
      * @jls 3.8 Identifiers
-     * @jls 6.5.5 Meaning of Type Names
+     * @jls 6.5 Determining the Meaning of a Name
      */
     Set<String> getSupportedAnnotationTypes();
 
--- a/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java	Thu Apr 27 17:16:25 2017 +0100
@@ -28,13 +28,14 @@
 import java.util.List;
 
 /**
- * Represents a module program element.  Provides access to information
- * about the module and its members.
+ * Represents a module program element.  Provides access to
+ * information about the module, its directives, and its members.
  *
  * @see javax.lang.model.util.Elements#getModuleOf
  * @since 9
+ * @jls 7.7 Module Declarations
  * @spec JPMS
- */  // TODO: add @jls to module section
+ */
 public interface ModuleElement extends Element, QualifiedNameable {
 
     /**
@@ -121,12 +122,13 @@
     };
 
     /**
-     * Represents a "module statement" within the declaration of this module.
+     * Represents a directive within the declaration of this
+     * module. The directives of a module declaration configure the
+     * module in the Java Platform Module System.
      *
      * @since 9
      * @spec JPMS
-     *
-     */ // TODO: add jls to Module Statement
+     */
     interface Directive {
         /**
          * Returns the {@code kind} of this directive.
--- a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java	Thu Apr 27 17:16:25 2017 +0100
@@ -204,4 +204,11 @@
     public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException {
         return fileManager.listLocationsForModules(location);
     }
+
+    /**
+     * @since 9
+     */
+    public boolean contains(Location location, FileObject fo) throws IOException {
+        return fileManager.contains(location, fo);
+    }
 }
--- a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java	Thu Apr 27 17:16:25 2017 +0100
@@ -566,4 +566,38 @@
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * Determines whether or not a given file object is "contained in" a specified location.
+     *
+     * <p>For a package-oriented location, a file object is contained in the location if there exist
+     * values for <i>packageName</i> and <i>relativeName</i> such that either of the following
+     * calls would return the {@link #isSameFile same} file object:
+     * <pre>
+     *     getFileForInput(location, <i>packageName</i>, <i>relativeName</i>)
+     *     getFileForOutput(location, <i>packageName</i>, <i>relativeName</i>, null)
+     * </pre>
+     *
+     * <p>For a module-oriented location, a file object is contained in the location if there exists
+     * a module that may be obtained by the call:
+     * <pre>
+     *     getLocationForModule(location, <i>moduleName</i>)
+     * </pre>
+     * such that the file object is contained in the (package-oriented) location for that module.
+     *
+     * @implSpec This implementation throws {@code UnsupportedOperationException}.
+     *
+     * @param location the location
+     * @param fo the file object
+     * @return whether or not the file is contained in the location
+     *
+     * @throws IOException if there is a problem determining the result
+     * @throws UnsupportedOperationException if the method is not supported
+     *
+     * @since 9
+     */
+
+    default boolean contains(Location location, FileObject fo) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
 }
--- a/src/jdk.compiler/share/classes/com/sun/source/doctree/package-info.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/package-info.java	Thu Apr 27 17:16:25 2017 +0100
@@ -29,6 +29,6 @@
  *
  * @author Jonathan Gibbons
  * @since 1.8
- * @see <a href="http://download.oracle.com/javase/6/docs/technotes/tools/solaris/javadoc.html#javadoctags">http://download.oracle.com/javase/6/docs/technotes/tools/solaris/javadoc.html#javadoctags</a>
+ * @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/unix/javadoc.html#CHDJGIJB">http://docs.oracle.com/javase/8/docs/technotes/tools/unix/javadoc.html#CHDJGIJB</a>
  */
 package com.sun.source.doctree;
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java	Thu Apr 27 17:16:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -32,7 +32,6 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Queue;
-import java.util.regex.Pattern;
 
 import javax.lang.model.element.Name;
 import javax.tools.StandardLocation;
@@ -148,9 +147,15 @@
 
         JavacFileManager fm = new JavacFileManager(new Context(), false, null);
         fm.setSymbolFileEnabled(false);
-        fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, javacBootClassPath);
-        fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
-        fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
+        if (javacBootClassPath != null) {
+            fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, javacBootClassPath);
+        }
+        if (javacClassPath != null) {
+            fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
+        }
+        if (javacSourcePath != null) {
+            fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
+        }
 
         JavacTask task = tool.getTask(out, fm, null, javacOpts, null,
                 fm.getJavaFileObjectsFromFiles(javacFiles));
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Thu Apr 27 17:16:25 2017 +0100
@@ -326,6 +326,17 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
+        public boolean contains(Location location, FileObject file) throws IOException {
+            try {
+                return clientJavaFileManager.contains(location, unwrap(file));
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
         public void flush() throws IOException {
             try {
                 clientJavaFileManager.flush();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/WrappingJavaFileManager.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/WrappingJavaFileManager.java	Thu Apr 27 17:16:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, 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
@@ -35,6 +35,7 @@
 import javax.tools.*;
 import javax.tools.JavaFileObject.Kind;
 
+import com.sun.tools.javac.util.ClientCodeException;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
 
@@ -214,4 +215,9 @@
                                            unwrap(sibling)));
     }
 
+    @Override @DefinedBy(Api.COMPILER)
+    public boolean contains(Location location, FileObject file) throws IOException {
+        return super.contains(location, unwrap(file));
+    }
+
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Thu Apr 27 17:16:25 2017 +0100
@@ -194,7 +194,13 @@
 
         lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
 
-        legacyModuleOverride = options.get(Option.XMODULE);
+        Collection<String> xmodules = options.keySet()
+                                             .stream()
+                                             .filter(opt -> opt.startsWith(XMODULES_PREFIX))
+                                             .map(opt -> opt.substring(XMODULES_PREFIX.length()))
+                                             .collect(Collectors.toList());
+
+        legacyModuleOverride = xmodules.size() == 1 ? xmodules.iterator().next() : null;
 
         multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
         ClassWriter classWriter = ClassWriter.instance(context);
@@ -211,6 +217,8 @@
         limitModsOpt = options.get(Option.LIMIT_MODULES);
         moduleVersionOpt = options.get(Option.MODULE_VERSION);
     }
+    //where
+        private static final String XMODULES_PREFIX = "-Xmodule:";
 
     int depth = -1;
     private void dprintln(String msg) {
@@ -524,12 +532,52 @@
                 module = defaultModule;
             }
 
-            for (JCCompilationUnit tree: trees) {
+            for (JCCompilationUnit tree : trees) {
+                if (defaultModule != syms.unnamedModule
+                        && defaultModule.sourceLocation == StandardLocation.SOURCE_PATH
+                        && fileManager.hasLocation(StandardLocation.SOURCE_PATH)) {
+                    checkSourceLocation(tree, module);
+                }
                 tree.modle = module;
             }
         }
     }
 
+    private void checkSourceLocation(JCCompilationUnit tree, ModuleSymbol msym) {
+        // skip check if legacy module override still in use
+        if (legacyModuleOverride != null) {
+            return;
+        }
+
+        try {
+            JavaFileObject fo = tree.sourcefile;
+            if (fileManager.contains(msym.sourceLocation, fo)) {
+                return;
+            }
+            if (msym.patchLocation != null && fileManager.contains(msym.patchLocation, fo)) {
+                return;
+            }
+            if (fileManager.hasLocation(StandardLocation.SOURCE_OUTPUT)) {
+                if (fileManager.contains(StandardLocation.SOURCE_OUTPUT, fo)) {
+                    return;
+                }
+            } else {
+                if (fileManager.contains(StandardLocation.CLASS_OUTPUT, fo)) {
+                    return;
+                }
+            }
+        } catch (IOException e) {
+            throw new Error(e);
+        }
+
+        JavaFileObject prev = log.useSource(tree.sourcefile);
+        try {
+            log.error(tree.pos(), "file.sb.on.source.or.patch.path.for.module");
+        } finally {
+            log.useSource(prev);
+        }
+    }
+
     private String singleModuleOverride(List<JCCompilationUnit> trees) {
         if (!fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) {
             return legacyModuleOverride;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Thu Apr 27 17:16:25 2017 +0100
@@ -946,6 +946,14 @@
         return locations.getLocation(location);
     }
 
+    @Override @DefinedBy(Api.COMPILER)
+    public boolean contains(Location location, FileObject fo) throws IOException {
+        nullCheck(location);
+        nullCheck(fo);
+        Path p = asPath(fo);
+        return locations.contains(location, p);
+    }
+
     private Path getClassOutDir() {
         return locations.getOutputLocation(CLASS_OUTPUT);
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Thu Apr 27 17:16:25 2017 +0100
@@ -85,6 +85,7 @@
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.jvm.ModuleNameReader;
+import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Pair;
 import com.sun.tools.javac.util.StringUtils;
 
@@ -226,6 +227,41 @@
         fsEnv = Collections.singletonMap("multi-release", multiReleaseValue);
     }
 
+    private boolean contains(Collection<Path> searchPath, Path file) throws IOException {
+
+        if (searchPath == null) {
+            return false;
+        }
+
+        Path enclosingJar = null;
+        if (file.getFileSystem().provider() == fsInfo.getJarFSProvider()) {
+            URI uri = file.toUri();
+            if (uri.getScheme().equals("jar")) {
+                String ssp = uri.getSchemeSpecificPart();
+                int sep = ssp.lastIndexOf("!");
+                if (ssp.startsWith("file:") && sep > 0) {
+                    enclosingJar = Paths.get(URI.create(ssp.substring(0, sep)));
+                }
+            }
+        }
+
+        Path nf = normalize(file);
+        for (Path p : searchPath) {
+            Path np = normalize(p);
+            if (np.getFileSystem() == nf.getFileSystem()
+                    && Files.isDirectory(np)
+                    && nf.startsWith(np)) {
+                return true;
+            }
+            if (enclosingJar != null
+                    && Files.isSameFile(enclosingJar, np)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Utility class to help evaluate a path option. Duplicate entries are ignored, jar class paths
      * can be expanded.
@@ -456,6 +492,11 @@
         Iterable<Set<Location>> listLocationsForModules() throws IOException {
             return null;
         }
+
+        /**
+         * @see JavaFileManager#contains
+         */
+        abstract boolean contains(Path file) throws IOException;
     }
 
     /**
@@ -611,6 +652,15 @@
 
             return Collections.singleton(moduleTable.locations());
         }
+
+        @Override
+        boolean contains(Path file) throws IOException {
+            if (moduleTable != null) {
+                return moduleTable.contains(file);
+            } else {
+                return (outputDir) != null && normalize(file).startsWith(normalize(outputDir));
+            }
+        }
     }
 
     /**
@@ -660,6 +710,11 @@
         protected SearchPath createPath() {
             return new SearchPath();
         }
+
+        @Override
+        boolean contains(Path file) throws IOException {
+            return Locations.this.contains(searchPath, file);
+        }
     }
 
     /**
@@ -879,13 +934,18 @@
         private void lazy() {
             if (searchPath == null) {
                 try {
-                searchPath = Collections.unmodifiableCollection(computePath());
+                    searchPath = Collections.unmodifiableCollection(computePath());
                 } catch (IOException e) {
                     // TODO: need better handling here, e.g. javac Abort?
                     throw new UncheckedIOException(e);
                 }
             }
         }
+
+        @Override
+        boolean contains(Path file) throws IOException {
+            return Locations.this.contains(searchPath, file);
+        }
     }
 
     /**
@@ -896,7 +956,7 @@
      * The Location can be specified to accept overriding classes from the
      * {@code --patch-module <module>=<path> } parameter.
      */
-    private static class ModuleLocationHandler extends LocationHandler implements Location {
+    private class ModuleLocationHandler extends LocationHandler implements Location {
         private final LocationHandler parent;
         private final String name;
         private final String moduleName;
@@ -949,6 +1009,11 @@
         }
 
         @Override
+        boolean contains(Path file) throws IOException {
+            return Locations.this.contains(searchPath, file);
+        }
+
+        @Override
         public String toString() {
             return name;
         }
@@ -957,7 +1022,7 @@
     /**
      * A table of module location handlers, indexed by name and path.
      */
-    private static class ModuleTable {
+    private class ModuleTable {
         private final Map<String, ModuleLocationHandler> nameMap = new LinkedHashMap<>();
         private final Map<Path, ModuleLocationHandler> pathMap = new LinkedHashMap<>();
 
@@ -1008,6 +1073,10 @@
             return nameMap.isEmpty();
         }
 
+        boolean contains(Path file) throws IOException {
+            return Locations.this.contains(pathMap.keySet(), file);
+        }
+
         Set<Location> locations() {
             return Collections.unmodifiableSet(nameMap.values().stream().collect(Collectors.toSet()));
         }
@@ -1040,6 +1109,12 @@
         }
 
         @Override
+        public Location getLocationForModule(Path file) {
+            initModuleLocations();
+            return moduleTable.get(file);
+        }
+
+        @Override
         Iterable<Set<Location>> listLocationsForModules() {
             if (searchPath == null)
                 return Collections.emptyList();
@@ -1048,6 +1123,14 @@
         }
 
         @Override
+        boolean contains(Path file) throws IOException {
+            if (moduleTable == null) {
+                initModuleLocations();
+            }
+            return moduleTable.contains(file);
+        }
+
+        @Override
         void setPaths(Iterable<? extends Path> paths) {
             if (paths != null) {
                 for (Path p: paths) {
@@ -1592,6 +1675,11 @@
             return Collections.singleton(moduleTable.locations());
         }
 
+        @Override
+        boolean contains(Path file) throws IOException {
+            return (moduleTable == null) ? false : moduleTable.contains(file);
+        }
+
     }
 
     private class SystemModulesLocationHandler extends BasicLocationHandler {
@@ -1698,6 +1786,12 @@
             return Collections.singleton(moduleTable.locations());
         }
 
+        @Override
+        boolean contains(Path file) throws IOException {
+            initSystemModules();
+            return moduleTable.contains(file);
+        }
+
         private void initSystemModules() throws IOException {
             if (moduleTable != null)
                 return;
@@ -1828,6 +1922,11 @@
         Iterable<Set<Location>> listLocationsForModules() throws IOException {
             return Collections.singleton(moduleTable.locations());
         }
+
+        @Override
+        boolean contains(Path file) throws IOException {
+            return moduleTable.contains(file);
+        }
     }
 
     Map<Location, LocationHandler> handlersForLocation;
@@ -1931,6 +2030,13 @@
         return (h == null ? null : h.listLocationsForModules());
     }
 
+    boolean contains(Location location, Path file) throws IOException {
+        LocationHandler h = getHandler(location);
+        if (h == null)
+            throw new IllegalArgumentException("unknown location");
+        return h.contains(file);
+    }
+
     protected LocationHandler getHandler(Location location) {
         Objects.requireNonNull(location);
         return (location instanceof LocationHandler)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java	Thu Apr 27 17:16:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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
@@ -150,6 +150,7 @@
      * @param fileManager the file manager creating this file object
      * @param path the path referred to by this file object
      * @param userJarPath the path of the jar file containing the file system.
+     * @return the file object
      */
     public static PathFileObject forJarPath(BaseFileManager fileManager,
             Path path, Path userJarPath) {
@@ -220,6 +221,7 @@
      *
      * @param fileManager the file manager creating this file object
      * @param path the path referred to by this file object
+     * @return the file object
      */
     public static PathFileObject forJRTPath(BaseFileManager fileManager,
             final Path path) {
@@ -304,6 +306,16 @@
             return null;
         }
 
+        @Override @DefinedBy(Api.COMPILER)
+        public Kind getKind() {
+            return BaseFileManager.getKind(userPath);
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public boolean isNameCompatible(String simpleName, Kind kind) {
+            return isPathNameCompatible(userPath, simpleName, kind);
+        }
+
         @Override
         PathFileObject getSibling(String baseName) {
             return new SimpleFileObject(fileManager,
@@ -369,34 +381,37 @@
 
     @Override @DefinedBy(Api.COMPILER)
     public Kind getKind() {
-        return BaseFileManager.getKind(path.getFileName().toString());
+        return BaseFileManager.getKind(path);
     }
 
     @Override @DefinedBy(Api.COMPILER)
     public boolean isNameCompatible(String simpleName, Kind kind) {
+        return isPathNameCompatible(path, simpleName, kind);
+    }
+
+    protected boolean isPathNameCompatible(Path p, String simpleName, Kind kind) {
         Objects.requireNonNull(simpleName);
         Objects.requireNonNull(kind);
 
-        if (kind == Kind.OTHER && getKind() != kind) {
+        if (kind == Kind.OTHER && BaseFileManager.getKind(p) != kind) {
             return false;
         }
 
         String sn = simpleName + kind.extension;
-        String pn = path.getFileName().toString();
+        String pn = p.getFileName().toString();
         if (pn.equals(sn)) {
             return true;
         }
 
-        if (path.getFileSystem() == defaultFileSystem) {
+        if (p.getFileSystem() == defaultFileSystem) {
             if (isMacOS) {
-                String name = path.getFileName().toString();
-                if (Normalizer.isNormalized(name, Normalizer.Form.NFD)
+                if (Normalizer.isNormalized(pn, Normalizer.Form.NFD)
                         && Normalizer.isNormalized(sn, Normalizer.Form.NFC)) {
                     // On Mac OS X it is quite possible to have the file name and the
                     // given simple name normalized in different ways.
                     // In that case we have to normalize file name to the
                     // Normal Form Composed (NFC).
-                    String normName = Normalizer.normalize(name, Normalizer.Form.NFC);
+                    String normName = Normalizer.normalize(pn, Normalizer.Form.NFC);
                     if (normName.equals(sn)) {
                         return true;
                     }
@@ -406,7 +421,7 @@
             if (pn.equalsIgnoreCase(sn)) {
                 try {
                     // allow for Windows
-                    return path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn);
+                    return p.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn);
                 } catch (IOException e) {
                 }
             }
@@ -552,9 +567,12 @@
         return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
     }
 
-    /** Return the last component of a presumed hierarchical URI.
-     *  From the scheme specific part of the URI, it returns the substring
-     *  after the last "/" if any, or everything if no "/" is found.
+    /**
+     * Return the last component of a presumed hierarchical URI.
+     * From the scheme specific part of the URI, it returns the substring
+     * after the last "/" if any, or everything if no "/" is found.
+     * @param fo the file object
+     * @return the simple name of the file object
      */
     public static String getSimpleName(FileObject fo) {
         URI uri = fo.toUri();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java	Thu Apr 27 17:16:25 2017 +0100
@@ -603,17 +603,6 @@
         }
     },
 
-    XMODULE("-Xmodule:", "opt.arg.module", "opt.module", HIDDEN, BASIC) {
-        @Override
-        public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
-            String prev = helper.get(XMODULE);
-            if (prev != null) {
-                throw helper.newInvalidValueException("err.option.too.many", XMODULE.primaryName);
-            }
-            helper.put(XMODULE.primaryName, arg);
-        }
-    },
-
     MODULE("--module -m", "opt.arg.m", "opt.m", STANDARD, BASIC),
 
     ADD_MODULES("--add-modules", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java	Thu Apr 27 17:16:25 2017 +0100
@@ -1012,7 +1012,7 @@
     }
 
     /**
-     * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javadoc.html#javadoctags">Javadoc Tags</a>
+     * @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/unix/javadoc.html#CHDJGIJB">Javadoc Tags</a>
      */
     private void initTagParsers() {
         TagParser[] parsers = {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Apr 27 17:16:25 2017 +0100
@@ -947,7 +947,7 @@
     package annotations should be in file package-info.java
 
 compiler.err.no.pkg.in.module-info.java=\
-    package clauses should not be in file module-info.java
+    package declarations not allowed in file module-info.java
 
 # 0: symbol
 compiler.err.pkg.clashes.with.class.of.same.name=\
@@ -1304,6 +1304,9 @@
 compiler.err.locn.invalid.arg.for.xpatch=\
     invalid argument for --patch-module option: {0}
 
+compiler.err.file.sb.on.source.or.patch.path.for.module=\
+    file should be on source path, or on patch path for module
+
 #####
 
 # Fatal Errors
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties	Thu Apr 27 17:16:25 2017 +0100
@@ -312,10 +312,6 @@
     in JAR files or directories
 javac.opt.arg.patch=\
     <module>=<file>(:<file>)*
-javac.opt.module=\
-    Specify a module to which the classes being compiled belong.
-javac.opt.arg.module=\
-    <module>
 javac.opt.addmods=\
     Root modules to resolve in addition to the initial modules, or all modules\n\
     on the module path if <module> is ALL-MODULE-PATH.
--- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java	Thu Apr 27 17:16:25 2017 +0100
@@ -53,14 +53,14 @@
  * <p>
  * Here are two sample taglets: <br>
  * <ul>
- *  <li><a href="{@docRoot}/../../../../technotes/guides/javadoc/taglet/ToDoTaglet.java">ToDoTaglet.java</a>
+ *  <li><a href="http://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/taglet/ToDoTaglet.java">ToDoTaglet.java</a>
  *         - Standalone taglet</li>
- *  <li><a href="{@docRoot}/../../../../technotes/guides/javadoc/taglet/UnderlineTaglet.java">UnderlineTaglet.java</a>
+ *  <li><a href="http://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/taglet/UnderlineTaglet.java">UnderlineTaglet.java</a>
  *         - Inline taglet</li>
  * </ul>
  * <p>
  * For more information on how to create your own Taglets, please see the
- * <a href="{@docRoot}/../../../../technotes/guides/javadoc/taglet/overview.html">Taglet Overview</a>.
+ * <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/taglet/overview.html">Taglet Overview</a>.
  *
  * @since 1.4
  * @author Jamie Ho
--- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavaScriptScanner.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavaScriptScanner.java	Thu Apr 27 17:16:25 2017 +0100
@@ -788,7 +788,7 @@
     }
 
     /**
-     * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javadoc.html#javadoctags">Javadoc Tags</a>
+     * @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/unix/javadoc.html#CHDJGIJB">Javadoc Tags</a>
      */
     @SuppressWarnings("deprecation")
     private void initTagParsers() {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Thu Apr 27 17:16:25 2017 +0100
@@ -336,26 +336,32 @@
         // Get all the exported and opened packages, for the transitive closure of the module, to be displayed in
         // the indirect packages tables.
         dependentModules.forEach((module, mod) -> {
-            SortedSet<PackageElement> pkgList = new TreeSet<>(utils.makePackageComparator());
+            SortedSet<PackageElement> exportPkgList = new TreeSet<>(utils.makePackageComparator());
             (ElementFilter.exportsIn(module.getDirectives())).forEach((directive) -> {
                 PackageElement pkg = directive.getPackage();
                 if (shouldDocument(pkg)) {
-                    pkgList.add(pkg);
+                    // Qualified exports are not displayed in API mode
+                    if (moduleMode == ModuleMode.ALL || directive.getTargetModules() == null) {
+                        exportPkgList.add(pkg);
+                    }
                 }
             });
-            // If none of the transitive modules have exported packages to be displayed, we should not be
+            // If none of the indirect modules have exported packages to be displayed, we should not be
             // displaying the table and so it should not be added to the map.
-            if (!pkgList.isEmpty()) {
-                indirectPackages.put(module, pkgList);
+            if (!exportPkgList.isEmpty()) {
+                indirectPackages.put(module, exportPkgList);
             }
             SortedSet<PackageElement> openPkgList = new TreeSet<>(utils.makePackageComparator());
             (ElementFilter.opensIn(module.getDirectives())).forEach((directive) -> {
                 PackageElement pkg = directive.getPackage();
                 if (shouldDocument(pkg)) {
-                    openPkgList.add(pkg);
+                    // Qualified opens are not displayed in API mode
+                    if (moduleMode == ModuleMode.ALL || directive.getTargetModules() == null) {
+                        openPkgList.add(pkg);
+                    }
                 }
             });
-            // If none of the transitive modules have opened packages to be displayed, we should not be
+            // If none of the indirect modules have opened packages to be displayed, we should not be
             // displaying the table and so it should not be added to the map.
             if (!openPkgList.isEmpty()) {
                 indirectOpenPackages.put(module, openPkgList);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Thu Apr 27 17:16:25 2017 +0100
@@ -332,6 +332,9 @@
 doclet.usage.charset.description=\
     Charset for cross-platform viewing of generated documentation
 
+doclet.usage.javafx.description=\
+    Enable javafx functionality
+
 doclet.usage.helpfile.parameters=\
     <file>
 doclet.usage.helpfile.description=\
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java	Thu Apr 27 17:16:25 2017 +0100
@@ -523,7 +523,7 @@
                     return true;
                 }
             },
-            new Hidden(resources, "-javafx") {
+            new Option(resources, "--javafx -javafx") {
                 @Override
                 public boolean process(String opt, List<String> args) {
                     javafx = true;
@@ -1082,11 +1082,14 @@
         private final int argCount;
 
         protected Option(Resources resources, String name, int argCount) {
-            this(resources, "doclet.usage." + name.toLowerCase().replaceAll("^-+", ""), name, argCount);
+            this(resources, null, name, argCount);
         }
 
         protected Option(Resources resources, String keyBase, String name, int argCount) {
             this.names = name.trim().split("\\s+");
+            if (keyBase == null) {
+                keyBase = "doclet.usage." + names[0].toLowerCase().replaceAll("^-+", "");
+            }
             String desc = getOptionsMessage(resources, keyBase + ".description");
             if (desc.isEmpty()) {
                 this.description = "<MISSING KEY>";
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Thu Apr 27 17:16:25 2017 +0100
@@ -27,21 +27,13 @@
     text-decoration:none;
     color:#4A6782;
 }
-a:hover, a:focus {
+a[href]:hover, a[href]:focus {
     text-decoration:none;
     color:#bb7a2a;
 }
-a:active {
-    text-decoration:none;
-    color:#4A6782;
-}
 a[name] {
     color:#353833;
 }
-a[name]:hover {
-    text-decoration:none;
-    color:#353833;
-}
 a[name]:before, a[name]:target, a[id]:before, a[id]:target {
     content:"";
     display:inline-block;
@@ -579,15 +571,13 @@
 .packagesSummary th.colLast, .packagesSummary td.colLast {
     white-space:normal;
 }
-td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover,
-td.colSecond a:link, td.colSecond a:active, td.colSecond a:visited, td.colSecond a:hover,
-th.colFirst a:link, th.colFirst a:active, th.colFirst a:visited, th.colFirst a:hover,
-th.colSecond a:link, th.colSecond a:active, th.colSecond a:visited, th.colSecond a:hover,
-th.colConstructorName a:link, th.colConstructorName a:active, th.colConstructorName a:visited,
-th.colConstructorName a:hover,
-td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover,
-.constantValuesContainer td a:link, .constantValuesContainer td a:active,
-.constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
+td.colFirst a:link, td.colFirst a:visited,
+td.colSecond a:link, td.colSecond a:visited,
+th.colFirst a:link, th.colFirst a:visited,
+th.colSecond a:link, th.colSecond a:visited,
+th.colConstructorName a:link, th.colConstructorName a:visited,
+td.colLast a:link, td.colLast a:visited,
+.constantValuesContainer td a:link, .constantValuesContainer td a:visited {
     font-weight:bold;
 }
 .tableSubHeadingColor {
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Thu Apr 27 17:16:25 2017 +0100
@@ -701,7 +701,8 @@
 help.set.mode = \
 Create a user-defined feedback mode, optionally copying from an existing mode:\n\
 \n\t\
-/set mode <mode> [<old-mode>] [-command|-quiet|-delete]\n\
+/set mode <new-mode> [<old-mode>] (-command|-quiet)\n\
+\n\
 Retain a user-defined feedback mode for future sessions:\n\
 \n\t\
 /set mode -retain <mode>\n\
@@ -715,25 +716,39 @@
 /set mode [<mode>]\n\
 \n\
 Where <new-mode> is the name of a mode you wish to create.\n\
-Where <old-mode> is the name of a previously defined feedback mode.\n\
+Where <old-mode> is the name of a existing feedback mode.\n\
+Where <mode> is the name of a existing feedback mode.\n\
+\n\
 If <old-mode> is present, its settings are copied to the new mode.\n\
-'-command' vs '-quiet' determines if informative/verifying command feedback is displayed.\n\
+\n\
+The feedback that a mode provides for entered snippets is determined by the\n\
+'/set format' settings. However, for entered commands, feedback is either on or off,\n\
+as determined by the option used when creating the mode; Either the option '-command'\n\
+or the option '-quiet' must be specified. If '-command' is used, informative and\n\
+verifying command feedback is displayed when in the new mode.  If '-quiet' is used,\n\
+commands give only essential feedback (e.g., errors).\n\
 \n\
 Once the new mode is created, use '/set format', '/set prompt' and '/set truncation'\n\
 to configure it.  Use '/set feedback' to use the new mode.\n\
 \n\
-When the -retain option is used, the mode (including its component prompt, format,\n\
-and truncation settings) will be used in this and future runs of the jshell tool.\n\
-When both -retain and -delete are used, the mode is deleted from the current\n\
-and future sessions.\n\
+When the '-retain' option is used (without the '-delete' option), the mode (including\n\
+its current prompt, format, and truncation settings) will be stored for use in\n\
+future runs of the jshell tool.  If retain is not used, the mode is only defined in\n\
+the current session. After updating the mode's settings, retain the mode again to\n\
+preserve the updates across sessions.\n\
 \n\
-The form without options shows the mode settings.\n\
-When the <mode> is specified only the mode settings for that mode are shown.\n\
+When only the '-delete' option is used, the mode is deleted from the current session.\n\
+When both '-retain' and '-delete' are used, the mode is deleted from the current and\n\
+future sessions.\n\
+\n\
+When the form without options is used, the mode settings are displayed.\n\
+When the <mode> is specified, only the mode settings for that mode are shown.\n\
 Note: the settings for the mode include the settings for prompt, format, and\n\
-truncation -- so these are displayed as well.\n\
+truncation.\n\
 Example:\n\t\
 /set mode myformat\n\
-shows the mode, prompt, format, and truncation settings for the mode myformat\n
+\n\
+shows the mode, prompt, format, and truncation settings for the mode myformat
 
 help.set.prompt = \
 Set the prompts.  Both the normal prompt and the continuation-prompt must be set:\n\
--- a/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java	Thu Apr 27 17:16:25 2017 +0100
@@ -559,6 +559,11 @@
         return stdFileManager.listLocationsForModules(location);
     }
 
+    @Override
+    public boolean contains(Location location, FileObject file) throws IOException {
+        return stdFileManager.contains(location, file);
+    }
+
     /**
      * Flushes any resources opened for output by this file manager
      * directly or indirectly.  Flushing a closed file manager has no
--- a/test/TEST.ROOT	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/TEST.ROOT	Thu Apr 27 17:16:25 2017 +0100
@@ -19,3 +19,6 @@
 
 # Use new module options
 useNewOptions=true
+
+# Use --patch-module instead of -Xmodule:
+useNewPatchModule=true
--- a/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Thu Apr 27 17:16:25 2017 +0100
@@ -23,7 +23,8 @@
 
 /*
  * @test
- * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363 8167967 8172528 8175200
+ * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363
+ *      8167967 8172528 8175200 8178830
  * @summary Test of the JavaFX doclet features.
  * @author jvalenta
  * @library ../lib
@@ -265,12 +266,13 @@
 
     /*
      * Force the doclet to emit a warning when processing a synthesized,
-     * DocComment, and ensure that the run succeeds.
+     * DocComment, and ensure that the run succeeds, using the newer
+     * --javafx flag.
      */
     @Test
     void test4() {
         javadoc("-d", "out4",
-                "-javafx",
+                "--javafx",
                 "-Xdoclint:none",
                 "-sourcepath", testSrc,
                 "-package",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017, 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
+ * @bug 8178339
+ * @summary Tests indirect exports and opens in the module summary page
+ * @modules jdk.javadoc/jdk.javadoc.internal.api
+ *          jdk.javadoc/jdk.javadoc.internal.tool
+ *          jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ * @library ../lib /tools/lib
+ * @build toolbox.ToolBox toolbox.ModuleBuilder JavadocTester
+ * @run main TestIndirectExportsOpens
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.*;
+
+public class TestIndirectExportsOpens extends JavadocTester {
+
+    public final ToolBox tb;
+    public static void main(String... args) throws Exception {
+        TestIndirectExportsOpens tester = new TestIndirectExportsOpens();
+        tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    public TestIndirectExportsOpens() {
+        tb = new ToolBox();
+    }
+
+    @Test
+    public void checkNoIndirects(Path base) throws Exception {
+
+        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
+                .classes("package pm; public class A {}");
+        Path p0 = mb0.write(base);
+
+        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
+                .requiresTransitive("m", p0)
+                .classes("package pa; public class NoOp {}")
+                .exports("pa");
+        mb1.write(base);
+
+        javadoc("-d", base.resolve("out-api").toString(),
+                "-quiet",
+                "--module-source-path", base.toString(),
+                "--expand-requires", "transitive",
+                "--module", "a");
+        checkExit(Exit.OK);
+        verifyIndirectExports(false);
+        verifyIndirectOpens(false);
+    }
+
+    @Test
+    public void checkExportsOpens(Path base) throws Exception {
+
+        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
+                .classes("package pm; public class A {}")
+                .exports("pm")
+                .opens("pm");
+
+        Path p0 = mb0.write(base);
+
+        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
+                .requiresTransitive("m", p0)
+                .classes("package pa ; public class NoOp {}")
+                .exports("pa");
+        mb1.write(base);
+
+        javadoc("-d", base.resolve("out-api").toString(),
+                "-quiet",
+                "--module-source-path", base.toString(),
+                "--expand-requires", "transitive",
+                "--module", "a");
+        checkExit(Exit.OK);
+        verifyIndirectExports(true);
+        verifyIndirectOpens(true);
+    }
+
+    @Test
+    public void checkExportsToOpensTo(Path base) throws Exception {
+
+        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
+                .classes("package pm; public class A {}")
+                .exportsTo("pm", "x")
+                .opensTo("pm", "x");
+
+        Path p0 = mb0.write(base);
+
+        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
+                .requiresTransitive("m", p0)
+                .classes("package pa ; public class NoOp {}")
+                .exports("pa");
+        mb1.write(base);
+
+        javadoc("-d", base.resolve("out-api").toString(),
+                "-quiet",
+                "--module-source-path", base.toString(),
+                "--expand-requires", "transitive",
+                "--module", "a");
+
+        checkExit(Exit.OK);
+        verifyIndirectExports(false);
+        verifyIndirectOpens(false);
+    }
+
+    @Test
+    public void checkExportsToOpensToDetailMode(Path base) throws Exception {
+
+        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
+                .classes("package exportsto; public class A {}")
+                .classes("package opensto; public class A {}")
+                .exportsTo("exportsto", "x")
+                .opensTo("opensto", "x");
+
+        Path p0 = mb0.write(base);
+
+        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
+                .requiresTransitive("m", p0)
+                .classes("package pa ; public class NoOp {}")
+                .exports("pa");
+        mb1.write(base);
+
+        javadoc("-d", base.resolve("out-detail").toString(),
+                "-quiet",
+                "--module-source-path", base.toString(),
+                "--expand-requires", "transitive",
+                "--show-module-contents", "all",
+                "--module", "a");
+
+        checkExit(Exit.OK);
+
+        // In details mode all kinds of packages from java.base,
+        // could be listed in the indirects section, so just
+        // check for minimal expected strings.
+        checkOutput("a-summary.html", true,
+                "Indirect Exports table",
+                "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
+                + "<td class=\"colLast\"><a href=\"exportsto/package-summary.html\">exportsto</a></td>\n"
+                + "</tr>\n");
+
+        checkOutput("a-summary.html", true,
+                "Indirect Opens table",
+                "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
+                + "<td class=\"colLast\">opensto</td>\n"
+                + "</tr>\n");
+    }
+
+    void verifyIndirectExports(boolean present) {
+        verifyIndirects(present, false);
+    }
+
+    void verifyIndirectOpens(boolean present) {
+        verifyIndirects(present, true);
+    }
+
+    void verifyIndirects(boolean present, boolean opens) {
+
+        String typeString = opens ? "Indirect Opens" : "Indirect Exports";
+
+        // Avoid false positives, just check for primary string absence.
+        if (!present) {
+            checkOutput("a-summary.html", false, typeString);
+            return;
+        }
+
+        checkOutput("a-summary.html", present,
+                "<table class=\"packagesSummary\" summary=\"" + typeString + " table, listing modules, and packages\">\n"
+                + "<caption><span>" + typeString + "</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<tr>\n"
+                + "<th class=\"colFirst\" scope=\"col\">From</th>\n"
+                + "<th class=\"colLast\" scope=\"col\">Packages</th>\n"
+                + "</tr>\n"
+                + "<tbody>\n"
+                + "<tr class=\"altColor\">\n"
+                + "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
+                + "<td class=\"colLast\"><a href=\"pm/package-summary.html\">pm</a></td>\n"
+                + "</tr>\n"
+                + "</tbody>\n"
+                + "</table>\n");
+    }
+
+}
+
--- a/test/jdk/javadoc/doclet/testModules/TestModules.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/jdk/javadoc/doclet/testModules/TestModules.java	Thu Apr 27 17:16:25 2017 +0100
@@ -752,14 +752,6 @@
         checkOutput("moduleA-summary.html", true,
                 "<li><a href=\"#module.description\">Description</a>&nbsp;|&nbsp;<a href=\"#modules.summary\">"
                 + "Modules</a>&nbsp;|&nbsp;<a href=\"#packages.summary\">Packages</a>&nbsp;|&nbsp;Services</li>",
-                "<table class=\"packagesSummary\" summary=\"Indirect Exports table, listing modules, and packages\">\n"
-                + "<caption><span>Indirect Exports</span><span class=\"tabEnd\">&nbsp;</span></caption>",
-                "<table class=\"packagesSummary\" summary=\"Indirect Opens table, listing modules, and packages\">\n"
-                + "<caption><span>Indirect Opens</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
-                + "<tr>\n"
-                + "<th class=\"colFirst\" scope=\"col\">From</th>\n"
-                + "<th class=\"colLast\" scope=\"col\">Packages</th>\n"
-                + "</tr>\n",
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"moduleB-summary.html\">moduleB</a></th>\n"
                 + "<td class=\"colLast\"><a href=\"testpkgmdlB/package-summary.html\">testpkgmdlB</a></td>\n");
         checkOutput("moduleB-summary.html", true,
--- a/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java	Thu Apr 27 17:16:25 2017 +0100
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug      4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261 8162363 8160196 8151743 8177417
- *           8175218
+ *           8175218 8176452
  * @summary  Run tests on doclet stylesheet.
  * @author   jamieh
  * @library  ../lib
@@ -173,13 +173,36 @@
                 + "}\n"
                 + ".searchTagResult:before, .searchTagResult:target {\n"
                 + "    color:red;\n"
+                + "}",
+                "a[href]:hover, a[href]:focus {\n"
+                + "    text-decoration:none;\n"
+                + "    color:#bb7a2a;\n"
+                + "}",
+                "td.colFirst a:link, td.colFirst a:visited,\n"
+                + "td.colSecond a:link, td.colSecond a:visited,\n"
+                + "th.colFirst a:link, th.colFirst a:visited,\n"
+                + "th.colSecond a:link, th.colSecond a:visited,\n"
+                + "th.colConstructorName a:link, th.colConstructorName a:visited,\n"
+                + "td.colLast a:link, td.colLast a:visited,\n"
+                + ".constantValuesContainer td a:link, .constantValuesContainer td a:visited {\n"
+                + "    font-weight:bold;\n"
                 + "}");
 
-        // Test whether a link to the stylesheet file is inserted properly
-        // in the class documentation.
         checkOutput("pkg/A.html", true,
+                // Test whether a link to the stylesheet file is inserted properly
+                // in the class documentation.
                 "<link rel=\"stylesheet\" type=\"text/css\" "
-                + "href=\"../stylesheet.css\" title=\"Style\">");
+                + "href=\"../stylesheet.css\" title=\"Style\">",
+                "<div class=\"block\">Test comment for a class which has an <a name=\"named_anchor\">"
+                + "anchor_with_name</a> and\n"
+                + " an <a id=\"named_anchor1\">anchor_with_id</a>.</div>");
+
+        checkOutput("pkg/package-summary.html", true,
+                "<td class=\"colLast\">\n"
+                + "<div class=\"block\">Test comment for a class which has an <a name=\"named_anchor\">"
+                + "anchor_with_name</a> and\n"
+                + " an <a id=\"named_anchor1\">anchor_with_id</a>.</div>\n"
+                + "</td>");
 
         checkOutput("index.html", true,
                 "<link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\" title=\"Style\">");
@@ -188,6 +211,14 @@
                 "* {\n"
                 + "    margin:0;\n"
                 + "    padding:0;\n"
+                + "}",
+                "a:active {\n"
+                + "    text-decoration:none;\n"
+                + "    color:#4A6782;\n"
+                + "}",
+                "a[name]:hover {\n"
+                + "    text-decoration:none;\n"
+                + "    color:#353833;\n"
                 + "}");
     }
 }
--- a/test/jdk/javadoc/doclet/testStylesheet/pkg/A.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/jdk/javadoc/doclet/testStylesheet/pkg/A.java	Thu Apr 27 17:16:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017 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,4 +23,8 @@
 
 package pkg;
 
+/**
+ * Test comment for a class which has an <a name="named_anchor">anchor_with_name</a> and
+ * an <a id="named_anchor1">anchor_with_id</a>.
+ */
 public class A {}
--- a/test/jdk/jshell/CompletionSuggestionTest.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/jdk/jshell/CompletionSuggestionTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -296,7 +296,7 @@
     }
 
     public void testImportStart() {
-        assertCompletion("import c|", "com");
+        assertCompletionIncludesExcludes("import c|", Set.of("com"), Set.of());
     }
 
     public void testBrokenClassFile() throws Exception {
--- a/test/jdk/jshell/HistoryUITest.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/jdk/jshell/HistoryUITest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -28,6 +28,7 @@
  * @modules
  *     jdk.compiler/com.sun.tools.javac.api
  *     jdk.compiler/com.sun.tools.javac.main
+ *     jdk.jshell/jdk.internal.jshell.tool.resources:open
  *     jdk.jshell/jdk.jshell:open
  * @library /tools/lib
  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jshell/MergedTabShiftTabCommandTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2017, 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
+ * @bug 8177076
+ * @modules
+ *     jdk.compiler/com.sun.tools.javac.api
+ *     jdk.compiler/com.sun.tools.javac.main
+ *     jdk.jshell/jdk.internal.jshell.tool.resources:open
+ *     jdk.jshell/jdk.jshell:open
+ * @library /tools/lib
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
+ * @build Compiler UITesting
+ * @build MergedTabShiftTabCommandTest
+ * @run testng MergedTabShiftTabCommandTest
+ */
+
+import java.util.regex.Pattern;
+
+import org.testng.annotations.Test;
+
+@Test
+public class MergedTabShiftTabCommandTest extends UITesting {
+
+    public void testCommand() throws Exception {
+        doRunTest((inputSink, out) -> {
+            inputSink.write("1\n");
+            waitOutput(out, "\u0005");
+            inputSink.write("/\011");
+            waitOutput(out, ".*/edit.*/list.*\n\n" + Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n\r\u0005/");
+            inputSink.write("\011");
+            waitOutput(out,   ".*\n/edit\n" + Pattern.quote(getResource("help.edit.summary")) +
+                            "\n.*\n/list\n" + Pattern.quote(getResource("help.list.summary")) +
+                            ".*\n\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/");
+            inputSink.write("\011");
+            waitOutput(out,  "/!\n" +
+                            Pattern.quote(getResource("help.bang")) + "\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.next.command.doc")) + "\n" +
+                            "\r\u0005/");
+            inputSink.write("\011");
+            waitOutput(out,  "/-<n>\n" +
+                            Pattern.quote(getResource("help.previous")) + "\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.next.command.doc")) + "\n" +
+                            "\r\u0005/");
+
+            inputSink.write("lis\011");
+            waitOutput(out, "list $");
+
+            inputSink.write("\011");
+            waitOutput(out, ".*-all.*" +
+                            "\n\n" + Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n\r\u0005/");
+            inputSink.write("\011");
+            waitOutput(out, Pattern.quote(getResource("help.list.summary")) + "\n\n" +
+                            Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/list ");
+            inputSink.write("\011");
+            waitOutput(out, Pattern.quote(getResource("help.list").replaceAll("\t", "    ")));
+
+            inputSink.write("\u0003/env \011");
+            waitOutput(out, "\u0005/env -\n" +
+                            "-add-exports    -add-modules    -class-path     -module-path    \n" +
+                            "\r\u0005/env -");
+
+            inputSink.write("\011");
+            waitOutput(out, "-add-exports    -add-modules    -class-path     -module-path    \n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n" +
+                            "\r\u0005/env -");
+
+            inputSink.write("\011");
+            waitOutput(out, Pattern.quote(getResource("help.env.summary")) + "\n\n" +
+                            Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
+                            "\r\u0005/env -");
+
+            inputSink.write("\011");
+            waitOutput(out, Pattern.quote(getResource("help.env").replaceAll("\t", "    ")) + "\n" +
+                            "\r\u0005/env -");
+
+            inputSink.write("\011");
+            waitOutput(out, "-add-exports    -add-modules    -class-path     -module-path    \n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n" +
+                            "\r\u0005/env -");
+
+            inputSink.write("\u0003/exit \011");
+            waitOutput(out, Pattern.quote(getResource("help.exit.summary")) + "\n\n" +
+                            Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/exit ");
+            inputSink.write("\011");
+            waitOutput(out, Pattern.quote(getResource("help.exit")) + "\n" +
+                            "\r\u0005/exit ");
+            inputSink.write("\011");
+            waitOutput(out, Pattern.quote(getResource("help.exit.summary")) + "\n\n" +
+                            Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/exit ");
+            inputSink.write("\u0003/doesnotexist\011");
+            waitOutput(out, "\u0005/doesnotexist\n" +
+                            Pattern.quote(getResource("jshell.console.no.such.command")) + "\n" +
+                            "\n" +
+                            "\r\u0005/doesnotexist");
+        });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jshell/MergedTabShiftTabExpressionTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2017, 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
+ * @bug 8177076
+ * @modules
+ *     jdk.compiler/com.sun.tools.javac.api
+ *     jdk.compiler/com.sun.tools.javac.main
+ *     jdk.jshell/jdk.internal.jshell.tool.resources:open
+ *     jdk.jshell/jdk.jshell:open
+ * @library /tools/lib
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
+ * @build Compiler UITesting
+ * @build MergedTabShiftTabExpressionTest
+ * @run testng/timeout=300 MergedTabShiftTabExpressionTest
+ */
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.regex.Pattern;
+
+import org.testng.annotations.Test;
+
+@Test
+public class MergedTabShiftTabExpressionTest extends UITesting {
+
+    public void testExpression() throws Exception {
+        Path classes = prepareZip();
+        doRunTest((inputSink, out) -> {
+            inputSink.write("/env -class-path " + classes.toString() + "\n");
+            waitOutput(out, Pattern.quote(getResource("jshell.msg.set.restore")) + "\n\u0005");
+            inputSink.write("import jshelltest.*;\n");
+            waitOutput(out, "\n\u0005");
+
+            //-> <tab>
+            inputSink.write("\011");
+            waitOutput(out, getMessage("jshell.console.completion.all.completions.number", "[0-9]+"));
+            inputSink.write("\011");
+            waitOutput(out, ".*String.*StringBuilder.*\n\r\u0005");
+
+            //new JShellTes<tab>
+            inputSink.write("new JShellTes\011");
+            waitOutput(out, "t\nJShellTest\\(      JShellTestAux\\(   \n\r\u0005new JShellTest");
+
+            //new JShellTest<tab>
+            inputSink.write("\011");
+            waitOutput(out, "JShellTest\\(      JShellTestAux\\(   \n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
+                            "jshelltest.JShellTest\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
+                            "\r\u0005new JShellTest");
+            inputSink.write("\011");
+            waitOutput(out, "jshelltest.JShellTest\n" +
+                            "JShellTest 0\n" +
+                            "\r\u0005new JShellTest");
+            inputSink.write("\011");
+            waitOutput(out, "JShellTest\\(      JShellTestAux\\(   \n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
+                            "jshelltest.JShellTest\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
+                            "\r\u0005new JShellTest");
+
+            //new JShellTest(<tab>
+            inputSink.write("(\011");
+            waitOutput(out, "\\(\n" +
+                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
+                            "JShellTest\\(String str\\)\n" +
+                            "JShellTest\\(String str, int i\\)\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
+                            "\r\u0005new JShellTest\\(");
+            inputSink.write("\011");
+            waitOutput(out, "JShellTest\\(String str\\)\n" +
+                            "JShellTest 1\n" +
+                            "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.next.page")) + "\n" +
+                            "\r\u0005new JShellTest\\(");
+            inputSink.write("\011");
+            waitOutput(out, "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.next.javadoc")) + "\n" +
+                            "\r\u0005new JShellTest\\(");
+            inputSink.write("\011");
+            waitOutput(out, "JShellTest\\(String str, int i\\)\n" +
+                            "JShellTest 2\n" +
+                            "\n" +
+                            getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + "\n" +
+                            "\r\u0005new JShellTest\\(");
+            inputSink.write("\011");
+            waitOutput(out, ".*String.*StringBuilder.*\n\r\u0005new JShellTest\\(");
+
+            inputSink.write("\u0003String str = \"\";\nnew JShellTest(");
+            waitOutput(out, "\u0005new JShellTest\\(");
+
+            inputSink.write("\011");
+            waitOutput(out, "\n" +
+                            "str   \n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
+                            "JShellTest\\(String str\\)\n" +
+                            "JShellTest\\(String str, int i\\)\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
+                            "\r\u0005new JShellTest\\(");
+            inputSink.write("\011");
+            waitOutput(out, "JShellTest\\(String str\\)\n" +
+                            "JShellTest 1\n" +
+                            "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.next.page")) + "\n" +
+                            "\r\u0005new JShellTest\\(");
+            inputSink.write("\011");
+            waitOutput(out, "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.next.javadoc")) + "\n" +
+                            "\r\u0005new JShellTest\\(");
+            inputSink.write("\011");
+            waitOutput(out, "JShellTest\\(String str, int i\\)\n" +
+                            "JShellTest 2\n" +
+                            "\n" +
+                            getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + "\n" +
+                            "\r\u0005new JShellTest\\(");
+            inputSink.write("\011");
+            waitOutput(out, ".*String.*StringBuilder.*\n\r\u0005new JShellTest\\(");
+
+            inputSink.write("\u0003JShellTest t = new JShellTest\011");
+            waitOutput(out, "\u0005JShellTest t = new JShellTest\n" +
+                            "JShellTest\\(   \n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
+                            "jshelltest.JShellTest\n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.completion.all.completions")) + "\n" +
+                            "\r\u0005JShellTest t = new JShellTest");
+            inputSink.write("\011");
+            waitOutput(out, "JShellTest\\(      JShellTestAux\\(   \n" +
+                            "\n" +
+                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
+                            "\r\u0005JShellTest t = new JShellTest");
+
+            inputSink.write("\u0003JShellTest t = new \011");
+            waitOutput(out, "\u0005JShellTest t = new \n" +
+                            "JShellTest\\(   \n" +
+                            "\n" +
+                            getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + "\n" +
+                            "\r\u0005JShellTest t = new ");
+            inputSink.write("\011");
+            waitOutput(out, ".*String.*StringBuilder.*\n\r\u0005JShellTest t = new ");
+
+            inputSink.write("\u0003class JShelX{}\n");
+            inputSink.write("new JShel\011");
+            waitOutput(out, "\u0005new JShel\n" +
+                            "JShelX\\(\\)         JShellTest\\(      JShellTestAux\\(   \n" +
+                            "\r\u0005new JShel");
+
+            //no crash:
+            inputSink.write("\u0003new Stringbuil\011");
+            waitOutput(out, "\u0005new Stringbuil\u0007");
+        });
+    }
+
+    private Path prepareZip() {
+        String clazz1 =
+                "package jshelltest;\n" +
+                "/**JShellTest 0" +
+                " */\n" +
+                "public class JShellTest {\n" +
+                "    /**JShellTest 1\n" +
+                "     * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" +
+                "     * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" +
+                "     * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" +
+                "     */\n" +
+                "    public JShellTest(String str) {}\n" +
+                "    /**JShellTest 2" +
+                "     */\n" +
+                "    public JShellTest(String str, int i) {}\n" +
+                "}\n";
+
+        String clazz2 =
+                "package jshelltest;\n" +
+                "/**JShellTestAux 0" +
+                " */\n" +
+                "public class JShellTestAux {\n" +
+                "    /**JShellTest 1" +
+                "     */\n" +
+                "    public JShellTestAux(String str) { }\n" +
+                "    /**JShellTest 2" +
+                "     */\n" +
+                "    public JShellTestAux(String str, int i) { }\n" +
+                "}\n";
+
+        Path srcZip = Paths.get("src.zip");
+
+        try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(srcZip))) {
+            out.putNextEntry(new JarEntry("jshelltest/JShellTest.java"));
+            out.write(clazz1.getBytes());
+            out.putNextEntry(new JarEntry("jshelltest/JShellTestAux.java"));
+            out.write(clazz2.getBytes());
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
+
+        compiler.compile(clazz1, clazz2);
+
+        try {
+            Field availableSources = Class.forName("jdk.jshell.SourceCodeAnalysisImpl").getDeclaredField("availableSourcesOverride");
+            availableSources.setAccessible(true);
+            availableSources.set(null, Arrays.asList(srcZip));
+        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException | ClassNotFoundException ex) {
+            throw new IllegalStateException(ex);
+        }
+
+        return compiler.getClassDir();
+    }
+    //where:
+        private final Compiler compiler = new Compiler();
+
+}
--- a/test/jdk/jshell/MergedTabShiftTabTest.java	Wed Apr 26 21:09:20 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,345 +0,0 @@
-/*
- * Copyright (c) 2017, 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
- * @bug 8177076
- * @modules
- *     jdk.compiler/com.sun.tools.javac.api
- *     jdk.compiler/com.sun.tools.javac.main
- *     jdk.jshell/jdk.internal.jshell.tool.resources:open
- *     jdk.jshell/jdk.jshell:open
- * @library /tools/lib
- * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
- * @build Compiler UITesting
- * @build MergedTabShiftTabTest
- * @run testng MergedTabShiftTabTest
- */
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.regex.Pattern;
-
-import jdk.jshell.JShell;
-import org.testng.annotations.Test;
-
-@Test
-public class MergedTabShiftTabTest extends UITesting {
-
-    public void testCommand() throws Exception {
-        doRunTest((inputSink, out) -> {
-            inputSink.write("1\n");
-            waitOutput(out, "\u0005");
-            inputSink.write("/\011");
-            waitOutput(out, ".*/edit.*/list.*\n\n" + Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n\r\u0005/");
-            inputSink.write("\011");
-            waitOutput(out,   ".*\n/edit\n" + Pattern.quote(getResource("help.edit.summary")) +
-                            "\n.*\n/list\n" + Pattern.quote(getResource("help.list.summary")) +
-                            ".*\n\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/");
-            inputSink.write("\011");
-            waitOutput(out,  "/!\n" +
-                            Pattern.quote(getResource("help.bang")) + "\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.next.command.doc")) + "\n" +
-                            "\r\u0005/");
-            inputSink.write("\011");
-            waitOutput(out,  "/-<n>\n" +
-                            Pattern.quote(getResource("help.previous")) + "\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.next.command.doc")) + "\n" +
-                            "\r\u0005/");
-
-            inputSink.write("lis\011");
-            waitOutput(out, "list $");
-
-            inputSink.write("\011");
-            waitOutput(out, ".*-all.*" +
-                            "\n\n" + Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n\r\u0005/");
-            inputSink.write("\011");
-            waitOutput(out, Pattern.quote(getResource("help.list.summary")) + "\n\n" +
-                            Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/list ");
-            inputSink.write("\011");
-            waitOutput(out, Pattern.quote(getResource("help.list").replaceAll("\t", "    ")));
-
-            inputSink.write("\u0003/env \011");
-            waitOutput(out, "\u0005/env -\n" +
-                            "-add-exports    -add-modules    -class-path     -module-path    \n" +
-                            "\r\u0005/env -");
-
-            inputSink.write("\011");
-            waitOutput(out, "-add-exports    -add-modules    -class-path     -module-path    \n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n" +
-                            "\r\u0005/env -");
-
-            inputSink.write("\011");
-            waitOutput(out, Pattern.quote(getResource("help.env.summary")) + "\n\n" +
-                            Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
-                            "\r\u0005/env -");
-
-            inputSink.write("\011");
-            waitOutput(out, Pattern.quote(getResource("help.env").replaceAll("\t", "    ")) + "\n" +
-                            "\r\u0005/env -");
-
-            inputSink.write("\011");
-            waitOutput(out, "-add-exports    -add-modules    -class-path     -module-path    \n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n" +
-                            "\r\u0005/env -");
-
-            inputSink.write("\u0003/exit \011");
-            waitOutput(out, Pattern.quote(getResource("help.exit.summary")) + "\n\n" +
-                            Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/exit ");
-            inputSink.write("\011");
-            waitOutput(out, Pattern.quote(getResource("help.exit")) + "\n" +
-                            "\r\u0005/exit ");
-            inputSink.write("\011");
-            waitOutput(out, Pattern.quote(getResource("help.exit.summary")) + "\n\n" +
-                            Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/exit ");
-            inputSink.write("\u0003/doesnotexist\011");
-            waitOutput(out, "\u0005/doesnotexist\n" +
-                            Pattern.quote(getResource("jshell.console.no.such.command")) + "\n" +
-                            "\n" +
-                            "\r\u0005/doesnotexist");
-        });
-    }
-
-    public void testExpression() throws Exception {
-        Path classes = prepareZip();
-        doRunTest((inputSink, out) -> {
-            inputSink.write("/env -class-path " + classes.toString() + "\n");
-            waitOutput(out, Pattern.quote(getResource("jshell.msg.set.restore")) + "\n\u0005");
-            inputSink.write("import jshelltest.*;\n");
-            waitOutput(out, "\n\u0005");
-
-            //-> <tab>
-            inputSink.write("\011");
-            waitOutput(out, getMessage("jshell.console.completion.all.completions.number", "[0-9]+"));
-            inputSink.write("\011");
-            waitOutput(out, ".*String.*StringBuilder.*\n\r\u0005");
-
-            //new JShellTes<tab>
-            inputSink.write("new JShellTes\011");
-            waitOutput(out, "t\nJShellTest\\(      JShellTestAux\\(   \n\r\u0005new JShellTest");
-
-            //new JShellTest<tab>
-            inputSink.write("\011");
-            waitOutput(out, "JShellTest\\(      JShellTestAux\\(   \n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
-                            "jshelltest.JShellTest\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
-                            "\r\u0005new JShellTest");
-            inputSink.write("\011");
-            waitOutput(out, "jshelltest.JShellTest\n" +
-                            "JShellTest 0\n" +
-                            "\r\u0005new JShellTest");
-            inputSink.write("\011");
-            waitOutput(out, "JShellTest\\(      JShellTestAux\\(   \n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
-                            "jshelltest.JShellTest\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
-                            "\r\u0005new JShellTest");
-
-            //new JShellTest(<tab>
-            inputSink.write("(\011");
-            waitOutput(out, "\\(\n" +
-                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
-                            "JShellTest\\(String str\\)\n" +
-                            "JShellTest\\(String str, int i\\)\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
-                            "\r\u0005new JShellTest\\(");
-            inputSink.write("\011");
-            waitOutput(out, "JShellTest\\(String str\\)\n" +
-                            "JShellTest 1\n" +
-                            "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.next.page")) + "\n" +
-                            "\r\u0005new JShellTest\\(");
-            inputSink.write("\011");
-            waitOutput(out, "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.next.javadoc")) + "\n" +
-                            "\r\u0005new JShellTest\\(");
-            inputSink.write("\011");
-            waitOutput(out, "JShellTest\\(String str, int i\\)\n" +
-                            "JShellTest 2\n" +
-                            "\n" +
-                            getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + "\n" +
-                            "\r\u0005new JShellTest\\(");
-            inputSink.write("\011");
-            waitOutput(out, ".*String.*StringBuilder.*\n\r\u0005new JShellTest\\(");
-
-            inputSink.write("\u0003String str = \"\";\nnew JShellTest(");
-            waitOutput(out, "\u0005new JShellTest\\(");
-
-            inputSink.write("\011");
-            waitOutput(out, "\n" +
-                            "str   \n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
-                            "JShellTest\\(String str\\)\n" +
-                            "JShellTest\\(String str, int i\\)\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
-                            "\r\u0005new JShellTest\\(");
-            inputSink.write("\011");
-            waitOutput(out, "JShellTest\\(String str\\)\n" +
-                            "JShellTest 1\n" +
-                            "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.next.page")) + "\n" +
-                            "\r\u0005new JShellTest\\(");
-            inputSink.write("\011");
-            waitOutput(out, "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.next.javadoc")) + "\n" +
-                            "\r\u0005new JShellTest\\(");
-            inputSink.write("\011");
-            waitOutput(out, "JShellTest\\(String str, int i\\)\n" +
-                            "JShellTest 2\n" +
-                            "\n" +
-                            getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + "\n" +
-                            "\r\u0005new JShellTest\\(");
-            inputSink.write("\011");
-            waitOutput(out, ".*String.*StringBuilder.*\n\r\u0005new JShellTest\\(");
-
-            inputSink.write("\u0003JShellTest t = new JShellTest\011");
-            waitOutput(out, "\u0005JShellTest t = new JShellTest\n" +
-                            "JShellTest\\(   \n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.completion.current.signatures")) + "\n" +
-                            "jshelltest.JShellTest\n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.completion.all.completions")) + "\n" +
-                            "\r\u0005JShellTest t = new JShellTest");
-            inputSink.write("\011");
-            waitOutput(out, "JShellTest\\(      JShellTestAux\\(   \n" +
-                            "\n" +
-                            Pattern.quote(getResource("jshell.console.see.documentation")) + "\n" +
-                            "\r\u0005JShellTest t = new JShellTest");
-
-            inputSink.write("\u0003JShellTest t = new \011");
-            waitOutput(out, "\u0005JShellTest t = new \n" +
-                            "JShellTest\\(   \n" +
-                            "\n" +
-                            getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + "\n" +
-                            "\r\u0005JShellTest t = new ");
-            inputSink.write("\011");
-            waitOutput(out, ".*String.*StringBuilder.*\n\r\u0005JShellTest t = new ");
-
-            inputSink.write("\u0003class JShelX{}\n");
-            inputSink.write("new JShel\011");
-            waitOutput(out, "\u0005new JShel\n" +
-                            "JShelX\\(\\)         JShellTest\\(      JShellTestAux\\(   \n" +
-                            "\r\u0005new JShel");
-
-            //no crash:
-            inputSink.write("\u0003new Stringbuil\011");
-            waitOutput(out, "\u0005new Stringbuil\u0007");
-        });
-    }
-
-    private Path prepareZip() {
-        String clazz1 =
-                "package jshelltest;\n" +
-                "/**JShellTest 0" +
-                " */\n" +
-                "public class JShellTest {\n" +
-                "    /**JShellTest 1\n" +
-                "     * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" +
-                "     * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" +
-                "     * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" +
-                "     */\n" +
-                "    public JShellTest(String str) {}\n" +
-                "    /**JShellTest 2" +
-                "     */\n" +
-                "    public JShellTest(String str, int i) {}\n" +
-                "}\n";
-
-        String clazz2 =
-                "package jshelltest;\n" +
-                "/**JShellTestAux 0" +
-                " */\n" +
-                "public class JShellTestAux {\n" +
-                "    /**JShellTest 1" +
-                "     */\n" +
-                "    public JShellTestAux(String str) { }\n" +
-                "    /**JShellTest 2" +
-                "     */\n" +
-                "    public JShellTestAux(String str, int i) { }\n" +
-                "}\n";
-
-        Path srcZip = Paths.get("src.zip");
-
-        try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(srcZip))) {
-            out.putNextEntry(new JarEntry("jshelltest/JShellTest.java"));
-            out.write(clazz1.getBytes());
-            out.putNextEntry(new JarEntry("jshelltest/JShellTestAux.java"));
-            out.write(clazz2.getBytes());
-        } catch (IOException ex) {
-            throw new IllegalStateException(ex);
-        }
-
-        compiler.compile(clazz1, clazz2);
-
-        try {
-            Field availableSources = Class.forName("jdk.jshell.SourceCodeAnalysisImpl").getDeclaredField("availableSourcesOverride");
-            availableSources.setAccessible(true);
-            availableSources.set(null, Arrays.asList(srcZip));
-        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException | ClassNotFoundException ex) {
-            throw new IllegalStateException(ex);
-        }
-
-        return compiler.getClassDir();
-    }
-    //where:
-        private final Compiler compiler = new Compiler();
-
-    private final ResourceBundle resources;
-    {
-        resources = ResourceBundle.getBundle("jdk.internal.jshell.tool.resources.l10n", Locale.US, JShell.class.getModule());
-    }
-
-    private String getResource(String key) {
-        return resources.getString(key);
-    }
-
-    private String getMessage(String key, Object... args) {
-        return MessageFormat.format(resources.getString(key), args);
-    }
-
-}
--- a/test/jdk/jshell/UITesting.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/jdk/jshell/UITesting.java	Thu Apr 27 17:16:25 2017 +0100
@@ -27,13 +27,16 @@
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
 import java.io.Writer;
+import java.text.MessageFormat;
 import java.util.HashMap;
 import java.util.Locale;
+import java.util.ResourceBundle;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import jdk.jshell.JShell;
 import jdk.jshell.tool.JavaShellToolBuilder;
 
 public class UITesting {
@@ -52,6 +55,14 @@
                     out.notifyAll();
                 }
             }
+            @Override public void write(byte[] b, int off, int len) throws IOException {
+                synchronized (out) {
+                    String data = new String(b, off, len);
+                    System.out.print(data);
+                    out.append(data);
+                    out.notifyAll();
+                }
+            }
         });
         Thread runner = new Thread(() -> {
             try {
@@ -168,6 +179,18 @@
         return result.toString();
     }
 
+    private final ResourceBundle resources;
+    {
+        resources = ResourceBundle.getBundle("jdk.internal.jshell.tool.resources.l10n", Locale.US, JShell.class.getModule());
+    }
+
+    protected String getResource(String key) {
+        return resources.getString(key);
+    }
+
+    protected String getMessage(String key, Object... args) {
+        return MessageFormat.format(resources.getString(key), args);
+    }
     private static class PipeInputStream extends InputStream {
 
         private static final int INITIAL_SIZE = 128;
--- a/test/tools/doclint/ProvidesTest.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/doclint/ProvidesTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -10,20 +10,20 @@
 /**
  * Invalid use of provides in class documentation.
  *
- * @provides UsesTest
+ * @provides NotFound
  */
 public class ProvidesTest {
     /**
      * Invalid use of provides in field documentation
      *
-     * @provides UsesTest Test description.
+     * @provides NotFound Test description.
      */
     public int invalid_param;
 
     /**
      * Invalid use of provides in method documentation
      *
-     * @provides UsesTest Test description.
+     * @provides NotFound Test description.
      */
     public class InvalidParam { }
 }
--- a/test/tools/doclint/ProvidesTest.out	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/doclint/ProvidesTest.out	Thu Apr 27 17:16:25 2017 +0100
@@ -1,28 +1,28 @@
 ProvidesTest.java:13: error: invalid use of @provides
- * @provides UsesTest
+ * @provides NotFound
    ^
 ProvidesTest.java:13: error: service-type not found
- * @provides UsesTest
+ * @provides NotFound
    ^
 ProvidesTest.java:13: error: reference not found
- * @provides UsesTest
+ * @provides NotFound
              ^
 ProvidesTest.java:19: error: invalid use of @provides
-     * @provides UsesTest Test description.
+     * @provides NotFound Test description.
        ^
 ProvidesTest.java:19: error: service-type not found
-     * @provides UsesTest Test description.
+     * @provides NotFound Test description.
        ^
 ProvidesTest.java:19: error: reference not found
-     * @provides UsesTest Test description.
+     * @provides NotFound Test description.
                  ^
 ProvidesTest.java:26: error: invalid use of @provides
-     * @provides UsesTest Test description.
+     * @provides NotFound Test description.
        ^
 ProvidesTest.java:26: error: service-type not found
-     * @provides UsesTest Test description.
+     * @provides NotFound Test description.
        ^
 ProvidesTest.java:26: error: reference not found
-     * @provides UsesTest Test description.
+     * @provides NotFound Test description.
                  ^
 9 errors
--- a/test/tools/doclint/UsesTest.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/doclint/UsesTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -10,20 +10,20 @@
 /**
  * Invalid use of uses in class documentation.
  *
- * @uses ProvidesTest
+ * @uses NotFound
  */
 public class UsesTest {
     /**
      * Invalid use of uses in field documentation
      *
-     * @uses ProvidesTest Test description.
+     * @uses NotFound Test description.
      */
     public int invalid_param;
 
     /**
      * Invalid use of uses in method documentation
      *
-     * @uses ProvidesTest Test description.
+     * @uses NotFound Test description.
      */
     public class InvalidParam { }
 }
--- a/test/tools/doclint/UsesTest.out	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/doclint/UsesTest.out	Thu Apr 27 17:16:25 2017 +0100
@@ -1,28 +1,28 @@
 UsesTest.java:13: error: invalid use of @uses
- * @uses ProvidesTest
+ * @uses NotFound
    ^
 UsesTest.java:13: error: service-type not found
- * @uses ProvidesTest
+ * @uses NotFound
    ^
 UsesTest.java:13: error: reference not found
- * @uses ProvidesTest
+ * @uses NotFound
          ^
 UsesTest.java:19: error: invalid use of @uses
-     * @uses ProvidesTest Test description.
+     * @uses NotFound Test description.
        ^
 UsesTest.java:19: error: service-type not found
-     * @uses ProvidesTest Test description.
+     * @uses NotFound Test description.
        ^
 UsesTest.java:19: error: reference not found
-     * @uses ProvidesTest Test description.
+     * @uses NotFound Test description.
              ^
 UsesTest.java:26: error: invalid use of @uses
-     * @uses ProvidesTest Test description.
+     * @uses NotFound Test description.
        ^
 UsesTest.java:26: error: service-type not found
-     * @uses ProvidesTest Test description.
+     * @uses NotFound Test description.
        ^
 UsesTest.java:26: error: reference not found
-     * @uses ProvidesTest Test description.
+     * @uses NotFound Test description.
              ^
 9 errors
--- a/test/tools/javac/api/TestClientCodeWrapper.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/javac/api/TestClientCodeWrapper.java	Thu Apr 27 17:16:25 2017 +0100
@@ -62,7 +62,7 @@
             defaultFileManager = fm;
 
             for (Method m: getMethodsExcept(JavaFileManager.class,
-                        "close", "getJavaFileForInput", "getLocationForModule", "getServiceLoader")) {
+                        "close", "getJavaFileForInput", "getLocationForModule", "getServiceLoader", "contains")) {
                 test(m);
             }
 
@@ -424,6 +424,12 @@
             return super.listLocationsForModules(location);
         }
 
+        @Override
+        public boolean contains(Location location, FileObject fo) throws IOException {
+            throwUserExceptionIfNeeded(fileManagerMethod, "contains");
+            return super.contains(location, fo);
+        }
+
         public FileObject wrap(FileObject fo) {
             if (fileObjectMethod == null || fo == null)
                 return fo;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/FileShouldBeOnSourcePathOrPatchPath/FileShouldBeOnSourcePathOrModulePath.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+//key: compiler.err.file.sb.on.source.or.patch.path.for.module
+
+public class FileShouldBeOnSourcePathOrModulePath {
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/FileShouldBeOnSourcePathOrPatchPath/sourcepath/module-info.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+module m { }
+
--- a/test/tools/javac/file/ModuleAndPackageLocations.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/javac/file/ModuleAndPackageLocations.java	Thu Apr 27 17:16:25 2017 +0100
@@ -117,7 +117,6 @@
             assertRefused(() -> fm.getJavaFileForOutput(StandardLocation.MODULE_SOURCE_PATH, "", Kind.SOURCE, null));
             assertRefused(() -> fm.getLocationForModule(StandardLocation.SOURCE_PATH, "test"));
             JavaFileObject out = fm.getJavaFileForInput(StandardLocation.CLASS_OUTPUT, "test.Test", Kind.CLASS);
-            assertRefused(() -> fm.getLocationForModule(StandardLocation.SOURCE_PATH, out));
             assertRefused(() -> fm.inferBinaryName(StandardLocation.MODULE_PATH, out));
             assertRefused(() -> fm.inferModuleName(StandardLocation.MODULE_SOURCE_PATH));
             assertRefused(() -> fm.list(StandardLocation.MODULE_SOURCE_PATH, "test", EnumSet.allOf(Kind.class), false));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/file/SymLinkTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014, 2017, 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
+ * @bug 8178017
+ * @summary JDK 9 change to symlink handling causes misleading
+ *      class.public.should.be.in.file diagnostic
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox
+ * @run main SymLinkTest
+ */
+
+import java.io.IOException;
+import java.nio.file.FileSystemException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.JavacTask;
+import toolbox.TestRunner;
+import toolbox.TestRunner.Test;
+import toolbox.ToolBox;
+
+public class SymLinkTest extends TestRunner {
+    public static void main(String... args) throws Exception {
+        new SymLinkTest().runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    private final ToolBox tb = new ToolBox();
+
+    public SymLinkTest() {
+        super(System.err);
+    }
+
+    @Test
+    public void testgetKind(Path base) throws IOException {
+        test(base, "SOURCE");
+    }
+
+    @Test
+    public void testSymLink(Path base) throws IOException {
+        test(base, "SOURCE.java");
+    }
+
+    void test(Path base, String name) throws IOException {
+        Path file = base.resolve(name);
+        Path javaFile = base.resolve("HelloWorld.java");
+        tb.writeFile(file,
+                "public class HelloWorld {\n"
+                + "    public static void main(String... args) {\n"
+                + "        System.err.println(\"Hello World!\");\n"
+                + "    }\n"
+                + "}");
+
+        try {
+            Files.createSymbolicLink(javaFile, file.getFileName());
+        } catch (FileSystemException fse) {
+            System.err.println("warning: test passes vacuously, sym-link could not be created");
+            System.err.println(fse.getMessage());
+            return;
+        }
+
+        Path classes = Files.createDirectories(base.resolve("classes"));
+        new JavacTask(tb)
+            .outdir(classes)
+            .files(javaFile)
+            .run()
+            .writeAll();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/ContainsTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017, 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
+ * @bug 8178518
+ * @summary Add method JavaFileManager.contains
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase
+ * @run main ContainsTest
+ */
+
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.EnumSet;
+import java.util.List;
+
+import javax.tools.FileObject;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import toolbox.JarTask;
+import toolbox.JavacTask;
+
+public class ContainsTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        ContainsTest t = new ContainsTest();
+        t.runTests();
+    }
+
+    JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+
+    @Test
+    public void testSimplePath(Path base) throws IOException {
+        // Test that we can look up in directories in the default file system.
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package p; class C { }");
+        Path c = src.resolve("p/C.java");
+        Path x = base.resolve("src2/p/C.java");
+        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+            fm.setLocationFromPaths(StandardLocation.SOURCE_PATH, List.of(src));
+            checkContains(fm, StandardLocation.SOURCE_PATH, c, true);
+            checkContains(fm, StandardLocation.SOURCE_PATH, x, false);
+        }
+    }
+
+    @Test
+    public void testJarPath(Path base) throws IOException {
+        // Test that we can look up in jar files on a search path.
+        // In this case, the path we look up must come from open file system
+        // as used by the file manager.
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package p; class C { }");
+        Path classes = Files.createDirectories(base.resolve("classes"));
+        new JavacTask(tb)
+            .options("-sourcepath", src.toString())
+            .outdir(classes)
+            .files(findJavaFiles(src))
+            .run()
+            .writeAll();
+
+        Path jar = base.resolve("classes.jar");
+        new JarTask(tb).run("cf", jar.toString(), "-C", classes.toString(), "p");
+
+        Path c = src.resolve("p/C.java");
+        Path x = base.resolve("src2/p/C.java");
+
+        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+            fm.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(src, jar));
+
+            checkContains(fm, StandardLocation.CLASS_PATH, c, true);
+            checkContains(fm, StandardLocation.CLASS_PATH, x, false);
+
+            JavaFileObject fo = fm.list(StandardLocation.CLASS_PATH, "p",
+                    EnumSet.of(JavaFileObject.Kind.CLASS), false).iterator().next();
+
+            checkContains(fm, StandardLocation.CLASS_PATH, fo, true);
+        }
+    }
+
+    @Test
+    public void testJarFSPath(Path base) throws IOException {
+        // Test that we can look up in non-default file systems on the search path,
+        // such as an open jar file system.
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package p; class C { }");
+        Path classes = Files.createDirectories(base.resolve("classes"));
+        new JavacTask(tb)
+            .options("-sourcepath", src.toString())
+            .outdir(classes)
+            .files(findJavaFiles(src))
+            .run()
+            .writeAll();
+
+        Path jar = base.resolve("classes.jar");
+        new JarTask(tb).run("cf", jar.toString(), "-C", classes.toString(), "p");
+
+        Path c = src.resolve("p/C.java");
+        Path x = base.resolve("src2/p/C.java");
+
+        try (FileSystem jarFS = FileSystems.newFileSystem(jar, null);
+                StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+            Path jarRoot = jarFS.getRootDirectories().iterator().next();
+            fm.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(src, jarRoot));
+
+            checkContains(fm, StandardLocation.CLASS_PATH, c, true);
+            checkContains(fm, StandardLocation.CLASS_PATH, x, false);
+
+            JavaFileObject fo = fm.list(StandardLocation.CLASS_PATH, "p",
+                    EnumSet.of(JavaFileObject.Kind.CLASS), false).iterator().next();
+
+            checkContains(fm, StandardLocation.CLASS_PATH, fo, true);
+            checkContains(fm, StandardLocation.CLASS_PATH, jarRoot.resolve("p/C.class"), true);
+        }
+    }
+
+    void checkContains(StandardJavaFileManager fm, Location l, Path p, boolean expect) throws IOException {
+        JavaFileObject fo = fm.getJavaFileObjects(p).iterator().next();
+        checkContains(fm, l, fo, expect);
+    }
+
+    void checkContains(StandardJavaFileManager fm, Location l, FileObject fo, boolean expect) throws IOException {
+        boolean found = fm.contains(l, fo);
+        if (found) {
+            if (expect) {
+                out.println("file found, as expected: " + l + " " + fo.getName());
+            } else {
+                error("file not found: " + l + " " + fo.getName());
+            }
+        } else {
+            if (expect) {
+                error("file found unexpectedly: " + l + " " + fo.getName());
+            } else {
+                out.println("file not found, as expected: " + l + " " + fo.getName());
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/LegacyXModuleTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, 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
+ * @bug 8178012
+ * @summary tests for multi-module mode compilation
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
+ * @run main LegacyXModuleTest
+ */
+
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+
+public class LegacyXModuleTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new LegacyXModuleTest().runTests();
+    }
+
+    @Test
+    public void testLegacyXModule(Path base) throws Exception {
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package com.sun.tools.javac.comp; public class Extra { Modules modules; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+            .options("-XD-Xmodule:jdk.compiler")
+            .outdir(classes)
+            .files(findJavaFiles(src))
+            .run()
+            .writeAll()
+            .getOutput(Task.OutputKind.DIRECT);
+
+        List<String> log = new JavacTask(tb)
+                .options("-XD-Xmodule:java.compiler",
+                         "-XD-Xmodule:jdk.compiler",
+                         "-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> actual =
+                Arrays.asList("Extra.java:1:56: compiler.err.cant.resolve.location: kindname.class, Modules, , , " +
+                                                "(compiler.misc.location: kindname.class, com.sun.tools.javac.comp.Extra, null)",
+                              "1 error");
+
+        if (!Objects.equals(actual, log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/modules/SourcePathTest.java	Thu Apr 27 17:16:25 2017 +0100
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2017, 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
+ * @bug 8176327
+ * @summary javac produces wrong module-info
+ * @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 SourcePathTest
+ */
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.List;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+
+public class SourcePathTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        SourcePathTest t = new SourcePathTest();
+        t.runTests();
+    }
+
+    @Test
+    public void test_unnamedModuleOnSourcePath_fileNotOnPath(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package p; public class A { }");
+        Path otherSrc = base.resolve("otherSrc");
+        tb.writeJavaFiles(otherSrc, "package p2; public class B { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        new JavacTask(tb)
+            .options("-sourcepath", src.toString())
+            .outdir(classes)
+            .files(findJavaFiles(otherSrc))
+            .run()
+            .writeAll();
+
+        showFiles(classes);
+    }
+
+    @Test
+    public void test_unnamedModuleOnSourcePath_fileOnPath(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package p; public class A { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        new JavacTask(tb)
+            .options("-sourcepath", src.toString())
+            .outdir(classes)
+            .files(findJavaFiles(src))
+            .run()
+            .writeAll();
+
+        showFiles(classes);
+    }
+
+    @Test
+    public void test_namedModuleOnSourcePath_fileNotOnPath_1(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "module m { exports p; }");
+        tb.writeJavaFiles(src, "package p; public class A { }");
+        Path otherSrc = base.resolve("otherSrc");
+        tb.writeJavaFiles(otherSrc, "package p2; public class B { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+            .options("-XDrawDiagnostics=true", "-sourcepath", src.toString())
+            .outdir(classes)
+            .files(findJavaFiles(otherSrc))
+            .run(Task.Expect.FAIL)
+            .writeAll()
+            .getOutput(Task.OutputKind.DIRECT);
+
+        showFiles(classes);
+        checkOutputContains(log,
+                "B.java:1:1: compiler.err.file.sb.on.source.or.patch.path.for.module");
+    }
+
+    @Test
+    public void test_namedModuleOnSourcePath_fileNotOnPath_2(Path base) throws Exception {
+        // This is the original test case:
+        // the source path contains one module, but the file to be compiled appears to be
+        // in another module.
+        Path src = base.resolve("src");
+        Path src_mA = src.resolve("mA");
+        tb.writeJavaFiles(src_mA,
+                "module mA { exports p; }",
+                "package p; public class A { }");
+        Path src_mB = src.resolve("mB");
+        tb.writeJavaFiles(src_mB,
+                "module mA { exports p2; }",
+                "package p2; public class B { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+            .options("-XDrawDiagnostics=true", "-sourcepath", src_mA.toString())
+            .outdir(classes)
+            .files(findJavaFiles(src_mB.resolve("p2")))
+            .run(Task.Expect.FAIL)
+            .writeAll()
+            .getOutput(Task.OutputKind.DIRECT);
+
+        showFiles(classes);
+        checkOutputContains(log,
+                "B.java:1:1: compiler.err.file.sb.on.source.or.patch.path.for.module");
+    }
+
+    @Test
+    public void test_namedModuleOnSourcePath_fileOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "module m { exports p; }");
+        tb.writeJavaFiles(src, "package p; public class A { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+            .options("-XDrawDiagnostics=true", "-sourcepath", src.toString())
+            .outdir(classes)
+            .files(findJavaFiles(src.resolve("p")))
+            .run()
+            .writeAll()
+            .getOutput(Task.OutputKind.DIRECT);
+
+        showFiles(classes);
+    }
+
+    @Test
+    public void test_namedModuleOnSourcePath_fileOnPatchPath(Path base) throws Exception {
+        // similar to test_namedModuleOnSourcePath_fileNotOnPath_1
+        // except that other src directory is not put on the patch path
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "module m { exports p; }");
+        tb.writeJavaFiles(src, "package p; public class A { }");
+        Path otherSrc = base.resolve("otherSrc");
+        tb.writeJavaFiles(otherSrc, "package p2; public class B { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+            .options("-XDrawDiagnostics=true",
+                    "-sourcepath", src.toString(),
+                    "--patch-module", "m=" + otherSrc)
+            .outdir(classes)
+            .files(findJavaFiles(otherSrc))
+            .run()
+            .writeAll()
+            .getOutput(Task.OutputKind.DIRECT);
+
+        showFiles(classes);
+    }
+
+    /*
+     * The following tests are not for the source path, but they exercise similar test
+     * cases for the module source path.
+     */
+
+    @Test
+    public void test_moduleSourcePath_fileNotOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_mA = src.resolve("mA");
+        tb.writeJavaFiles(src_mA,
+                "module mA { exports p; }",
+                "package p; public class A { }");
+        Path src_mB = src.resolve("mB");
+        tb.writeJavaFiles(src_mB,
+                "module mB { exports p2; }",
+                "package p2; public class B { }");
+        Path otherSrc = base.resolve("otherSrc");
+        tb.writeJavaFiles(otherSrc, "package p3; public class C { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+            .options("-XDrawDiagnostics=true",
+                    "--module-source-path", src.toString())
+            .outdir(classes)
+            .files(findJavaFiles(otherSrc))
+            .run(Task.Expect.FAIL)
+            .writeAll()
+            .getOutput(Task.OutputKind.DIRECT);
+
+        showFiles(classes);
+        checkOutputContains(log,
+                "C.java:1:1: compiler.err.not.in.module.on.module.source.path");
+    }
+
+    @Test
+    public void test_moduleSourcePath_fileOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_mA = src.resolve("mA");
+        tb.writeJavaFiles(src_mA,
+                "module mA { exports p; }",
+                "package p; public class A { }");
+        Path src_mB = src.resolve("mB");
+        tb.writeJavaFiles(src_mB,
+                "module mB { exports p2; }",
+                "package p2; public class B { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+            .options("-XDrawDiagnostics=true",
+                    "--module-source-path", src.toString())
+            .outdir(classes)
+            .files(findJavaFiles(src_mB.resolve("p2")))
+            .run()
+            .writeAll()
+            .getOutput(Task.OutputKind.DIRECT);
+
+        showFiles(classes);
+
+    }
+
+    @Test
+    public void test_moduleSourcePath_fileOnPatchPath(Path base) throws Exception {
+        // similar to test_moduleSourcePath_fileNotOnPath
+        // except that other src directory is not put on the patch path
+        Path src = base.resolve("src");
+        Path src_mA = src.resolve("mA");
+        tb.writeJavaFiles(src_mA,
+                "module mA { exports p; }",
+                "package p; public class A { }");
+        Path src_mB = src.resolve("mB");
+        tb.writeJavaFiles(src_mB,
+                "module mB { exports p2; }",
+                "package p2; public class B { }");
+        Path otherSrc = base.resolve("otherSrc");
+        tb.writeJavaFiles(otherSrc, "package p3; public class C { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+            .options("-XDrawDiagnostics=true",
+                    "--module-source-path", src.toString(),
+                    "--patch-module", "mA=" + otherSrc)
+            .outdir(classes)
+            .files(findJavaFiles(otherSrc))
+            .run()
+            .writeAll()
+            .getOutput(Task.OutputKind.DIRECT);
+
+        showFiles(classes);
+    }
+
+    /**
+     * This method is primarily used to give visual confirmation that a test case
+     * generated files when the compilation succeeds and so generates no other output,
+     * such as error messages.
+     */
+    List<Path> showFiles(Path dir) throws IOException {
+        List<Path> files = new ArrayList<>();
+        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+                    throws IOException {
+                if (Files.isRegularFile(file)) {
+                    out.println("Found " + file);
+                    files.add(file);
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+        return files;
+    }
+}
+
--- a/test/tools/javac/modules/T8158224/T8158224.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/javac/modules/T8158224/T8158224.java	Thu Apr 27 17:16:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -25,8 +25,41 @@
  * @test
  * @bug 8158224
  * @summary NullPointerException in com.sun.tools.javac.comp.Modules.checkCyclicDependencies when module missing
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask
  * @build Processor
- * @compile/fail/ref=T8158224.out -XDrawDiagnostics -processor Processor mods/foo/module-info.java
+ * @run main T8158224
  */
 
-// No code here, this file is just to host test description.
+// previously:
+// @compile/fail/ref=T8158224.out -XDrawDiagnostics -processor Processor mods/foo/module-info.java
+
+import java.util.List;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class T8158224 {
+    public static void main(String... args) throws Exception {
+        ToolBox tb = new ToolBox();
+
+        List<String> log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                        "-processor", "Processor",
+                        "-sourcepath", tb.testSrc + "/mods/foo",
+                        "-classpath", tb.testClasses)
+                .files(tb.testSrc + "/mods/foo/module-info.java")
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!log.equals(List.of(
+                "module-info.java:4:14: compiler.err.module.not.found: nonexistent",
+                "1 error"))) {
+            throw new Exception("Expected output not found");
+        }
+    }
+}
--- a/test/tools/javac/modules/T8158224/T8158224.out	Wed Apr 26 21:09:20 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-module-info.java:4:14: compiler.err.module.not.found: nonexistent
-1 error
--- a/test/tools/javadoc/CompletionError.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/javadoc/CompletionError.java	Thu Apr 27 17:16:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -27,8 +27,10 @@
  * @summary Check that CompletionFailures for missing classes are not incorrectly passed to
  *          the javadoc API clients.
  * @library /tools/lib
- * @modules jdk.javadoc com.sun.tools.javac.api
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.JavacTask toolbox.ToolBox
  * @run main CompletionError
  */
 
@@ -37,6 +39,9 @@
 import com.sun.javadoc.*;
 import com.sun.tools.javadoc.Main;
 
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
 public class CompletionError extends Doclet
 {
     private static final String template =
@@ -49,6 +54,9 @@
             "   public String toString() { return null; }" +
             "}";
 
+    private static final String testSrc = System.getProperty("test.src");
+    private static final String testClassPath = System.getProperty("test.class.path");
+
     public static void main(String[] args) throws Exception {
         String[] templateParts = template.split("#");
         int sources = templateParts.length / 2;
@@ -75,8 +83,8 @@
                 tb.deleteFiles("CompletionErrorMissing.class", "CompletionErrorIntfMissing.class", "CompletionErrorExcMissing.class");
                 // run javadoc:
                 if (Main.execute("javadoc", "CompletionError", CompletionError.class.getClassLoader(),
-                                 "-classpath", ".",
-                                 System.getProperty("test.src", ".") + File.separatorChar + "CompletionError.java") != 0)
+                                 "-classpath", "." + File.pathSeparator + testClassPath,
+                                 new File(testSrc, "CompletionError.java").getPath()) != 0)
                     throw new Error();
             }
         }
--- a/test/tools/lib/toolbox/ModuleBuilder.java	Wed Apr 26 21:09:20 2017 +0100
+++ b/test/tools/lib/toolbox/ModuleBuilder.java	Thu Apr 27 17:16:25 2017 +0100
@@ -45,6 +45,7 @@
     private String comment = "";
     private List<String> requires = new ArrayList<>();
     private List<String> exports = new ArrayList<>();
+    private List<String> opens = new ArrayList<>();
     private List<String> uses = new ArrayList<>();
     private List<String> provides = new ArrayList<>();
     private List<String> content = new ArrayList<>();
@@ -134,33 +135,6 @@
     }
 
     /**
-     * Adds an unqualified "exports dynamic" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @return this builder
-     */
-    public ModuleBuilder exportsDynamic(String pkg) {
-        return addDirective(exports, "exports dynamic " + pkg + ";");
-    }
-
-    /**
-     * Adds an unqualified "exports private" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @return this builder
-     */
-    public ModuleBuilder exportsPrivate(String pkg) {
-        return addDirective(exports, "exports private " + pkg + ";");
-    }
-
-    /**
-     * Adds an unqualified "exports dynamic private" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @return this builder
-     */
-    public ModuleBuilder exportsDynamicPrivate(String pkg) {
-        return addDirective(exports, "exports dynamic private " + pkg + ";");
-    }
-
-    /**
      * Adds a qualified "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
@@ -171,33 +145,22 @@
     }
 
     /**
-     * Adds a qualified "exports dynamic" 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
+     * Adds an unqualified "opens" directive to the declaration.
+     * @param pkg the name of the package to be opened
      * @return this builder
      */
-    public ModuleBuilder exportsDynamicTo(String pkg, String module) {
-        return addDirective(exports, "exports dynamic " + pkg + " to " + module + ";");
+    public ModuleBuilder opens(String pkg) {
+        return addDirective(opens, "opens " + pkg + ";");
     }
 
     /**
-     * Adds a qualified "exports private" 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
+     * Adds a qualified "opens" directive to the declaration.
+     * @param pkg the name of the package to be opened
+     * @param module the name of the module to which it is to be opened
      * @return this builder
      */
-    public ModuleBuilder exportsPrivateTo(String pkg, String module) {
-        return addDirective(exports, "exports private " + pkg + " to " + module + ";");
-    }
-
-    /**
-     * Adds a qualified "exports dynamic private" 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 exportsDynamicPrivateTo(String pkg, String module) {
-        return addDirective(exports, "exports dynamic private " + pkg + " to " + module + ";");
+    public ModuleBuilder opensTo(String pkg, String module) {
+        return addDirective(opens, "opens " + pkg + " to " + module + ";");
     }
 
     /**
@@ -254,6 +217,7 @@
         sb.append("module ").append(name).append(" {\n");
         requires.forEach(r -> sb.append("    " + r + "\n"));
         exports.forEach(e -> sb.append("    " + e + "\n"));
+        opens.forEach(o -> sb.append("    " + o + "\n"));
         uses.forEach(u -> sb.append("    " + u + "\n"));
         provides.forEach(p -> sb.append("    " + p + "\n"));
         sb.append("}");