changeset 4860:166097231ebe

Merge
author alanb
date Thu, 06 Apr 2017 18:56:04 +0100
parents a564c0126103 77a4b2e2e5be
children ff80ebf4ace6
files .hgtags make/CompileInterim.gmk make/build.properties make/build.xml src/java.compiler/share/classes/module-info.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java src/jdk.compiler/share/classes/module-info.java 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 src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties src/jdk.javadoc/share/classes/module-info.java src/jdk.jdeps/share/classes/module-info.java src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java src/jdk.jshell/share/classes/module-info.java test/jdk/jshell/CommandCompletionTest.java test/tools/javac/modules/EdgeCases.java
diffstat 40 files changed, 1601 insertions(+), 547 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Apr 04 22:09:23 2017 -0700
+++ b/.hgtags	Thu Apr 06 18:56:04 2017 +0100
@@ -408,3 +408,4 @@
 2340259b31554a3761e9909953c8ab8ef124ac07 jdk-9+161
 440c45c2e8cee78f6883fa6f2505a781505f323c jdk-9+162
 24582dd2649a155876de89273975ebe1adb5f18c jdk-9+163
+c7f3df19667b093538c6eecb73dcb3fb531706b4 jdk-9+164
--- a/make/CompileInterim.gmk	Tue Apr 04 22:09:23 2017 -0700
+++ b/make/CompileInterim.gmk	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -47,7 +47,8 @@
           $$(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$(strip $1)), \
       EXCLUDES := sun com/sun/tools/jdeps com/sun/tools/javap \
           com/sun/tools/jdeprscan, \
-      EXCLUDE_FILES := module-info.java JavacToolProvider.java JavadocToolProvider.java, \
+      EXCLUDE_FILES := module-info.java JavacToolProvider.java \
+	  JavadocToolProvider.java Standard.java, \
       COPY := .gif .png .xml .css .js javax.tools.JavaCompilerTool, \
       BIN := $(BUILDTOOLS_OUTPUTDIR)/override_modules/$(strip $1), \
       ADD_JAVAC_FLAGS := -Xbootclasspath/p:$$(call PathList, \
--- a/make/build.properties	Tue Apr 04 22:09:23 2017 -0700
+++ b/make/build.properties	Thu Apr 06 18:56:04 2017 +0100
@@ -56,7 +56,7 @@
 tool.javap.main.class=com.sun.tools.javap.Main
 tool.javah.main.class=com.sun.tools.javah.Main
 tool.sjavac.main.class=com.sun.tools.sjavac.Main
-tool.jshell.main.class=jdk.internal.jshell.tool.JShellTool
+tool.jshell.main.class=jdk.internal.jshell.tool.JShellToolProvider
 
 #test configuration:
 jtreg.tests=
--- a/make/build.xml	Tue Apr 04 22:09:23 2017 -0700
+++ b/make/build.xml	Thu Apr 06 18:56:04 2017 +0100
@@ -89,16 +89,22 @@
     </pathconvert>
 
     <pathconvert property="xpatch.rest" pathsep=" --patch-module=">
-        <regexpmapper from="/([^$/]+)$"
-                      to='\1="${build.modules}/\1"'
-                      handledirsep="yes"/>
+        <scriptmapper language="javascript">
+            fs = project.getProperty("file.separator");
+            path = project.getProperty("build.modules");
+            mod = source.substr(source.lastIndexOf(fs)+1);
+            self.addMappedName(mod + "=\"" + path + fs + mod + "\"");
+        </scriptmapper>
         <dirset dir="${src.dir}" includes="*.*"/>
     </pathconvert>
 
     <pathconvert property="xpatch.noquotes.rest" pathsep=" --patch-module=">
-        <regexpmapper from="/([^$/]+)$"
-                      to="\1=${build.modules}/\1"
-                      handledirsep="yes"/>
+        <scriptmapper language="javascript">
+            fs = project.getProperty("file.separator");
+            path = project.getProperty("build.modules");
+            mod = source.substr(source.lastIndexOf(fs)+1);
+            self.addMappedName(mod + "=" + path + fs + mod);
+        </scriptmapper>
         <dirset dir="${src.dir}" includes="*.*"/>
     </pathconvert>
 
@@ -341,7 +347,7 @@
             <attribute name="agentvm" default="true"/>
             <attribute name="verbose" default="${default.jtreg.verbose}"/>
             <attribute name="options" default="${other.jtreg.options}"/>
-            <attribute name="keywords" default="-keywords:!ignore"/>
+            <attribute name="ignore" default="-keywords:!ignore -exclude:${test.dir}/ProblemList.txt"/>
             <attribute name="jpda.jvmargs" default=""/>
             <attribute name="extra.jvmargs" default=""/>
             <attribute name="build.modules" default="${build.modules}"/>
@@ -360,7 +366,7 @@
                     failonerror="false" resultproperty="jtreg.@{name}.result"
                     vmoptions="${coverage.options} @{extra.jvmargs} ${xpatch.noquotes.cmd}">
                     <arg value="-debug:@{jpda.jvmargs}"/>
-                    <arg line="@{keywords}"/>
+                    <arg line="@{ignore}"/>
                     <arg line="@{options}"/>
                     <arg line="@{tests}"/>
                 </jtreg>
--- a/make/intellij/runConfigurations/javadoc.xml	Tue Apr 04 22:09:23 2017 -0700
+++ b/make/intellij/runConfigurations/javadoc.xml	Thu Apr 06 18:56:04 2017 +0100
@@ -1,8 +1,8 @@
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="javadoc" type="Application" factoryName="Application">
     <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
-    <option name="MAIN_CLASS_NAME" value="com.sun.tools.javadoc.Main" />
-    <option name="VM_PARAMETERS" value='@XPATCH@' />
+    <option name="MAIN_CLASS_NAME" value="jdk.javadoc.internal.tool.Main" />
+    <option name="VM_PARAMETERS" value='@XPATCH@ --add-exports=jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED' />
     <option name="PROGRAM_PARAMETERS" value="" />
     <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
     <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
--- a/make/intellij/runConfigurations/jshell.xml	Tue Apr 04 22:09:23 2017 -0700
+++ b/make/intellij/runConfigurations/jshell.xml	Thu Apr 06 18:56:04 2017 +0100
@@ -1,7 +1,7 @@
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="jshell" type="Application" factoryName="Application">
     <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
-    <option name="MAIN_CLASS_NAME" value="jdk.internal.jshell.tool.JShellTool" />
+    <option name="MAIN_CLASS_NAME" value="jdk.internal.jshell.tool.JShellToolProvider" />
     <option name="VM_PARAMETERS" value='@XPATCH@ --add-exports=jdk.jshell/jdk.internal.jshell.tool=ALL-UNNAMED' />
     <option name="PROGRAM_PARAMETERS" value="" />
     <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.compiler/share/classes/javax/annotation/processing/Generated.java	Thu Apr 06 18:56:04 2017 +0100
@@ -0,0 +1,81 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package javax.annotation.processing;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * The Generated annotation is used to mark source code that has been generated.
+ * It can also be used to differentiate user written code from generated code in
+ * a single file.
+ *
+ * <h3>Examples:</h3>
+ * <pre>
+ *   &#064;Generated("com.example.Generator")
+ * </pre>
+ * <pre>
+ *   &#064;Generated(value="com.example.Generator", date= "2017-07-04T12:08:56.235-0700")
+ * </pre>
+ * <pre>
+ *   &#064;Generated(value="com.example.Generator", date= "2017-07-04T12:08:56.235-0700",
+ *      comments= "comment 1")
+ * </pre>
+ *
+ * @since 9
+ */
+@Documented
+@Retention(SOURCE)
+@Target({PACKAGE, TYPE, METHOD, CONSTRUCTOR, FIELD,
+    LOCAL_VARIABLE, PARAMETER})
+public @interface Generated {
+
+    /**
+     * The value element MUST have the name of the code generator. The
+     * name is the fully qualified name of the code generator.
+     *
+     * @return The name of the code generator
+     */
+    String[] value();
+
+    /**
+     * Date when the source was generated. The date element must follow the ISO
+     * 8601 standard. For example the date element would have the following
+     * value 2017-07-04T12:08:56.235-0700 which represents 2017-07-04 12:08:56
+     * local time in the U.S. Pacific Time time zone.
+     *
+     * @return The date the source was generated
+     */
+    String date() default "";
+
+    /**
+     * A place holder for any comments that the code generator may want to
+     * include in the generated code.
+     *
+     * @return Comments that the code generated included
+     */
+    String comments() default "";
+}
--- a/src/java.compiler/share/classes/module-info.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/java.compiler/share/classes/module-info.java	Thu Apr 06 18:56:04 2017 +0100
@@ -30,6 +30,7 @@
   * and define interfaces for tools such as compilers which can be invoked
   * from a program.
   *
+  * @moduleGraph
   * @since 9
   */
 module java.compiler {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Apr 06 18:56:04 2017 +0100
@@ -334,7 +334,10 @@
                     currModule.complete();
                     PackageSymbol p = c.packge();
                     isAccessible =
-                        (currModule == p.modle) || currModule.visiblePackages.get(p.fullname) == p || p == syms.rootPackage;
+                        currModule == p.modle ||
+                        currModule.visiblePackages.get(p.fullname) == p ||
+                        p == syms.rootPackage ||
+                        (p.modle == syms.unnamedModule && currModule.readModules.contains(p.modle));
                 } else {
                     isAccessible = true;
                 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java	Thu Apr 06 18:56:04 2017 +0100
@@ -186,37 +186,12 @@
                         Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
                 Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
                 Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
-                return ensureReadable(constr.newInstance(urls, thisClassLoader));
+                return constr.newInstance(urls, thisClassLoader);
             } catch (ReflectiveOperationException t) {
                 // ignore errors loading user-provided class loader, fall through
             }
         }
-        return ensureReadable(new URLClassLoader(urls, thisClassLoader));
-    }
-
-    /**
-     * Ensures that the unnamed module of the given classloader is readable to this
-     * module.
-     */
-    private ClassLoader ensureReadable(ClassLoader targetLoader) {
-        try {
-            Method getModuleMethod = Class.class.getMethod("getModule");
-            Object thisModule = getModuleMethod.invoke(this.getClass());
-            Method getUnnamedModuleMethod = ClassLoader.class.getMethod("getUnnamedModule");
-            Object targetModule = getUnnamedModuleMethod.invoke(targetLoader);
-
-            Class<?> moduleClass = getModuleMethod.getReturnType();
-            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
-            addReadsMethod.invoke(thisModule, targetModule);
-        } catch (NoSuchMethodException e) {
-            // ignore
-        } catch (IllegalAccessException
-                | IllegalArgumentException
-                | SecurityException
-                | InvocationTargetException e) {
-            throw new Abort(e);
-        }
-        return targetLoader;
+        return new URLClassLoader(urls, thisClassLoader);
     }
 
     public boolean isDefaultBootClassPath() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Thu Apr 06 18:56:04 2017 +0100
@@ -39,6 +39,7 @@
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
@@ -283,23 +284,14 @@
     }
 
     /**
-     * Processes strings containing options and operands.
-     * @param args the strings to be processed
-     * @param allowableOpts the set of option declarations that are applicable
-     * @param helper a help for use by Option.process
-     * @param allowOperands whether or not to check for files and classes
-     * @param checkFileManager whether or not to check if the file manager can handle
-     *      options which are not recognized by any of allowableOpts
-     * @return true if all the strings were successfully processed; false otherwise
-     * @throws IllegalArgumentException if a problem occurs and errorMode is set to
-     *      ILLEGAL_ARGUMENT
+     * Handles the {@code --release} option.
+     *
+     * @param additionalOptions a predicate to handle additional options implied by the
+     * {@code --release} option. The predicate should return true if all the additional
+     * options were processed successfully.
+     * @return true if successful, false otherwise
      */
-    private boolean processArgs(Iterable<String> args,
-            Set<Option> allowableOpts, OptionHelper helper,
-            boolean allowOperands, boolean checkFileManager) {
-        if (!doProcessArgs(args, allowableOpts, helper, allowOperands, checkFileManager))
-            return false;
-
+    public boolean handleReleaseOptions(Predicate<Iterable<String>> additionalOptions) {
         String platformString = options.get(Option.RELEASE);
 
         checkOptionAllowed(platformString == null,
@@ -323,7 +315,7 @@
 
             context.put(PlatformDescription.class, platformDescription);
 
-            if (!doProcessArgs(platformDescription.getAdditionalOptions(), allowableOpts, helper, allowOperands, checkFileManager))
+            if (!additionalOptions.test(platformDescription.getAdditionalOptions()))
                 return false;
 
             Collection<Path> platformCP = platformDescription.getPlatformPath();
@@ -348,6 +340,30 @@
             }
         }
 
+        return true;
+    }
+
+    /**
+     * Processes strings containing options and operands.
+     * @param args the strings to be processed
+     * @param allowableOpts the set of option declarations that are applicable
+     * @param helper a help for use by Option.process
+     * @param allowOperands whether or not to check for files and classes
+     * @param checkFileManager whether or not to check if the file manager can handle
+     *      options which are not recognized by any of allowableOpts
+     * @return true if all the strings were successfully processed; false otherwise
+     * @throws IllegalArgumentException if a problem occurs and errorMode is set to
+     *      ILLEGAL_ARGUMENT
+     */
+    private boolean processArgs(Iterable<String> args,
+            Set<Option> allowableOpts, OptionHelper helper,
+            boolean allowOperands, boolean checkFileManager) {
+        if (!doProcessArgs(args, allowableOpts, helper, allowOperands, checkFileManager))
+            return false;
+
+        if (!handleReleaseOptions(extra -> doProcessArgs(extra, allowableOpts, helper, allowOperands, checkFileManager)))
+            return false;
+
         options.notifyListeners();
 
         return true;
--- a/src/jdk.compiler/share/classes/module-info.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.compiler/share/classes/module-info.java	Thu Apr 06 18:56:04 2017 +0100
@@ -27,6 +27,7 @@
  *  {@link javax.tools.ToolProvider#getSystemJavaCompiler system Java compiler}
  *  and its command line equivalent, <em>javac</em>, as well as <em>javah</em>.
  *
+ *  @moduleGraph
  *  @since 9
  */
 module jdk.compiler {
--- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/standard/Standard.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/standard/Standard.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -33,7 +33,7 @@
  * @deprecated The doclet has been superseded by its replacement,
  * {@code jdk.javadoc.doclets.StandardDoclet}.
  */
-@Deprecated
+@Deprecated(forRemoval=true, since="9")
 public class Standard {
 
     public static int optionLength(String option) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -69,9 +69,9 @@
     public ConstructorWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) {
         super(writer, typeElement);
 
-        VisibleMemberMap visibleMemberMap = new VisibleMemberMap(
+        VisibleMemberMap visibleMemberMap = configuration.getVisibleMemberMap(
                 typeElement,
-                VisibleMemberMap.Kind.CONSTRUCTORS, configuration);
+                VisibleMemberMap.Kind.CONSTRUCTORS);
         List<Element> constructors = visibleMemberMap.getMembers(typeElement);
         for (Element constructor : constructors) {
             if (utils.isProtected(constructor) || utils.isPrivate(constructor)) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java	Thu Apr 06 18:56:04 2017 +0100
@@ -26,6 +26,7 @@
 package jdk.javadoc.internal.doclets.toolkit;
 
 import java.io.*;
+import java.lang.ref.*;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -54,7 +55,9 @@
 import jdk.javadoc.internal.doclets.toolkit.util.SimpleDocletException;
 import jdk.javadoc.internal.doclets.toolkit.util.TypeElementCatalog;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.GetterSetter;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
 
 import static javax.tools.Diagnostic.Kind.*;
 
@@ -296,6 +299,8 @@
 
     private List<GroupContainer> groups;
 
+    private final Map<TypeElement, EnumMap<Kind, Reference<VisibleMemberMap>>> typeElementMemberCache;
+
     public abstract Messages getMessages();
     public abstract Resources getResources();
 
@@ -355,6 +360,7 @@
         setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
         metakeywords = new MetaKeywords(this);
         groups = new ArrayList<>(0);
+        typeElementMemberCache = new HashMap<>();
     }
 
     private boolean initialized = false;
@@ -1259,4 +1265,18 @@
     public boolean isAllowScriptInComments() {
         return allowScriptInComments;
     }
+
+    public VisibleMemberMap getVisibleMemberMap(TypeElement te, VisibleMemberMap.Kind kind) {
+        EnumMap<Kind, Reference<VisibleMemberMap>> cacheMap = typeElementMemberCache
+                .computeIfAbsent(te, k -> new EnumMap<>(VisibleMemberMap.Kind.class));
+
+        Reference<VisibleMemberMap> vmapRef = cacheMap.get(kind);
+        // recompute, if referent has been garbage collected
+        VisibleMemberMap vMap = vmapRef == null ? null : vmapRef.get();
+        if (vMap == null) {
+            vMap = new VisibleMemberMap(te, kind, this);
+            cacheMap.put(kind, new SoftReference<>(vMap));
+        }
+        return vMap;
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -90,7 +90,7 @@
         super(context);
         this.typeElement = typeElement;
         this.writer = writer;
-        this.visibleMemberMap = new VisibleMemberMap(typeElement, memberType, configuration);
+        this.visibleMemberMap = configuration.getVisibleMemberMap(typeElement, memberType);
         this.members = this.visibleMemberMap.getMembers(typeElement);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -91,7 +91,7 @@
         super(context);
         this.typeElement = typeElement;
         this.writer = writer;
-        this.visibleMemberMap = new VisibleMemberMap(typeElement, memberType, configuration);
+        this.visibleMemberMap = configuration.getVisibleMemberMap(typeElement, memberType);
         this.members = this.visibleMemberMap.getMembers(typeElement);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -273,8 +273,8 @@
      * @return true if the given package has constant fields to document.
      */
     private boolean hasConstantField (TypeElement typeElement) {
-        VisibleMemberMap visibleMemberMapFields = new VisibleMemberMap(typeElement,
-            VisibleMemberMap.Kind.FIELDS, configuration);
+        VisibleMemberMap visibleMemberMapFields = configuration.getVisibleMemberMap(typeElement,
+            VisibleMemberMap.Kind.FIELDS);
         List<Element> fields = visibleMemberMapFields.getLeafMembers();
         for (Element f : fields) {
             VariableElement field = (VariableElement)f;
@@ -329,10 +329,10 @@
          */
         public ConstantFieldBuilder(TypeElement typeElement) {
             this.typeElement = typeElement;
-            visibleMemberMapFields = new VisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.FIELDS, configuration);
-            visibleMemberMapEnumConst = new VisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.ENUM_CONSTANTS, configuration);
+            visibleMemberMapFields = configuration.getVisibleMemberMap(typeElement,
+                VisibleMemberMap.Kind.FIELDS);
+            visibleMemberMapEnumConst = configuration.getVisibleMemberMap(typeElement,
+                VisibleMemberMap.Kind.ENUM_CONSTANTS);
         }
 
         /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -94,11 +94,8 @@
         super(context);
         this.typeElement = typeElement;
         this.writer = writer;
-        visibleMemberMap =
-                new VisibleMemberMap(
-                typeElement,
-                VisibleMemberMap.Kind.CONSTRUCTORS,
-                configuration);
+        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
+                VisibleMemberMap.Kind.CONSTRUCTORS);
         constructors = visibleMemberMap.getMembers(typeElement);
         for (Element ctor : constructors) {
             if (utils.isProtected(ctor) || utils.isPrivate(ctor)) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -89,11 +89,8 @@
         super(context);
         this.typeElement = typeElement;
         this.writer = writer;
-        visibleMemberMap =
-                new VisibleMemberMap(
-                typeElement,
-                VisibleMemberMap.Kind.ENUM_CONSTANTS,
-                configuration);
+        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
+                VisibleMemberMap.Kind.ENUM_CONSTANTS);
         enumConstants = visibleMemberMap.getMembers(typeElement);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -90,11 +90,8 @@
         super(context);
         this.typeElement = typeElement;
         this.writer = writer;
-        visibleMemberMap =
-                new VisibleMemberMap(
-                typeElement,
-                VisibleMemberMap.Kind.FIELDS,
-                configuration);
+        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
+                VisibleMemberMap.Kind.FIELDS);
         fields = visibleMemberMap.getLeafMembers();
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -70,10 +70,6 @@
     public static final String NAME = "MemberSummary";
 
     /**
-     * The visible members for the given class.
-     */
-    private final EnumMap<VisibleMemberMap.Kind, VisibleMemberMap> visibleMemberMaps;
-    /**
      * The member summary writers for the given class.
      */
     private final EnumMap<VisibleMemberMap.Kind, MemberSummaryWriter> memberSummaryWriters;
@@ -94,14 +90,6 @@
         super(context);
         this.typeElement = typeElement;
         memberSummaryWriters = new EnumMap<>(VisibleMemberMap.Kind.class);
-        visibleMemberMaps = new EnumMap<>(VisibleMemberMap.Kind.class);
-        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-            visibleMemberMaps.put(kind,
-                    new VisibleMemberMap(
-                    typeElement,
-                    kind,
-                    configuration));
-        }
     }
 
     /**
@@ -117,7 +105,7 @@
                 classWriter.getTypeElement());
         WriterFactory wf = context.configuration.getWriterFactory();
         for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-            MemberSummaryWriter msw = builder.visibleMemberMaps.get(kind).noVisibleMembers()
+            MemberSummaryWriter msw =  builder.getVisibleMemberMap(kind).noVisibleMembers()
                     ? null
                     : wf.getMemberSummaryWriter(classWriter, kind);
             builder.memberSummaryWriters.put(kind, msw);
@@ -138,7 +126,7 @@
                 annotationTypeWriter.getAnnotationTypeElement());
         WriterFactory wf = context.configuration.getWriterFactory();
         for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-            MemberSummaryWriter msw = builder.visibleMemberMaps.get(kind).noVisibleMembers()
+            MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
                     ? null
                     : wf.getMemberSummaryWriter(annotationTypeWriter, kind);
             builder.memberSummaryWriters.put(kind, msw);
@@ -157,25 +145,25 @@
     /**
      * Return the specified visible member map.
      *
-     * @param type the type of visible member map to return.
+     * @param kind the kind of visible member map to return.
      * @return the specified visible member map.
      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
      * @see VisibleMemberMap
      */
-    public VisibleMemberMap getVisibleMemberMap(VisibleMemberMap.Kind type) {
-        return visibleMemberMaps.get(type);
+    public VisibleMemberMap getVisibleMemberMap(VisibleMemberMap.Kind kind) {
+        return configuration.getVisibleMemberMap(typeElement, kind);
     }
 
     /**.
      * Return the specified member summary writer.
      *
-     * @param type the type of member summary writer to return.
+     * @param kind the kind of member summary writer to return.
      * @return the specified member summary writer.
      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
      * @see VisibleMemberMap
      */
-    public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberMap.Kind type) {
-        return memberSummaryWriters.get(type);
+    public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberMap.Kind kind) {
+        return memberSummaryWriters.get(kind);
     }
 
     /**
@@ -183,13 +171,13 @@
      * This information can be used for doclet specific documentation
      * generation.
      *
-     * @param type the type of members to return.
+     * @param kind the kind of elements to return.
      * @return a list of methods that will be documented.
      * @see VisibleMemberMap
      */
-    public SortedSet<Element> members(VisibleMemberMap.Kind type) {
+    public SortedSet<Element> members(VisibleMemberMap.Kind kind) {
         TreeSet<Element> out = new TreeSet<>(comparator);
-        out.addAll(visibleMemberMaps.get(type).getLeafMembers());
+        out.addAll(getVisibleMemberMap(kind).getLeafMembers());
         return out;
     }
 
@@ -204,7 +192,7 @@
             return !utils.getAnnotationMethods(typeElement).isEmpty();
         }
         for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-            VisibleMemberMap members = visibleMemberMaps.get(kind);
+            VisibleMemberMap members = getVisibleMemberMap(kind);
             if (!members.noVisibleMembers()) {
                 return true;
             }
@@ -222,7 +210,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.ENUM_CONSTANTS);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.ENUM_CONSTANTS);
+                getVisibleMemberMap(VisibleMemberMap.Kind.ENUM_CONSTANTS);
         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
     }
 
@@ -236,7 +224,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
+                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
     }
 
@@ -250,7 +238,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
+                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
     }
 
@@ -264,7 +252,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
+                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
     }
 
@@ -278,7 +266,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.FIELDS);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.FIELDS);
+                getVisibleMemberMap(VisibleMemberMap.Kind.FIELDS);
         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
     }
 
@@ -289,7 +277,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.PROPERTIES);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.PROPERTIES);
+                getVisibleMemberMap(VisibleMemberMap.Kind.PROPERTIES);
         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
     }
 
@@ -303,7 +291,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.INNER_CLASSES);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.INNER_CLASSES);
+                getVisibleMemberMap(VisibleMemberMap.Kind.INNER_CLASSES);
         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
     }
 
@@ -317,7 +305,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.METHODS);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.METHODS);
+               getVisibleMemberMap(VisibleMemberMap.Kind.METHODS);
         addSummary(writer, visibleMemberMap, true, memberSummaryTree);
     }
 
@@ -331,7 +319,7 @@
         MemberSummaryWriter writer =
                 memberSummaryWriters.get(VisibleMemberMap.Kind.CONSTRUCTORS);
         VisibleMemberMap visibleMemberMap =
-                visibleMemberMaps.get(VisibleMemberMap.Kind.CONSTRUCTORS);
+                getVisibleMemberMap(VisibleMemberMap.Kind.CONSTRUCTORS);
         addSummary(writer, visibleMemberMap, false, memberSummaryTree);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -94,10 +94,8 @@
         super(context);
         this.typeElement = typeElement;
         this.writer = writer;
-        visibleMemberMap = new VisibleMemberMap(
-                typeElement,
-                VisibleMemberMap.Kind.METHODS,
-                configuration);
+        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
+                VisibleMemberMap.Kind.METHODS);
         methods = visibleMemberMap.getLeafMembers();
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -90,11 +90,8 @@
         super(context);
         this.typeElement = typeElement;
         this.writer = writer;
-        visibleMemberMap =
-                new VisibleMemberMap(
-                typeElement,
-                VisibleMemberMap.Kind.PROPERTIES,
-                configuration);
+        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
+                VisibleMemberMap.Kind.PROPERTIES);
         properties = visibleMemberMap.getMembers(typeElement);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Thu Apr 06 18:56:04 2017 +0100
@@ -787,3 +787,15 @@
     font-style:italic;
     font-size:12px;
 }
+
+.moduleGraph span {
+    display:none;
+    position:absolute;
+}
+.moduleGraph:hover span {
+    display:block;
+    margin: -100px 0 0 100px;
+    z-index: 1;
+}
+
+
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java	Thu Apr 06 18:56:04 2017 +0100
@@ -88,9 +88,8 @@
  */
 public class Start extends ToolOption.Helper {
 
-    @SuppressWarnings("deprecation")
-    private static final Class<?> OldStdDoclet =
-            com.sun.tools.doclets.standard.Standard.class;
+    private static final String OldStdDocletName =
+        "com.sun.tools.doclets.standard.Standard";
 
     private static final Class<?> StdDoclet =
             jdk.javadoc.doclet.StandardDoclet.class;
@@ -334,7 +333,7 @@
                     messager.getWriter(WriterKind.ERROR),
                     messager.getWriter(WriterKind.WARNING),
                     messager.getWriter(WriterKind.NOTICE),
-                    "com.sun.tools.doclets.standard.Standard",
+                    OldStdDocletName,
                     nargv);
             return (rc == 0) ? OK : ERROR;
         }
@@ -513,12 +512,22 @@
         } catch (com.sun.tools.javac.main.Option.InvalidValueException ignore) {
         }
 
+        Arguments arguments = Arguments.instance(context);
+        arguments.init(ProgramName);
+        arguments.allowEmpty();
+
         doclet.init(locale, messager);
         parseArgs(argList, javaNames);
 
-        Arguments arguments = Arguments.instance(context);
-        arguments.init(ProgramName);
-        arguments.allowEmpty();
+        if (!arguments.handleReleaseOptions(extra -> true)) {
+            // Arguments does not always increase the error count in the
+            // case of errors, so increment the error count only if it has
+            // not been updated previously, preventing complaints by callers
+            if (!messager.hasErrors() && !messager.hasWarnings())
+                messager.nerrors++;
+            return CMDERR;
+        }
+
         if (!arguments.validate()) {
             // Arguments does not always increase the error count in the
             // case of errors, so increment the error count only if it has
@@ -532,49 +541,6 @@
             ((BaseFileManager) fileManager).handleOptions(fileManagerOpts);
         }
 
-        String platformString = compOpts.get("--release");
-
-        if (platformString != null) {
-            if (compOpts.isSet("-source")) {
-                String text = messager.getText("main.release.bootclasspath.conflict", "-source");
-                throw new ToolException(CMDERR, text);
-            }
-            if (fileManagerOpts.containsKey(BOOT_CLASS_PATH)) {
-                String text = messager.getText("main.release.bootclasspath.conflict",
-                        BOOT_CLASS_PATH.getPrimaryName());
-                throw new ToolException(CMDERR, text);
-            }
-
-            PlatformDescription platformDescription =
-                    PlatformUtils.lookupPlatformDescription(platformString);
-
-            if (platformDescription == null) {
-                String text = messager.getText("main.unsupported.release.version", platformString);
-                throw new IllegalArgumentException(text);
-            }
-
-            compOpts.put(SOURCE, platformDescription.getSourceVersion());
-
-            context.put(PlatformDescription.class, platformDescription);
-
-            Collection<Path> platformCP = platformDescription.getPlatformPath();
-
-            if (platformCP != null) {
-                if (fileManager instanceof StandardJavaFileManager) {
-                    StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
-                    try {
-                        sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
-                    } catch (IOException ioe) {
-                        throw new ToolException(SYSERR, ioe.getMessage(), ioe);
-                    }
-                } else {
-                    String text = messager.getText("main.release.not.standard.file.manager",
-                                                    platformString);
-                    throw new ToolException(ABNORMAL, text);
-                }
-            }
-        }
-
         compOpts.notifyListeners();
         List<String> modules = (List<String>) jdtoolOpts.computeIfAbsent(ToolOption.MODULE,
                 s -> Collections.EMPTY_LIST);
@@ -797,27 +763,31 @@
 
         // Step 4: we have a doclet, try loading it
         if (docletName != null) {
-            try {
-                return Class.forName(docletName, true, getClass().getClassLoader());
-            } catch (ClassNotFoundException cnfe) {
-                if (apiMode) {
-                    throw new IllegalArgumentException("Cannot find doclet class " + userDocletName);
-                }
-                String text = messager.getText("main.doclet_class_not_found", userDocletName);
-                throw new ToolException(CMDERR, text, cnfe);
-            }
+            return loadDocletClass(docletName);
         }
 
         // Step 5: we don't have a doclet specified, do we have taglets ?
         if (!userTagletNames.isEmpty() && hasOldTaglet(userTagletNames, userTagletPath)) {
             // found a bogey, return the old doclet
-            return OldStdDoclet;
+            return loadDocletClass(OldStdDocletName);
         }
 
         // finally
         return StdDoclet;
     }
 
+    private Class<?> loadDocletClass(String docletName) throws ToolException {
+        try {
+            return Class.forName(docletName, true, getClass().getClassLoader());
+        } catch (ClassNotFoundException cnfe) {
+            if (apiMode) {
+                throw new IllegalArgumentException("Cannot find doclet class " + docletName);
+            }
+            String text = messager.getText("main.doclet_class_not_found", docletName);
+            throw new ToolException(CMDERR, text, cnfe);
+        }
+    }
+
     /*
      * This method returns true iff it finds a legacy taglet, but for
      * all other conditions including errors it returns false, allowing
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties	Thu Apr 06 18:56:04 2017 +0100
@@ -284,9 +284,6 @@
 main.illegal_class_name=Illegal class name: "{0}"
 main.illegal_package_name=Illegal package name: "{0}"
 main.illegal_option_value=Illegal option value: "{0}"
-main.release.bootclasspath.conflict=option {0} cannot be used together with -release
-main.unsupported.release.version=release version {0} not supported
-main.release.not.standard.file.manager=-release option specified, but the provided JavaFileManager is not a StandardJavaFileManager.
 main.file.manager.list=FileManager error listing files: "{0}"
 main.assertion.error=assertion failed: "{0}}"
 main.unknown.error=an unknown error has occurred
--- a/src/jdk.javadoc/share/classes/module-info.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.javadoc/share/classes/module-info.java	Thu Apr 06 18:56:04 2017 +0100
@@ -27,6 +27,7 @@
  *  {@link javax.tools.ToolProvider#getSystemDocumentationTool system documentation tool}
  *  and its command line equivalent, <em>javadoc</em>.
  *
+ *  @moduleGraph
  *  @since 9
  */
 module jdk.javadoc {
--- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java	Thu Apr 06 18:56:04 2017 +0100
@@ -32,6 +32,7 @@
 import java.io.PrintWriter;
 import java.lang.module.Configuration;
 import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.*;
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReference;
 import java.lang.module.ResolvedModule;
@@ -39,8 +40,8 @@
 import java.nio.file.Path;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Deque;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -76,10 +77,16 @@
      * @param dir output directory
      */
     public boolean genDotFiles(Path dir) throws IOException {
+        return genDotFiles(dir, DotGraphAttributes.DEFAULT);
+    }
+
+    public boolean genDotFiles(Path dir, Attributes attributes)
+        throws IOException
+    {
         Files.createDirectories(dir);
         for (String mn : configurations.keySet()) {
             Path path = dir.resolve(mn + ".dot");
-            genDotFile(path, mn, configurations.get(mn));
+            genDotFile(path, mn, configurations.get(mn), attributes);
         }
         return true;
     }
@@ -87,7 +94,9 @@
     /**
      * Generate dotfile of the given path
      */
-    public void genDotFile(Path path, String name, Configuration configuration)
+    public void genDotFile(Path path, String name,
+                           Configuration configuration,
+                           Attributes attributes)
         throws IOException
     {
         // transitive reduction
@@ -95,12 +104,12 @@
                 ? requiresTransitiveGraph(configuration, Set.of(name))
                 : gengraph(configuration);
 
-        DotGraphBuilder builder = new DotGraphBuilder(name, graph);
-        builder.subgraph("se", "java", DotGraphBuilder.ORANGE,
+        DotGraphBuilder builder = new DotGraphBuilder(name, graph, attributes);
+        builder.subgraph("se", "java", attributes.javaSubgraphColor(),
                          DotGraphBuilder.JAVA_SE_SUBGRAPH)
-               .subgraph("jdk", "jdk", DotGraphBuilder.BLUE,
+               .subgraph("jdk", "jdk", attributes.jdkSubgraphColor(),
                          DotGraphBuilder.JDK_SUBGRAPH)
-               .descriptors(graph.nodes().stream()
+               .modules(graph.nodes().stream()
                                  .map(mn -> configuration.findModule(mn).get()
                                                 .reference().descriptor()));
         // build dot file
@@ -118,12 +127,12 @@
     private Graph<String> gengraph(Configuration cf) {
         Graph.Builder<String> builder = new Graph.Builder<>();
         cf.modules().stream()
-            .forEach(resolvedModule -> {
-                String mn = resolvedModule.reference().descriptor().name();
+            .forEach(rm -> {
+                String mn = rm.name();
                 builder.addNode(mn);
-                resolvedModule.reads().stream()
-                    .map(ResolvedModule::name)
-                    .forEach(target -> builder.addEdge(mn, target));
+                rm.reads().stream()
+                  .map(ResolvedModule::name)
+                  .forEach(target -> builder.addEdge(mn, target));
             });
 
         Graph<String> rpg = requiresTransitiveGraph(cf, builder.nodes);
@@ -149,22 +158,103 @@
 
             visited.add(mn);
             builder.addNode(mn);
-            ModuleDescriptor descriptor = cf.findModule(mn).get()
-                .reference().descriptor();
-            descriptor.requires().stream()
-                .filter(d -> d.modifiers().contains(TRANSITIVE)
+            cf.findModule(mn).get()
+              .reference().descriptor().requires().stream()
+              .filter(d -> d.modifiers().contains(TRANSITIVE)
                                 || d.name().equals("java.base"))
-                .map(d -> d.name())
-                .forEach(d -> {
-                    deque.add(d);
-                    builder.addEdge(mn, d);
-                });
+              .map(Requires::name)
+              .forEach(d -> {
+                  deque.add(d);
+                  builder.addEdge(mn, d);
+              });
         }
 
         return builder.build().reduce();
     }
 
-    public static class DotGraphBuilder {
+    public interface Attributes {
+        static final String ORANGE = "#e76f00";
+        static final String BLUE = "#437291";
+        static final String BLACK = "#000000";
+        static final String DARK_GRAY = "#999999";
+        static final String LIGHT_GRAY = "#dddddd";
+
+        int fontSize();
+        String fontName();
+        String fontColor();
+
+        int arrowSize();
+        int arrowWidth();
+        String arrowColor();
+
+        default double rankSep() {
+            return 1;
+        }
+
+        default List<Set<String>> ranks() {
+            return Collections.emptyList();
+        }
+
+        default int weightOf(String s, String t) {
+            return 1;
+        }
+
+        default String requiresMandatedColor() {
+            return LIGHT_GRAY;
+        }
+
+        default String javaSubgraphColor() {
+            return ORANGE;
+        }
+
+        default String jdkSubgraphColor() {
+            return BLUE;
+        }
+    }
+
+    static class DotGraphAttributes implements Attributes {
+        static final DotGraphAttributes DEFAULT = new DotGraphAttributes();
+
+        static final String FONT_NAME = "DejaVuSans";
+        static final int FONT_SIZE = 12;
+        static final int ARROW_SIZE = 1;
+        static final int ARROW_WIDTH = 2;
+
+        @Override
+        public int fontSize() {
+            return FONT_SIZE;
+        }
+
+        @Override
+        public String fontName() {
+            return FONT_NAME;
+        }
+
+        @Override
+        public String fontColor() {
+            return BLACK;
+        }
+
+        @Override
+        public int arrowSize() {
+            return ARROW_SIZE;
+        }
+
+        @Override
+        public int arrowWidth() {
+            return ARROW_WIDTH;
+        }
+
+        @Override
+        public String arrowColor() {
+            return DARK_GRAY;
+        }
+    }
+
+    private static class DotGraphBuilder {
+        static final String REEXPORTS = "";
+        static final String REQUIRES = "style=\"dashed\"";
+
         static final Set<String> JAVA_SE_SUBGRAPH = javaSE();
         static final Set<String> JDK_SUBGRAPH = jdk();
 
@@ -215,41 +305,20 @@
             }
         }
 
-        static final String ORANGE = "#e76f00";
-        static final String BLUE = "#437291";
-        static final String GRAY = "#dddddd";
-        static final String BLACK = "#000000";
-
-        static final String FONT_NAME = "DejaVuSans";
-        static final int FONT_SIZE = 12;
-        static final int ARROW_SIZE = 1;
-        static final int ARROW_WIDTH = 2;
-        static final int RANK_SEP = 1;
-
-        static final String REEXPORTS = "";
-        static final String REQUIRES = "style=\"dashed\"";
-        static final String REQUIRES_BASE = "color=\"" + GRAY + "\"";
-
-        // can be configured
-        static double rankSep   = RANK_SEP;
-        static String fontColor = BLACK;
-        static String fontName  = FONT_NAME;
-        static int fontsize     = FONT_SIZE;
-        static int arrowWidth   = ARROW_WIDTH;
-        static int arrowSize    = ARROW_SIZE;
-        static final Map<String, Integer> weights = new HashMap<>();
-        static final List<Set<String>> ranks = new ArrayList<>();
-
         private final String name;
         private final Graph<String> graph;
         private final Set<ModuleDescriptor> descriptors = new TreeSet<>();
         private final List<SubGraph> subgraphs = new ArrayList<>();
-        public DotGraphBuilder(String name, Graph<String> graph) {
+        private final Attributes attributes;
+        public DotGraphBuilder(String name,
+                               Graph<String> graph,
+                               Attributes attributes) {
             this.name = name;
             this.graph = graph;
+            this.attributes = attributes;
         }
 
-        public DotGraphBuilder descriptors(Stream<ModuleDescriptor> descriptors) {
+        public DotGraphBuilder modules(Stream<ModuleDescriptor> descriptors) {
             descriptors.forEach(this.descriptors::add);
             return this;
         }
@@ -260,22 +329,27 @@
 
                 out.format("digraph \"%s\" {%n", name);
                 out.format("  nodesep=.5;%n");
-                out.format("  ranksep=%f;%n", rankSep);
+                out.format("  ranksep=%f;%n", attributes.rankSep());
                 out.format("  pencolor=transparent;%n");
-                out.format("  node [shape=plaintext, fontname=\"%s\", fontsize=%d, margin=\".2,.2\"];%n",
-                           fontName, fontsize);
-                out.format("  edge [penwidth=%d, color=\"#999999\", arrowhead=open, arrowsize=%d];%n",
-                           arrowWidth, arrowSize);
+                out.format("  node [shape=plaintext, fontcolor=\"%s\", fontname=\"%s\","
+                                + " fontsize=%d, margin=\".2,.2\"];%n",
+                           attributes.fontColor(),
+                           attributes.fontName(),
+                           attributes.fontSize());
+                out.format("  edge [penwidth=%d, color=\"%s\", arrowhead=open, arrowsize=%d];%n",
+                           attributes.arrowWidth(),
+                           attributes.arrowColor(),
+                           attributes.arrowSize());
 
                 // same RANKS
-                ranks.stream()
-                     .map(nodes -> descriptors.stream()
+                attributes.ranks().stream()
+                    .map(nodes -> descriptors.stream()
                                         .map(ModuleDescriptor::name)
                                         .filter(nodes::contains)
                                         .map(mn -> "\"" + mn + "\"")
                                         .collect(joining(",")))
-                     .filter(group -> group.length() > 0)
-                     .forEach(group -> out.format("  {rank=same %s}%n", group));
+                    .filter(group -> group.length() > 0)
+                    .forEach(group -> out.format("  {rank=same %s}%n", group));
 
                 subgraphs.forEach(subgraph -> {
                     out.format("  subgraph %s {%n", subgraph.name);
@@ -314,10 +388,14 @@
 
             String mn = md.name();
             edges.stream().forEach(dn -> {
-                String attr = dn.equals("java.base") ? REQUIRES_BASE
-                    : (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
+                String attr;
+                if (dn.equals("java.base")) {
+                    attr = "color=\"" + attributes.requiresMandatedColor() + "\"";
+                } else {
+                    attr = (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
+                }
 
-                int w = weightOf(mn, dn);
+                int w = attributes.weightOf(mn, dn);
                 if (w > 1) {
                     if (!attr.isEmpty())
                         attr += ", ";
@@ -328,41 +406,5 @@
             });
         }
 
-        public int weightOf(String s, String t) {
-            int w = weights.getOrDefault(s + ":" + t, 1);
-            if (w != 1)
-                return w;
-            if (s.startsWith("java.") && t.startsWith("java."))
-                return 10;
-            return 1;
-        }
-
-        public static void sameRankNodes(Set<String> nodes) {
-            ranks.add(nodes);
-        }
-
-        public static void weight(String s, String t, int w) {
-            weights.put(s + ":" + t, w);
-        }
-
-        public static void setRankSep(double value) {
-            rankSep = value;
-        }
-
-        public static void setFontSize(int size) {
-            fontsize = size;
-        }
-
-        public static void setFontColor(String color) {
-            fontColor = color;
-        }
-
-        public static void setArrowSize(int size) {
-            arrowSize = size;
-        }
-
-        public static void setArrowWidth(int width) {
-            arrowWidth = width;
-        }
     }
 }
--- a/src/jdk.jdeps/share/classes/module-info.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.jdeps/share/classes/module-info.java	Thu Apr 06 18:56:04 2017 +0100
@@ -26,6 +26,7 @@
 /** Defines tools for analysing dependencies in Java libraries and programs, including
  *  the <em>jdeps</em> and <em>javap</em> tools.
  *
+ *  @moduleGraph
  *  @since 9
  */
 module jdk.jdeps {
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Thu Apr 06 18:56:04 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
@@ -33,7 +33,6 @@
 import java.io.InputStream;
 import java.io.InterruptedIOException;
 import java.io.PrintStream;
-import java.io.UncheckedIOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -44,7 +43,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BooleanSupplier;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -59,10 +58,10 @@
 import jdk.internal.jline.console.KeyMap;
 import jdk.internal.jline.console.Operation;
 import jdk.internal.jline.console.UserInterruptException;
-import jdk.internal.jline.console.completer.Completer;
 import jdk.internal.jline.console.history.History;
 import jdk.internal.jline.console.history.MemoryHistory;
 import jdk.internal.jline.extra.EditingHistory;
+import jdk.internal.jline.internal.NonBlockingInputStream;
 import jdk.internal.jshell.tool.StopDetectingInputStream.State;
 import jdk.internal.misc.Signal;
 import jdk.internal.misc.Signal.Handler;
@@ -91,10 +90,14 @@
             term = new JShellUnixTerminal(input);
         }
         term.init();
-        AtomicBoolean allowSmart = new AtomicBoolean();
+        List<CompletionTask> completionTODO = new ArrayList<>();
         in = new ConsoleReader(cmdin, cmdout, term) {
             @Override public KeyMap getKeys() {
-                return new CheckCompletionKeyMap(super.getKeys(), allowSmart);
+                return new CheckCompletionKeyMap(super.getKeys(), completionTODO);
+            }
+            @Override
+            protected boolean complete() throws IOException {
+                return ConsoleIOContext.this.complete(completionTODO);
             }
         };
         in.setExpandEvents(false);
@@ -111,67 +114,7 @@
         });
         in.setBellEnabled(true);
         in.setCopyPasteDetection(true);
-        in.addCompleter(new Completer() {
-            @Override public int complete(String test, int cursor, List<CharSequence> result) {
-                int[] anchor = new int[] {-1};
-                List<Suggestion> suggestions;
-                if (prefix.isEmpty() && test.trim().startsWith("/")) {
-                    suggestions = repl.commandCompletionSuggestions(test, cursor, anchor);
-                } else {
-                    int prefixLength = prefix.length();
-                    suggestions = repl.analysis.completionSuggestions(prefix + test, cursor + prefixLength, anchor);
-                    anchor[0] -= prefixLength;
-                }
-                boolean smart = allowSmart.get() &&
-                                suggestions.stream()
-                                           .anyMatch(Suggestion::matchesType);
-
-                allowSmart.set(!allowSmart.get());
-
-                suggestions.stream()
-                           .filter(s -> !smart || s.matchesType())
-                           .map(Suggestion::continuation)
-                           .forEach(result::add);
-
-                boolean onlySmart = suggestions.stream()
-                                               .allMatch(Suggestion::matchesType);
-
-                if (smart && !onlySmart) {
-                    Optional<String> prefix =
-                            suggestions.stream()
-                                       .map(Suggestion::continuation)
-                                       .reduce(ConsoleIOContext::commonPrefix);
-
-                    String prefixStr = prefix.orElse("").substring(cursor - anchor[0]);
-                    try {
-                        in.putString(prefixStr);
-                        cursor += prefixStr.length();
-                    } catch (IOException ex) {
-                        throw new IllegalStateException(ex);
-                    }
-                    result.add(repl.messageFormat("jshell.console.see.more"));
-                    return cursor; //anchor should not be used.
-                }
-
-                if (result.isEmpty()) {
-                    try {
-                        //provide "empty completion" feedback
-                        //XXX: this only works correctly when there is only one Completer:
-                        in.beep();
-                    } catch (IOException ex) {
-                        throw new UncheckedIOException(ex);
-                    }
-                }
-
-                return anchor[0];
-            }
-        });
-        bind(DOCUMENTATION_SHORTCUT, (Runnable) () -> documentation(repl));
-        for (FixComputer computer : FIX_COMPUTERS) {
-            for (String shortcuts : SHORTCUT_FIXES) {
-                bind(shortcuts + computer.shortcut, (Runnable) () -> fixes(computer));
-            }
-        }
+        bind(FIXES_SHORTCUT, (Runnable) () -> fixes());
         try {
             Signal.handle(new Signal("CONT"), new Handler() {
                 @Override public void handle(Signal sig) {
@@ -248,136 +191,184 @@
         }
     }
 
-    private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
-    private static final String[] SHORTCUT_FIXES = {
-        "\033\015", //Alt-Enter (Linux)
-        "\033\012", //Alt-Enter (Linux)
-        "\033\133\061\067\176", //F6/Alt-F1 (Mac)
-        "\u001BO3P" //Alt-F1 (Linux)
-    };
+    private static final String FIXES_SHORTCUT = "\033\133\132"; //Shift-TAB
 
-    private String lastDocumentationBuffer;
-    private int lastDocumentationCursor = (-1);
+    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+    private static final String LINE_SEPARATORS2 = LINE_SEPARATOR + LINE_SEPARATOR;
 
-    private void documentation(JShellTool repl) {
-        String buffer = in.getCursorBuffer().buffer.toString();
-        int cursor = in.getCursorBuffer().cursor;
-        boolean firstInvocation = !buffer.equals(lastDocumentationBuffer) || cursor != lastDocumentationCursor;
-        lastDocumentationBuffer = buffer;
-        lastDocumentationCursor = cursor;
-        List<String> doc;
-        String seeMore;
-        Terminal term = in.getTerminal();
-        if (prefix.isEmpty() && buffer.trim().startsWith("/")) {
-            doc = Arrays.asList(repl.commandDocumentation(buffer, cursor, firstInvocation));
-            seeMore = "jshell.console.see.help";
-        } else {
-            JavadocFormatter formatter = new JavadocFormatter(term.getWidth(),
-                                                              term.isAnsiSupported());
-            Function<Documentation, String> convertor;
-            if (firstInvocation) {
-                convertor = Documentation::signature;
-            } else {
-                convertor = d -> formatter.formatJavadoc(d.signature(), d.javadoc()) +
-                                 (d.javadoc() == null ? repl.messageFormat("jshell.console.no.javadoc")
-                                                      : "");
-            }
-            doc = repl.analysis.documentation(prefix + buffer, cursor + prefix.length(), !firstInvocation)
-                               .stream()
-                               .map(convertor)
-                               .collect(Collectors.toList());
-            seeMore = "jshell.console.see.javadoc";
-        }
+    @SuppressWarnings("fallthrough")
+    private boolean complete(List<CompletionTask> todo) {
+        //The completion has multiple states (invoked by subsequent presses of <tab>).
+        //On the first invocation in a given sequence, all steps are precomputed
+        //and placed into the todo list. The todo list is then followed on both the first
+        //and subsequent <tab> presses:
+        try {
+            String text = in.getCursorBuffer().toString();
+            int cursor = in.getCursorBuffer().cursor;
+            if (todo.isEmpty()) {
+                int[] anchor = new int[] {-1};
+                List<Suggestion> suggestions;
+                List<String> doc;
+                boolean command = prefix.isEmpty() && text.trim().startsWith("/");
+                if (command) {
+                    suggestions = repl.commandCompletionSuggestions(text, cursor, anchor);
+                    doc = repl.commandDocumentation(text, cursor, true);
+                } else {
+                    int prefixLength = prefix.length();
+                    suggestions = repl.analysis.completionSuggestions(prefix + text, cursor + prefixLength, anchor);
+                    anchor[0] -= prefixLength;
+                    doc = repl.analysis.documentation(prefix + text, cursor + prefix.length(), false)
+                                       .stream()
+                                       .map(Documentation::signature)
+                                       .collect(Collectors.toList());
+                }
+                long smartCount = suggestions.stream().filter(Suggestion::matchesType).count();
+                boolean hasSmart = smartCount > 0 && smartCount <= in.getAutoprintThreshold();
+                boolean hasBoth = hasSmart &&
+                                  suggestions.stream()
+                                             .map(s -> s.matchesType())
+                                             .distinct()
+                                             .count() == 2;
+                boolean tooManyItems = suggestions.size() > in.getAutoprintThreshold();
+                CompletionTask ordinaryCompletion = new OrdinaryCompletionTask(suggestions, anchor[0], !command && !doc.isEmpty(), hasSmart);
+                CompletionTask allCompletion = new AllSuggestionsCompletionTask(suggestions, anchor[0]);
 
-        try {
-            if (doc != null && !doc.isEmpty()) {
-                if (firstInvocation) {
-                    in.println();
-                    in.println(doc.stream().collect(Collectors.joining("\n")));
-                    in.println(repl.messageFormat(seeMore));
-                    in.redrawLine();
-                    in.flush();
+                //the main decission tree:
+                if (command) {
+                    CompletionTask shortDocumentation = new CommandSynopsisTask(doc);
+                    CompletionTask fullDocumentation = new CommandFullDocumentationTask(todo);
+
+                    if (!doc.isEmpty()) {
+                        if (tooManyItems) {
+                            todo.add(new NoopCompletionTask());
+                            todo.add(allCompletion);
+                        } else {
+                            todo.add(ordinaryCompletion);
+                        }
+                        todo.add(shortDocumentation);
+                        todo.add(fullDocumentation);
+                    } else {
+                        todo.add(new NoSuchCommandCompletionTask());
+                    }
                 } else {
-                    in.println();
+                    if (doc.isEmpty()) {
+                        if (hasSmart) {
+                            todo.add(ordinaryCompletion);
+                        } else if (tooManyItems) {
+                            todo.add(new NoopCompletionTask());
+                        }
+                        if (!hasSmart || hasBoth) {
+                            todo.add(allCompletion);
+                        }
+                    } else {
+                        CompletionTask shortDocumentation = new ExpressionSignaturesTask(doc);
+                        CompletionTask fullDocumentation = new ExpressionJavadocTask(todo);
 
-                    int height = term.getHeight();
-                    String lastNote = "";
-
-                    PRINT_DOC: for (Iterator<String> docIt = doc.iterator(); docIt.hasNext(); ) {
-                        String currentDoc = docIt.next();
-                        String[] lines = currentDoc.split("\n");
-                        int firstLine = 0;
-
-                        PRINT_PAGE: while (true) {
-                            in.print(lastNote.replaceAll(".", " ") + ConsoleReader.RESET_LINE);
-
-                            int toPrint = height - 1;
-
-                            while (toPrint > 0 && firstLine < lines.length) {
-                                in.println(lines[firstLine++]);
-                                toPrint--;
-                            }
-
-                            if (firstLine >= lines.length) {
-                                break;
-                            }
-
-                            lastNote = repl.getResourceString("jshell.console.see.next.page");
-                            in.print(lastNote + ConsoleReader.RESET_LINE);
-                            in.flush();
-
-                            while (true) {
-                                int r = in.readCharacter();
-
-                                switch (r) {
-                                    case ' ': continue PRINT_PAGE;
-                                    case 'q':
-                                    case 3:
-                                        break PRINT_DOC;
-                                    default:
-                                        in.beep();
-                                        break;
-                                }
-                            }
+                        if (hasSmart) {
+                            todo.add(ordinaryCompletion);
                         }
-
-                        if (docIt.hasNext()) {
-                            lastNote = repl.getResourceString("jshell.console.see.next.javadoc");
-                            in.print(lastNote + ConsoleReader.RESET_LINE);
-                            in.flush();
-
-                            while (true) {
-                                int r = in.readCharacter();
-
-                                switch (r) {
-                                    case ' ': continue PRINT_DOC;
-                                    case 'q':
-                                    case 3:
-                                        break PRINT_DOC;
-                                    default:
-                                        in.beep();
-                                        break;
-                                }
-                            }
+                        todo.add(shortDocumentation);
+                        if (!hasSmart || hasBoth) {
+                            todo.add(allCompletion);
+                        }
+                        if (tooManyItems) {
+                            todo.add(todo.size() - 1, fullDocumentation);
+                        } else {
+                            todo.add(fullDocumentation);
                         }
                     }
-                    //clear the "press space" line:
-                    in.getCursorBuffer().buffer.replace(0, buffer.length(), lastNote);
-                    in.getCursorBuffer().cursor = 0;
-                    in.killLine();
-                    in.getCursorBuffer().buffer.append(buffer);
-                    in.getCursorBuffer().cursor = cursor;
-                    in.redrawLine();
-                    in.flush();
                 }
-            } else {
-                in.beep();
             }
+
+            boolean success = false;
+            boolean repaint = true;
+
+            OUTER: while (!todo.isEmpty()) {
+                CompletionTask.Result result = todo.remove(0).perform(text, cursor);
+
+                switch (result) {
+                    case CONTINUE:
+                        break;
+                    case SKIP_NOREPAINT:
+                        repaint = false;
+                    case SKIP:
+                        todo.clear();
+                        //intentional fall-through
+                    case FINISH:
+                        success = true;
+                        //intentional fall-through
+                    case NO_DATA:
+                        if (!todo.isEmpty()) {
+                            in.println();
+                            in.println(todo.get(0).description());
+                        }
+                        break OUTER;
+                }
+            }
+
+            if (repaint) {
+                in.redrawLine();
+                in.flush();
+            }
+
+            return success;
         } catch (IOException ex) {
             throw new IllegalStateException(ex);
         }
     }
 
+    private CompletionTask.Result doPrintFullDocumentation(List<CompletionTask> todo, List<String> doc, boolean command) {
+        if (doc != null && !doc.isEmpty()) {
+            Terminal term = in.getTerminal();
+            int pageHeight = term.getHeight() - NEEDED_LINES;
+            List<CompletionTask> thisTODO = new ArrayList<>();
+
+            for (Iterator<String> docIt = doc.iterator(); docIt.hasNext(); ) {
+                String currentDoc = docIt.next();
+                String[] lines = currentDoc.split("\n");
+                int firstLine = 0;
+
+                while (firstLine < lines.length) {
+                    boolean first = firstLine == 0;
+                    String[] thisPageLines =
+                            Arrays.copyOfRange(lines,
+                                               firstLine,
+                                               Math.min(firstLine + pageHeight, lines.length));
+
+                    thisTODO.add(new CompletionTask() {
+                        @Override
+                        public String description() {
+                            String key =  !first ? "jshell.console.see.next.page"
+                                                 : command ? "jshell.console.see.next.command.doc"
+                                                           : "jshell.console.see.next.javadoc";
+
+                            return repl.getResourceString(key);
+                        }
+
+                        @Override
+                        public Result perform(String text, int cursor) throws IOException {
+                            in.println();
+                            for (String line : thisPageLines) {
+                                in.println(line);
+                            }
+                            return Result.FINISH;
+                        }
+                    });
+
+                    firstLine += pageHeight;
+                }
+            }
+
+            todo.addAll(0, thisTODO);
+
+            return CompletionTask.Result.CONTINUE;
+        }
+
+        return CompletionTask.Result.FINISH;
+    }
+    //where:
+        private static final int NEEDED_LINES = 4;
+
     private static String commonPrefix(String str1, String str2) {
         for (int i = 0; i < str2.length(); i++) {
             if (!str1.startsWith(str2.substring(0, i + 1))) {
@@ -388,6 +379,262 @@
         return str2;
     }
 
+    private interface CompletionTask {
+        public String description();
+        public Result perform(String text, int cursor) throws IOException;
+
+        enum Result {
+            NO_DATA,
+            CONTINUE,
+            FINISH,
+            SKIP,
+            SKIP_NOREPAINT;
+        }
+    }
+
+    private final class NoopCompletionTask implements CompletionTask {
+
+        @Override
+        public String description() {
+            throw new UnsupportedOperationException("Should not get here.");
+        }
+
+        @Override
+        public Result perform(String text, int cursor) throws IOException {
+            return Result.FINISH;
+        }
+
+    }
+
+    private final class NoSuchCommandCompletionTask implements CompletionTask {
+
+        @Override
+        public String description() {
+            throw new UnsupportedOperationException("Should not get here.");
+        }
+
+        @Override
+        public Result perform(String text, int cursor) throws IOException {
+            in.println();
+            in.println(repl.getResourceString("jshell.console.no.such.command"));
+            in.println();
+            return Result.SKIP;
+        }
+
+    }
+
+    private final class OrdinaryCompletionTask implements CompletionTask {
+        private final List<Suggestion> suggestions;
+        private final int anchor;
+        private final boolean cont;
+        private final boolean smart;
+
+        public OrdinaryCompletionTask(List<Suggestion> suggestions,
+                                      int anchor,
+                                      boolean cont,
+                                      boolean smart) {
+            this.suggestions = suggestions;
+            this.anchor = anchor;
+            this.cont = cont;
+            this.smart = smart;
+        }
+
+        @Override
+        public String description() {
+            throw new UnsupportedOperationException("Should not get here.");
+        }
+
+        @Override
+        public Result perform(String text, int cursor) throws IOException {
+            List<CharSequence> toShow;
+
+            if (smart) {
+                toShow =
+                    suggestions.stream()
+                               .filter(Suggestion::matchesType)
+                               .map(Suggestion::continuation)
+                               .distinct()
+                               .collect(Collectors.toList());
+            } else {
+                toShow =
+                    suggestions.stream()
+                               .map(Suggestion::continuation)
+                               .distinct()
+                               .collect(Collectors.toList());
+            }
+
+            if (toShow.isEmpty()) {
+                return Result.CONTINUE;
+            }
+
+            Optional<String> prefix =
+                    suggestions.stream()
+                               .map(Suggestion::continuation)
+                               .reduce(ConsoleIOContext::commonPrefix);
+
+            String prefixStr = prefix.orElse("").substring(cursor - anchor);
+            in.putString(prefixStr);
+
+            boolean showItems = toShow.size() > 1 || smart;
+
+            if (showItems) {
+                in.println();
+                in.printColumns(toShow);
+            }
+
+            if (!prefixStr.isEmpty())
+                return showItems ? Result.SKIP : Result.SKIP_NOREPAINT;
+
+            return cont ? Result.CONTINUE : Result.FINISH;
+        }
+
+    }
+
+    private final class AllSuggestionsCompletionTask implements CompletionTask {
+        private final List<Suggestion> suggestions;
+        private final int anchor;
+
+        public AllSuggestionsCompletionTask(List<Suggestion> suggestions,
+                                            int anchor) {
+            this.suggestions = suggestions;
+            this.anchor = anchor;
+        }
+
+        @Override
+        public String description() {
+            if (suggestions.size() <= in.getAutoprintThreshold()) {
+                return repl.getResourceString("jshell.console.completion.all.completions");
+            } else {
+                return repl.messageFormat("jshell.console.completion.all.completions.number", suggestions.size());
+            }
+        }
+
+        @Override
+        public Result perform(String text, int cursor) throws IOException {
+            List<String> candidates =
+                    suggestions.stream()
+                               .map(Suggestion::continuation)
+                               .distinct()
+                               .collect(Collectors.toList());
+
+            Optional<String> prefix =
+                    candidates.stream()
+                              .reduce(ConsoleIOContext::commonPrefix);
+
+            String prefixStr = prefix.map(str -> str.substring(cursor - anchor)).orElse("");
+            in.putString(prefixStr);
+            if (candidates.size() > 1) {
+                in.println();
+                in.printColumns(candidates);
+            }
+            return suggestions.isEmpty() ? Result.NO_DATA : Result.FINISH;
+        }
+
+    }
+
+    private final class CommandSynopsisTask implements CompletionTask {
+
+        private final List<String> synopsis;
+
+        public CommandSynopsisTask(List<String> synposis) {
+            this.synopsis = synposis;
+        }
+
+        @Override
+        public String description() {
+            return repl.getResourceString("jshell.console.see.synopsis");
+        }
+
+        @Override
+        public Result perform(String text, int cursor) throws IOException {
+            try {
+                in.println();
+                in.println(synopsis.stream()
+                                   .map(l -> l.replaceAll("\n", LINE_SEPARATOR))
+                                   .collect(Collectors.joining(LINE_SEPARATORS2)));
+            } catch (IOException ex) {
+                throw new IllegalStateException(ex);
+            }
+            return Result.FINISH;
+        }
+
+    }
+
+    private final class CommandFullDocumentationTask implements CompletionTask {
+
+        private final List<CompletionTask> todo;
+
+        public CommandFullDocumentationTask(List<CompletionTask> todo) {
+            this.todo = todo;
+        }
+
+        @Override
+        public String description() {
+            return repl.getResourceString("jshell.console.see.full.documentation");
+        }
+
+        @Override
+        public Result perform(String text, int cursor) throws IOException {
+            List<String> fullDoc = repl.commandDocumentation(text, cursor, false);
+            return doPrintFullDocumentation(todo, fullDoc, true);
+        }
+
+    }
+
+    private final class ExpressionSignaturesTask implements CompletionTask {
+
+        private final List<String> doc;
+
+        public ExpressionSignaturesTask(List<String> doc) {
+            this.doc = doc;
+        }
+
+        @Override
+        public String description() {
+            throw new UnsupportedOperationException("Should not get here.");
+        }
+
+        @Override
+        public Result perform(String text, int cursor) throws IOException {
+            in.println();
+            in.println(repl.getResourceString("jshell.console.completion.current.signatures"));
+            in.println(doc.stream().collect(Collectors.joining(LINE_SEPARATOR)));
+            return Result.FINISH;
+        }
+
+    }
+
+    private final class ExpressionJavadocTask implements CompletionTask {
+
+        private final List<CompletionTask> todo;
+
+        public ExpressionJavadocTask(List<CompletionTask> todo) {
+            this.todo = todo;
+        }
+
+        @Override
+        public String description() {
+            return repl.getResourceString("jshell.console.see.documentation");
+        }
+
+        @Override
+        public Result perform(String text, int cursor) throws IOException {
+            //schedule showing javadoc:
+            Terminal term = in.getTerminal();
+            JavadocFormatter formatter = new JavadocFormatter(term.getWidth(),
+                                                              term.isAnsiSupported());
+            Function<Documentation, String> convertor = d -> formatter.formatJavadoc(d.signature(), d.javadoc()) +
+                             (d.javadoc() == null ? repl.messageFormat("jshell.console.no.javadoc")
+                                                  : "");
+            List<String> doc = repl.analysis.documentation(prefix + text, cursor + prefix.length(), true)
+                                            .stream()
+                                            .map(convertor)
+                                            .collect(Collectors.toList());
+            return doPrintFullDocumentation(todo, doc, false);
+        }
+
+    }
+
     @Override
     public boolean terminalEditorRunning() {
         Terminal terminal = in.getTerminal();
@@ -428,6 +675,50 @@
         history.fullHistoryReplace(source);
     }
 
+    private static final long ESCAPE_TIMEOUT = 100;
+
+    private void fixes() {
+        try {
+            int c = in.readCharacter();
+
+            if (c == (-1)) {
+                return ;
+            }
+
+            for (FixComputer computer : FIX_COMPUTERS) {
+                if (computer.shortcut == c) {
+                    fixes(computer);
+                    return ;
+                }
+            }
+
+            readOutRemainingEscape(c);
+
+            in.beep();
+            in.println();
+            in.println(repl.getResourceString("jshell.fix.wrong.shortcut"));
+            in.redrawLine();
+            in.flush();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private void readOutRemainingEscape(int c) throws IOException {
+        if (c == '\033') {
+            //escape, consume waiting input:
+            InputStream inp = in.getInput();
+
+            if (inp instanceof NonBlockingInputStream) {
+                NonBlockingInputStream nbis = (NonBlockingInputStream) inp;
+
+                while (nbis.isNonBlockingEnabled() && nbis.peek(ESCAPE_TIMEOUT) > 0) {
+                    in.readCharacter();
+                }
+            }
+        }
+    }
+
     //compute possible options/Fixes based on the selected FixComputer, present them to the user,
     //and perform the selected one:
     private void fixes(FixComputer computer) {
@@ -493,7 +784,7 @@
                 in.flush();
             }
         } catch (IOException ex) {
-            ex.printStackTrace();
+            throw new IllegalStateException(ex);
         }
     }
 
@@ -766,7 +1057,7 @@
         public TestTerminal(StopDetectingInputStream input) throws Exception {
             super(true);
             setAnsiSupported(false);
-            setEchoEnabled(true);
+            setEchoEnabled(false);
             this.input = input;
         }
 
@@ -786,12 +1077,12 @@
     private static final class CheckCompletionKeyMap extends KeyMap {
 
         private final KeyMap del;
-        private final AtomicBoolean allowSmart;
+        private final List<CompletionTask> completionTODO;
 
-        public CheckCompletionKeyMap(KeyMap del, AtomicBoolean allowSmart) {
+        public CheckCompletionKeyMap(KeyMap del, List<CompletionTask> completionTODO) {
             super(del.getName(), del.isViKeyMap());
             this.del = del;
-            this.allowSmart = allowSmart;
+            this.completionTODO = completionTODO;
         }
 
         @Override
@@ -819,7 +1110,7 @@
             Object res = del.getBound(keySeq);
 
             if (res != Operation.COMPLETE) {
-                allowSmart.set(true);
+                completionTODO.clear();
             }
 
             return res;
@@ -835,4 +1126,4 @@
             return "check: " + del.toString();
         }
     }
-}
+    }
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1429,9 +1429,15 @@
             List<Suggestion> result;
             int pastSpace = code.indexOf(' ') + 1; // zero if no space
             if (pastSpace == 0) {
+                // initially suggest commands (with slash) and subjects,
+                // however, if their subject starts without slash, include
+                // commands without slash
+                boolean noslash = code.length() > 0 && !code.startsWith("/");
                 result = new FixedCompletionProvider(commands.values().stream()
                         .filter(cmd -> cmd.kind.showInHelp || cmd.kind == CommandKind.HELP_SUBJECT)
-                        .map(c -> c.command + " ")
+                        .map(c -> ((noslash && c.command.startsWith("/"))
+                                ? c.command.substring(1)
+                                : c.command) + " ")
                         .toArray(String[]::new))
                         .completionSuggestions(code, cursor, anchor);
             } else if (code.startsWith("/se")) {
@@ -1689,19 +1695,29 @@
         return commandCompletions.completionSuggestions(code, cursor, anchor);
     }
 
-    public String commandDocumentation(String code, int cursor, boolean shortDescription) {
+    public List<String> commandDocumentation(String code, int cursor, boolean shortDescription) {
         code = code.substring(0, cursor);
         int space = code.indexOf(' ');
-
-        if (space != (-1)) {
-            String cmd = code.substring(0, space);
-            Command command = commands.get(cmd);
-            if (command != null) {
-                return getResourceString(command.helpKey + (shortDescription ? ".summary" : ""));
+        String prefix = space != (-1) ? code.substring(0, space) : code;
+        List<String> result = new ArrayList<>();
+
+        List<Entry<String, Command>> toShow =
+                commands.entrySet()
+                        .stream()
+                        .filter(e -> e.getKey().startsWith(prefix))
+                        .filter(e -> e.getValue().kind.showInHelp)
+                        .sorted((e1, e2) -> e1.getKey().compareTo(e2.getKey()))
+                        .collect(Collectors.toList());
+
+        if (toShow.size() == 1) {
+            result.add(getResourceString(toShow.get(0).getValue().helpKey + (shortDescription ? ".summary" : "")));
+        } else {
+            for (Entry<String, Command> e : toShow) {
+                result.add(e.getKey() + "\n" +getResourceString(e.getValue().helpKey + (shortDescription ? ".summary" : "")));
             }
         }
 
-        return null;
+        return result;
     }
 
     // Attempt to stop currently running evaluation
@@ -2087,8 +2103,11 @@
         ArgTokenizer at = new ArgTokenizer("/help", arg);
         String subject = at.next();
         if (subject != null) {
+            // check if the requested subject is a help subject or
+            // a command, with or without slash
             Command[] matches = commands.values().stream()
-                    .filter(c -> c.command.startsWith(subject))
+                    .filter(c -> c.command.startsWith(subject)
+                              || c.command.substring(1).startsWith(subject))
                     .toArray(Command[]::new);
             if (matches.length == 1) {
                 String cmd = matches[0].command;
@@ -2113,6 +2132,18 @@
                 }
                 return true;
             } else {
+                // failing everything else, check if this is the start of
+                // a /set sub-command name
+                String[] subs = Arrays.stream(SET_SUBCOMMANDS)
+                        .filter(s -> s.startsWith(subject))
+                        .toArray(String[]::new);
+                if (subs.length > 0) {
+                    for (String sub : subs) {
+                        hardrb("help.set." + sub);
+                        hard("");
+                    }
+                    return true;
+                }
                 errormsg("jshell.err.help.arg", arg);
             }
         }
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Thu Apr 06 18:56:04 2017 +0100
@@ -97,7 +97,10 @@
 jshell.msg.help.subject =\n\
 For more information type ''/help'' followed by the name of a\n\
 command or a subject.\n\
-For example ''/help /list'' or ''/help intro''.  Subjects:\n
+For example ''/help /list'' or ''/help intro''.\n\
+\n\
+Subjects:\n\
+\n
 
 jshell.err.drop.arg =\
 In the /drop argument, please specify an import, variable, method, or class to drop.\n\
@@ -150,12 +153,17 @@
 
 jshell.err.corrupted.stored.startup = Corrupted stored startup, using default -- {0}
 
-jshell.console.see.more = <press tab to see more>
-jshell.console.see.javadoc = <press shift-tab again to see javadoc>
-jshell.console.see.help = <press shift-tab again to see detailed help>
-jshell.console.see.next.page = <press space for next page, Q to quit>
-jshell.console.see.next.javadoc = <press space for next javadoc, Q to quit>
-jshell.console.no.javadoc = <no javadoc found>
+jshell.console.see.synopsis = <press tab again to see synopsis>
+jshell.console.see.full.documentation = <press tab again to see full documentation>
+jshell.console.see.documentation = <press tab again to see documentation>
+jshell.console.see.next.page = <press tab again to see next page>
+jshell.console.see.next.javadoc = <press tab to see next documentation>
+jshell.console.see.next.command.doc = <press tab to see next command>
+jshell.console.no.such.command = No such command
+jshell.console.completion.current.signatures = Signatures:
+jshell.console.completion.all.completions.number = <press tab again to see all possible completions; total possible completions: {0}>
+jshell.console.completion.all.completions = <press tab again to see all possible completions>
+jshell.console.no.javadoc = <no documentation found>
 jshell.console.do.nothing = Do nothing
 jshell.console.choice = Choice: \
 
@@ -403,7 +411,7 @@
 /help\n\t\
      List the jshell commands and help subjects.\n\n\
 /help <command>\n\t\
-     Display information about the specified comand. The slash must be included.\n\t\
+     Display information about the specified command. The slash must be included.\n\t\
      Only the first few letters of the command are needed -- if more than one\n\t\
      each will be displayed.  Example:  /help /li\n\n\
 /help <subject>\n\t\
@@ -444,7 +452,7 @@
 /?\n\t\
      Display list of commands and help subjects.\n\
 /? <command>\n\t\
-     Display information about the specified comand. The slash must be included.\n\t\
+     Display information about the specified command. The slash must be included.\n\t\
      Only the first few letters of the command are needed -- if more than one\n\t\
      match, each will be displayed.  Example:  /? /li\n\
 /? <subject>\n\t\
@@ -478,7 +486,8 @@
 \n\
 For a list of commands: /help
 
-help.shortcuts.summary = a description of shortcuts
+help.shortcuts.summary = a description of keystrokes for snippet and command completion,\n\
+information access, and automatic code generation
 help.shortcuts =\
 Supported shortcuts include:\n\
 \n\
@@ -486,19 +495,16 @@
         After entering the first few letters of a Java identifier,\n\t\t\
         a jshell command, or, in some cases, a jshell command argument,\n\t\t\
         press the <tab> key to complete the input.\n\t\t\
-        If there is more than one completion, show possible completions.\n\n\
-Shift-<tab>\n\t\t\
-        After the name and open parenthesis of a method or constructor invocation,\n\t\t\
-        hold the <shift> key and press the <tab> to see a synopsis of all\n\t\t\
-        matching methods/constructors.\n\n\
-<fix-shortcut> v\n\t\t\
-        After a complete expression, press "<fix-shortcut> v" to introduce a new variable\n\t\t\
-        whose type is based on the type of the expression.\n\t\t\
-        The "<fix-shortcut>" is either Alt-F1 or Alt-Enter, depending on the platform.\n\n\
-<fix-shortcut> i\n\t\t\
-        After an unresolvable identifier, press "<fix-shortcut> i" and jshell will propose\n\t\t\
-        possible fully qualified names based on the content of the specified classpath.\n\t\t\
-        The "<fix-shortcut>" is either Alt-F1 or Alt-Enter, depending on the platform.
+        If there is more than one completion, then possible completions will be shown.\n\t\t\
+        Will show documentation if available and appropriate.\n\n\
+Shift-<tab> v\n\t\t\
+        After a complete expression, hold down <shift> while pressing <tab>,\n\t\t\
+        then release and press "v", the expression will be converted to\n\t\t\
+        a variable declaration whose type is based on the type of the expression.\n\t\t\
+Shift-<tab> i\n\t\t\
+        After an unresolvable identifier, hold down <shift> while pressing <tab>,\n\t\t\
+        then release and press "i", and jshell will propose possible imports\n\t\t\
+        which will resolve the identifier based on the content of the specified classpath.\n\t\t\
 
 help.context.summary = the evaluation context options for /env /reload and /reset
 help.context =\
@@ -791,7 +797,7 @@
 help.set.start =\
 Set the start-up configuration -- a sequence of snippets and commands read at start-up:\n\
 \n\t\
-/set start [-retain] <file>\n\
+/set start [-retain] <file>...\n\
 \n\t\
 /set start [-retain] -default\n\
 \n\t\
@@ -806,9 +812,9 @@
 /set start\n\
 \n\
 The contents of the specified <file> become the start-up snippets and commands used\n\
-when the /reset or /reload commands are used in this session.\n\
-If instead the -default option is specified, the predefined start-up snippets\n\
-will be used.\n\
+when the /reset, /reload, or /env commands are used in this session.\n\
+If instead the -default option is specified, the predefined start-up import\n\
+snippets will be used.\n\
 If the -none option is used, the start-up will be empty -- no start-up snippets\n\
 or commands will be used.\n\
 This command is good for testing the start-up settings.  To retain them for future\n\
@@ -820,7 +826,16 @@
 \n\
 The form without <file> or options shows the start-up setting.\n\
 Note: if the start-up was last set from a file, this is shown with the\n\
-contents of the file followed by a 'set start' command.
+'set start' command followed by the contents of the file.\n\
+\n\
+The <file> may be an operating system file name, or one of the predefined\n\
+startup file names: DEFAULT, PRINTING, or JAVASE.\n\
+These are respectively: the default import snippets (as used by -default),\n\
+definitions of print(), println(), and printf() method snippets, or\n\
+imports of all Java SE packages.\n\
+More than one <file> may be specified, for example:\n\
+\n\t\
+/set start -retain DEFAULT PRINTING
 
 startup.feedback = \
 /set mode verbose -command    \n\
@@ -911,3 +926,7 @@
 /set format silent errorpre '|  '    \n\
 /set format silent errorpost '%n'    \n\
 /set format silent display ''    \n
+
+jshell.fix.wrong.shortcut =\
+Invalid <fix> character.  Use "i" for auto-import or "v" for variable creation.  For more information see:\n\
+   /help shortcuts
--- a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java	Thu Apr 06 18:56:04 2017 +0100
@@ -1277,12 +1277,16 @@
                  .allMatch(param -> param.getSimpleName().toString().startsWith("arg"));
     }
 
+    private static List<Path> availableSourcesOverride; //for tests
     private List<Path> availableSources;
 
     private List<Path> findSources() {
         if (availableSources != null) {
             return availableSources;
         }
+        if (availableSourcesOverride != null) {
+            return availableSources = availableSourcesOverride;
+        }
         List<Path> result = new ArrayList<>();
         Path home = Paths.get(System.getProperty("java.home"));
         Path srcZip = home.resolve("lib").resolve("src.zip");
--- a/src/jdk.jshell/share/classes/module-info.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/src/jdk.jshell/share/classes/module-info.java	Thu Apr 06 18:56:04 2017 +0100
@@ -52,6 +52,7 @@
  *     definitions.
  * </p>
  *
+ * @moduleGraph
  * @since 9
  */
 module jdk.jshell {
--- a/test/jdk/javadoc/tool/modules/ReleaseOptions.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/test/jdk/javadoc/tool/modules/ReleaseOptions.java	Thu Apr 06 18:56:04 2017 +0100
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8175346
+ * @bug 8175346 8175277
  * @summary Test release option interactions
  * @modules
  *      jdk.javadoc/jdk.javadoc.internal.api
@@ -58,7 +58,7 @@
         Task.Result result = execNegativeTask("--release", "8",
                 "--patch-module", "m=" + mpath.toString(),
                 "p");
-        assertMessagePresent(".*No source files for package p.*");
+        assertMessagePresent(".*not allowed with target 1.8.*");
         assertMessageNotPresent(".*Exception*");
         assertMessageNotPresent(".java.lang.AssertionError.*");
     }
@@ -80,20 +80,20 @@
         assertMessageNotPresent(".java.lang.AssertionError.*");
     }
 
-//    @Test TBD, JDK-8175277, argument validation should fail on this
-//    public void testReleaseWithModuleSourcepath(Path base) throws Exception {
-//        Path src = Paths.get(base.toString(), "src");
-//        Path mpath = Paths.get(src.toString(), "m");
-//
-//        tb.writeJavaFiles(mpath,
-//                "module m { exports p; }",
-//                "package p; public class C { }");
-//
-//        Task.Result result = execNegativeTask("--release", "8",
-//                "--module-source-path", src.toString(),
-//                "--module", "m");
-//        assertMessagePresent(".*(use -source 9 or higher to enable modules).*");
-//        assertMessageNotPresent(".*Exception*");
-//        assertMessageNotPresent(".java.lang.AssertionError.*");
-//    }
+    @Test
+    public void testReleaseWithModuleSourcepath(Path base) throws Exception {
+        Path src = Paths.get(base.toString(), "src");
+        Path mpath = Paths.get(src.toString(), "m");
+
+        tb.writeJavaFiles(mpath,
+                "module m { exports p; }",
+                "package p; public class C { }");
+
+        Task.Result result = execNegativeTask("--release", "8",
+                "--module-source-path", src.toString(),
+                "--module", "m");
+        assertMessagePresent(".*not allowed with target 1.8.*");
+        assertMessageNotPresent(".*Exception*");
+        assertMessageNotPresent(".java.lang.AssertionError.*");
+    }
 }
--- a/test/jdk/jshell/CommandCompletionTest.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/test/jdk/jshell/CommandCompletionTest.java	Thu Apr 06 18:56:04 2017 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8144095 8164825 8169818 8153402 8165405
+ * @bug 8144095 8164825 8169818 8153402 8165405 8177079
  * @summary Test Command Completion
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -173,7 +173,9 @@
                 "/save ", "/set "),
                 a -> assertCompletion(a, "/help /set |", false,
                 "editor", "feedback", "format", "mode", "prompt", "start", "truncation"),
-                a -> assertCompletion(a, "/help /edit |", false)
+                a -> assertCompletion(a, "/help /edit |", false),
+                a -> assertCompletion(a, "/help dr|", false,
+                "drop ")
         );
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jshell/MergedTabShiftTabTest.java	Thu Apr 06 18:56:04 2017 +0100
@@ -0,0 +1,565 @@
+/*
+ * 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
+ * @build MergedTabShiftTabTest
+ * @run testng MergedTabShiftTabTest
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.Writer;
+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.HashMap;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import jdk.jshell.JShell;
+import jdk.jshell.tool.JavaShellToolBuilder;
+import org.testng.annotations.Test;
+
+@Test
+public class MergedTabShiftTabTest {
+
+    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 void doRunTest(Test test) throws Exception {
+        PipeInputStream input = new PipeInputStream();
+        StringBuilder out = new StringBuilder();
+        PrintStream outS = new PrintStream(new OutputStream() {
+            @Override public void write(int b) throws IOException {
+                synchronized (out) {
+                    System.out.print((char) b);
+                    out.append((char) b);
+                    out.notifyAll();
+                }
+            }
+        });
+        Thread runner = new Thread(() -> {
+            try {
+                JavaShellToolBuilder.builder()
+                        .in(input, input)
+                        .out(outS)
+                        .err(outS)
+                        .promptCapture(true)
+                        .persistence(new HashMap<>())
+                        .locale(Locale.US)
+                        .run("--no-startup");
+            } catch (Exception ex) {
+                throw new IllegalStateException(ex);
+            }
+        });
+
+        Writer inputSink = new OutputStreamWriter(input.createOutput()) {
+            @Override
+            public void write(String str) throws IOException {
+                super.write(str);
+                flush();
+            }
+        };
+
+        runner.start();
+
+        try {
+            waitOutput(out, "\u0005");
+            test.test(inputSink, out);
+        } finally {
+            inputSink.write("\003\003/exit");
+
+            runner.join(1000);
+            if (runner.isAlive()) {
+                runner.stop();
+            }
+        }
+    }
+
+    interface Test {
+        public void test(Writer inputSink, StringBuilder out) throws Exception;
+    }
+
+    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);
+    }
+
+    private static final long TIMEOUT;
+
+    static {
+        long factor;
+
+        try {
+            factor = (long) Double.parseDouble(System.getProperty("test.timeout.factor", "1"));
+        } catch (NumberFormatException ex) {
+            factor = 1;
+        }
+        TIMEOUT = 60_000 * factor;
+    }
+
+    private void waitOutput(StringBuilder out, String expected) {
+        expected = expected.replaceAll("\n", System.getProperty("line.separator"));
+        Pattern expectedPattern = Pattern.compile(expected, Pattern.DOTALL);
+        synchronized (out) {
+            long s = System.currentTimeMillis();
+
+            while (true) {
+                Matcher m = expectedPattern.matcher(out);
+                if (m.find()) {
+                    out.delete(0, m.end() + 1);
+                    return ;
+                }
+                long e =  System.currentTimeMillis();
+                if ((e - s) > TIMEOUT) {
+                    throw new IllegalStateException("Timeout waiting for: " + quote(expected) + ", actual output so far: " + quote(out.toString()));
+                }
+                try {
+                    out.wait(TIMEOUT);
+                } catch (InterruptedException ex) {
+                    ex.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private String quote(String original) {
+        StringBuilder output = new StringBuilder();
+
+        for (char c : original.toCharArray()) {
+            if (c < 32) {
+                output.append(String.format("\\u%04X", (int) c));
+            } else {
+                output.append(c);
+            }
+        }
+
+        return output.toString();
+    }
+
+    private static class PipeInputStream extends InputStream {
+
+        private static final int INITIAL_SIZE = 128;
+        private int[] buffer = new int[INITIAL_SIZE];
+        private int start;
+        private int end;
+        private boolean closed;
+
+        @Override
+        public synchronized int read() throws IOException {
+            if (start == end && !closed) {
+                inputNeeded();
+            }
+            while (start == end) {
+                if (closed) {
+                    return -1;
+                }
+                try {
+                    wait();
+                } catch (InterruptedException ex) {
+                    //ignore
+                }
+            }
+            try {
+                return buffer[start];
+            } finally {
+                start = (start + 1) % buffer.length;
+            }
+        }
+
+        @Override
+        public synchronized int read(byte[] b, int off, int len) throws IOException {
+            if (b == null) {
+                throw new NullPointerException();
+            } else if (off < 0 || len < 0 || len > b.length - off) {
+                throw new IndexOutOfBoundsException();
+            } else if (len == 0) {
+                return 0;
+            }
+
+            int c = read();
+            if (c == -1) {
+                return -1;
+            }
+            b[off] = (byte)c;
+
+            int totalRead = 1;
+            while (totalRead < len && start != end) {
+                int r = read();
+                if (r == (-1))
+                    break;
+                b[off + totalRead++] = (byte) r;
+            }
+            return totalRead;
+        }
+
+        protected void inputNeeded() throws IOException {}
+
+        private synchronized void write(int b) {
+            if (closed) {
+                throw new IllegalStateException("Already closed.");
+            }
+            int newEnd = (end + 1) % buffer.length;
+            if (newEnd == start) {
+                //overflow:
+                int[] newBuffer = new int[buffer.length * 2];
+                int rightPart = (end > start ? end : buffer.length) - start;
+                int leftPart = end > start ? 0 : start - 1;
+                System.arraycopy(buffer, start, newBuffer, 0, rightPart);
+                System.arraycopy(buffer, 0, newBuffer, rightPart, leftPart);
+                buffer = newBuffer;
+                start = 0;
+                end = rightPart + leftPart;
+                newEnd = end + 1;
+            }
+            buffer[end] = b;
+            end = newEnd;
+            notifyAll();
+        }
+
+        @Override
+        public synchronized void close() {
+            closed = true;
+            notifyAll();
+        }
+
+        public OutputStream createOutput() {
+            return new OutputStream() {
+                @Override public void write(int b) throws IOException {
+                    PipeInputStream.this.write(b);
+                }
+                @Override
+                public void write(byte[] b, int off, int len) throws IOException {
+                    for (int i = 0 ; i < len ; i++) {
+                        write(Byte.toUnsignedInt(b[off + i]));
+                    }
+                }
+                @Override
+                public void close() throws IOException {
+                    PipeInputStream.this.close();
+                }
+            };
+        }
+
+    }
+
+}
--- a/test/jdk/jshell/ToolSimpleTest.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/test/jdk/jshell/ToolSimpleTest.java	Thu Apr 06 18:56:04 2017 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103  8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103  8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079
  * @summary Simple jshell tool tests
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -350,7 +350,9 @@
                 (a) -> assertHelp(a, "/help short", "shortcuts", "<tab>"),
                 (a) -> assertHelp(a, "/? /li", "/list -all", "snippets"),
                 (a) -> assertHelp(a, "/help /set prompt", "optionally contain '%s'", "quoted"),
-                (a) -> assertHelp(a, "/help /help", "/help <command>")
+                (a) -> assertHelp(a, "/help /help", "/help <command>"),
+                (a) -> assertHelp(a, "/help li", "/list -start"),
+                (a) -> assertHelp(a, "/help fe", "/set feedback -retain")
         );
     }
 
--- a/test/tools/javac/modules/EdgeCases.java	Tue Apr 04 22:09:23 2017 -0700
+++ b/test/tools/javac/modules/EdgeCases.java	Thu Apr 06 18:56:04 2017 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8154283 8167320 8171098 8172809 8173068 8173117 8176045
+ * @bug 8154283 8167320 8171098 8172809 8173068 8173117 8176045 8177311
  * @summary tests for multi-module mode compilation
  * @library /tools/lib
  * @modules
@@ -958,4 +958,41 @@
             throw new Exception("expected output not found: " + log);
     }
 
+    @Test
+    public void testDependOnUnnamedAccessibility(Path base) throws Exception {
+        Path unnamedSrc = base.resolve("unnamed-src");
+        tb.writeJavaFiles(unnamedSrc,
+                          "package p1; public class First { public static p2.Second get() { return null; } }",
+                          "package p2; public class Second { public void test() { } }");
+        Path unnamedClasses = base.resolve("unnamed-classes");
+        tb.createDirectories(unnamedClasses);
+
+        System.err.println("compiling unnamed sources:");
+
+        new JavacTask(tb)
+                .outdir(unnamedClasses)
+                .files(findJavaFiles(unnamedSrc))
+                .run()
+                .writeAll();
+
+        //test sources:
+        Path src = base.resolve("src");
+        Path m = src.resolve("m");
+        tb.writeJavaFiles(m,
+                          "module m { }",
+                          "package p; public class Test { { p1.First.get().test(); } }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        System.err.println("compiling test module:");
+
+        new JavacTask(tb)
+            .options("-classpath", unnamedClasses.toString(),
+                     "--add-reads", "m=ALL-UNNAMED")
+            .outdir(classes)
+            .files(findJavaFiles(src))
+            .run()
+            .writeAll();
+    }
+
 }