--- a/langtools/.hgtags Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/.hgtags Mon Dec 05 08:36:16 2016 -0800
@@ -389,3 +389,4 @@
47871e348144bafddea0ede3a44299461e254a2d jdk-9+144
cb9e896265ef45295fdd09986dee76624e4d41e4 jdk-9+145
26f972dc2d174a75bc32131c29661c78568586b0 jdk-9+146
+76389430a13e82a9321cdc085216f6bff526e316 jdk-9+147
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Mon Dec 05 08:36:16 2016 -0800
@@ -1869,6 +1869,12 @@
*/
public static class UndetVar extends DelegatedType {
+ enum Kind {
+ NORMAL,
+ CAPTURED,
+ THROWS;
+ }
+
/** Inference variable change listener. The listener method is called
* whenever a change to the inference variable's bounds occurs
*/
@@ -1929,6 +1935,8 @@
/** inference variable's change listener */
public UndetVarListener listener = null;
+ Kind kind;
+
@Override
public <R,S> R accept(Type.Visitor<R,S> v, S s) {
return v.visitUndetVar(this, s);
@@ -1937,6 +1945,9 @@
public UndetVar(TypeVar origin, UndetVarListener listener, Types types) {
// This is a synthesized internal type, so we cannot annotate it.
super(UNDETVAR, origin);
+ this.kind = origin.isCaptured() ?
+ Kind.CAPTURED :
+ Kind.NORMAL;
this.listener = listener;
bounds = new EnumMap<>(InferenceBound.class);
List<Type> declaredBounds = types.getBounds(origin);
@@ -1948,6 +1959,10 @@
//add bound works in reverse order
addBound(InferenceBound.UPPER, t, types, true);
}
+ if (origin.isCaptured() && !origin.lower.hasTag(BOT)) {
+ //add lower bound if needed
+ addBound(InferenceBound.LOWER, origin.lower, types, true);
+ }
}
@DefinedBy(Api.LANGUAGE_MODEL)
@@ -1977,6 +1992,14 @@
return result;
}
+ public void setThrow() {
+ if (this.kind == Kind.CAPTURED) {
+ //invalid state transition
+ throw new IllegalStateException();
+ }
+ this.kind = Kind.THROWS;
+ }
+
/**
* Returns a new copy of this undet var.
*/
@@ -2062,17 +2085,29 @@
addBound(ib, bound, types, false);
}
- protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
- Type bound2 = bound.map(toTypeVarMap).baseType();
- List<Type> prevBounds = bounds.get(ib);
- if (bound == qtype) return;
- for (Type b : prevBounds) {
- //check for redundancy - use strict version of isSameType on tvars
- //(as the standard version will lead to false positives w.r.t. clones ivars)
- if (types.isSameType(b, bound2, true)) return;
+ @SuppressWarnings("fallthrough")
+ private void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
+ if (kind == Kind.CAPTURED && !update) {
+ //Captured inference variables bounds must not be updated during incorporation,
+ //except when some inference variable (beta) has been instantiated in the
+ //right-hand-side of a 'C<alpha> = capture(C<? extends/super beta>) constraint.
+ if (bound.hasTag(UNDETVAR) && !((UndetVar)bound).isCaptured()) {
+ //If the new incoming bound is itself a (regular) inference variable,
+ //then we are allowed to propagate this inference variable bounds to it.
+ ((UndetVar)bound).addBound(ib.complement(), this, types, false);
+ }
+ } else {
+ Type bound2 = bound.map(toTypeVarMap).baseType();
+ List<Type> prevBounds = bounds.get(ib);
+ if (bound == qtype) return;
+ for (Type b : prevBounds) {
+ //check for redundancy - use strict version of isSameType on tvars
+ //(as the standard version will lead to false positives w.r.t. clones ivars)
+ if (types.isSameType(b, bound2, true)) return;
+ }
+ bounds.put(ib, prevBounds.prepend(bound2));
+ notifyBoundChange(ib, bound2, false);
}
- bounds.put(ib, prevBounds.prepend(bound2));
- notifyBoundChange(ib, bound2, false);
}
//where
TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() {
@@ -2128,46 +2163,12 @@
}
}
- public boolean isCaptured() {
- return false;
- }
- }
-
- /**
- * This class is used to represent synthetic captured inference variables
- * that can be generated during nested generic method calls. The only difference
- * between these inference variables and ordinary ones is that captured inference
- * variables cannot get new bounds through incorporation.
- */
- public static class CapturedUndetVar extends UndetVar {
-
- public CapturedUndetVar(CapturedType origin, UndetVarListener listener, Types types) {
- super(origin, listener, types);
- if (!origin.lower.hasTag(BOT)) {
- addBound(InferenceBound.LOWER, origin.lower, types, true);
- }
+ public final boolean isCaptured() {
+ return kind == Kind.CAPTURED;
}
- @Override
- public void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
- if (update) {
- //only change bounds if request comes from substBounds
- super.addBound(ib, bound, types, update);
- }
- else if (bound.hasTag(UNDETVAR) && !((UndetVar) bound).isCaptured()) {
- ((UndetVar) bound).addBound(ib.complement(), this, types, false);
- }
- }
-
- @Override
- public boolean isCaptured() {
- return true;
- }
-
- public UndetVar dup(Types types) {
- UndetVar uv2 = new CapturedUndetVar((CapturedType)qtype, listener, types);
- dupTo(uv2, types);
- return uv2;
+ public final boolean isThrows() {
+ return kind == Kind.THROWS;
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Mon Dec 05 08:36:16 2016 -0800
@@ -2494,6 +2494,11 @@
List<Type> thrownTypes = resultInfo.checkContext.inferenceContext().asUndetVars(lambdaType.getThrownTypes());
chk.unhandled(inferredThrownTypes, thrownTypes);
+
+ //18.2.5: "In addition, for all j (1 <= j <= n), the constraint reduces to the bound throws Ej"
+ thrownTypes.stream()
+ .filter(t -> t.hasTag(UNDETVAR))
+ .forEach(t -> ((UndetVar)t).setThrow());
}
checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, currentTarget);
@@ -3074,6 +3079,10 @@
if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) {
log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes());
}
+ //18.2.5: "In addition, for all j (1 <= j <= n), the constraint reduces to the bound throws Ej"
+ thrownTypes.stream()
+ .filter(t -> t.hasTag(UNDETVAR))
+ .forEach(t -> ((UndetVar)t).setThrow());
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java Mon Dec 05 08:36:16 2016 -0800
@@ -412,6 +412,17 @@
if (owner.kind == TYP) {
// We are seeing a member class.
c = syms.enterClass(env.toplevel.modle, tree.name, (TypeSymbol)owner);
+ if (c.owner != owner) {
+ //anonymous class loaded from a classfile may be recreated from source (see below)
+ //if this class is a member of such an anonymous class, fix the owner:
+ Assert.check(owner.owner.kind != TYP, () -> owner.toString());
+ Assert.check(c.owner.kind == TYP, () -> c.owner.toString());
+ ClassSymbol cowner = (ClassSymbol) c.owner;
+ if (cowner.members_field != null) {
+ cowner.members_field.remove(c);
+ }
+ c.owner = owner;
+ }
if ((owner.flags_field & INTERFACE) != 0) {
tree.mods.flags |= PUBLIC | STATIC;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Mon Dec 05 08:36:16 2016 -0800
@@ -627,12 +627,11 @@
TypeMapping<Void> fromTypeVarFun = new TypeMapping<Void>() {
@Override
public Type visitTypeVar(TypeVar tv, Void aVoid) {
- return new UndetVar(tv, incorporationEngine(), types);
- }
-
- @Override
- public Type visitCapturedType(CapturedType t, Void aVoid) {
- return new CapturedUndetVar(t, incorporationEngine(), types);
+ UndetVar uv = new UndetVar(tv, incorporationEngine(), types);
+ if ((tv.tsym.flags() & Flags.THROWS) != 0) {
+ uv.setThrow();
+ }
+ return uv;
}
};
@@ -1463,7 +1462,7 @@
THROWS(InferenceBound.UPPER) {
@Override
public boolean accepts(UndetVar t, InferenceContext inferenceContext) {
- if ((t.qtype.tsym.flags() & Flags.THROWS) == 0) {
+ if (!t.isThrows()) {
//not a throws undet var
return false;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Mon Dec 05 08:36:16 2016 -0800
@@ -890,6 +890,8 @@
* like UPGRADE_MODULE_PATH and MODULE_PATH.
*/
private class ModulePathLocationHandler extends SimpleLocationHandler {
+ private Map<String, ModuleLocationHandler> pathModules;
+
ModulePathLocationHandler(Location location, Option... options) {
super(location, options);
}
@@ -904,6 +906,12 @@
}
@Override
+ public Location getLocationForModule(String moduleName) {
+ initPathModules();
+ return pathModules.get(moduleName);
+ }
+
+ @Override
Iterable<Set<Location>> listLocationsForModules() {
if (searchPath == null)
return Collections.emptyList();
@@ -921,6 +929,23 @@
super.setPaths(paths);
}
+ private void initPathModules() {
+ if (pathModules != null) {
+ return;
+ }
+
+ pathModules = new LinkedHashMap<>();
+
+ for (Set<Location> set : listLocationsForModules()) {
+ for (Location locn : set) {
+ if (locn instanceof ModuleLocationHandler) {
+ ModuleLocationHandler h = (ModuleLocationHandler) locn;
+ pathModules.put(h.moduleName, h);
+ }
+ }
+ }
+ }
+
private void checkValidModulePathEntry(Path p) {
if (Files.isDirectory(p)) {
// either an exploded module or a directory of modules
@@ -1158,7 +1183,6 @@
private Map<String, Location> moduleLocations;
private Map<Path, Location> pathLocations;
-
ModuleSourcePathLocationHandler() {
super(StandardLocation.MODULE_SOURCE_PATH,
Option.MODULE_SOURCE_PATH);
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Mon Dec 05 08:36:16 2016 -0800
@@ -279,7 +279,7 @@
*/
@Override
public void hard(String format, Object... args) {
- rawout(feedback.getPre() + format + feedback.getPost(), args);
+ rawout(prefix(format), args);
}
/**
@@ -289,7 +289,7 @@
* @param args printf args
*/
void error(String format, Object... args) {
- rawout(feedback.getErrorPre() + format + feedback.getErrorPost(), args);
+ rawout(prefixError(format), args);
}
/**
@@ -315,18 +315,6 @@
}
/**
- * Optional output -- with embedded per- and post-fix
- *
- * @param format printf format
- * @param args printf args
- */
- void fluffRaw(String format, Object... args) {
- if (showFluff()) {
- rawout(format, args);
- }
- }
-
- /**
* Resource bundle look-up
*
* @param key the resource key
@@ -351,28 +339,42 @@
}
/**
- * Add prefixing to embedded newlines in a string, leading with the normal
- * prefix
+ * Add normal prefixing/postfixing to embedded newlines in a string,
+ * bracketing with normal prefix/postfix
*
* @param s the string to prefix
+ * @return the pre/post-fixed and bracketed string
*/
String prefix(String s) {
- return prefix(s, feedback.getPre());
+ return prefix(s, feedback.getPre(), feedback.getPost());
}
/**
- * Add prefixing to embedded newlines in a string
+ * Add error prefixing/postfixing to embedded newlines in a string,
+ * bracketing with error prefix/postfix
*
* @param s the string to prefix
- * @param leading the string to prepend
+ * @return the pre/post-fixed and bracketed string
*/
- String prefix(String s, String leading) {
- if (s == null || s.isEmpty()) {
+ String prefixError(String s) {
+ return prefix(s, feedback.getErrorPre(), feedback.getErrorPost());
+ }
+
+ /**
+ * Add prefixing/postfixing to embedded newlines in a string,
+ * bracketing with prefix/postfix
+ *
+ * @param s the string to prefix
+ * @param pre the string to prepend to each line
+ * @param post the string to append to each line (replacing newline)
+ * @return the pre/post-fixed and bracketed string
+ */
+ String prefix(String s, String pre, String post) {
+ if (s == null) {
return "";
}
- return leading
- + s.substring(0, s.length() - 1).replaceAll("\\R", System.getProperty("line.separator") + feedback.getPre())
- + s.substring(s.length() - 1, s.length());
+ String pp = s.replaceAll("\\R", post + pre);
+ return pre + pp + post;
}
/**
@@ -381,8 +383,7 @@
* @param key the resource key
*/
void hardrb(String key) {
- String s = prefix(getResourceString(key));
- cmdout.println(s);
+ hard(getResourceString(key));
}
/**
@@ -405,7 +406,7 @@
*/
@Override
public void hardmsg(String key, Object... args) {
- cmdout.println(prefix(messageFormat(key, args)));
+ hard(messageFormat(key, args));
}
/**
@@ -418,7 +419,7 @@
@Override
public void errormsg(String key, Object... args) {
if (isRunningInteractive()) {
- cmdout.println(prefix(messageFormat(key, args), feedback.getErrorPre()));
+ rawout(prefixError(messageFormat(key, args)));
} else {
startmsg(key, args);
}
@@ -431,7 +432,7 @@
* @param args
*/
void startmsg(String key, Object... args) {
- cmderr.println(prefix(messageFormat(key, args), ""));
+ cmderr.println(messageFormat(key, args));
}
/**
@@ -452,15 +453,9 @@
Map<String, String> a2b = stream.collect(toMap(a, b,
(m1, m2) -> m1,
() -> new LinkedHashMap<>()));
- int aLen = 0;
- for (String av : a2b.keySet()) {
- aLen = Math.max(aLen, av.length());
- }
- String format = " %-" + aLen + "s -- %s";
- String indentedNewLine = LINE_SEP + feedback.getPre()
- + String.format(" %-" + (aLen + 4) + "s", "");
for (Entry<String, String> e : a2b.entrySet()) {
- hard(format, e.getKey(), e.getValue().replaceAll("\n", indentedNewLine));
+ hard("%s", e.getKey());
+ rawout(prefix(e.getValue(), feedback.getPre() + "\t", feedback.getPost()));
}
}
@@ -1096,6 +1091,7 @@
}
if (path.isEmpty()) {
StreamSupport.stream(FileSystems.getDefault().getRootDirectories().spliterator(), false)
+ .filter(root -> Files.exists(root))
.filter(root -> accept.test(root) && root.toString().startsWith(prefix))
.map(root -> new ArgSuggestion(root.toString()))
.forEach(result::add);
@@ -1697,7 +1693,7 @@
} else if (start.isEmpty()) {
stset = cmd + "-none";
} else {
- stset = prefix("startup.jsh:\n" + start + "\n" + cmd + "startup.jsh", "");
+ stset = "startup.jsh:\n" + start + "\n" + cmd + "startup.jsh";
}
hard(stset);
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Mon Dec 05 08:36:16 2016 -0800
@@ -25,7 +25,7 @@
jshell.msg.welcome =\
Welcome to JShell -- Version {0}\n\
-For an introduction type: /help intro\n
+For an introduction type: /help intro
jshell.err.opt.arg = Argument to {0} missing.
jshell.err.opt.invalid = Invalid options: {0}.
jshell.err.opt.one = Only one {0} option may be used.
@@ -94,7 +94,8 @@
Type a Java language expression, statement, or declaration.\n\
Or type one of the following commands:\n
jshell.msg.help.subject =\n\
-For more information type ''/help'' followed by the name of command or a 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
jshell.err.drop.arg =\
@@ -674,7 +675,7 @@
\n\
Where <mode> is the name of a previously defined feedback mode.\n\
Where <prompt> and <continuation-prompt> are quoted strings printed as input prompts;\n\
-Both may optionally contain '%s' which will be substituted with the next snippet id --\n\
+Both may optionally contain '%%s' which will be substituted with the next snippet id --\n\
note that what is entered may not be assigned that id, for example it may be an error or command.\n\
The continuation-prompt is used on the second and subsequent lines of a multi-line snippet.\n\
\n\
--- a/langtools/src/jdk.jshell/share/classes/module-info.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/module-info.java Mon Dec 05 08:36:16 2016 -0800
@@ -30,12 +30,12 @@
*/
module jdk.jshell {
requires transitive java.compiler;
+ requires transitive jdk.jdi;
requires java.prefs;
requires jdk.compiler;
requires jdk.internal.le;
requires jdk.internal.ed;
requires jdk.internal.opt;
- requires jdk.jdi;
exports jdk.jshell;
exports jdk.jshell.spi;
--- a/langtools/test/jdk/jshell/CommandCompletionTest.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/test/jdk/jshell/CommandCompletionTest.java Mon Dec 05 08:36:16 2016 -0800
@@ -46,6 +46,7 @@
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import org.testng.annotations.Test;
@@ -144,7 +145,7 @@
Compiler compiler = new Compiler();
assertCompletion("/o|", false, "/open ");
List<String> p1 = listFiles(Paths.get(""));
- FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
+ getRootDirectories().forEach(s -> p1.add(s.toString()));
Collections.sort(p1);
assertCompletion("/open |", false, p1.toArray(new String[p1.size()]));
Path classDir = compiler.getClassDir();
@@ -157,7 +158,7 @@
assertCompletion("/s|", false, "/save ", "/set ");
List<String> p1 = listFiles(Paths.get(""));
Collections.addAll(p1, "-all ", "-history ", "-start ");
- FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
+ getRootDirectories().forEach(s -> p1.add(s.toString()));
Collections.sort(p1);
assertCompletion("/save |", false, p1.toArray(new String[p1.size()]));
Path classDir = compiler.getClassDir();
@@ -198,7 +199,7 @@
public void testSet() throws IOException {
List<String> p1 = listFiles(Paths.get(""));
- FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
+ getRootDirectories().forEach(s -> p1.add(s.toString()));
Collections.sort(p1);
String[] modes = {"concise ", "normal ", "silent ", "verbose "};
@@ -267,4 +268,13 @@
(Files.isDirectory(file) ||
file.getFileName().toString().endsWith(".jar") ||
file.getFileName().toString().endsWith(".zip"));
+
+ private static Iterable<? extends Path> getRootDirectories() {
+ return StreamSupport.stream(FileSystems.getDefault()
+ .getRootDirectories()
+ .spliterator(),
+ false)
+ .filter(p -> Files.exists(p))
+ .collect(Collectors.toList());
+ }
}
--- a/langtools/test/jdk/jshell/EditorTestBase.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/test/jdk/jshell/EditorTestBase.java Mon Dec 05 08:36:16 2016 -0800
@@ -253,7 +253,11 @@
a -> assertEditOutput(a, "/ed", "b ==> 10", () -> {
writeSource(getSource() + "\nint b = 10");
exit();
- })
+ }),
+
+ //TODO: this is a work-around to JDK-8170369
+ a -> assertCommand(a, "1234",
+ null, "", null, null, "")
);
}
--- a/langtools/test/jdk/jshell/ExternalEditorTest.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/test/jdk/jshell/ExternalEditorTest.java Mon Dec 05 08:36:16 2016 -0800
@@ -24,7 +24,7 @@
/*
* @test
* @summary Testing external editor.
- * @bug 8143955 8080843 8163816 8143006
+ * @bug 8143955 8080843 8163816 8143006 8169828
* @modules jdk.jshell/jdk.internal.jshell.tool
* @build ReplToolTesting CustomEditor EditorTestBase
* @run testng ExternalEditorTest
--- a/langtools/test/jdk/jshell/ToolCommandOptionTest.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/test/jdk/jshell/ToolCommandOptionTest.java Mon Dec 05 08:36:16 2016 -0800
@@ -23,12 +23,16 @@
/*
* @test
- * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637
+ * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637 8170368
* @summary Tests of jshell comand options, and undoing operations
* @modules jdk.jshell/jdk.internal.jshell.tool
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @library /tools/lib
* @build ToolCommandOptionTest ReplToolTesting
* @run testng ToolCommandOptionTest
*/
+import java.nio.file.Path;
import org.testng.annotations.Test;
import static org.testng.Assert.assertFalse;
@@ -240,6 +244,9 @@
}
public void setStartTest() {
+ Compiler compiler = new Compiler();
+ Path startup = compiler.getPath("StartTest/startup.txt");
+ compiler.writeToFile(startup, "int iAmHere = 1234;");
test(
(a) -> assertCommand(a, "/set start -furball",
"| Unknown option: -furball -- /set start -furball"),
@@ -257,6 +264,13 @@
""),
(a) -> assertCommand(a, "/set start",
"| /set start -default"),
+ (a) -> assertCommand(a, "/set start " + startup.toString(),
+ ""),
+ (a) -> assertCommand(a, "/set start",
+ "| startup.jsh:\n" +
+ "| int iAmHere = 1234;\n" +
+ "| \n" +
+ "| /set start startup.jsh"),
(a) -> assertCommand(a, "/se sta -no",
""),
(a) -> assertCommand(a, "/set start",
@@ -265,6 +279,9 @@
}
public void retainStartTest() {
+ Compiler compiler = new Compiler();
+ Path startup = compiler.getPath("StartTest/startup.txt");
+ compiler.writeToFile(startup, "int iAmHere = 1234;");
test(
(a) -> assertCommand(a, "/set start -retain -furball",
"| Unknown option: -furball -- /set start -retain -furball"),
@@ -292,7 +309,14 @@
(a) -> assertCommand(a, "/se st -ret",
""),
(a) -> assertCommand(a, "/se sta",
- "| /set start -retain -none")
+ "| /set start -retain -none"),
+ (a) -> assertCommand(a, "/set start -retain " + startup.toString(),
+ ""),
+ (a) -> assertCommand(a, "/set start",
+ "| startup.jsh:\n" +
+ "| int iAmHere = 1234;\n" +
+ "| \n" +
+ "| /set start -retain startup.jsh")
);
}
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java Thu Dec 01 10:34:29 2016 -0800
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java Mon Dec 05 08:36:16 2016 -0800
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368
* @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -280,6 +280,16 @@
);
}
+ public void testApplicationOfPost() {
+ test(
+ (a) -> assertCommand(a, "/set mode t normal -command", "| Created new feedback mode: t"),
+ (a) -> assertCommand(a, "/set feedback t", "| Feedback mode: t"),
+ (a) -> assertCommand(a, "/set format t post \"$%n\"", ""),
+ (a) -> assertCommand(a, "/set prompt t \"+\" \"-\"", ""),
+ (a) -> assertCommand(a, "/set prompt t", "| /set prompt t \"+\" \"-\"$")
+ );
+ }
+
public void testHelpLength() {
Consumer<String> testOutput = (s) -> {
List<String> ss = Stream.of(s.split("\n"))
@@ -300,14 +310,35 @@
(a) -> assertHelp(a, "/help", "/list", "/help", "/exit", "intro"),
(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>")
);
}
+ public void testHelpFormat() {
+ test(
+ (a) -> assertCommandCheckOutput(a, "/help", s -> {
+ String[] lines = s.split("\\R");
+ assertTrue(lines.length > 20,
+ "Too few lines of /help output: " + lines.length
+ + "\n" + s);
+ for (int i = 0; i < lines.length; ++i) {
+ String l = lines[i];
+ assertTrue(l.startsWith("| "),
+ "Expected /help line to start with | :\n" + l);
+ assertTrue(l.length() <= 80,
+ "/help line too long: " + l.length() + "\n" + l);
+ }
+ })
+ );
+ }
+
private void assertHelp(boolean a, String command, String... find) {
assertCommandCheckOutput(a, command, s -> {
for (String f : find) {
- assertTrue(s.contains(f), "Expected output of " + command + " to contain: " + f);
+ assertTrue(s.contains(f),
+ "Expected output of " + command + " to contain: " + f
+ + "\n" + s);
}
});
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/8170410/T8170410.java Mon Dec 05 08:36:16 2016 -0800
@@ -0,0 +1,23 @@
+/*
+ * @test
+ * @bug 8170410
+ * @summary inference: javac doesn't implement 18.2.5 correctly
+ * @compile T8170410.java
+ */
+
+class T8170410 {
+ interface CheckedSupplier<T extends Throwable, R> {
+ R get() throws T;
+ }
+
+ static <T extends Throwable, R> CheckedSupplier<T, R> checked(CheckedSupplier<T, R> checkedSupplier) {
+ return checkedSupplier;
+ }
+
+ static void test() {
+ checked(() -> null).get();
+ checked(T8170410::m).get();
+ }
+
+ static String m() { return ""; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/GetLocationForModuleTest.java Mon Dec 05 08:36:16 2016 -0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8162712
+ * @summary StandardJavaFileManager.getModuleLocation() can't find a module
+ * @library /tools/lib
+ * @modules
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.JavacTask toolbox.ToolBox
+ * @run main GetLocationForModuleTest
+ */
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.util.*;
+import javax.tools.*;
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
+public class GetLocationForModuleTest extends ModuleTestBase {
+ public static void main(String... args) throws Exception {
+ new GetLocationForModuleTest().run(Paths.get("."));
+ }
+
+ public void run(Path base) throws Exception {
+ // Set up some trivial modules
+ Path moduleSrc = base.resolve("module-src");
+ Path m1 = moduleSrc.resolve("m1");
+ tb.writeJavaFiles(m1, "module m1 { }");
+ Path m2 = moduleSrc.resolve("m2");
+ tb.writeJavaFiles(m2, "module m2 { }");
+
+ Path modulePath = base.resolve("module-path");
+ Files.createDirectories(modulePath);
+ new JavacTask(tb)
+ .options("--module-source-path", moduleSrc.toString())
+ .outdir(modulePath)
+ .files(findJavaFiles(moduleSrc))
+ .run()
+ .writeAll();
+
+ // Init file manager
+ StandardJavaFileManager fm =
+ ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null);
+ fm.setLocationFromPaths(StandardLocation.MODULE_PATH, Arrays.asList(modulePath));
+
+ // Test
+ test(fm, StandardLocation.SYSTEM_MODULES, "java.base", "java.compiler");
+ test(fm, StandardLocation.MODULE_PATH, "m1", "m2");
+ }
+
+ void test(JavaFileManager fm, JavaFileManager.Location locn, String... mods) throws IOException {
+ for (String mod : mods) {
+ JavaFileManager.Location modLocn = fm.getLocationForModule(locn, mod);
+ if (modLocn == null) {
+ error(locn.getName() + ": can't find " + mod);
+ } else {
+ System.err.println(locn.getName() + ": found " + mod + ": " + modLocn.getName());
+ }
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/LocalInAnonymous.java Mon Dec 05 08:36:16 2016 -0800
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8166628
+ * @summary Verify that loading a classfile for a local class that is a member of an anonymous class
+ * won't break compilation.
+ * @modules jdk.compiler
+ */
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+import com.sun.source.tree.BlockTree;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskEvent.Kind;
+import com.sun.source.util.TaskListener;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+
+public class LocalInAnonymous {
+
+ public static void main(String[] args) throws Exception {
+ Path base = Paths.get(".").toAbsolutePath();
+ Path classes = base.resolve("classes");
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ DiagnosticListener<JavaFileObject> noErrors = d -> {
+ if (d.getKind() == Diagnostic.Kind.ERROR) {
+ throw new AssertionError(d.getMessage(null));
+ }
+ };
+ List<TJFO> files = Arrays.asList(new TJFO("Test", CODE));
+ List<String> options = Arrays.asList("-d", classes.toString());
+ StringWriter out = new StringWriter();
+ JavacTask task = (JavacTask) compiler.getTask(out, null, noErrors, options, null, files);
+ task.call();
+ if (!out.toString().isEmpty()) {
+ throw new AssertionError("Unexpected output: " + out);
+ }
+ options = Arrays.asList("-classpath", classes.toString(), "-d", classes.toString());
+ JavacTask task2 = (JavacTask) compiler.getTask(out, null, noErrors, options, null, files);
+ task2.addTaskListener(new TaskListener() {
+ @Override
+ public void started(TaskEvent te) {
+ }
+ @Override
+ public void finished(TaskEvent te) {
+ if (te.getKind() == Kind.ENTER) {
+ Element pack = task2.getElements().getTypeElement("Test").getEnclosingElement();
+ System.err.println(pack.getEnclosedElements());
+ }
+ if (te.getKind() == Kind.ANALYZE) {
+ PackageElement pack = task2.getElements().getPackageOf(te.getTypeElement());
+ new OwnerCheck(Trees.instance(task2), pack).scan(te.getCompilationUnit(), null);
+ }
+ }
+ });
+ task2.call();
+ if (!out.toString().isEmpty()) {
+ throw new AssertionError("Unexpected output: " + out);
+ }
+ options = Arrays.asList("-classpath", classes.toString(),
+ "-d", classes.toString(),
+ "-processorpath", System.getProperty("test.classes"),
+ "-processor", Processor.class.getName());
+ JavacTask task3 = (JavacTask) compiler.getTask(out, null, noErrors, options, null, files);
+ task3.call();
+ if (!out.toString().isEmpty()) {
+ throw new AssertionError("Unexpected output: " + out);
+ }
+ }
+
+ private static final class TJFO extends SimpleJavaFileObject {
+
+ private final String code;
+
+ public TJFO(String name, String code) throws URISyntaxException {
+ super(new URI("mem:///" + name + ".java"), Kind.SOURCE);
+ this.code = code;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ return code;
+ }
+
+ }
+
+ @SupportedAnnotationTypes("*")
+ public static final class Processor extends AbstractProcessor {
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ Trees trees = Trees.instance(processingEnv);
+ Elements elements = processingEnv.getElementUtils();
+ Element pack = elements.getTypeElement("Test").getEnclosingElement();
+ for (Element root : pack.getEnclosedElements()) {
+ TreePath tp = trees.getPath(root);
+ new OwnerCheck(trees, pack).scan(tp.getCompilationUnit(), null);
+
+ }
+ return false;
+ }
+
+ }
+
+ private static final class OwnerCheck extends TreePathScanner<Void, Void> {
+ private final Trees trees;
+ private Element currentOwner;
+
+ public OwnerCheck(Trees trees, Element pack) {
+ this.trees = trees;
+ this.currentOwner = pack;
+ }
+
+ @Override
+ public Void visitClass(ClassTree node, Void p) {
+ Element prevOwner = currentOwner;
+ try {
+ Element currentElement = trees.getElement(getCurrentPath());
+ if (currentOwner != null && currentElement.getEnclosingElement() != currentOwner) {
+ throw new AssertionError("Unexpected owner!");
+ }
+ currentOwner = currentElement;
+ return super.visitClass(node, p);
+ } finally {
+ currentOwner = prevOwner;
+ }
+ }
+
+ @Override
+ public Void visitMethod(MethodTree node, Void p) {
+ Element prevOwner = currentOwner;
+ try {
+ Element currentElement = trees.getElement(getCurrentPath());
+ if (currentElement.getEnclosingElement() != currentOwner) {
+ throw new AssertionError("Unexpected owner!");
+ }
+ currentOwner = currentElement;
+ return super.visitMethod(node, p);
+ } finally {
+ currentOwner = prevOwner;
+ }
+ }
+
+ @Override
+ public Void visitVariable(VariableTree node, Void p) {
+ Element currentElement = trees.getElement(getCurrentPath());
+ if (!currentElement.getKind().isField()) {
+ return super.visitVariable(node, p);
+ }
+ Element prevOwner = currentOwner;
+ try {
+ if (currentElement.getEnclosingElement() != currentOwner) {
+ throw new AssertionError("Unexpected owner!");
+ }
+ currentOwner = currentElement;
+ return super.visitVariable(node, p);
+ } finally {
+ currentOwner = prevOwner;
+ }
+ }
+
+ @Override
+ public Void visitBlock(BlockTree node, Void p) {
+ if (getCurrentPath().getParentPath().getLeaf().getKind() != Tree.Kind.CLASS) {
+ return super.visitBlock(node, p);
+ }
+ Element prevOwner = currentOwner;
+ try {
+ currentOwner = null;
+ return super.visitBlock(node, p);
+ } finally {
+ currentOwner = prevOwner;
+ }
+ }
+
+ }
+
+ private static final String CODE =
+ "public class Test {\n" +
+ " void test() {\n" +
+ " Object o = new Object() {\n" +
+ " class IC {}\n" +
+ " public Object get() {\n" +
+ " return new IC();\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ " {\n" +
+ " Object o = new Object() {\n" +
+ " class IC {}\n" +
+ " public Object get() {\n" +
+ " return new IC();\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ " static {\n" +
+ " Object o = new Object() {\n" +
+ " class IC {}\n" +
+ " public Object get() {\n" +
+ " return new IC();\n" +
+ " }\n" +
+ " };\n" +
+ " }\n" +
+ " Object o1 = new Object() {\n" +
+ " class IC {}\n" +
+ " public Object get() {\n" +
+ " return new IC();\n" +
+ " }\n" +
+ " };\n" +
+ " static Object o2 = new Object() {\n" +
+ " class IC {}\n" +
+ " public Object get() {\n" +
+ " return new IC();\n" +
+ " }\n" +
+ " };\n" +
+ "}";
+}