--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Jan 14 12:03:24 2016 -0800
@@ -1146,14 +1146,21 @@
if (!visit(supertype(t), supertype(s)))
return false;
- HashSet<UniqueType> set = new HashSet<>();
- for (Type x : interfaces(t))
- set.add(new UniqueType(x, Types.this));
- for (Type x : interfaces(s)) {
- if (!set.remove(new UniqueType(x, Types.this)))
+ Map<Symbol,Type> tMap = new HashMap<>();
+ for (Type ti : interfaces(t)) {
+ if (tMap.containsKey(ti)) {
+ throw new AssertionError("Malformed intersection");
+ }
+ tMap.put(ti.tsym, ti);
+ }
+ for (Type si : interfaces(s)) {
+ if (!tMap.containsKey(si.tsym))
+ return false;
+ Type ti = tMap.remove(si.tsym);
+ if (!visit(ti, si))
return false;
}
- return (set.isEmpty());
+ return tMap.isEmpty();
}
return t.tsym == s.tsym
&& visit(t.getEnclosingType(), s.getEnclosingType())
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Jan 14 12:03:24 2016 -0800
@@ -1137,7 +1137,56 @@
/** Parameters {@code t} and {@code s} are unrelated functional interface types. */
private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree) {
- FunctionalInterfaceMostSpecificChecker msc = new FunctionalInterfaceMostSpecificChecker(t, s);
+ Type tDesc = types.findDescriptorType(t);
+ Type sDesc = types.findDescriptorType(s);
+
+ // compare type parameters -- can't use Types.hasSameBounds because bounds may have ivars
+ final List<Type> tTypeParams = tDesc.getTypeArguments();
+ final List<Type> sTypeParams = sDesc.getTypeArguments();
+ List<Type> tIter = tTypeParams;
+ List<Type> sIter = sTypeParams;
+ while (tIter.nonEmpty() && sIter.nonEmpty()) {
+ Type tBound = tIter.head.getUpperBound();
+ Type sBound = types.subst(sIter.head.getUpperBound(), sTypeParams, tTypeParams);
+ if (tBound.containsAny(tTypeParams) && inferenceContext().free(sBound)) {
+ return false;
+ }
+ if (!types.isSameType(tBound, inferenceContext().asUndetVar(sBound))) {
+ return false;
+ }
+ tIter = tIter.tail;
+ sIter = sIter.tail;
+ }
+ if (!tIter.isEmpty() || !sIter.isEmpty()) {
+ return false;
+ }
+
+ // compare parameters
+ List<Type> tParams = tDesc.getParameterTypes();
+ List<Type> sParams = sDesc.getParameterTypes();
+ while (tParams.nonEmpty() && sParams.nonEmpty()) {
+ Type tParam = tParams.head;
+ Type sParam = types.subst(sParams.head, sTypeParams, tTypeParams);
+ if (tParam.containsAny(tTypeParams) && inferenceContext().free(sParam)) {
+ return false;
+ }
+ if (!types.isSameType(tParam, inferenceContext().asUndetVar(sParam))) {
+ return false;
+ }
+ tParams = tParams.tail;
+ sParams = sParams.tail;
+ }
+ if (!tParams.isEmpty() || !sParams.isEmpty()) {
+ return false;
+ }
+
+ // compare returns
+ Type tRet = tDesc.getReturnType();
+ Type sRet = types.subst(sDesc.getReturnType(), sTypeParams, tTypeParams);
+ if (tRet.containsAny(tTypeParams) && inferenceContext().free(sRet)) {
+ return false;
+ }
+ MostSpecificFunctionReturnChecker msc = new MostSpecificFunctionReturnChecker(tRet, sRet);
msc.scan(tree);
return msc.result;
}
@@ -1146,16 +1195,16 @@
* Tests whether one functional interface type can be considered more specific
* than another unrelated functional interface type for the scanned expression.
*/
- class FunctionalInterfaceMostSpecificChecker extends DeferredAttr.PolyScanner {
-
- final Type t;
- final Type s;
+ class MostSpecificFunctionReturnChecker extends DeferredAttr.PolyScanner {
+
+ final Type tRet;
+ final Type sRet;
boolean result;
/** Parameters {@code t} and {@code s} are unrelated functional interface types. */
- FunctionalInterfaceMostSpecificChecker(Type t, Type s) {
- this.t = t;
- this.s = s;
+ MostSpecificFunctionReturnChecker(Type tRet, Type sRet) {
+ this.tRet = tRet;
+ this.sRet = sRet;
result = true;
}
@@ -1172,29 +1221,18 @@
@Override
public void visitReference(JCMemberReference tree) {
- Type desc_t = types.findDescriptorType(t);
- Type desc_s = types.findDescriptorType(s);
- // use inference variables here for more-specific inference (18.5.4)
- if (!types.isSameTypes(desc_t.getParameterTypes(),
- inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
+ if (sRet.hasTag(VOID)) {
+ result &= true;
+ } else if (tRet.hasTag(VOID)) {
result &= false;
+ } else if (tRet.isPrimitive() != sRet.isPrimitive()) {
+ boolean retValIsPrimitive =
+ tree.refPolyKind == PolyKind.STANDALONE &&
+ tree.sym.type.getReturnType().isPrimitive();
+ result &= (retValIsPrimitive == tRet.isPrimitive()) &&
+ (retValIsPrimitive != sRet.isPrimitive());
} else {
- // compare return types
- Type ret_t = desc_t.getReturnType();
- Type ret_s = desc_s.getReturnType();
- if (ret_s.hasTag(VOID)) {
- result &= true;
- } else if (ret_t.hasTag(VOID)) {
- result &= false;
- } else if (ret_t.isPrimitive() != ret_s.isPrimitive()) {
- boolean retValIsPrimitive =
- tree.refPolyKind == PolyKind.STANDALONE &&
- tree.sym.type.getReturnType().isPrimitive();
- result &= (retValIsPrimitive == ret_t.isPrimitive()) &&
- (retValIsPrimitive != ret_s.isPrimitive());
- } else {
- result &= compatibleBySubtyping(ret_t, ret_s);
- }
+ result &= compatibleBySubtyping(tRet, sRet);
}
}
@@ -1205,32 +1243,24 @@
@Override
public void visitLambda(JCLambda tree) {
- Type desc_t = types.findDescriptorType(t);
- Type desc_s = types.findDescriptorType(s);
- // use inference variables here for more-specific inference (18.5.4)
- if (!types.isSameTypes(desc_t.getParameterTypes(),
- inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
+ if (sRet.hasTag(VOID)) {
+ result &= true;
+ } else if (tRet.hasTag(VOID)) {
result &= false;
} else {
- // compare return types
- Type ret_t = desc_t.getReturnType();
- Type ret_s = desc_s.getReturnType();
- if (ret_s.hasTag(VOID)) {
- result &= true;
- } else if (ret_t.hasTag(VOID)) {
- result &= false;
- } else if (unrelatedFunctionalInterfaces(ret_t, ret_s)) {
- for (JCExpression expr : lambdaResults(tree)) {
- result &= functionalInterfaceMostSpecific(ret_t, ret_s, expr);
+ List<JCExpression> lambdaResults = lambdaResults(tree);
+ if (!lambdaResults.isEmpty() && unrelatedFunctionalInterfaces(tRet, sRet)) {
+ for (JCExpression expr : lambdaResults) {
+ result &= functionalInterfaceMostSpecific(tRet, sRet, expr);
}
- } else if (ret_t.isPrimitive() != ret_s.isPrimitive()) {
- for (JCExpression expr : lambdaResults(tree)) {
+ } else if (!lambdaResults.isEmpty() && tRet.isPrimitive() != sRet.isPrimitive()) {
+ for (JCExpression expr : lambdaResults) {
boolean retValIsPrimitive = expr.isStandalone() && expr.type.isPrimitive();
- result &= (retValIsPrimitive == ret_t.isPrimitive()) &&
- (retValIsPrimitive != ret_s.isPrimitive());
+ result &= (retValIsPrimitive == tRet.isPrimitive()) &&
+ (retValIsPrimitive != sRet.isPrimitive());
}
} else {
- result &= compatibleBySubtyping(ret_t, ret_s);
+ result &= compatibleBySubtyping(tRet, sRet);
}
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Thu Jan 14 12:03:24 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -301,15 +301,16 @@
}
/** Read a number.
- * @param radix The radix of the number; one of 2, j8, 10, 16.
+ * @param radix The radix of the number; one of 2, 8, 10, 16.
*/
private void scanNumber(int pos, int radix) {
// for octal, allow base-10 digit in case it's a float literal
this.radix = radix;
int digitRadix = (radix == 8 ? 10 : radix);
- boolean seendigit = false;
- if (reader.digit(pos, digitRadix) >= 0) {
- seendigit = true;
+ int firstDigit = reader.digit(pos, Math.max(10, digitRadix));
+ boolean seendigit = firstDigit >= 0;
+ boolean seenValidDigit = firstDigit >= 0 && firstDigit < digitRadix;
+ if (seendigit) {
scanDigits(pos, digitRadix);
}
if (radix == 16 && reader.ch == '.') {
@@ -325,6 +326,16 @@
reader.ch == 'd' || reader.ch == 'D')) {
scanFractionAndSuffix(pos);
} else {
+ if (!seenValidDigit) {
+ switch (radix) {
+ case 2:
+ lexError(pos, "invalid.binary.number");
+ break;
+ case 16:
+ lexError(pos, "invalid.hex.number");
+ break;
+ }
+ }
if (reader.ch == 'l' || reader.ch == 'L') {
reader.scanChar();
tk = TokenKind.LONGLITERAL;
@@ -491,13 +502,7 @@
if (reader.ch == 'x' || reader.ch == 'X') {
reader.scanChar();
skipIllegalUnderscores();
- if (reader.ch == '.') {
- scanHexFractionAndSuffix(pos, false);
- } else if (reader.digit(pos, 16) < 0) {
- lexError(pos, "invalid.hex.number");
- } else {
- scanNumber(pos, 16);
- }
+ scanNumber(pos, 16);
} else if (reader.ch == 'b' || reader.ch == 'B') {
if (!allowBinaryLiterals) {
lexError(pos, "unsupported.binary.lit", source.name);
@@ -505,11 +510,7 @@
}
reader.scanChar();
skipIllegalUnderscores();
- if (reader.digit(pos, 2) < 0) {
- lexError(pos, "invalid.binary.number");
- } else {
- scanNumber(pos, 2);
- }
+ scanNumber(pos, 2);
} else {
reader.putChar('0');
if (reader.ch == '_') {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java Thu Jan 14 12:03:24 2016 -0800
@@ -26,11 +26,20 @@
package com.sun.tools.sjavac;
import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.Set;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
+import java.util.regex.PatternSyntaxException;
/** A Source object maintains information about a source file.
* For example which package it belongs to and kind of source it is.
@@ -56,8 +65,6 @@
private long lastModified;
// The source File.
private File file;
- // The source root under which file resides.
- private File root;
// If the source is generated.
private boolean isGenerated;
// If the source is only linked to, not compiled.
@@ -78,7 +85,7 @@
return name.hashCode();
}
- public Source(Module m, String n, File f, File r) {
+ public Source(Module m, String n, File f) {
name = n;
int dp = n.lastIndexOf(".");
if (dp != -1) {
@@ -87,7 +94,6 @@
suffix = "";
}
file = f;
- root = r;
lastModified = f.lastModified();
linkedOnly = false;
}
@@ -102,7 +108,6 @@
suffix = "";
}
file = null;
- root = null;
lastModified = lm;
linkedOnly = false;
int ls = n.lastIndexOf('/');
@@ -112,7 +117,6 @@
public String suffix() { return suffix; }
public Package pkg() { return pkg; }
public File file() { return file; }
- public File root() { return root; }
public long lastModified() {
return lastModified;
}
@@ -183,225 +187,122 @@
*/
static public void scanRoot(File root,
Set<String> suffixes,
- List<String> excludes, List<String> includes,
- List<String> excludeFiles, List<String> includeFiles,
+ List<String> excludes,
+ List<String> includes,
Map<String,Source> foundFiles,
Map<String,Module> foundModules,
- Module currentModule,
+ final Module currentModule,
boolean permitSourcesWithoutPackage,
boolean inGensrc,
boolean inLinksrc)
- throws ProblemException {
+ throws IOException, ProblemException {
+
+ if (root == null)
+ return;
+
+ FileSystem fs = root.toPath().getFileSystem();
+
+ if (includes.isEmpty()) {
+ includes = Collections.singletonList("**");
+ }
+
+ List<PathMatcher> includeMatchers = createPathMatchers(fs, includes);
+ List<PathMatcher> excludeMatchers = createPathMatchers(fs, excludes);
- if (root == null) return;
- int root_prefix = root.getPath().length()+1;
- // This is the root source directory, it must not contain any Java sources files
- // because we do not allow Java source files without a package.
- // (Unless of course --permit-sources-without-package has been specified.)
- // It might contain other source files however, (for -tr and -copy) these will
- // always be included, since no package pattern can match the root directory.
- currentModule = addFilesInDir(root, root_prefix, root, suffixes, permitSourcesWithoutPackage,
- excludeFiles, includeFiles,
- foundFiles, foundModules, currentModule,
- inGensrc, inLinksrc);
+ Files.walkFileTree(root.toPath(), new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+
+ Path relToRoot = root.toPath().relativize(file);
- File[] dirfiles = root.listFiles();
- for (File d : dirfiles) {
- if (d.isDirectory()) {
- // Descend into the directory structure.
- scanDirectory(d, root_prefix, root, suffixes,
- excludes, includes, excludeFiles, includeFiles,
- foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
- }
- }
- }
+ if (includeMatchers.stream().anyMatch(im -> im.matches(relToRoot))
+ && excludeMatchers.stream().noneMatch(em -> em.matches(relToRoot))
+ && suffixes.contains(Util.fileSuffix(file))) {
+
+ // TODO: Test this.
+ Source existing = foundFiles.get(file);
+ if (existing != null) {
+ throw new IOException("You have already added the file "+file+" from "+existing.file().getPath());
+ }
+ existing = currentModule.lookupSource(file.toString());
+ if (existing != null) {
- /**
- * Test if a path matches any of the patterns given.
- * The pattern foo/bar matches only foo/bar
- * The pattern foo/* matches foo/bar and foo/bar/zoo etc
- */
- static private boolean hasMatch(String path, List<String> patterns) {
-
- // Convert Windows '\' to '/' for the sake of comparing with the patterns
- path = path.replace(File.separatorChar, '/');
+ // Oups, the source is already added, could be ok, could be not, lets check.
+ if (inLinksrc) {
+ // So we are collecting sources for linking only.
+ if (existing.isLinkedOnly()) {
+ // Ouch, this one is also for linking only. Bad.
+ throw new IOException("You have already added the link only file " + file + " from " + existing.file().getPath());
+ }
+ // Ok, the existing source is to be compiled. Thus this link only is redundant
+ // since all compiled are also linked to. Continue to the next source.
+ // But we need to add the source, so that it will be visible to linking,
+ // if not the multi core compile will fail because a JavaCompiler cannot
+ // find the necessary dependencies for its part of the source.
+ foundFiles.put(file.toString(), existing);
+ } else {
+ // We are looking for sources to compile, if we find an existing to be compiled
+ // source with the same name, it is an internal error, since we must
+ // find the sources to be compiled before we find the sources to be linked to.
+ throw new IOException("Internal error: Double add of file " + file + " from " + existing.file().getPath());
+ }
- for (String p : patterns) {
- // Exact match
- if (p.equals(path))
- return true;
+ } else {
- // Single dot the end matches this package and all its subpackages.
- if (p.endsWith("/*")) {
- // Remove the wildcard
- String patprefix = p.substring(0,p.length()-2);
- // Does the path start with the pattern prefix?
- if (path.startsWith(patprefix)) {
- // If the path has the same length as the pattern prefix, then it is a match.
- // If the path is longer, then make sure that
- // the next part of the path starts with a dot (.) to prevent
- // wildcard matching in the middle of a package name.
- if (path.length()==patprefix.length() || path.charAt(patprefix.length())=='/') {
- return true;
+ //////////////////////////////////////////////////////////////
+ // Add source
+ Source s = new Source(currentModule, file.toString(), file.toFile());
+ if (inGensrc) {
+ s.markAsGenerated();
+ }
+ if (inLinksrc) {
+ s.markAsLinkedOnly();
+ }
+ String pkg = packageOfJavaFile(root.toPath(), file);
+ pkg = currentModule.name() + ":" + pkg;
+ foundFiles.put(file.toString(), s);
+ currentModule.addSource(pkg, s);
+ //////////////////////////////////////////////////////////////
}
}
+
+ return FileVisitResult.CONTINUE;
}
- }
- return false;
- }
-
- /**
- * Matches patterns with the asterisk first. */
- // The pattern foo/bar.java only matches foo/bar.java
- // The pattern */bar.java matches foo/bar.java and zoo/bar.java etc
- static private boolean hasFileMatch(String path, List<String> patterns) {
- // Convert Windows '\' to '/' for the sake of comparing with the patterns
- path = path.replace(File.separatorChar, '/');
-
- path = Util.normalizeDriveLetter(path);
- for (String p : patterns) {
- // Exact match
- if (p.equals(path)) {
- return true;
- }
- // Single dot the end matches this package and all its subpackages.
- if (p.startsWith("*")) {
- // Remove the wildcard
- String patsuffix = p.substring(1);
- // Does the path start with the pattern prefix?
- if (path.endsWith(patsuffix)) {
- return true;
- }
- }
- }
- return false;
+ });
}
- /**
- * Add the files in the directory, assuming that the file has not been excluded.
- * Returns a fresh Module object, if this was a dir with a module-info.java file.
- */
- static private Module addFilesInDir(File dir, int rootPrefix, File root,
- Set<String> suffixes, boolean allow_javas,
- List<String> excludeFiles, List<String> includeFiles,
- Map<String,Source> foundFiles,
- Map<String,Module> foundModules,
- Module currentModule,
- boolean inGensrc,
- boolean inLinksrc)
- throws ProblemException
- {
- for (File f : dir.listFiles()) {
-
- if (!f.isFile())
- continue;
-
- boolean should_add =
- (excludeFiles == null || excludeFiles.isEmpty() || !hasFileMatch(f.getPath(), excludeFiles))
- && (includeFiles == null || includeFiles.isEmpty() || hasFileMatch(f.getPath(), includeFiles));
-
- if (!should_add)
- continue;
-
- if (!allow_javas && f.getName().endsWith(".java")) {
- throw new ProblemException("No .java files are allowed in the source root "+dir.getPath()+
- ", please remove "+f.getName());
- }
- // Extract the file name relative the root.
- String fn = f.getPath().substring(rootPrefix);
- // Extract the package name.
- int sp = fn.lastIndexOf(File.separatorChar);
- String pkg = "";
- if (sp != -1) {
- pkg = fn.substring(0,sp).replace(File.separatorChar,'.');
- }
- // Is this a module-info.java file?
- if (fn.endsWith("module-info.java")) {
- // Aha! We have recursed into a module!
- if (!currentModule.name().equals("")) {
- throw new ProblemException("You have an extra module-info.java inside a module! Please remove "+fn);
- }
- String module_name = fn.substring(0,fn.length()-16);
- currentModule = new Module(module_name, f.getPath());
- foundModules.put(module_name, currentModule);
- }
- // Extract the suffix.
- int dp = fn.lastIndexOf(".");
- String suffix = "";
- if (dp > 0) {
- suffix = fn.substring(dp);
- }
- // Should the file be added?
- if (suffixes.contains(suffix)) {
- Source of = foundFiles.get(f.getPath());
- if (of != null) {
- throw new ProblemException("You have already added the file "+fn+" from "+of.file().getPath());
- }
- of = currentModule.lookupSource(f.getPath());
- if (of != null) {
- // Oups, the source is already added, could be ok, could be not, lets check.
- if (inLinksrc) {
- // So we are collecting sources for linking only.
- if (of.isLinkedOnly()) {
- // Ouch, this one is also for linking only. Bad.
- throw new ProblemException("You have already added the link only file "+fn+" from "+of.file().getPath());
- }
- // Ok, the existing source is to be compiled. Thus this link only is redundant
- // since all compiled are also linked to. Continue to the next source.
- // But we need to add the source, so that it will be visible to linking,
- // if not the multi core compile will fail because a JavaCompiler cannot
- // find the necessary dependencies for its part of the source.
- foundFiles.put(f.getPath(), of);
- continue;
- } else {
- // We are looking for sources to compile, if we find an existing to be compiled
- // source with the same name, it is an internal error, since we must
- // find the sources to be compiled before we find the sources to be linked to.
- throw new ProblemException("Internal error: Double add of file "+fn+" from "+of.file().getPath());
- }
- }
- Source s = new Source(currentModule, f.getPath(), f, root);
- if (inGensrc) s.markAsGenerated();
- if (inLinksrc) {
- s.markAsLinkedOnly();
- }
- pkg = currentModule.name()+":"+pkg;
- foundFiles.put(f.getPath(), s);
- currentModule.addSource(pkg, s);
+ private static List<PathMatcher> createPathMatchers(FileSystem fs, List<String> patterns) {
+ List<PathMatcher> matchers = new ArrayList<>();
+ for (String pattern : patterns) {
+ try {
+ matchers.add(fs.getPathMatcher("glob:" + pattern));
+ } catch (PatternSyntaxException e) {
+ Log.error("Invalid pattern: " + pattern);
+ throw e;
}
}
- return currentModule;
+ return matchers;
+ }
+
+ private static String packageOfJavaFile(Path sourceRoot, Path javaFile) {
+ Path javaFileDir = javaFile.getParent();
+ Path packageDir = sourceRoot.relativize(javaFileDir);
+ List<String> separateDirs = new ArrayList<>();
+ for (Path pathElement : packageDir) {
+ separateDirs.add(pathElement.getFileName().toString());
+ }
+ return String.join(".", separateDirs);
}
- static private void scanDirectory(File dir, int rootPrefix, File root,
- Set<String> suffixes,
- List<String> excludes, List<String> includes,
- List<String> excludeFiles, List<String> includeFiles,
- Map<String,Source> foundFiles,
- Map<String,Module> foundModules,
- Module currentModule, boolean inGensrc, boolean inLinksrc)
- throws ProblemException {
-
- String path = "";
- // Remove the root prefix from the dir path
- if (dir.getPath().length() > rootPrefix) {
- path = dir.getPath().substring(rootPrefix);
- }
- // Should this package directory be included and not excluded?
- if ((includes==null || includes.isEmpty() || hasMatch(path, includes)) &&
- (excludes==null || excludes.isEmpty() || !hasMatch(path, excludes))) {
- // Add the source files.
- currentModule = addFilesInDir(dir, rootPrefix, root, suffixes, true, excludeFiles, includeFiles,
- foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
- }
-
- for (File d : dir.listFiles()) {
- if (d.isDirectory()) {
- // Descend into the directory structure.
- scanDirectory(d, rootPrefix, root, suffixes,
- excludes, includes, excludeFiles, includeFiles,
- foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
- }
- }
+ @Override
+ public String toString() {
+ return String.format("%s[pkg: %s, name: %s, suffix: %s, file: %s, isGenerated: %b, linkedOnly: %b]",
+ getClass().getSimpleName(),
+ pkg,
+ name,
+ suffix,
+ file,
+ isGenerated,
+ linkedOnly);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Thu Jan 14 12:03:24 2016 -0800
@@ -230,4 +230,10 @@
Function<? super T, ? extends I> indexFunction) {
return c.stream().collect(Collectors.<T, I, T>toMap(indexFunction, o -> o));
}
+
+ public static String fileSuffix(Path file) {
+ String fileNameStr = file.getFileName().toString();
+ int dotIndex = fileNameStr.indexOf('.');
+ return dotIndex == -1 ? "" : fileNameStr.substring(dotIndex);
+ }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Thu Jan 14 12:03:24 2016 -0800
@@ -144,77 +144,77 @@
Module current_module = new Module("", "");
modules.put("", current_module);
- // Find all sources, use the suffix rules to know which files are sources.
- Map<String,Source> sources = new HashMap<>();
+ try {
+ // Find all sources, use the suffix rules to know which files are sources.
+ Map<String,Source> sources = new HashMap<>();
- // Find the files, this will automatically populate the found modules
- // with found packages where the sources are found!
- findSourceFiles(options.getSources(),
- suffixRules.keySet(),
- sources,
- modules,
- current_module,
- options.isDefaultPackagePermitted(),
- false);
+ // Find the files, this will automatically populate the found modules
+ // with found packages where the sources are found!
+ findSourceFiles(options.getSources(),
+ suffixRules.keySet(),
+ sources,
+ modules,
+ current_module,
+ options.isDefaultPackagePermitted(),
+ false);
- if (sources.isEmpty()) {
- Log.error("Found nothing to compile!");
- return RC_FATAL;
- }
+ if (sources.isEmpty()) {
+ Log.error("Found nothing to compile!");
+ return RC_FATAL;
+ }
- // Create a map of all source files that are available for linking. Both -src and
- // -sourcepath point to such files. It is possible to specify multiple
- // -sourcepath options to enable different filtering rules. If the
- // filters are the same for multiple sourcepaths, they may be concatenated
- // using :(;). Before sending the list of sourcepaths to javac, they are
- // all concatenated. The list created here is used by the SmartFileWrapper to
- // make sure only the correct sources are actually available.
- // We might find more modules here as well.
- Map<String,Source> sources_to_link_to = new HashMap<>();
+ // Create a map of all source files that are available for linking. Both -src and
+ // -sourcepath point to such files. It is possible to specify multiple
+ // -sourcepath options to enable different filtering rules. If the
+ // filters are the same for multiple sourcepaths, they may be concatenated
+ // using :(;). Before sending the list of sourcepaths to javac, they are
+ // all concatenated. The list created here is used by the SmartFileWrapper to
+ // make sure only the correct sources are actually available.
+ // We might find more modules here as well.
+ Map<String,Source> sources_to_link_to = new HashMap<>();
- List<SourceLocation> sourceResolutionLocations = new ArrayList<>();
- sourceResolutionLocations.addAll(options.getSources());
- sourceResolutionLocations.addAll(options.getSourceSearchPaths());
- findSourceFiles(sourceResolutionLocations,
- Collections.singleton(".java"),
- sources_to_link_to,
- modules,
- current_module,
- options.isDefaultPackagePermitted(),
- true);
+ List<SourceLocation> sourceResolutionLocations = new ArrayList<>();
+ sourceResolutionLocations.addAll(options.getSources());
+ sourceResolutionLocations.addAll(options.getSourceSearchPaths());
+ findSourceFiles(sourceResolutionLocations,
+ Collections.singleton(".java"),
+ sources_to_link_to,
+ modules,
+ current_module,
+ options.isDefaultPackagePermitted(),
+ true);
- // Add the set of sources to the build database.
- javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
- javac_state.now().checkInternalState("checking sources", false, sources);
- javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to);
- javac_state.setVisibleSources(sources_to_link_to);
+ // Add the set of sources to the build database.
+ javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
+ javac_state.now().checkInternalState("checking sources", false, sources);
+ javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to);
+ javac_state.setVisibleSources(sources_to_link_to);
- int round = 0;
- printRound(round);
+ int round = 0;
+ printRound(round);
- // If there is any change in the source files, taint packages
- // and mark the database in need of saving.
- javac_state.checkSourceStatus(false);
+ // If there is any change in the source files, taint packages
+ // and mark the database in need of saving.
+ javac_state.checkSourceStatus(false);
- // Find all existing artifacts. Their timestamp will match the last modified timestamps stored
- // in javac_state, simply because loading of the JavacState will clean out all artifacts
- // that do not match the javac_state database.
- javac_state.findAllArtifacts();
+ // Find all existing artifacts. Their timestamp will match the last modified timestamps stored
+ // in javac_state, simply because loading of the JavacState will clean out all artifacts
+ // that do not match the javac_state database.
+ javac_state.findAllArtifacts();
- // Remove unidentified artifacts from the bin, gensrc and header dirs.
- // (Unless we allow them to be there.)
- // I.e. artifacts that are not known according to the build database (javac_state).
- // For examples, files that have been manually copied into these dirs.
- // Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp
- // in javac_state) have already been removed when the javac_state was loaded.
- if (!options.areUnidentifiedArtifactsPermitted()) {
- javac_state.removeUnidentifiedArtifacts();
- }
- // Go through all sources and taint all packages that miss artifacts.
- javac_state.taintPackagesThatMissArtifacts();
+ // Remove unidentified artifacts from the bin, gensrc and header dirs.
+ // (Unless we allow them to be there.)
+ // I.e. artifacts that are not known according to the build database (javac_state).
+ // For examples, files that have been manually copied into these dirs.
+ // Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp
+ // in javac_state) have already been removed when the javac_state was loaded.
+ if (!options.areUnidentifiedArtifactsPermitted()) {
+ javac_state.removeUnidentifiedArtifacts();
+ }
+ // Go through all sources and taint all packages that miss artifacts.
+ javac_state.taintPackagesThatMissArtifacts();
- try {
// Check recorded classpath public apis. Taint packages that depend on
// classpath classes whose public apis have changed.
javac_state.taintPackagesDependingOnChangedClasspathPackages();
@@ -229,8 +229,16 @@
// (Generated sources must always have a package.)
Map<String,Source> generated_sources = new HashMap<>();
- Source.scanRoot(Util.pathToFile(options.getGenSrcDir()), Util.set(".java"), null, null, null, null,
- generated_sources, modules, current_module, false, true, false);
+ Source.scanRoot(Util.pathToFile(options.getGenSrcDir()),
+ Util.set(".java"),
+ Collections.emptyList(),
+ Collections.emptyList(),
+ generated_sources,
+ modules,
+ current_module,
+ false,
+ true,
+ false);
javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
// Recheck the the source files and their timestamps again.
javac_state.checkSourceStatus(true);
@@ -254,7 +262,10 @@
printRound(round);
// Clean out artifacts in tainted packages.
javac_state.deleteClassArtifactsInTaintedPackages();
- again = javac_state.performJavaCompilations(compilationService, options, recently_compiled, rc);
+ again = javac_state.performJavaCompilations(compilationService,
+ options,
+ recently_compiled,
+ rc);
if (!rc[0]) {
Log.debug("Compilation failed.");
break;
@@ -344,7 +355,8 @@
Map<String, Module> foundModules,
Module currentModule,
boolean permitSourcesInDefaultPackage,
- boolean inLinksrc) {
+ boolean inLinksrc)
+ throws IOException {
for (SourceLocation source : sourceLocations) {
source.findSourceFiles(sourceTypes,
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java Thu Jan 14 12:03:24 2016 -0800
@@ -93,7 +93,7 @@
CLASSPATH.processMatching(iter, helper);
}
},
- X("-x", "Exclude directory from the subsequent source directory") {
+ X("-x", "Exclude files matching the given pattern") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
String pattern = getFilePatternArg(iter, helper);
@@ -101,7 +101,7 @@
helper.exclude(pattern);
}
},
- I("-i", "Include only the given directory from the subsequent source directory") {
+ I("-i", "Include only files matching the given pattern") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
String pattern = getFilePatternArg(iter, helper);
@@ -109,22 +109,6 @@
helper.include(pattern);
}
},
- XF("-xf", "Exclude a given file") {
- @Override
- protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
- String pattern = getFilePatternArg(iter, helper);
- if (pattern != null)
- helper.excludeFile(pattern);
- }
- },
- IF("-if", "Include only the given file") {
- @Override
- protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
- String pattern = getFilePatternArg(iter, helper);
- if (pattern != null)
- helper.includeFile(pattern);
- }
- },
TR("-tr", "Translate resources") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
@@ -338,7 +322,7 @@
String getFilePatternArg(ArgumentIterator iter, OptionHelper helper) {
if (!iter.hasNext()) {
- helper.reportError(arg + " must be followed by a file or directory pattern.");
+ helper.reportError(arg + " must be followed by a glob pattern.");
return null;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/OptionHelper.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/OptionHelper.java Thu Jan 14 12:03:24 2016 -0800
@@ -53,12 +53,6 @@
/** Record a package inclusion pattern */
public abstract void include(String incl);
- /** Record a file exclusion */
- public abstract void excludeFile(String exclFile);
-
- /** Record a file inclusion */
- public abstract void includeFile(String inclFile);
-
/** Record a root of sources to be compiled */
public abstract void sourceRoots(List<Path> path);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Thu Jan 14 12:03:24 2016 -0800
@@ -220,8 +220,6 @@
for (SourceLocation sl : locs) {
for (String pkg : sl.includes) addArg(Option.I, pkg);
for (String pkg : sl.excludes) addArg(Option.X, pkg);
- for (String f : sl.excludedFiles) addArg(Option.XF, f);
- for (String f : sl.includedFiles) addArg(Option.IF, f);
addArg(opt, sl.getPath());
}
}
@@ -380,18 +378,6 @@
}
@Override
- public void excludeFile(String exclFilePattern) {
- exclFilePattern = Util.normalizeDriveLetter(exclFilePattern);
- excludeFiles.add(exclFilePattern);
- }
-
- @Override
- public void includeFile(String inclFilePattern) {
- inclFilePattern = Util.normalizeDriveLetter(inclFilePattern);
- includeFiles.add(inclFilePattern);
- }
-
- @Override
public void addTransformer(String suffix, Transformer tr) {
if (trRules.containsKey(suffix)) {
reportError("More than one transformer specified for " +
@@ -519,9 +505,7 @@
result.add(new SourceLocation(
path,
includes,
- excludes,
- includeFiles,
- excludeFiles));
+ excludes));
}
resetFilters();
return result;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/SourceLocation.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/SourceLocation.java Thu Jan 14 12:03:24 2016 -0800
@@ -25,11 +25,13 @@
package com.sun.tools.sjavac.options;
+import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import com.sun.tools.sjavac.Log;
import com.sun.tools.sjavac.Module;
import com.sun.tools.sjavac.ProblemException;
import com.sun.tools.sjavac.Source;
@@ -49,18 +51,14 @@
private Path path;
// Package include / exclude patterns and file includes / excludes.
- List<String> includes, excludes, includedFiles, excludedFiles;
+ List<String> includes, excludes;
public SourceLocation(Path path,
List<String> includes,
- List<String> excludes,
- List<String> includedFiles,
- List<String> excludedFiles) {
+ List<String> excludes) {
this.path = path;
this.includes = includes;
this.excludes = excludes;
- this.includedFiles = includedFiles;
- this.excludedFiles = excludedFiles;
}
@@ -81,17 +79,23 @@
Map<String, Module> foundModules,
Module currentModule,
boolean permitSourcesInDefaultPackage,
- boolean inLinksrc) {
+ boolean inLinksrc)
+ throws IOException {
try {
- Source.scanRoot(path.toFile(), suffixes, excludes, includes,
- excludedFiles, includedFiles, foundFiles, foundModules,
- currentModule, permitSourcesInDefaultPackage, false,
- inLinksrc);
+ Source.scanRoot(path.toFile(),
+ suffixes,
+ excludes,
+ includes,
+ foundFiles,
+ foundModules,
+ currentModule,
+ permitSourcesInDefaultPackage,
+ false,
+ inLinksrc);
} catch (ProblemException e) {
e.printStackTrace();
}
}
-
/** Get the root directory of this source location */
public Path getPath() {
return path;
@@ -107,14 +111,9 @@
return excludes;
}
- /** Get the file include patterns */
- public List<String> getIncludedFiles() {
- return includedFiles;
+ @Override
+ public String toString() {
+ return String.format("%s[\"%s\", includes: %s, excludes: %s]",
+ getClass().getSimpleName(), path, includes, excludes);
}
-
- /** Get the file exclude patterns */
- public List<String> getExcludedFiles() {
- return excludedFiles;
- }
-
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Thu Jan 14 12:03:24 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -174,11 +174,20 @@
/**
* Delete the port file.
*/
- public void delete() throws IOException {
+ public void delete() throws IOException, InterruptedException {
// Access to file must be closed before deleting.
rwfile.close();
- // Now delete.
+
file.delete();
+
+ // Wait until file has been deleted (deletes are asynchronous on Windows!) otherwise we
+ // might shutdown the server and prevent another one from starting.
+ for (int i = 0; i < 10 && file.exists(); i++) {
+ Thread.sleep(1000);
+ }
+ if (file.exists()) {
+ throw new IOException("Failed to delete file.");
+ }
}
/**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Thu Jan 14 12:03:24 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -279,7 +279,7 @@
// failed connection attempts
try {
portFile.delete();
- } catch (IOException e) {
+ } catch (IOException | InterruptedException e) {
e.printStackTrace(theLog);
}
try {
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java Thu Jan 14 12:03:24 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -248,7 +248,7 @@
for (ProgramElementDoc element : list) {
Object key = getMemberKey(element);
Map<ProgramElementDoc, String> memberLevelMap = memberNameMap.get(key);
- if (level.equals(memberLevelMap.get(element)))
+ if (memberLevelMap != null && level.equals(memberLevelMap.get(element)))
memberLevelMap.remove(element);
}
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java Thu Jan 14 12:03:24 2016 -0800
@@ -28,6 +28,9 @@
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -35,7 +38,9 @@
import java.util.ArrayList;
import java.util.List;
+
import static jdk.internal.jshell.remote.RemoteCodes.*;
+
import java.util.Map;
import java.util.TreeMap;
@@ -59,7 +64,10 @@
void commandLoop(Socket socket) throws IOException {
// in before out -- so we don't hang the controlling process
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
- ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
+ OutputStream socketOut = socket.getOutputStream();
+ System.setOut(new PrintStream(new MultiplexingOutputStream("out", socketOut), true));
+ System.setErr(new PrintStream(new MultiplexingOutputStream("err", socketOut), true));
+ ObjectOutputStream out = new ObjectOutputStream(new MultiplexingOutputStream("command", socketOut));
while (true) {
int cmd = in.readInt();
switch (cmd) {
@@ -260,4 +268,64 @@
}
return sb.toString();
}
+
+ private static final class MultiplexingOutputStream extends OutputStream {
+
+ private static final int PACKET_SIZE = 127;
+
+ private final byte[] name;
+ private final OutputStream delegate;
+
+ public MultiplexingOutputStream(String name, OutputStream delegate) {
+ try {
+ this.name = name.getBytes("UTF-8");
+ this.delegate = delegate;
+ } catch (UnsupportedEncodingException ex) {
+ throw new IllegalStateException(ex); //should not happen
+ }
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ synchronized (delegate) {
+ delegate.write(name.length); //assuming the len is small enough to fit into byte
+ delegate.write(name);
+ delegate.write(1);
+ delegate.write(b);
+ delegate.flush();
+ }
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ synchronized (delegate) {
+ int i = 0;
+ while (len > 0) {
+ int size = Math.min(PACKET_SIZE, len);
+
+ delegate.write(name.length); //assuming the len is small enough to fit into byte
+ delegate.write(name);
+ delegate.write(size);
+ delegate.write(b, off + i, size);
+ i += size;
+ len -= size;
+ }
+
+ delegate.flush();
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ super.flush();
+ delegate.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ super.close();
+ delegate.close();
+ }
+
+ }
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu Jan 14 12:03:24 2016 -0800
@@ -1,3 +1,4 @@
+
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -90,8 +91,10 @@
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Spliterators;
+import java.util.function.Function;
import java.util.function.Supplier;
import static java.util.stream.Collectors.toList;
+import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND;
/**
* Command line REPL tool for Java using the JShell API.
@@ -102,6 +105,7 @@
private static final Pattern LINEBREAK = Pattern.compile("\\R");
private static final Pattern HISTORY_ALL_START_FILENAME = Pattern.compile(
"((?<cmd>(all|history|start))(\\z|\\p{javaWhitespace}+))?(?<filename>.*)");
+ private static final String RECORD_SEPARATOR = "\u241E";
final InputStream cmdin;
final PrintStream cmdout;
@@ -150,9 +154,14 @@
private String cmdlineStartup = null;
private String editor = null;
- static final Preferences PREFS = Preferences.userRoot().node("tool/REPL");
+ // Commands and snippets which should be replayed
+ private List<String> replayableHistory;
+ private List<String> replayableHistoryPrevious;
+
+ static final Preferences PREFS = Preferences.userRoot().node("tool/JShell");
static final String STARTUP_KEY = "STARTUP";
+ static final String REPLAY_RESTORE_KEY = "REPLAY_RESTORE";
static final String DEFAULT_STARTUP =
"\n" +
@@ -165,11 +174,14 @@
"import java.util.regex.*;\n" +
"void printf(String format, Object... args) { System.out.printf(format, args); }\n";
- // Tool id (tid) mapping
+ // Tool id (tid) mapping: the three name spaces
NameSpace mainNamespace;
NameSpace startNamespace;
NameSpace errorNamespace;
+
+ // Tool id (tid) mapping: the current name spaces
NameSpace currentNameSpace;
+
Map<Snippet,SnippetInfo> mapSnippet;
void debug(String format, Object... args) {
@@ -252,6 +264,12 @@
private void start(IOContext in, List<String> loadList) {
resetState(); // Initialize
+ // Read replay history from last jshell session into previous history
+ String prevReplay = PREFS.get(REPLAY_RESTORE_KEY, null);
+ if (prevReplay != null) {
+ replayableHistoryPrevious = Arrays.asList(prevReplay.split(RECORD_SEPARATOR));
+ }
+
for (String loadFile : loadList) {
cmdOpen(loadFile);
}
@@ -370,6 +388,10 @@
mapSnippet = new LinkedHashMap<>();
currentNameSpace = startNamespace;
+ // Reset the replayable history, saving the old for restore
+ replayableHistoryPrevious = replayableHistory;
+ replayableHistory = new ArrayList<>();
+
state = JShell.builder()
.in(userin)
.out(userout)
@@ -382,7 +404,8 @@
analysis = state.sourceCodeAnalysis();
shutdownSubscription = state.onShutdown((JShell deadState) -> {
if (deadState == state) {
- hard("State engine terminated. See /history");
+ hard("State engine terminated.");
+ hard("Restore definitions with: /reload restore");
live = false;
}
});
@@ -392,7 +415,6 @@
state.addToClasspath(cmdlineClasspath);
}
-
String start;
if (cmdlineStartup == null) {
start = PREFS.get(STARTUP_KEY, "<nada>");
@@ -431,7 +453,7 @@
String incomplete = "";
while (live) {
String prompt;
- if (in.interactiveOutput() && displayPrompt) {
+ if (displayPrompt) {
prompt = testPrompt
? incomplete.isEmpty()
? "\u0005" //ENQ
@@ -480,6 +502,12 @@
}
}
+ private void addToReplayHistory(String s) {
+ if (currentNameSpace == mainNamespace) {
+ replayableHistory.add(s);
+ }
+ }
+
private String processSourceCatchingReset(String src) {
try {
input.beforeUserCode();
@@ -516,7 +544,12 @@
fluff("Type /help for help.");
}
} else if (candidates.length == 1) {
- candidates[0].run.accept(arg);
+ Command command = candidates[0];
+
+ // If comand was successful and is of a replayable kind, add it the replayable history
+ if (command.run.apply(arg) && command.kind == CommandKind.REPLAY) {
+ addToReplayHistory((command.command + " " + arg).trim());
+ }
} else {
hard("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", ")));
fluff("Type /help for help.");
@@ -546,15 +579,15 @@
public final String command;
public final String params;
public final String description;
- public final Consumer<String> run;
+ public final Function<String,Boolean> run;
public final CompletionProvider completions;
public final CommandKind kind;
- public Command(String command, String params, String description, Consumer<String> run, CompletionProvider completions) {
+ public Command(String command, String params, String description, Function<String,Boolean> run, CompletionProvider completions) {
this(command, params, description, run, completions, CommandKind.NORMAL);
}
- public Command(String command, String params, String description, Consumer<String> run, CompletionProvider completions, CommandKind kind) {
+ public Command(String command, String params, String description, Function<String,Boolean> run, CompletionProvider completions, CommandKind kind) {
this.command = command;
this.params = params;
this.description = description;
@@ -571,6 +604,7 @@
enum CommandKind {
NORMAL,
+ REPLAY,
HIDDEN,
HELP_ONLY;
}
@@ -602,6 +636,7 @@
private static final CompletionProvider EMPTY_COMPLETION_PROVIDER = new FixedCompletionProvider();
private static final CompletionProvider KEYWORD_COMPLETION_PROVIDER = new FixedCompletionProvider("all ", "start ", "history ");
+ private static final CompletionProvider RELOAD_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider("restore", "quiet");
private static final CompletionProvider FILE_COMPLETION_PROVIDER = fileCompletions(p -> true);
private final Map<String, Command> commands = new LinkedHashMap<>();
private void registerCommand(Command cmd) {
@@ -674,6 +709,16 @@
};
}
+ private static CompletionProvider reloadCompletion() {
+ return (code, cursor, anchor) -> {
+ List<Suggestion> result = new ArrayList<>();
+ int pastSpace = code.indexOf(' ') + 1; // zero if no space
+ result.addAll(RELOAD_OPTIONS_COMPLETION_PROVIDER.completionSuggestions(code.substring(pastSpace), cursor - pastSpace, anchor));
+ anchor[0] += pastSpace;
+ return result;
+ };
+ }
+
// Table of commands -- with command forms, argument kinds, help message, implementation, ...
{
@@ -688,7 +733,8 @@
editCompletion()));
registerCommand(new Command("/drop", "<name or id>", "delete a source entry referenced by name or id",
arg -> cmdDrop(arg),
- editCompletion()));
+ editCompletion(),
+ CommandKind.REPLAY));
registerCommand(new Command("/save", "[all|history|start] <file>", "save: <none> - current source;\n" +
" all - source including overwritten, failed, and start-up code;\n" +
" history - editing history;\n" +
@@ -716,6 +762,9 @@
registerCommand(new Command("/reset", null, "reset everything in the REPL",
arg -> cmdReset(),
EMPTY_COMPLETION_PROVIDER));
+ registerCommand(new Command("/reload", "[restore] [quiet]", "reset and replay relevant history -- current or previous (restore)",
+ arg -> cmdReload(arg),
+ reloadCompletion()));
registerCommand(new Command("/feedback", "<level>", "feedback information: off, concise, normal, verbose, default, or ?",
arg -> cmdFeedback(arg),
new FixedCompletionProvider("off", "concise", "normal", "verbose", "default", "?")));
@@ -724,7 +773,8 @@
EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/classpath", "<path>", "add a path to the classpath",
arg -> cmdClasspath(arg),
- classPathCompletion()));
+ classPathCompletion(),
+ CommandKind.REPLAY));
registerCommand(new Command("/history", null, "history of what you have typed",
arg -> cmdHistory(),
EMPTY_COMPLETION_PROVIDER));
@@ -801,25 +851,29 @@
// --- Command implementations ---
- void cmdSetEditor(String arg) {
+ boolean cmdSetEditor(String arg) {
if (arg.isEmpty()) {
hard("/seteditor requires a path argument");
+ return false;
} else {
editor = arg;
fluff("Editor set to: %s", arg);
+ return true;
}
}
- void cmdClasspath(String arg) {
+ boolean cmdClasspath(String arg) {
if (arg.isEmpty()) {
hard("/classpath requires a path argument");
+ return false;
} else {
state.addToClasspath(toPathResolvingUserHome(arg).toString());
fluff("Path %s added to classpath", arg);
+ return true;
}
}
- void cmdDebug(String arg) {
+ boolean cmdDebug(String arg) {
if (arg.isEmpty()) {
debug = !debug;
InternalDebugControl.setDebugFlags(state, debug ? InternalDebugControl.DBG_GEN : 0);
@@ -860,20 +914,26 @@
default:
hard("Unknown debugging option: %c", ch);
fluff("Use: 0 r g f c d");
- break;
+ return false;
}
}
InternalDebugControl.setDebugFlags(state, flags);
}
+ return true;
}
- private void cmdExit() {
+ private boolean cmdExit() {
regenerateOnDeath = false;
live = false;
+ if (!replayableHistory.isEmpty()) {
+ PREFS.put(REPLAY_RESTORE_KEY, replayableHistory.stream().reduce(
+ (a, b) -> a + RECORD_SEPARATOR + b).get());
+ }
fluff("Goodbye\n");
+ return true;
}
- private void cmdFeedback(String arg) {
+ private boolean cmdFeedback(String arg) {
switch (arg) {
case "":
case "d":
@@ -905,12 +965,13 @@
hard(" default");
hard("You may also use just the first letter, for example: /f c");
hard("In interactive mode 'default' is the same as 'normal', from a file it is the same as 'off'");
- return;
+ return false;
}
fluff("Feedback mode: %s", feedback.name().toLowerCase());
+ return true;
}
- void cmdHelp() {
+ boolean cmdHelp() {
int synopsisLen = 0;
Map<String, String> synopsis2Description = new LinkedHashMap<>();
for (Command cmd : new LinkedHashSet<>(commands.values())) {
@@ -936,14 +997,16 @@
cmdout.println("Supported shortcuts include:");
cmdout.println("<tab> -- show possible completions for the current text");
cmdout.println("Shift-<tab> -- for current method or constructor invocation, show a synopsis of the method/constructor");
+ return true;
}
- private void cmdHistory() {
+ private boolean cmdHistory() {
cmdout.println();
for (String s : input.currentSessionHistory()) {
// No number prefix, confusing with snippet ids
cmdout.printf("%s\n", s);
}
+ return true;
}
/**
@@ -1010,23 +1073,23 @@
}
}
- private void cmdDrop(String arg) {
+ private boolean cmdDrop(String arg) {
if (arg.isEmpty()) {
hard("In the /drop argument, please specify an import, variable, method, or class to drop.");
hard("Specify by id or name. Use /list to see ids. Use /reset to reset all state.");
- return;
+ return false;
}
Stream<Snippet> stream = argToSnippets(arg, false);
if (stream == null) {
hard("No definition or id named %s found. See /classes, /methods, /vars, or /list", arg);
- return;
+ return false;
}
List<Snippet> snippets = stream
.filter(sn -> state.status(sn).isActive && sn instanceof PersistentSnippet)
.collect(toList());
if (snippets.isEmpty()) {
hard("The argument did not specify an active import, variable, method, or class to drop.");
- return;
+ return false;
}
if (snippets.size() > 1) {
hard("The argument references more than one import, variable, method, or class.");
@@ -1034,17 +1097,18 @@
for (Snippet sn : snippets) {
cmdout.printf("%4s : %s\n", sn.id(), sn.source().replace("\n", "\n "));
}
- return;
+ return false;
}
PersistentSnippet psn = (PersistentSnippet) snippets.get(0);
state.drop(psn).forEach(this::handleEvent);
+ return true;
}
- private void cmdEdit(String arg) {
+ private boolean cmdEdit(String arg) {
Stream<Snippet> stream = argToSnippets(arg, true);
if (stream == null) {
hard("No definition or id named %s found. See /classes, /methods, /vars, or /list", arg);
- return;
+ return false;
}
Set<String> srcSet = new LinkedHashSet<>();
stream.forEachOrdered(sn -> {
@@ -1078,6 +1142,7 @@
} else {
ExternalEditor.edit(editor, errorHandler, src, saveHandler, input);
}
+ return true;
}
//where
// receives editor requests to save
@@ -1135,10 +1200,9 @@
}
}
- private void cmdList(String arg) {
+ private boolean cmdList(String arg) {
if (arg.equals("history")) {
- cmdHistory();
- return;
+ return cmdHistory();
}
Stream<Snippet> stream = argToSnippets(arg, true);
if (stream == null) {
@@ -1148,7 +1212,7 @@
} else {
hard("No definition or id named %s found. There are no active definitions.", arg);
}
- return;
+ return false;
}
// prevent double newline on empty list
@@ -1160,38 +1224,72 @@
}
cmdout.printf("%4s : %s\n", sn.id(), sn.source().replace("\n", "\n "));
});
+ return true;
}
- private void cmdOpen(String filename) {
+ private boolean cmdOpen(String filename) {
if (filename.isEmpty()) {
hard("The /open command requires a filename argument.");
+ return false;
} else {
try {
run(new FileScannerIOContext(toPathResolvingUserHome(filename).toString()));
} catch (FileNotFoundException e) {
hard("File '%s' is not found: %s", filename, e.getMessage());
+ return false;
} catch (Exception e) {
hard("Exception while reading file: %s", e);
+ return false;
}
}
+ return true;
}
- private void cmdPrompt() {
+ private boolean cmdPrompt() {
displayPrompt = !displayPrompt;
fluff("Prompt will %sdisplay. Use /prompt to toggle.", displayPrompt ? "" : "NOT ");
concise("Prompt: %s", displayPrompt ? "on" : "off");
+ return true;
+ }
+
+ private boolean cmdReset() {
+ live = false;
+ fluff("Resetting state.");
+ return true;
}
- private void cmdReset() {
- live = false;
- fluff("Resetting state.");
+ private boolean cmdReload(String arg) {
+ Iterable<String> history = replayableHistory;
+ boolean echo = true;
+ if (arg.length() > 0) {
+ if ("restore".startsWith(arg)) {
+ if (replayableHistoryPrevious == null) {
+ hard("No previous history to restore\n", arg);
+ return false;
+ }
+ history = replayableHistoryPrevious;
+ } else if ("quiet".startsWith(arg)) {
+ echo = false;
+ } else {
+ hard("Invalid argument to reload command: %s\nUse 'restore', 'quiet', or no argument\n", arg);
+ return false;
+ }
+ }
+ fluff("Restarting and restoring %s.",
+ history == replayableHistoryPrevious
+ ? "from previous state"
+ : "state");
+ resetState();
+ run(new ReloadIOContext(history,
+ echo? cmdout : null));
+ return true;
}
- private void cmdSave(String arg_filename) {
+ private boolean cmdSave(String arg_filename) {
Matcher mat = HISTORY_ALL_START_FILENAME.matcher(arg_filename);
if (!mat.find()) {
hard("Malformed argument to the /save command: %s", arg_filename);
- return;
+ return false;
}
boolean useHistory = false;
String saveAll = "";
@@ -1211,7 +1309,7 @@
String filename = mat.group("filename");
if (filename == null ||filename.isEmpty()) {
hard("The /save command requires a filename argument.");
- return;
+ return false;
}
try (BufferedWriter writer = Files.newBufferedWriter(toPathResolvingUserHome(filename),
Charset.defaultCharset(),
@@ -1234,12 +1332,15 @@
}
} catch (FileNotFoundException e) {
hard("File '%s' for save is not accessible: %s", filename, e.getMessage());
+ return false;
} catch (Exception e) {
hard("Exception while saving: %s", e);
+ return false;
}
+ return true;
}
- private void cmdSetStart(String filename) {
+ private boolean cmdSetStart(String filename) {
if (filename.isEmpty()) {
hard("The /setstart command requires a filename argument.");
} else {
@@ -1249,30 +1350,36 @@
PREFS.put(STARTUP_KEY, init);
} catch (AccessDeniedException e) {
hard("File '%s' for /setstart is not accessible.", filename);
+ return false;
} catch (NoSuchFileException e) {
hard("File '%s' for /setstart is not found.", filename);
+ return false;
} catch (Exception e) {
hard("Exception while reading start set file: %s", e);
+ return false;
}
}
+ return true;
}
- private void cmdVars() {
+ private boolean cmdVars() {
for (VarSnippet vk : state.variables()) {
String val = state.status(vk) == Status.VALID
? state.varValue(vk)
: "(not-active)";
hard(" %s %s = %s", vk.typeName(), vk.name(), val);
}
+ return true;
}
- private void cmdMethods() {
+ private boolean cmdMethods() {
for (MethodSnippet mk : state.methods()) {
hard(" %s %s", mk.name(), mk.signature());
}
+ return true;
}
- private void cmdClasses() {
+ private boolean cmdClasses() {
for (TypeDeclSnippet ck : state.types()) {
String kind;
switch (ck.subKind()) {
@@ -1295,15 +1402,17 @@
}
hard(" %s %s", kind, ck.name());
}
+ return true;
}
- private void cmdImports() {
+ private boolean cmdImports() {
state.imports().forEach(ik -> {
hard(" import %s%s", ik.isStatic() ? "static " : "", ik.fullname());
});
+ return true;
}
- private void cmdUseHistoryEntry(int index) {
+ private boolean cmdUseHistoryEntry(int index) {
List<Snippet> keys = state.snippets();
if (index < 0)
index += keys.size();
@@ -1313,7 +1422,9 @@
rerunSnippet(keys.get(index));
} else {
hard("Cannot find snippet %d", index + 1);
+ return false;
}
+ return true;
}
private boolean rerunHistoryEntryById(String id) {
@@ -1357,7 +1468,7 @@
}
}
- for (String line : diag.getMessage(null).split("\\r?\\n")) {
+ for (String line : diag.getMessage(null).split("\\r?\\n")) { // TODO: Internationalize
if (!line.trim().startsWith("location:")) {
hard("%s%s", padding, line);
}
@@ -1425,10 +1536,24 @@
private boolean processCompleteSource(String source) throws IllegalStateException {
debug("Compiling: %s", source);
boolean failed = false;
+ boolean isActive = false;
List<SnippetEvent> events = state.eval(source);
for (SnippetEvent e : events) {
+ // Report the event, recording failure
failed |= handleEvent(e);
+
+ // If any main snippet is active, this should be replayable
+ // also ignore var value queries
+ isActive |= e.causeSnippet() == null &&
+ e.status().isActive &&
+ e.snippet().subKind() != VAR_VALUE_SUBKIND;
}
+ // If this is an active snippet and it didn't cause the backend to die,
+ // add it to the replayable history
+ if (isActive && live) {
+ addToReplayHistory(source);
+ }
+
return failed;
}
@@ -1784,31 +1909,11 @@
}
}
-class ScannerIOContext extends IOContext {
-
- private final Scanner scannerIn;
- private final PrintStream pStream;
-
- public ScannerIOContext(Scanner scannerIn, PrintStream pStream) {
- this.scannerIn = scannerIn;
- this.pStream = pStream;
- }
-
- @Override
- public String readLine(String prompt, String prefix) {
- if (pStream != null && prompt != null) {
- pStream.print(prompt);
- }
- if (scannerIn.hasNextLine()) {
- return scannerIn.nextLine();
- } else {
- return null;
- }
- }
+abstract class NonInteractiveIOContext extends IOContext {
@Override
public boolean interactiveOutput() {
- return true;
+ return false;
}
@Override
@@ -1817,11 +1922,6 @@
}
@Override
- public void close() {
- scannerIn.close();
- }
-
- @Override
public boolean terminalEditorRunning() {
return false;
}
@@ -1847,19 +1947,62 @@
}
}
+class ScannerIOContext extends NonInteractiveIOContext {
+ private final Scanner scannerIn;
+
+ ScannerIOContext(Scanner scannerIn) {
+ this.scannerIn = scannerIn;
+ }
+
+ @Override
+ public String readLine(String prompt, String prefix) {
+ if (scannerIn.hasNextLine()) {
+ return scannerIn.nextLine();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void close() {
+ scannerIn.close();
+ }
+}
+
class FileScannerIOContext extends ScannerIOContext {
- public FileScannerIOContext(String fn) throws FileNotFoundException {
+ FileScannerIOContext(String fn) throws FileNotFoundException {
this(new FileReader(fn));
}
- public FileScannerIOContext(Reader rdr) throws FileNotFoundException {
- super(new Scanner(rdr), null);
+ FileScannerIOContext(Reader rdr) throws FileNotFoundException {
+ super(new Scanner(rdr));
+ }
+}
+
+class ReloadIOContext extends NonInteractiveIOContext {
+ private final Iterator<String> it;
+ private final PrintStream echoStream;
+
+ ReloadIOContext(Iterable<String> history, PrintStream echoStream) {
+ this.it = history.iterator();
+ this.echoStream = echoStream;
}
@Override
- public boolean interactiveOutput() {
- return false;
+ public String readLine(String prompt, String prefix) {
+ String s = it.hasNext()
+ ? it.next()
+ : null;
+ if (echoStream != null && s != null) {
+ String p = "-: ";
+ String p2 = "\n ";
+ echoStream.printf("%s%s\n", p, s.replace("\n", p2));
+ }
+ return s;
+ }
+
+ @Override
+ public void close() {
}
}
-
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Thu Jan 14 12:03:24 2016 -0800
@@ -26,9 +26,12 @@
package jdk.jshell;
import static jdk.internal.jshell.remote.RemoteCodes.*;
+import java.io.DataInputStream;
+import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.sun.jdi.*;
@@ -69,7 +72,9 @@
socket = listener.accept();
// out before in -- match remote creation so we don't hang
out = new ObjectOutputStream(socket.getOutputStream());
- in = new ObjectInputStream(socket.getInputStream());
+ PipeInputStream commandIn = new PipeInputStream();
+ new DemultiplexInput(socket.getInputStream(), commandIn, proc.out, proc.err).start();
+ in = new ObjectInputStream(commandIn);
}
}
@@ -117,11 +122,13 @@
String result = in.readUTF();
return result;
}
- } catch (EOFException ex) {
- env.shutdown();
} catch (IOException | ClassNotFoundException ex) {
- proc.debug(DBG_GEN, "Exception on remote invoke: %s\n", ex);
- return "Execution failure: " + ex.getMessage();
+ if (!env.connection().isRunning()) {
+ env.shutdown();
+ } else {
+ proc.debug(DBG_GEN, "Exception on remote invoke: %s\n", ex);
+ return "Execution failure: " + ex.getMessage();
+ }
} finally {
synchronized (STOP_LOCK) {
userCodeRunning = false;
@@ -310,4 +317,112 @@
}
}
}
+
+ private final class DemultiplexInput extends Thread {
+
+ private final DataInputStream delegate;
+ private final PipeInputStream command;
+ private final PrintStream out;
+ private final PrintStream err;
+
+ public DemultiplexInput(InputStream input,
+ PipeInputStream command,
+ PrintStream out,
+ PrintStream err) {
+ super("output reader");
+ this.delegate = new DataInputStream(input);
+ this.command = command;
+ this.out = out;
+ this.err = err;
+ }
+
+ public void run() {
+ try {
+ while (true) {
+ int nameLen = delegate.read();
+ if (nameLen == (-1))
+ break;
+ byte[] name = new byte[nameLen];
+ DemultiplexInput.this.delegate.readFully(name);
+ int dataLen = delegate.read();
+ byte[] data = new byte[dataLen];
+ DemultiplexInput.this.delegate.readFully(data);
+ switch (new String(name, "UTF-8")) {
+ case "err":
+ err.write(data);
+ break;
+ case "out":
+ out.write(data);
+ break;
+ case "command":
+ for (byte b : data) {
+ command.write(Byte.toUnsignedInt(b));
+ }
+ break;
+ }
+ }
+ } catch (IOException ex) {
+ proc.debug(ex, "Failed reading output");
+ } finally {
+ command.close();
+ }
+ }
+
+ }
+
+ public static final class PipeInputStream extends InputStream {
+ public 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() {
+ while (start == end) {
+ if (closed) {
+ return -1;
+ }
+ try {
+ wait();
+ } catch (InterruptedException ex) {
+ //ignore
+ }
+ }
+ try {
+ return buffer[start];
+ } finally {
+ start = (start + 1) % buffer.length;
+ }
+ }
+
+ public 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();
+ }
+
+ }
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIConnection.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIConnection.java Thu Jan 14 12:03:24 2016 -0800
@@ -133,7 +133,7 @@
return vm;
}
- boolean setConnectorArg(String name, String value) {
+ synchronized boolean setConnectorArg(String name, String value) {
/*
* Too late if the connection already made
*/
@@ -165,7 +165,7 @@
}
}
- boolean isOpen() {
+ synchronized boolean isOpen() {
return (vm != null);
}
@@ -173,13 +173,17 @@
return (connector instanceof LaunchingConnector);
}
- public void disposeVM() {
+ synchronized boolean isRunning() {
+ return process != null && process.isAlive();
+ }
+
+ public synchronized void disposeVM() {
try {
if (vm != null) {
vm.dispose(); // This could NPE, so it is caught below
vm = null;
}
- } catch (VMDisconnectedException | NullPointerException ex) {
+ } catch (VMDisconnectedException ex) {
// Ignore if already closed
} finally {
if (process != null) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java Thu Jan 14 12:03:24 2016 -0800
@@ -182,9 +182,9 @@
return null;
}
- @Override
- public String toString() {
- return "WrappedDiagnostic(" + getMessage(null) + ":" + getPosition() + ")";
- }
+ @Override
+ public String toString() {
+ return "WrappedDiagnostic(" + getMessage(null) + ":" + getPosition() + ")";
+ }
}
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Thu Jan 14 12:03:24 2016 -0800
@@ -33,7 +33,6 @@
import com.sun.tools.javac.util.Context;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Iterator;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
@@ -395,7 +394,7 @@
LinkedHashMap<String, Diag> diagMap = new LinkedHashMap<>();
for (Diagnostic<? extends JavaFileObject> in : diagnostics.getDiagnostics()) {
Diag d = diag(in);
- String uniqueKey = d.getCode() + ":" + d.getPosition() + ":" + d.getMessage(null);
+ String uniqueKey = d.getCode() + ":" + d.getPosition() + ":" + d.getMessage(PARSED_LOCALE);
diagMap.put(uniqueKey, d);
}
diags = new DiagList(diagMap.values());
@@ -410,7 +409,7 @@
String shortErrorMessage() {
StringBuilder sb = new StringBuilder();
for (Diag diag : getDiagnostics()) {
- for (String line : diag.getMessage(null).split("\\r?\\n")) {
+ for (String line : diag.getMessage(PARSED_LOCALE).split("\\r?\\n")) {
if (!line.trim().startsWith("location:")) {
sb.append(line);
}
@@ -422,7 +421,7 @@
void debugPrintDiagnostics(String src) {
for (Diag diag : getDiagnostics()) {
state.debug(DBG_GEN, "ERROR --\n");
- for (String line : diag.getMessage(null).split("\\r?\\n")) {
+ for (String line : diag.getMessage(PARSED_LOCALE).split("\\r?\\n")) {
if (!line.trim().startsWith("location:")) {
state.debug(DBG_GEN, "%s\n", line);
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java Thu Jan 14 12:03:24 2016 -0800
@@ -50,6 +50,7 @@
import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED;
import static jdk.jshell.Snippet.Status.REJECTED;
import static jdk.jshell.Snippet.Status.VALID;
+import static jdk.jshell.Util.PARSED_LOCALE;
import static jdk.jshell.Util.expunge;
/**
@@ -456,7 +457,7 @@
for (Diag diag : diags) {
if (diag.isError()) {
if (diag.isResolutionError()) {
- String m = diag.getMessage(null);
+ String m = diag.getMessage(PARSED_LOCALE);
int symPos = m.indexOf(RESOLVE_ERROR_SYMBOL);
if (symPos >= 0) {
m = m.substring(symPos + RESOLVE_ERROR_SYMBOL.length());
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java Thu Jan 14 12:03:24 2016 -0800
@@ -25,6 +25,7 @@
package jdk.jshell;
+import java.util.Locale;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.lang.model.element.Name;
@@ -40,6 +41,8 @@
static final String REPL_CLASS_PREFIX = "$REPL";
static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX+"00DOESNOTMATTER";
+ static final Locale PARSED_LOCALE = Locale.ROOT;
+
static boolean isDoIt(Name name) {
return isDoIt(name.toString());
}
--- a/langtools/test/jdk/jshell/ReplToolTesting.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/jdk/jshell/ReplToolTesting.java Thu Jan 14 12:03:24 2016 -0800
@@ -152,13 +152,13 @@
}
public String getCommandOutput() {
- String s = cmdout.toString();
+ String s = normalizeLineEndings(cmdout.toString());
cmdout.reset();
return s;
}
public String getCommandErrorOutput() {
- String s = cmderr.toString();
+ String s = normalizeLineEndings(cmderr.toString());
cmderr.reset();
return s;
}
@@ -168,13 +168,13 @@
}
public String getUserOutput() {
- String s = userout.toString();
+ String s = normalizeLineEndings(userout.toString());
userout.reset();
return s;
}
public String getUserErrorOutput() {
- String s = usererr.toString();
+ String s = normalizeLineEndings(usererr.toString());
usererr.reset();
return s;
}
@@ -461,6 +461,10 @@
}
}
+ private String normalizeLineEndings(String text) {
+ return text.replace(System.getProperty("line.separator"), "\n");
+ }
+
public static abstract class MemberInfo {
public final String source;
public final String type;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/T8146368/JShellTest8146368.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 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 8146368
+ * @summary Test Smashing Error when user language is Japanese
+ * @library /tools/lib /jdk/jshell
+ * @build KullaTesting
+ * @run testng/othervm -Duser.language=ja JShellTest8146368
+ */
+
+import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED;
+import org.testng.annotations.Test;
+
+@Test
+public class JShellTest8146368 extends KullaTesting {
+ public void test() {
+ assertEval("class A extends B {}", added(RECOVERABLE_NOT_DEFINED));
+ assertEval("und m() { return new und(); }", added(RECOVERABLE_NOT_DEFINED));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/T8146368/JShellToolTest8146368.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, 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 8146368
+ * @summary Test Smashing Error when user language is Japanese
+ * @library /tools/lib /jdk/jshell
+ * @build ReplToolTesting
+ * @run testng/othervm -Duser.language=ja JShellToolTest8146368
+ */
+
+import org.testng.annotations.Test;
+
+@Test
+public class JShellToolTest8146368 extends ReplToolTesting {
+ public void test() {
+ test(
+ a -> assertCommand(a, "class A extends B {}", "| Added class A, however, it cannot be referenced until class B is declared\n"),
+ a -> assertCommand(a, "und m() { return new und(); }", "| Added method m(), however, it cannot be referenced until class und is declared\n")
+ );
+ }
+}
--- a/langtools/test/jdk/jshell/ToolBasicTest.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/jdk/jshell/ToolBasicTest.java Thu Jan 14 12:03:24 2016 -0800
@@ -23,14 +23,16 @@
/*
* @test
- * @bug 8143037 8142447 8144095 8140265
+ * @bug 8143037 8142447 8144095 8140265 8144906
+ * @requires os.family != "solaris"
* @summary Tests for Basic tests for REPL tool
* @library /tools/lib
* @ignore 8139873
* @build KullaTesting TestingInputStream ToolBox Compiler
- * @run testng ToolBasicTest
+ * @run testng/timeout=600 ToolBasicTest
*/
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -460,8 +462,7 @@
Path unknown = compiler.getPath("UNKNOWN.jar");
test(true, new String[]{unknown.toString()},
"| File '" + unknown
- + "' is not found: " + unknown
- + " (No such file or directory)\n");
+ + "' is not found: " + unresolvableMessage(unknown) + "\n");
}
public void testReset() {
@@ -514,8 +515,7 @@
test(
(a) -> assertCommand(a, s + " " + unknown,
"| File '" + unknown
- + "' is not found: " + unknown
- + " (No such file or directory)\n")
+ + "' is not found: " + unresolvableMessage(unknown) + "\n")
);
}
}
@@ -874,6 +874,15 @@
);
}
+ private String unresolvableMessage(Path p) {
+ try {
+ new FileInputStream(p.toFile());
+ throw new AssertionError("Expected exception did not occur.");
+ } catch (IOException ex) {
+ return ex.getMessage();
+ }
+ }
+
public void testCommandPrefix() {
test(a -> assertCommandCheckOutput(a, "/s",
assertStartsWith("| Command: /s is ambiguous: /seteditor, /save, /setstart")),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/ToolReloadTest.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015, 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 8081845
+ * @summary Tests for /reload in JShell tool
+ * @library /tools/lib
+ * @build KullaTesting TestingInputStream ToolBox Compiler
+ * @run testng ToolReloadTest
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.Function;
+
+import org.testng.annotations.Test;
+
+
+@Test
+public class ToolReloadTest extends ReplToolTesting {
+
+ public void testReloadSnippets() {
+ test(
+ (a) -> assertVariable(a, "int", "x", "5", "5"),
+ (a) -> assertMethod(a, "int m(int z) { return z * z; }",
+ "(int)int", "m"),
+ (a) -> evaluateExpression(a, "int", "m(x)", "25"),
+ (a) -> assertCommand(a, "/reload",
+ "| Restarting and restoring state.\n" +
+ "-: int x = 5;\n" +
+ "-: int m(int z) { return z * z; }\n" +
+ "-: m(x)\n"),
+ (a) -> evaluateExpression(a, "int", "m(x)", "25"),
+ (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
+ (a) -> assertCommandCheckOutput(a, "/methods", assertMethods())
+ );
+ }
+
+ public void testReloadClasspath() {
+ Function<String,String> prog = (s) -> String.format(
+ "package pkg; public class A { public String toString() { return \"%s\"; } }\n", s);
+ Compiler compiler = new Compiler();
+ Path outDir = Paths.get("testClasspathDirectory");
+ compiler.compile(outDir, prog.apply("A"));
+ Path classpath = compiler.getPath(outDir);
+ test(
+ (a) -> assertCommand(a, "/classpath " + classpath,
+ String.format("| Path %s added to classpath\n", classpath)),
+ (a) -> assertMethod(a, "String foo() { return (new pkg.A()).toString(); }",
+ "()String", "foo"),
+ (a) -> assertVariable(a, "String", "v", "foo()", "\"A\""),
+ (a) -> {
+ if (!a) compiler.compile(outDir, prog.apply("Aprime"));
+ assertCommand(a, "/reload",
+ "| Restarting and restoring state.\n" +
+ "-: /classpath " + classpath + "\n" +
+ "-: String foo() { return (new pkg.A()).toString(); }\n" +
+ "-: String v = foo();\n");
+ },
+ (a) -> assertCommand(a, "v", "| Variable v of type String has value \"Aprime\"\n"),
+ (a) -> evaluateExpression(a, "String", "foo()", "\"Aprime\""),
+ (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "\"Aprime\"")
+ );
+ }
+
+ public void testReloadDrop() {
+ test(false, new String[]{"-nostartup"},
+ a -> assertVariable(a, "int", "a"),
+ a -> dropVariable(a, "/dr 1", "int a = 0"),
+ a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
+ a -> dropMethod(a, "/drop b", "b ()I"),
+ a -> assertClass(a, "class A {}", "class", "A"),
+ a -> dropClass(a, "/dr A", "class A"),
+ a -> assertCommand(a, "/reload",
+ "| Restarting and restoring state.\n" +
+ "-: int a;\n" +
+ "-: /drop 1\n" +
+ "-: int b() { return 0; }\n" +
+ "-: /drop b\n" +
+ "-: class A {}\n" +
+ "-: /drop A\n"),
+ a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
+ a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
+ a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ a -> assertCommandCheckOutput(a, "/imports", assertImports())
+ );
+ }
+
+ public void testReloadRepeat() {
+ test(false, new String[]{"-nostartup"},
+ (a) -> assertVariable(a, "int", "c", "7", "7"),
+ (a) -> assertCommand(a, "++c", null),
+ (a) -> assertCommand(a, "/!", null),
+ (a) -> assertCommand(a, "/2", null),
+ (a) -> assertCommand(a, "/-1", null),
+ (a) -> assertCommand(a, "/reload",
+ "| Restarting and restoring state.\n" +
+ "-: int c = 7;\n" +
+ "-: ++c\n" +
+ "-: ++c\n" +
+ "-: ++c\n" +
+ "-: ++c\n"
+ ),
+ (a) -> assertCommand(a, "c", "| Variable c of type int has value 11\n"),
+ (a) -> assertCommand(a, "$4", "| Variable $4 of type int has value 10\n")
+ );
+ }
+
+ public void testReloadIgnore() {
+ test(false, new String[]{"-nostartup"},
+ (a) -> assertCommand(a, "(-)", null),
+ (a) -> assertCommand(a, "/list", null),
+ (a) -> assertCommand(a, "/history", null),
+ (a) -> assertCommand(a, "/help", null),
+ (a) -> assertCommand(a, "/vars", null),
+ (a) -> assertCommand(a, "/save abcd", null),
+ (a) -> assertCommand(a, "/reload",
+ "| Restarting and restoring state.\n")
+ );
+ }
+
+ public void testReloadResetRestore() {
+ test(
+ (a) -> assertVariable(a, "int", "x", "5", "5"),
+ (a) -> assertMethod(a, "int m(int z) { return z * z; }",
+ "(int)int", "m"),
+ (a) -> evaluateExpression(a, "int", "m(x)", "25"),
+ (a) -> assertCommand(a, "/reset", "| Resetting state.\n"),
+ (a) -> assertCommand(a, "/reload restore",
+ "| Restarting and restoring from previous state.\n" +
+ "-: int x = 5;\n" +
+ "-: int m(int z) { return z * z; }\n" +
+ "-: m(x)\n"),
+ (a) -> evaluateExpression(a, "int", "m(x)", "25"),
+ (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
+ (a) -> assertCommandCheckOutput(a, "/methods", assertMethods())
+ );
+ }
+
+ public void testReloadCrashRestore() {
+ test(
+ (a) -> assertVariable(a, "int", "x", "5", "5"),
+ (a) -> assertMethod(a, "int m(int z) { return z * z; }",
+ "(int)int", "m"),
+ (a) -> evaluateExpression(a, "int", "m(x)", "25"),
+ (a) -> assertCommand(a, "System.exit(1);",
+ "| State engine terminated.\n" +
+ "| Restore definitions with: /reload restore\n"),
+ (a) -> assertCommand(a, "/reload restore",
+ "| Restarting and restoring from previous state.\n" +
+ "-: int x = 5;\n" +
+ "-: int m(int z) { return z * z; }\n" +
+ "-: m(x)\n"),
+ (a) -> evaluateExpression(a, "int", "m(x)", "25"),
+ (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
+ (a) -> assertCommandCheckOutput(a, "/methods", assertMethods())
+ );
+ }
+
+ public void testReloadExitRestore() {
+ test(false, new String[]{"-nostartup"},
+ (a) -> assertVariable(a, "int", "x", "5", "5"),
+ (a) -> assertMethod(a, "int m(int z) { return z * z; }",
+ "(int)int", "m"),
+ (a) -> evaluateExpression(a, "int", "m(x)", "25")
+ );
+ test(false, new String[]{"-nostartup"},
+ (a) -> assertCommand(a, "/reload restore",
+ "| Restarting and restoring from previous state.\n" +
+ "-: int x = 5;\n" +
+ "-: int m(int z) { return z * z; }\n" +
+ "-: m(x)\n"),
+ (a) -> evaluateExpression(a, "int", "m(x)", "25")
+ );
+ }
+}
--- a/langtools/test/tools/javac/BadHexConstant.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/javac/BadHexConstant.java Thu Jan 14 12:03:24 2016 -0800
@@ -1,6 +1,6 @@
/*
* @test /nodynamiccopyright/
- * @bug 4049982
+ * @bug 4049982 8056897
* @summary Compiler permitted invalid hex literal.
* @author turnidge
*
--- a/langtools/test/tools/javac/BadHexConstant.out Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/javac/BadHexConstant.out Thu Jan 14 12:03:24 2016 -0800
@@ -1,3 +1,2 @@
BadHexConstant.java:12:14: compiler.err.invalid.hex.number
-BadHexConstant.java:12:17: compiler.err.expected: token.identifier
-2 errors
+1 error
--- a/langtools/test/tools/javac/api/T6430241.java Thu Jan 14 08:08:24 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,259 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, 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 6430241
- * @summary Hard to disable symbol file feature through API
- * @library /tools/lib
- * @modules jdk.compiler/com.sun.tools.javac.api
- * jdk.compiler/com.sun.tools.javac.file
- * jdk.compiler/com.sun.tools.javac.main
- * jdk.compiler/com.sun.tools.javac.util
- * @build ToolBox
- * @run main T6430241
- */
-
-import java.io.*;
-import java.util.*;
-
-import javax.tools.*;
-
-import com.sun.source.util.JavacTask;
-import com.sun.tools.javac.api.JavacTool;
-import com.sun.tools.javac.file.JavacFileManager;
-import com.sun.tools.javac.util.Context;
-
-public class T6430241 {
- public static void main(String... args) throws Exception {
- new T6430241().run();
- }
-
- void run() throws Exception {
- setup();
- testCommandLine();
- testSimpleAPI();
- testTaskAPI();
-
- if (errors > 0)
- throw new Exception(errors + " errors found");
- }
-
- void setup() throws Exception {
- classesDir = new File("classes");
- classesDir.mkdirs();
-
- emptyDir = new File("empty");
- emptyDir.mkdirs();
-
- bootClassPath = createJar().getPath();
-
- File srcDir = new File("src");
- String test = "import sun.misc.Unsafe; class Test { }";
- testFile = writeFile(srcDir, "Test.java", test);
- }
-
- //----- tests for command line invocation
-
- void testCommandLine() throws Exception {
- testCommandLine(true);
- testCommandLine(false, "-Xbootclasspath/p:" + emptyDir);
- testCommandLine(false, "-Xbootclasspath:" + bootClassPath);
- testCommandLine(false, "-Xbootclasspath/a:" + emptyDir);
- testCommandLine(false, "-XDignore.symbol.file");
- System.err.println();
- }
-
- void testCommandLine(boolean expectWarnings, String... opts) throws Exception {
- System.err.println("test command line: " + Arrays.asList(opts));
-
- String[] args = initArgs(opts);
-
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- int rc = com.sun.tools.javac.Main.compile(args, pw);
- String out = showOutput(sw.toString());
-
- checkCompilationOK(rc);
- checkOutput(out, expectWarnings);
- }
-
- //----- tests for simple API invocation
-
- void testSimpleAPI() {
- testSimpleAPI(true);
- testSimpleAPI(false, "-Xbootclasspath/p:" + emptyDir);
- testSimpleAPI(false, "-Xbootclasspath:" + bootClassPath);
- testSimpleAPI(false, "-Xbootclasspath/a:" + emptyDir);
- testSimpleAPI(false, "-XDignore.symbol.file");
- System.err.println();
- }
-
- void testSimpleAPI(boolean expectWarnings, String... opts) {
- System.err.println("test simple API: " + Arrays.asList(opts));
-
- String[] args = initArgs(opts);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream ps = new PrintStream(baos);
-
- JavacTool tool = JavacTool.create();
- int rc = tool.run(null, null, ps, args);
-
- String out = showOutput(baos.toString());
-
- checkCompilationOK(rc);
- checkOutput(out, expectWarnings);
- }
-
- //----- tests for CompilationTask API invocation
-
- void testTaskAPI() throws Exception {
- List<File> bcp = new ArrayList<File>();
- for (String f: bootClassPath.split(File.pathSeparator)) {
- if (!f.isEmpty())
- bcp.add(new File(f));
- }
-
- testTaskAPI(true, null);
- testTaskAPI(false, bcp);
- System.err.println();
- }
-
- void testTaskAPI(boolean expectWarnings, Iterable<? extends File> pcp) throws Exception {
- System.err.println("test task API: " + pcp);
-
- JavacTool tool = JavacTool.create();
- try (StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
-
- if (pcp != null)
- fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, pcp);
-
- Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(testFile);
-
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- JavacTask task = tool.getTask(pw, fm, null, null, null, files);
- boolean ok = task.call();
- String out = showOutput(sw.toString());
-
- checkCompilationOK(ok);
- checkOutput(out, expectWarnings);
- }
- }
-
- //----- utility methods
-
- File createJar() throws IOException {
- File f = new File("test.jar");
- try (JavaFileManager fm = new JavacFileManager(new Context(), false, null)) {
- ToolBox tb = new ToolBox();
- tb.new JarTask(f.getPath())
- .files(fm, StandardLocation.PLATFORM_CLASS_PATH, "java.lang.*", "sun.misc.*")
- .run();
- }
- return f;
- }
-
- /**
- * Create a file with given content.
- */
- File writeFile(File dir, String path, String content) throws IOException {
- File f = new File(dir, path);
- f.getParentFile().mkdirs();
- FileWriter out = new FileWriter(f);
- try {
- out.write(content);
- } finally {
- out.close();
- }
- return f;
- }
-
- /**
- * Initialize args for compilation with given opts.
- * @return opts -d classesDir testFile
- */
- String[] initArgs(String[] opts) {
- List<String> args = new ArrayList<String>();
- args.addAll(Arrays.asList(opts));
- args.add("-d");
- args.add(classesDir.getPath());
- args.add(testFile.getPath());
- return args.toArray(new String[args.size()]);
- }
-
- /**
- * Show output from compilation if non empty.
- */
- String showOutput(String out) {
- if (!out.isEmpty())
- System.err.println(out);
- return out;
- }
-
- /**
- * Verify compilation succeeded.
- */
- void checkCompilationOK(boolean ok) {
- if (!ok)
- error("compilation failed");
- }
-
- /**
- * Verify compilation succeeded.
- */
- void checkCompilationOK(int rc) {
- if (rc != 0)
- error("compilation failed, rc: " + rc);
- }
-
- /**
- * Check whether output contains warnings if and only if warnings
- * are expected.
- */
- void checkOutput(String out, boolean expectWarnings) {
- boolean foundWarnings = out.contains("warning");
- if (foundWarnings) {
- if (!expectWarnings)
- error("unexpected warnings found");
- } else {
- if (expectWarnings)
- error("expected warnings not found");
- }
- }
-
- /**
- * Report an error.
- */
- void error(String msg) {
- System.err.println("error: " + msg);
- errors++;
- }
-
- String bootClassPath;
- File classesDir;
- File emptyDir;
- File testFile;
- int errors;
-}
--- a/langtools/test/tools/javac/diags/examples/IdentifierExpected.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/javac/diags/examples/IdentifierExpected.java Thu Jan 14 12:03:24 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -23,11 +23,9 @@
// key: compiler.misc.token.identifier
// key: compiler.err.expected
-// key: compiler.err.invalid.binary.number
-// key: compiler.misc.count.error.plural
+// key: compiler.misc.count.error
// key: compiler.err.error
// run: backdoor
-class IdentifierExpected {
- long bl = 0BL;
+class {
}
--- a/langtools/test/tools/javac/file/BootClassPathPrepend.java Thu Jan 14 08:08:24 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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 8067445
- * @summary Verify that file.Locations analyze sun.boot.class.path for BCP prepends/appends
- * @library /tools/lib
- * @modules jdk.compiler/com.sun.tools.javac.api
- * jdk.compiler/com.sun.tools.javac.file
- * jdk.compiler/com.sun.tools.javac.main
- */
-
-import java.io.IOException;
-import java.util.EnumSet;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-import javax.tools.JavaFileObject.Kind;
-import javax.tools.StandardLocation;
-import javax.tools.ToolProvider;
-
-public class BootClassPathPrepend {
- public static void main(String... args) throws IOException {
- if (args.length == 0) {
- new BootClassPathPrepend().reRun();
- } else {
- new BootClassPathPrepend().run();
- }
- }
-
- void reRun() {
- String testClasses = System.getProperty("test.classes");
- ToolBox tb = new ToolBox();
- tb.new JavaTask().vmOptions("-Xbootclasspath/p:" + testClasses)
- .classArgs("real-run")
- .className("BootClassPathPrepend")
- .run()
- .writeAll();
- }
-
- EnumSet<Kind> classKind = EnumSet.of(JavaFileObject.Kind.CLASS);
-
- void run() throws IOException {
- JavaCompiler toolProvider = ToolProvider.getSystemJavaCompiler();
- try (JavaFileManager fm = toolProvider.getStandardFileManager(null, null, null)) {
- Iterable<JavaFileObject> files =
- fm.list(StandardLocation.PLATFORM_CLASS_PATH, "", classKind, false);
- for (JavaFileObject fo : files) {
- if (fo.isNameCompatible("BootClassPathPrepend", JavaFileObject.Kind.CLASS)) {
- System.err.println("Found BootClassPathPrepend on bootclasspath");
- return ;//found
- }
- }
-
- throw new AssertionError("Cannot find class that was prepended on BCP");
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific15.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * 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 8143852
+ * @summary Rename functional interface method type parameters during most specific test
+ * @compile MostSpecific15.java
+ */
+class MostSpecific15 {
+ interface F1 { <X> Object apply(X arg); }
+ interface F2 { <Y> String apply(Y arg); }
+
+ static void m1(F1 f) {}
+ static void m1(F2 f) {}
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific15::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific16.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8143852
+ * @summary Rename functional interface method type parameters during most specific test
+ * @compile/fail/ref=MostSpecific16.out -XDrawDiagnostics MostSpecific16.java
+ */
+class MostSpecific16 {
+ interface F1 { <X> Object apply(Object arg); }
+ interface F2 { String apply(Object arg); }
+
+ static void m1(F1 f) {}
+ static void m1(F2 f) {}
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific16::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific16.out Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,2 @@
+MostSpecific16.java:17:9: compiler.err.ref.ambiguous: m1, kindname.method, m1(MostSpecific16.F1), MostSpecific16, kindname.method, m1(MostSpecific16.F2), MostSpecific16
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific17.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * 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 8143852
+ * @summary Rename functional interface method type parameters during most specific test
+ * @compile MostSpecific17.java
+ */
+class MostSpecific17 {
+
+ interface A<T> {}
+ interface B<T> extends A<T> {}
+
+ interface F1 { <X> A<? super X> apply(Object arg); }
+ interface F2 { <Y> B<? super Y> apply(Object arg); }
+
+ static void m1(F1 f) {}
+ static void m1(F2 f) {}
+
+ static B<Object> foo(Object in) { return null; }
+
+ void test() {
+ m1(MostSpecific17::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific18.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * 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 8143852
+ * @summary Test that generic function interface method bounds are the same
+ * @compile MostSpecific18.java
+ */
+class MostSpecific18 {
+ interface F1 { <X extends Number> Object apply(X arg); }
+ interface F2 { <Y extends Number> String apply(Y arg); }
+
+ static void m1(F1 f) {}
+ static void m1(F2 f) {}
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific18::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific19.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8143852
+ * @summary Test that generic function interface method bounds are the same
+ * @compile/fail/ref=MostSpecific19.out -XDrawDiagnostics MostSpecific19.java
+ */
+class MostSpecific19 {
+ interface F1 { <X extends Number> Object apply(X arg); }
+ interface F2 { <Y extends Integer> String apply(Y arg); }
+
+ static void m1(F1 f) {}
+ static void m1(F2 f) {}
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific19::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific19.out Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,2 @@
+MostSpecific19.java:17:9: compiler.err.ref.ambiguous: m1, kindname.method, m1(MostSpecific19.F1), MostSpecific19, kindname.method, m1(MostSpecific19.F2), MostSpecific19
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific20.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * 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 8143852
+ * @summary Test that generic function interface method bounds are the same
+ * @compile MostSpecific20.java
+ */
+class MostSpecific20 {
+ interface F1 { <X extends Iterable<X>> Object apply(X arg); }
+ interface F2 { <Y extends Iterable<Y>> String apply(Y arg); }
+
+ static void m1(F1 f) {}
+ static void m1(F2 f) {}
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific20::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific21.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8143852
+ * @summary Most specific inference constraints derived from both functional interface method parameters and tparam bounds
+ * @compile/fail/ref=MostSpecific21.out -XDrawDiagnostics MostSpecific21.java
+ */
+class MostSpecific21 {
+ interface F1<T> { <X extends T> Object apply(T arg); }
+ interface F2 { <Y extends Number> String apply(Integer arg); }
+
+ static <T> T m1(F1<T> f) { return null; }
+ static Object m1(F2 f) { return null; }
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific21::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific21.out Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,2 @@
+MostSpecific21.java:17:9: compiler.err.ref.ambiguous: m1, kindname.method, <T>m1(MostSpecific21.F1<T>), MostSpecific21, kindname.method, m1(MostSpecific21.F2), MostSpecific21
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific22.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * 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 8143852
+ * @summary Most specific inference constraints derived from both functional interface method parameters and tparam bounds
+ * @compile MostSpecific22.java
+ */
+class MostSpecific22 {
+ interface F1<T> { <X extends T> Object apply(T arg); }
+ interface F2 { <Y extends Number> String apply(Number arg); }
+
+ static <T> T m1(F1<T> f) { return null; }
+ static Object m1(F2 f) { return null; }
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific22::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific23.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8143852
+ * @summary Most specific failure if ivar can be bounded by functional interface method tparam
+ * @compile/fail/ref=MostSpecific23.out -XDrawDiagnostics MostSpecific23.java
+ */
+class MostSpecific23 {
+ interface F1<T> { <X extends T> Object apply(Integer arg); }
+ interface F2 { <Y extends Class<Y>> String apply(Integer arg); }
+
+ static <T> T m1(F1<T> f) { return null; }
+ static Object m1(F2 f) { return null; }
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific23::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific23.out Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,2 @@
+MostSpecific23.java:17:9: compiler.err.ref.ambiguous: m1, kindname.method, <T>m1(MostSpecific23.F1<T>), MostSpecific23, kindname.method, m1(MostSpecific23.F2), MostSpecific23
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific24.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8143852
+ * @summary Most specific failure if ivar can be bounded by functional interface method tparam
+ * @compile/fail/ref=MostSpecific24.out -XDrawDiagnostics MostSpecific24.java
+ */
+class MostSpecific24 {
+ interface F1<T> { <X> Object apply(Class<T> arg); }
+ interface F2 { <Y> String apply(Class<Y> arg); }
+
+ static <T> T m1(F1<T> f) { return null; }
+ static Object m1(F2 f) { return null; }
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific24::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific24.out Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,2 @@
+MostSpecific24.java:17:9: compiler.err.ref.ambiguous: m1, kindname.method, <T>m1(MostSpecific24.F1<T>), MostSpecific24, kindname.method, m1(MostSpecific24.F2), MostSpecific24
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific25.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8143852
+ * @summary Most specific failure if ivar can be bounded by functional interface method tparam
+ * @compile/fail/ref=MostSpecific25.out -XDrawDiagnostics MostSpecific25.java
+ */
+class MostSpecific25 {
+ interface F1<T> { <X> T apply(Integer arg); }
+ interface F2 { <Y> Class<? super Y> apply(Integer arg); }
+
+ static <T> T m1(F1<T> f) { return null; }
+ static Object m1(F2 f) { return null; }
+
+ static Class<Object> foo(Object in) { return Object.class; }
+
+ void test() {
+ m1(MostSpecific25::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific25.out Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,2 @@
+MostSpecific25.java:17:9: compiler.err.ref.ambiguous: m1, kindname.method, <T>m1(MostSpecific25.F1<T>), MostSpecific25, kindname.method, m1(MostSpecific25.F2), MostSpecific25
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific26.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8143852
+ * @summary Most specific inference constraints derived from intersection bound
+ * @compile/fail/ref=MostSpecific26.out -XDrawDiagnostics MostSpecific26.java
+ */
+class MostSpecific26 {
+ interface F1<T> { <X extends Iterable<T> & Runnable> Object apply(T arg); }
+ interface F2 { <Y extends Iterable<Number> & Runnable> String apply(Integer arg); }
+
+ static <T> T m1(F1<T> f) { return null; }
+ static Object m1(F2 f) { return null; }
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific26::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific26.out Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,2 @@
+MostSpecific26.java:17:9: compiler.err.ref.ambiguous: m1, kindname.method, <T>m1(MostSpecific26.F1<T>), MostSpecific26, kindname.method, m1(MostSpecific26.F2), MostSpecific26
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific27.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * 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 8143852
+ * @summary Most specific inference constraints derived from intersection bound
+ * @compile MostSpecific27.java
+ */
+class MostSpecific27 {
+ interface F1<T> { <X extends Iterable<T> & Runnable> Object apply(T arg); }
+ interface F2 { <Y extends Iterable<Number> & Runnable> String apply(Number arg); }
+
+ static <T> T m1(F1<T> f) { return null; }
+ static Object m1(F2 f) { return null; }
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1(MostSpecific27::foo);
+ }
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific28.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,21 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8143852
+ * @summary Test that functional interface method parameter types are equal, even for an explicit lambda
+ * @compile/fail/ref=MostSpecific28.out -XDrawDiagnostics MostSpecific28.java
+ */
+class MostSpecific28 {
+
+ interface Pred<T> { boolean test(T arg); }
+ interface Fun<T,R> { R apply(T arg); }
+
+ static void m1(Pred<? super Integer> f) {}
+ static void m1(Fun<Number, Boolean> f) {}
+
+ static String foo(Object in) { return "a"; }
+
+ void test() {
+ m1((Number n) -> true);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific28.out Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,2 @@
+MostSpecific28.java:18:9: compiler.err.ref.ambiguous: m1, kindname.method, m1(MostSpecific28.Pred<? super java.lang.Integer>), MostSpecific28, kindname.method, m1(MostSpecific28.Fun<java.lang.Number,java.lang.Boolean>), MostSpecific28
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lexer/JavaLexerTest.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,81 @@
+/*
+ * 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 8056897
+ * @summary Proper lexing of integer literals.
+ */
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Objects;
+
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+
+import com.sun.tools.javac.parser.JavaTokenizer;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.parser.Tokens.Token;
+import com.sun.tools.javac.parser.Tokens.TokenKind;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+
+public class JavaLexerTest {
+ public static void main(String... args) throws Exception {
+ new JavaLexerTest().run();
+ }
+
+ void run() throws Exception {
+ Context ctx = new Context();
+ Log log = Log.instance(ctx);
+ String input = "0bL 0b20L 0xL ";
+ log.useSource(new SimpleJavaFileObject(new URI("mem://Test.java"), JavaFileObject.Kind.SOURCE) {
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ return input;
+ }
+ });
+ char[] inputArr = input.toCharArray();
+ JavaTokenizer tokenizer = new JavaTokenizer(ScannerFactory.instance(ctx), inputArr, inputArr.length) {
+ };
+
+ assertKind(input, tokenizer, TokenKind.LONGLITERAL, "0bL");
+ assertKind(input, tokenizer, TokenKind.LONGLITERAL, "0b20L");
+ assertKind(input, tokenizer, TokenKind.LONGLITERAL, "0xL");
+ }
+
+ void assertKind(String input, JavaTokenizer tokenizer, TokenKind kind, String expectedText) {
+ Token token = tokenizer.readToken();
+
+ if (token.kind != kind) {
+ throw new AssertionError("Unexpected token kind: " + token.kind);
+ }
+
+ String actualText = input.substring(token.pos, token.endPos);
+
+ if (!Objects.equals(actualText, expectedText)) {
+ throw new AssertionError("Unexpected token text: " + actualText);
+ }
+ }
+}
\ No newline at end of file
--- a/langtools/test/tools/javac/literals/T6891079.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/javac/literals/T6891079.java Thu Jan 14 12:03:24 2016 -0800
@@ -1,5 +1,5 @@
/* @test /nodynamiccopyright/
- * @bug 6891079
+ * @bug 6891079 8056897
* @summary Compiler allows invalid binary literals 0b and oBL
* @compile/fail/ref=T6891079.out -XDrawDiagnostics T6891079.java
*/
--- a/langtools/test/tools/javac/literals/T6891079.out Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/javac/literals/T6891079.out Thu Jan 14 12:03:24 2016 -0800
@@ -1,7 +1,5 @@
T6891079.java:8:14: compiler.err.invalid.binary.number
T6891079.java:9:15: compiler.err.invalid.binary.number
-T6891079.java:9:18: compiler.err.expected: token.identifier
T6891079.java:10:14: compiler.err.invalid.hex.number
T6891079.java:11:15: compiler.err.invalid.hex.number
-T6891079.java:11:18: compiler.err.expected: token.identifier
-6 errors
+4 errors
--- a/langtools/test/tools/sjavac/CompileExcludingDependency.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/sjavac/CompileExcludingDependency.java Thu Jan 14 12:03:24 2016 -0800
@@ -55,9 +55,9 @@
tb.writeFile(GENSRC.resolve("beta/B.java"),
"package beta; public class B { }");
- compile("-x", "beta",
+ compile("-x", "beta/*",
"-src", GENSRC.toString(),
- "-x", "alfa/omega",
+ "-x", "alfa/omega/*",
"-sourcepath", GENSRC.toString(),
"-d", BIN.toString(),
"--state-dir=" + BIN,
--- a/langtools/test/tools/sjavac/CompileWithAtFile.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/sjavac/CompileWithAtFile.java Thu Jan 14 12:03:24 2016 -0800
@@ -47,8 +47,8 @@
void test() throws Exception {
tb.writeFile(GENSRC.resolve("list.txt"),
- "-if */alfa/omega/A.java\n" +
- "-if */beta/B.java\n" +
+ "-i alfa/omega/A.java\n" +
+ "-i beta/B.java\n" +
GENSRC + "\n" +
"-d " + BIN + "\n" +
"--state-dir=" + BIN + "\n");
--- a/langtools/test/tools/sjavac/CompileWithInvisibleSources.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/sjavac/CompileWithInvisibleSources.java Thu Jan 14 12:03:24 2016 -0800
@@ -64,7 +64,7 @@
"package beta; public class B { }");
compile(GENSRC.toString(),
- "-x", "beta",
+ "-x", "beta/*",
"-sourcepath", GENSRC2.toString(),
"-sourcepath", GENSRC3.toString(),
"-d", BIN.toString(),
--- a/langtools/test/tools/sjavac/CompileWithOverrideSources.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/sjavac/CompileWithOverrideSources.java Thu Jan 14 12:03:24 2016 -0800
@@ -62,7 +62,7 @@
tb.writeFile(GENSRC2.resolve("beta/B.java"),
"package beta; public class B { }");
- compile("-x", "beta",
+ compile("-x", "beta/*",
GENSRC.toString(),
GENSRC2.toString(),
"-d", BIN.toString(),
--- a/langtools/test/tools/sjavac/ExclPattern.java Thu Jan 14 08:08:24 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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 8037085
- * @summary Ensures that sjavac can handle various exclusion patterns.
- *
- * @modules jdk.compiler/com.sun.tools.sjavac
- * @build Wrapper
- * @run main Wrapper ExclPattern
- */
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-public class ExclPattern {
-
- public static void main(String[] ignore) throws IOException {
-
- String toBeExcluded = "pkg/excl-dir/excluded.txt";
- String toBeIncluded = "pkg/incl-dir/included.txt";
-
- // Set up source directory with directory to be excluded
- populate(Paths.get("srcdir"),
- "pkg/SomeClass.java",
- "package pkg; public class SomeClass { }",
-
- toBeExcluded,
- "This file should not end up in the dest directory.",
-
- toBeIncluded,
- "This file should end up in the dest directory.");
-
- String[] args = {
- "-x", "pkg/excl-dir/*",
- "-src", "srcdir",
- "-d", "dest",
- "--state-dir=dest",
- "-j", "1",
- "-copy", ".txt",
- "--server:portfile=testserver,background=false",
- "--log=debug"
- };
-
- int rc = com.sun.tools.sjavac.Main.go(args);
- if (rc != 0) throw new RuntimeException("Error during compile!");
-
- if (!Files.exists(Paths.get("dest/" + toBeIncluded)))
- throw new AssertionError("File missing: " + toBeIncluded);
-
- if (Files.exists(Paths.get("dest/" + toBeExcluded)))
- throw new AssertionError("File present: " + toBeExcluded);
- }
-
- static void populate(Path root, String... args) throws IOException {
- if (!Files.exists(root))
- Files.createDirectory(root);
- for (int i = 0; i < args.length; i += 2) {
- String filename = args[i];
- String content = args[i+1];
- Path p = root.resolve(filename);
- Files.createDirectories(p.getParent());
- try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(p,
- Charset.defaultCharset()))) {
- out.println(content);
- }
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/sjavac/HiddenFiles.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/*
+ * @test
+ * @bug 8144226
+ * @summary Ensures that excluded files are inaccessible (even for implicit
+ * compilation)
+ *
+ * @modules jdk.compiler/com.sun.tools.sjavac
+ * @library /tools/lib
+ * @build Wrapper ToolBox
+ * @run main Wrapper HiddenFiles
+ */
+
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.sjavac.server.Sjavac;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class HiddenFiles extends SjavacBase {
+
+ public static void main(String[] ignore) throws Exception {
+ Path BIN = Paths.get("bin");
+ Path STATE_DIR = Paths.get("state-dir");
+ Path SRC = Paths.get("src");
+
+ Files.createDirectories(BIN);
+ Files.createDirectories(STATE_DIR);
+
+ toolbox.writeJavaFiles(SRC, "package pkg; class A { B b; }");
+ toolbox.writeJavaFiles(SRC, "package pkg; class B { }");
+
+ // This compilation should fail (return RC_FATAL) since A.java refers to B.java and B.java
+ // is excluded.
+ int rc = compile("-x", "pkg/B.java", SRC.toString(),
+ "--server:portfile=testportfile,background=false",
+ "-d", BIN.toString(),
+ "--state-dir=" + STATE_DIR);
+
+ Assert.check(rc == Sjavac.RC_FATAL, "Compilation succeeded unexpectedly.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/sjavac/IncludeExcludePatterns.java Thu Jan 14 12:03:24 2016 -0800
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014, 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 8037085
+ * @summary Ensures that sjavac can handle various exclusion patterns.
+ *
+ * @modules jdk.compiler/com.sun.tools.sjavac
+ * @library /tools/lib
+ * @build Wrapper ToolBox
+ * @run main Wrapper IncludeExcludePatterns
+ */
+
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.sjavac.server.Sjavac;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class IncludeExcludePatterns extends SjavacBase {
+
+ final Path SRC = Paths.get("src");
+ final Path BIN = Paths.get("bin");
+ final Path STATE_DIR = Paths.get("state-dir");
+
+ // An arbitrarily but sufficiently complicated source tree.
+ final Path A = Paths.get("pkga/A.java");
+ final Path X1 = Paths.get("pkga/subpkg/Xx.java");
+ final Path Y = Paths.get("pkga/subpkg/subsubpkg/Y.java");
+ final Path B = Paths.get("pkgb/B.java");
+ final Path C = Paths.get("pkgc/C.java");
+ final Path X2 = Paths.get("pkgc/Xx.java");
+
+ final Path[] ALL_PATHS = {A, X1, Y, B, C, X2};
+
+ public static void main(String[] ignore) throws Exception {
+ new IncludeExcludePatterns().runTest();
+ }
+
+ public void runTest() throws IOException, ReflectiveOperationException {
+ Files.createDirectories(BIN);
+ Files.createDirectories(STATE_DIR);
+ for (Path p : ALL_PATHS) {
+ writeDummyClass(p);
+ }
+
+ // Single file
+ testPattern("pkga/A.java", A);
+
+ // Leading wild cards
+ testPattern("*/A.java", A);
+ testPattern("**/Xx.java", X1, X2);
+ testPattern("**x.java", X1, X2);
+
+ // Wild card in middle of path
+ testPattern("pkga/*/Xx.java", X1);
+ testPattern("pkga/**/Y.java", Y);
+
+ // Trailing wild cards
+ testPattern("pkga/*", A);
+ testPattern("pkga/**", A, X1, Y);
+
+ // Multiple wildcards
+ testPattern("pkga/*/*/Y.java", Y);
+ testPattern("**/*/**", X1, Y);
+
+ }
+
+ // Given "src/pkg/subpkg/A.java" this method returns "A"
+ String classNameOf(Path javaFile) {
+ return javaFile.getFileName()
+ .toString()
+ .replace(".java", "");
+ }
+
+ // Puts an empty (dummy) class definition in the given path.
+ void writeDummyClass(Path javaFile) throws IOException {
+ String pkg = javaFile.getParent().toString().replace(File.separatorChar, '.');
+ String cls = javaFile.getFileName().toString().replace(".java", "");
+ toolbox.writeFile(SRC.resolve(javaFile), "package " + pkg + "; class " + cls + " {}");
+ }
+
+ void testPattern(String filterArgs, Path... sourcesExpectedToBeVisible)
+ throws ReflectiveOperationException, IOException {
+ testFilter("-i " + filterArgs, Arrays.asList(sourcesExpectedToBeVisible));
+
+ Set<Path> complement = new HashSet<>(Arrays.asList(ALL_PATHS));
+ complement.removeAll(Arrays.asList(sourcesExpectedToBeVisible));
+ testFilter("-x " + filterArgs, complement);
+ }
+
+ void testFilter(String filterArgs, Collection<Path> sourcesExpectedToBeVisible)
+ throws IOException, ReflectiveOperationException {
+ System.out.println("Testing filter: " + filterArgs);
+ toolbox.cleanDirectory(BIN);
+ toolbox.cleanDirectory(STATE_DIR);
+ String args = filterArgs + " " + SRC
+ + " --server:portfile=testportfile,background=false"
+ + " -d " + BIN
+ + " --state-dir=" + STATE_DIR;
+ int rc = compile((Object[]) args.split(" "));
+
+ // Compilation should always pass in these tests
+ Assert.check(rc == Sjavac.RC_OK, "Compilation failed unexpectedly.");
+
+ // The resulting .class files should correspond to the visible source files
+ Set<Path> result = allFilesInDir(BIN);
+ Set<Path> expected = correspondingClassFiles(sourcesExpectedToBeVisible);
+ if (!result.equals(expected)) {
+ System.out.println("Result:");
+ printPaths(result);
+ System.out.println("Expected:");
+ printPaths(expected);
+ Assert.error("Test case failed: " + filterArgs);
+ }
+ }
+
+ void printPaths(Collection<Path> paths) {
+ paths.stream()
+ .sorted()
+ .forEachOrdered(p -> System.out.println(" " + p));
+ }
+
+ // Given "pkg/A.java, pkg/B.java" this method returns "bin/pkg/A.class, bin/pkg/B.class"
+ Set<Path> correspondingClassFiles(Collection<Path> javaFiles) {
+ return javaFiles.stream()
+ .map(javaFile -> javaFile.resolveSibling(classNameOf(javaFile) + ".class"))
+ .map(BIN::resolve)
+ .collect(Collectors.toSet());
+ }
+
+ Set<Path> allFilesInDir(Path p) throws IOException {
+ try (Stream<Path> files = Files.walk(p).filter(Files::isRegularFile)) {
+ return files.collect(Collectors.toSet());
+ }
+ }
+}
--- a/langtools/test/tools/sjavac/OptionDecoding.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/sjavac/OptionDecoding.java Thu Jan 14 12:03:24 2016 -0800
@@ -61,7 +61,6 @@
public static void main(String[] args) throws IOException {
testPaths();
testDupPaths();
- testSourceLocations();
testSimpleOptions();
testServerConf();
testSearchPaths();
@@ -110,78 +109,6 @@
}
}
- // Test source locations and -x, -i, -xf, -if filters
- static void testSourceLocations() throws IOException {
- Path a1 = Paths.get("root/pkg1/ClassA1.java");
- Path a2 = Paths.get("root/pkg1/ClassA2.java");
- Path b1 = Paths.get("root/pkg1/pkg2/ClassB1.java");
- Path b2 = Paths.get("root/pkg1/pkg2/ClassB2.java");
- Path c1 = Paths.get("root/pkg3/ClassC1.java");
- Path c2 = Paths.get("root/pkg3/ClassC2.java");
-
- for (Path p : Arrays.asList(a1, a2, b1, b2, c1, c2)) {
- Files.createDirectories(p.getParent());
- Files.createFile(p);
- }
-
- // Test -if
- {
- Options options = Options.parseArgs("-if", "root/pkg1/ClassA1.java", "root");
-
- Map<String, Source> foundFiles = new HashMap<>();
- SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
- new HashMap<String, Module>(), new Module("", ""), false, true);
-
- checkFilesFound(foundFiles.keySet(), a1);
- }
-
- // Test -i
- System.out.println("--------------------------- CHECKING -i ----------------");
- {
- Options options = Options.parseArgs("-i", "pkg1/*", "root");
-
- Map<String, Source> foundFiles = new HashMap<>();
- SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
- new HashMap<String, Module>(), new Module("", ""), false, true);
-
- checkFilesFound(foundFiles.keySet(), a1, a2, b1, b2);
- }
- System.out.println("--------------------------------------------------------");
-
- // Test -xf
- {
- Options options = Options.parseArgs("-xf", "root/pkg1/ClassA1.java", "root");
-
- Map<String, Source> foundFiles = new HashMap<>();
- SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
- new HashMap<String, Module>(), new Module("", ""), false, true);
-
- checkFilesFound(foundFiles.keySet(), a2, b1, b2, c1, c2);
- }
-
- // Test -x
- {
- Options options = Options.parseArgs("-i", "pkg1/*", "root");
-
- Map<String, Source> foundFiles = new HashMap<>();
- SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
- new HashMap<String, Module>(), new Module("", ""), false, true);
-
- checkFilesFound(foundFiles.keySet(), a1, a2, b1, b2);
- }
-
- // Test -x and -i
- {
- Options options = Options.parseArgs("-i", "pkg1/*", "-x", "pkg1/pkg2/*", "root");
-
- Map<String, Source> foundFiles = new HashMap<>();
- SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
- new HashMap<String, Module>(), new Module("", ""), false, true);
-
- checkFilesFound(foundFiles.keySet(), a1, a2);
- }
- }
-
// Test basic options
static void testSimpleOptions() {
Options options = Options.parseArgs("-j", "17", "--log=debug");
@@ -216,8 +143,8 @@
List<String> i, x, iF, xF;
i = x = iF = xF = new ArrayList<>();
- SourceLocation dir1 = new SourceLocation(Paths.get("dir1"), i, x, iF, xF);
- SourceLocation dir2 = new SourceLocation(Paths.get("dir2"), i, x, iF, xF);
+ SourceLocation dir1 = new SourceLocation(Paths.get("dir1"), i, x);
+ SourceLocation dir2 = new SourceLocation(Paths.get("dir2"), i, x);
String dir1_PS_dir2 = "dir1" + File.pathSeparator + "dir2";
Options options = Options.parseArgs("-sourcepath", dir1_PS_dir2);
--- a/langtools/test/tools/sjavac/Serialization.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/sjavac/Serialization.java Thu Jan 14 12:03:24 2016 -0800
@@ -58,8 +58,6 @@
Option.D.arg, "dest",
Option.I.arg, "pkg/*",
Option.X.arg, "pkg/pkg/*",
- Option.IF.arg, "root/pkg/MyClass1.java",
- Option.XF.arg, "root/pkg/MyClass2.java",
Option.SRC.arg, "root",
Option.SOURCEPATH.arg, "sourcepath",
Option.CLASSPATH.arg, "classpath",
@@ -87,8 +85,6 @@
assertEquals(sl1.getPath(), sl2.getPath());
assertEquals(sl1.getIncludes(), sl2.getIncludes());
assertEquals(sl1.getExcludes(), sl2.getExcludes());
- assertEquals(sl1.getIncludedFiles(), sl2.getIncludedFiles());
- assertEquals(sl1.getExcludedFiles(), sl2.getExcludedFiles());
assertEquals(options1.getClassSearchPath(), options2.getClassSearchPath());
assertEquals(options1.getSourceSearchPaths(), options2.getSourceSearchPaths());
--- a/langtools/test/tools/sjavac/util/OptionTestUtil.java Thu Jan 14 08:08:24 2016 -0800
+++ b/langtools/test/tools/sjavac/util/OptionTestUtil.java Thu Jan 14 12:03:24 2016 -0800
@@ -62,9 +62,7 @@
if (!sl1.getPath().equals(sl2.getPath()) ||
!sl1.getIncludes().equals(sl2.getIncludes()) ||
- !sl1.getExcludes().equals(sl2.getExcludes()) ||
- !sl1.getIncludedFiles().equals(sl2.getIncludedFiles()) ||
- !sl1.getExcludedFiles().equals(sl2.getExcludedFiles()))
+ !sl1.getExcludes().equals(sl2.getExcludes()))
throw new AssertionError("Expected " + sl1 + " but got " + sl2);
}
}