Tue, 20 Jul 2010 22:22:32 -0700
Merge
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Kinds.java Thu Jul 15 20:11:54 2010 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Kinds.java Tue Jul 20 22:22:32 2010 -0700 1.3 @@ -92,7 +92,7 @@ 1.4 public static final int ABSENT_TYP = ERRONEOUS+8; // missing type 1.5 1.6 public enum KindName implements Formattable { 1.7 - ANNOTATION("kindname.interface"), 1.8 + ANNOTATION("kindname.annotation"), 1.9 CONSTRUCTOR("kindname.constructor"), 1.10 INTERFACE("kindname.interface"), 1.11 ENUM("kindname.enum"),
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Jul 15 20:11:54 2010 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Jul 20 22:22:32 2010 -0700 2.3 @@ -563,7 +563,7 @@ 2.4 while (args.nonEmpty()) { 2.5 if (args.head.tag == WILDCARD) 2.6 return typeTagError(pos, 2.7 - Log.getLocalizedString("type.req.exact"), 2.8 + diags.fragment("type.req.exact"), 2.9 args.head); 2.10 args = args.tail; 2.11 }
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Jul 15 20:11:54 2010 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Tue Jul 20 22:22:32 2010 -0700 3.3 @@ -674,6 +674,40 @@ 3.4 return rs.resolveInternalField(pos, attrEnv, qual, name); 3.5 } 3.6 3.7 + /** Anon inner classes are used as access constructor tags. 3.8 + * accessConstructorTag will use an existing anon class if one is available, 3.9 + * and synthethise a class (with makeEmptyClass) if one is not available. 3.10 + * However, there is a small possibility that an existing class will not 3.11 + * be generated as expected if it is inside a conditional with a constant 3.12 + * expression. If that is found to be the case, create an empty class here. 3.13 + */ 3.14 + private void checkAccessConstructorTags() { 3.15 + for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) { 3.16 + ClassSymbol c = l.head; 3.17 + if (isTranslatedClassAvailable(c)) 3.18 + continue; 3.19 + // Create class definition tree. 3.20 + JCClassDecl cdef = make.ClassDef( 3.21 + make.Modifiers(STATIC | SYNTHETIC), names.empty, 3.22 + List.<JCTypeParameter>nil(), 3.23 + null, List.<JCExpression>nil(), List.<JCTree>nil()); 3.24 + cdef.sym = c; 3.25 + cdef.type = c.type; 3.26 + // add it to the list of classes to be generated 3.27 + translated.append(cdef); 3.28 + } 3.29 + } 3.30 + // where 3.31 + private boolean isTranslatedClassAvailable(ClassSymbol c) { 3.32 + for (JCTree tree: translated) { 3.33 + if (tree.getTag() == JCTree.CLASSDEF 3.34 + && ((JCClassDecl) tree).sym == c) { 3.35 + return true; 3.36 + } 3.37 + } 3.38 + return false; 3.39 + } 3.40 + 3.41 /************************************************************************** 3.42 * Access methods 3.43 *************************************************************************/ 3.44 @@ -718,6 +752,10 @@ 3.45 */ 3.46 private Map<Symbol,MethodSymbol> accessConstrs; 3.47 3.48 + /** A list of all class symbols used for access constructor tags. 3.49 + */ 3.50 + private List<ClassSymbol> accessConstrTags; 3.51 + 3.52 /** A queue for all accessed symbols. 3.53 */ 3.54 private ListBuffer<Symbol> accessed; 3.55 @@ -1138,6 +1176,8 @@ 3.56 ClassSymbol ctag = chk.compiled.get(flatname); 3.57 if (ctag == null) 3.58 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass); 3.59 + // keep a record of all tags, to verify that all are generated as required 3.60 + accessConstrTags = accessConstrTags.prepend(ctag); 3.61 return ctag; 3.62 } 3.63 3.64 @@ -3394,6 +3434,7 @@ 3.65 accessNums = new HashMap<Symbol,Integer>(); 3.66 accessSyms = new HashMap<Symbol,MethodSymbol[]>(); 3.67 accessConstrs = new HashMap<Symbol,MethodSymbol>(); 3.68 + accessConstrTags = List.nil(); 3.69 accessed = new ListBuffer<Symbol>(); 3.70 translate(cdef, (JCExpression)null); 3.71 for (List<Symbol> l = accessed.toList(); l.nonEmpty(); l = l.tail) 3.72 @@ -3401,6 +3442,7 @@ 3.73 for (EnumMapping map : enumSwitchMap.values()) 3.74 map.translate(); 3.75 checkConflicts(this.translated.toList()); 3.76 + checkAccessConstructorTags(); 3.77 translated = this.translated; 3.78 } finally { 3.79 // note that recursive invocations of this method fail hard 3.80 @@ -3420,6 +3462,7 @@ 3.81 accessNums = null; 3.82 accessSyms = null; 3.83 accessConstrs = null; 3.84 + accessConstrTags = null; 3.85 accessed = null; 3.86 enumSwitchMap.clear(); 3.87 }
4.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Jul 15 20:11:54 2010 -0700 4.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Jul 20 22:22:32 2010 -0700 4.3 @@ -111,14 +111,14 @@ 4.4 try { 4.5 versionRB = ResourceBundle.getBundle(versionRBName); 4.6 } catch (MissingResourceException e) { 4.7 - return Log.getLocalizedString("version.resource.missing", System.getProperty("java.version")); 4.8 + return Log.getLocalizedString("version.not.available"); 4.9 } 4.10 } 4.11 try { 4.12 return versionRB.getString(key); 4.13 } 4.14 catch (MissingResourceException e) { 4.15 - return Log.getLocalizedString("version.unknown", System.getProperty("java.version")); 4.16 + return Log.getLocalizedString("version.not.available"); 4.17 } 4.18 } 4.19
5.1 --- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java Thu Jul 15 20:11:54 2010 -0700 5.2 +++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java Tue Jul 20 22:22:32 2010 -0700 5.3 @@ -419,7 +419,7 @@ 5.4 putChar(ch); 5.5 } else { 5.6 if (!allowUnderscoresInLiterals) { 5.7 - lexError("unsupported.underscore", source.name); 5.8 + lexError("unsupported.underscore.lit", source.name); 5.9 allowUnderscoresInLiterals = true; 5.10 } 5.11 }
6.1 --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Jul 15 20:11:54 2010 -0700 6.2 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Jul 20 22:22:32 2010 -0700 6.3 @@ -637,6 +637,9 @@ 6.4 compiler.misc.count.warn.plural=\ 6.5 {0} warnings 6.6 6.7 +compiler.misc.version.not.available=\ 6.8 + (version info not available) 6.9 + 6.10 ## extra output when using -verbose (JavaCompiler) 6.11 6.12 compiler.misc.verbose.checking.attribution=\ 6.13 @@ -1036,7 +1039,7 @@ 6.14 ## diagnostics whose key ends in ".1" 6.15 compiler.misc.undetermined.type=\ 6.16 undetermined type 6.17 -ncompiler.misc.type.variable.has.undetermined.type=\ 6.18 +compiler.misc.type.variable.has.undetermined.type=\ 6.19 type variable {0} has undetermined type 6.20 compiler.misc.no.unique.maximal.instance.exists=\ 6.21 no unique maximal instance exists for type variable {0} with upper bounds {1} 6.22 @@ -1122,6 +1125,8 @@ 6.23 @interface 6.24 compiler.misc.kindname.constructor=\ 6.25 constructor 6.26 +compiler.misc.kindname.enum=\ 6.27 + enum 6.28 compiler.misc.kindname.interface=\ 6.29 interface 6.30 compiler.misc.kindname.static=\ 6.31 @@ -1256,6 +1261,10 @@ 6.32 enums are not supported in -source {0}\n\ 6.33 (use -source 5 or higher to enable enums) 6.34 6.35 +compiler.err.diamond.not.supported.in.source=\ 6.36 + diamond operator is not supported in -source {0}\n\ 6.37 +(use -source 7 or higher to enable multi-catch statement) 6.38 + 6.39 compiler.err.multicatch.not.supported.in.source=\ 6.40 multi-catch statement is not supported in -source {0}\n\ 6.41 (use -source 7 or higher to enable multi-catch statement)
7.1 --- a/src/share/classes/javax/lang/model/element/ElementKind.java Thu Jul 15 20:11:54 2010 -0700 7.2 +++ b/src/share/classes/javax/lang/model/element/ElementKind.java Tue Jul 20 22:22:32 2010 -0700 7.3 @@ -88,7 +88,13 @@ 7.4 * An implementation-reserved element. This is not the element 7.5 * you are looking for. 7.6 */ 7.7 - OTHER; 7.8 + OTHER, 7.9 + 7.10 + /** 7.11 + * A resource variable. 7.12 + * @since 1.7 7.13 + */ 7.14 + RESOURCE_VARIABLE; 7.15 7.16 7.17 /**
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/tools/javac/6917288/GraphicalInstaller.java Tue Jul 20 22:22:32 2010 -0700 8.3 @@ -0,0 +1,55 @@ 8.4 +/* 8.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + */ 8.26 + 8.27 +/** 8.28 + * Complex example for the "access constructor tags" issue. 8.29 + * This test causes Lower to evaluate all classes defined in installNext 8.30 + * before they are lowered, thus preventing the use of Lower.classdefs 8.31 + * as a way of determining whether a class has been translated or not. 8.32 + */ 8.33 +class GraphicalInstaller { 8.34 + private BackgroundInstaller backgroundInstaller; 8.35 + 8.36 + private void installNext() { 8.37 + final Integer x = 0; 8.38 + class X { 8.39 + Object o = new Object() { int y = x; }; 8.40 + }; 8.41 + new X(); 8.42 + if (false) { 8.43 + new Runnable(){ 8.44 + public void run() { 8.45 + } 8.46 + }; 8.47 + } 8.48 + } 8.49 + 8.50 + private void installSuiteCommon() { 8.51 + backgroundInstaller = new BackgroundInstaller(); 8.52 + } 8.53 + 8.54 + private static class BackgroundInstaller { 8.55 + private BackgroundInstaller() { 8.56 + } 8.57 + } 8.58 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/tools/javac/6917288/GraphicalInstallerTest.java Tue Jul 20 22:22:32 2010 -0700 9.3 @@ -0,0 +1,106 @@ 9.4 +/* 9.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.7 + * 9.8 + * This code is free software; you can redistribute it and/or modify it 9.9 + * under the terms of the GNU General Public License version 2 only, as 9.10 + * published by the Free Software Foundation. 9.11 + * 9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 9.15 + * version 2 for more details (a copy is included in the LICENSE file that 9.16 + * accompanied this code). 9.17 + * 9.18 + * You should have received a copy of the GNU General Public License version 9.19 + * 2 along with this work; if not, write to the Free Software Foundation, 9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 9.21 + * 9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 9.23 + * or visit www.oracle.com if you need additional information or have any 9.24 + * questions. 9.25 + */ 9.26 + 9.27 + 9.28 +/* @test 9.29 + * @bug 6917288 9.30 + * @summary Unnamed nested class is not generated 9.31 + */ 9.32 + 9.33 +import java.io.*; 9.34 +import java.util.*; 9.35 + 9.36 +public class GraphicalInstallerTest { 9.37 + public static void main(String... args) throws Exception { 9.38 + new GraphicalInstallerTest().run(); 9.39 + } 9.40 + 9.41 + void run() throws Exception { 9.42 + File testSrc = new File(System.getProperty("test.src")); 9.43 + File classes = new File("classes"); 9.44 + classes.mkdirs(); 9.45 + List<String> opts = Arrays.asList("-d", classes.getPath()); 9.46 + int rc = compile(opts, new File(testSrc, "GraphicalInstaller.java")); 9.47 + if (rc != 0) { 9.48 + error("compilation failed: rc=" + rc); 9.49 + return; 9.50 + } 9.51 + 9.52 + check(classes, 9.53 + "GraphicalInstaller$1.class", 9.54 + "GraphicalInstaller$1X$1.class", 9.55 + "GraphicalInstaller$1X.class", 9.56 + "GraphicalInstaller$BackgroundInstaller.class", 9.57 + "GraphicalInstaller.class"); 9.58 + 9.59 + if (errors > 0) 9.60 + throw new Exception(errors + " errors occurred"); 9.61 + } 9.62 + 9.63 + /** 9.64 + * Compile files with given options. 9.65 + * Display any output from compiler, and return javac return code. 9.66 + */ 9.67 + int compile(List<String> opts, File... files) { 9.68 + List<String> args = new ArrayList<String>(); 9.69 + args.addAll(opts); 9.70 + for (File f: files) 9.71 + args.add(f.getPath()); 9.72 + StringWriter sw = new StringWriter(); 9.73 + PrintWriter pw = new PrintWriter(sw); 9.74 + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); 9.75 + pw.close(); 9.76 + String out = sw.toString(); 9.77 + if (out.length() > 0) 9.78 + System.err.println(out); 9.79 + return rc; 9.80 + } 9.81 + 9.82 + /** 9.83 + * Check that a directory contains the expected files. 9.84 + */ 9.85 + void check(File dir, String... paths) { 9.86 + Set<String> found = new TreeSet<String>(Arrays.asList(dir.list())); 9.87 + Set<String> expect = new TreeSet<String>(Arrays.asList(paths)); 9.88 + if (found.equals(expect)) 9.89 + return; 9.90 + for (String f: found) { 9.91 + if (!expect.contains(f)) 9.92 + error("Unexpected file found: " + f); 9.93 + } 9.94 + for (String e: expect) { 9.95 + if (!found.contains(e)) 9.96 + error("Expected file not found: " + e); 9.97 + } 9.98 + } 9.99 + 9.100 + /** 9.101 + * Record an error message. 9.102 + */ 9.103 + void error(String msg) { 9.104 + System.err.println(msg); 9.105 + errors++; 9.106 + } 9.107 + 9.108 + int errors; 9.109 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/tools/javac/6917288/T6917288.java Tue Jul 20 22:22:32 2010 -0700 10.3 @@ -0,0 +1,158 @@ 10.4 +/* 10.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.7 + * 10.8 + * This code is free software; you can redistribute it and/or modify it 10.9 + * under the terms of the GNU General Public License version 2 only, as 10.10 + * published by the Free Software Foundation. 10.11 + * 10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 10.15 + * version 2 for more details (a copy is included in the LICENSE file that 10.16 + * accompanied this code). 10.17 + * 10.18 + * You should have received a copy of the GNU General Public License version 10.19 + * 2 along with this work; if not, write to the Free Software Foundation, 10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 10.21 + * 10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 10.23 + * or visit www.oracle.com if you need additional information or have any 10.24 + * questions. 10.25 + */ 10.26 + 10.27 +/* @test 10.28 + * @bug 6917288 10.29 + * @summary Unnamed nested class is not generated 10.30 + */ 10.31 + 10.32 +import java.io.*; 10.33 +import java.util.*; 10.34 + 10.35 +public class T6917288 { 10.36 + // refers to kind of reference to an anon inner class that may be generated 10.37 + enum Kind { NONE, FALSE, TRUE, ALWAYS }; 10.38 + 10.39 + public static void main(String... args) throws Exception { 10.40 + new T6917288().run(); 10.41 + } 10.42 + 10.43 + void run() throws Exception { 10.44 + for (Kind k: Kind.values()) { 10.45 + test(k); 10.46 + } 10.47 + 10.48 + if (errors > 0) 10.49 + throw new Exception(errors + " errors occurred"); 10.50 + } 10.51 + 10.52 + /** 10.53 + * Run a test case for Kind k. 10.54 + */ 10.55 + void test(Kind k) throws Exception { 10.56 + System.err.println("Test " + (++count) + ": " + k); 10.57 + File testDir = new File("test" + count); 10.58 + File srcDir = new File(testDir, "src"); 10.59 + srcDir.mkdirs(); 10.60 + File classesDir = new File(testDir, "classes"); 10.61 + classesDir.mkdirs(); 10.62 + 10.63 + List<String> opts = new ArrayList<String>(); 10.64 + opts.add("-d"); 10.65 + opts.add(classesDir.getPath()); 10.66 + 10.67 + File f = writeFile(srcDir, k); 10.68 + int rc = compile(opts, f); 10.69 + if (rc != 0) { 10.70 + error("compilation failed: rc=" + rc); 10.71 + return; 10.72 + } 10.73 + 10.74 + check(classesDir, "Test.class", "Test$Inner.class", "Test$1.class"); 10.75 + } 10.76 + 10.77 + /** 10.78 + * Compile files with given options. 10.79 + * Display any output from compiler, and return javac return code. 10.80 + */ 10.81 + int compile(List<String> opts, File... files) { 10.82 + List<String> args = new ArrayList<String>(); 10.83 + args.addAll(opts); 10.84 + for (File f: files) 10.85 + args.add(f.getPath()); 10.86 + StringWriter sw = new StringWriter(); 10.87 + PrintWriter pw = new PrintWriter(sw); 10.88 + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); 10.89 + pw.close(); 10.90 + String out = sw.toString(); 10.91 + if (out.length() > 0) 10.92 + System.err.println(out); 10.93 + return rc; 10.94 + } 10.95 + 10.96 + /** 10.97 + * Check that a directory contains the expected files. 10.98 + */ 10.99 + void check(File dir, String... paths) { 10.100 + Set<String> found = new TreeSet<String>(Arrays.asList(dir.list())); 10.101 + Set<String> expect = new TreeSet<String>(Arrays.asList(paths)); 10.102 + if (found.equals(expect)) 10.103 + return; 10.104 + for (String f: found) { 10.105 + if (!expect.contains(f)) 10.106 + error("Unexpected file found: " + f); 10.107 + } 10.108 + for (String e: expect) { 10.109 + if (!found.contains(e)) 10.110 + error("Expected file not found: " + e); 10.111 + } 10.112 + } 10.113 + 10.114 + /** 10.115 + * Write source file for test case k. 10.116 + */ 10.117 + File writeFile(File dir, Kind k) throws Exception { 10.118 + StringBuilder sb = new StringBuilder(); 10.119 + sb.append("public class Test {\n"); 10.120 + sb.append(" private Inner inner;\n"); 10.121 + 10.122 + // generate different cases of an anon inner class 10.123 + if (k != Kind.NONE) { 10.124 + sb.append(" private void m() {\n"); 10.125 + sb.append(" "); 10.126 + switch (k) { 10.127 + case FALSE: case TRUE: 10.128 + sb.append("if (" + k.toString().toLowerCase() + ") "); 10.129 + } 10.130 + sb.append("new Runnable() { public void run() { } };\n"); 10.131 + sb.append(" }\n"); 10.132 + } 10.133 + 10.134 + sb.append(" private void init() {\n"); 10.135 + sb.append(" inner = new Inner();\n"); 10.136 + sb.append(" }\n"); 10.137 + sb.append("\n"); 10.138 + sb.append(" private static class Inner {\n"); 10.139 + sb.append(" private Inner() {\n"); 10.140 + sb.append(" }\n"); 10.141 + sb.append(" }\n"); 10.142 + sb.append("}\n"); 10.143 + 10.144 + File f = new File(dir, "Test.java"); 10.145 + FileWriter w = new FileWriter(f); 10.146 + w.write(sb.toString()); 10.147 + w.close(); 10.148 + return f; 10.149 + } 10.150 + 10.151 + /** 10.152 + * Record an error message. 10.153 + */ 10.154 + void error(String msg) { 10.155 + System.err.println(msg); 10.156 + errors++; 10.157 + } 10.158 + 10.159 + int count; 10.160 + int errors; 10.161 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/tools/javac/diags/CheckResourceKeys.java Tue Jul 20 22:22:32 2010 -0700 11.3 @@ -0,0 +1,362 @@ 11.4 +/* 11.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. 11.11 + * 11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.15 + * version 2 for more details (a copy is included in the LICENSE file that 11.16 + * accompanied this code). 11.17 + * 11.18 + * You should have received a copy of the GNU General Public License version 11.19 + * 2 along with this work; if not, write to the Free Software Foundation, 11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.21 + * 11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 11.23 + * or visit www.oracle.com if you need additional information or have any 11.24 + * questions. 11.25 + */ 11.26 + 11.27 +/* 11.28 + * @test 11.29 + * @bug 6964768 6964461 6964469 6964487 6964460 6964481 11.30 + * @summary need test program to validate javac resource bundles 11.31 + */ 11.32 + 11.33 +import java.io.*; 11.34 +import java.util.*; 11.35 +import javax.tools.*; 11.36 +import com.sun.tools.classfile.*; 11.37 + 11.38 +/** 11.39 + * Compare string constants in javac classes against keys in javac resource bundles. 11.40 + */ 11.41 +public class CheckResourceKeys { 11.42 + /** 11.43 + * Main program. 11.44 + * Options: 11.45 + * -finddeadkeys 11.46 + * look for keys in resource bundles that are no longer required 11.47 + * -findmissingkeys 11.48 + * look for keys in resource bundles that are missing 11.49 + * 11.50 + * @throws Exception if invoked by jtreg and errors occur 11.51 + */ 11.52 + public static void main(String... args) throws Exception { 11.53 + CheckResourceKeys c = new CheckResourceKeys(); 11.54 + if (c.run(args)) 11.55 + return; 11.56 + 11.57 + if (is_jtreg()) 11.58 + throw new Exception(c.errors + " errors occurred"); 11.59 + else 11.60 + System.exit(1); 11.61 + } 11.62 + 11.63 + static boolean is_jtreg() { 11.64 + return (System.getProperty("test.src") != null); 11.65 + } 11.66 + 11.67 + /** 11.68 + * Main entry point. 11.69 + */ 11.70 + boolean run(String... args) throws Exception { 11.71 + boolean findDeadKeys = false; 11.72 + boolean findMissingKeys = false; 11.73 + 11.74 + if (args.length == 0) { 11.75 + if (is_jtreg()) { 11.76 + findDeadKeys = true; 11.77 + findMissingKeys = true; 11.78 + } else { 11.79 + System.err.println("Usage: java CheckResourceKeys <options>"); 11.80 + System.err.println("where options include"); 11.81 + System.err.println(" -finddeadkeys find keys in resource bundles which are no longer required"); 11.82 + System.err.println(" -findmissingkeys find keys in resource bundles that are required but missing"); 11.83 + return true; 11.84 + } 11.85 + } else { 11.86 + for (String arg: args) { 11.87 + if (arg.equalsIgnoreCase("-finddeadkeys")) 11.88 + findDeadKeys = true; 11.89 + else if (arg.equalsIgnoreCase("-findmissingkeys")) 11.90 + findMissingKeys = true; 11.91 + else 11.92 + error("bad option: " + arg); 11.93 + } 11.94 + } 11.95 + 11.96 + if (errors > 0) 11.97 + return false; 11.98 + 11.99 + Set<String> codeStrings = getCodeStrings(); 11.100 + Set<String> resourceKeys = getResourceKeys(); 11.101 + 11.102 + if (findDeadKeys) 11.103 + findDeadKeys(codeStrings, resourceKeys); 11.104 + 11.105 + if (findMissingKeys) 11.106 + findMissingKeys(codeStrings, resourceKeys); 11.107 + 11.108 + return (errors == 0); 11.109 + } 11.110 + 11.111 + /** 11.112 + * Find keys in resource bundles which are probably no longer required. 11.113 + * A key is probably required if there is a string fragment in the code 11.114 + * that is part of the resource key, or if the key is well-known 11.115 + * according to various pragmatic rules. 11.116 + */ 11.117 + void findDeadKeys(Set<String> codeStrings, Set<String> resourceKeys) { 11.118 + String[] prefixes = { 11.119 + "compiler.err.", "compiler.warn.", "compiler.note.", "compiler.misc.", 11.120 + "javac." 11.121 + }; 11.122 + for (String rk: resourceKeys) { 11.123 + // some keys are used directly, without a prefix. 11.124 + if (codeStrings.contains(rk)) 11.125 + continue; 11.126 + 11.127 + // remove standard prefix 11.128 + String s = null; 11.129 + for (int i = 0; i < prefixes.length && s == null; i++) { 11.130 + if (rk.startsWith(prefixes[i])) { 11.131 + s = rk.substring(prefixes[i].length()); 11.132 + } 11.133 + } 11.134 + if (s == null) { 11.135 + error("Resource key does not start with a standard prefix: " + rk); 11.136 + continue; 11.137 + } 11.138 + 11.139 + if (codeStrings.contains(s)) 11.140 + continue; 11.141 + 11.142 + // keys ending in .1 are often synthesized 11.143 + if (s.endsWith(".1") && codeStrings.contains(s.substring(0, s.length() - 2))) 11.144 + continue; 11.145 + 11.146 + // verbose keys are generated by ClassReader.printVerbose 11.147 + if (s.startsWith("verbose.") && codeStrings.contains(s.substring(8))) 11.148 + continue; 11.149 + 11.150 + // mandatory warning messages are synthesized with no characteristic substring 11.151 + if (isMandatoryWarningString(s)) 11.152 + continue; 11.153 + 11.154 + // check known (valid) exceptions 11.155 + if (knownRequired.contains(rk)) 11.156 + continue; 11.157 + 11.158 + // check known suspects 11.159 + if (needToInvestigate.contains(rk)) 11.160 + continue; 11.161 + 11.162 + error("Resource key not found in code: " + rk); 11.163 + } 11.164 + } 11.165 + 11.166 + /** 11.167 + * The keys for mandatory warning messages are all synthesized and do not 11.168 + * have a significant recognizable substring to look for. 11.169 + */ 11.170 + private boolean isMandatoryWarningString(String s) { 11.171 + String[] bases = { "deprecated", "unchecked", "varargs", "sunapi" }; 11.172 + String[] tails = { ".filename", ".filename.additional", ".plural", ".plural.additional", ".recompile" }; 11.173 + for (String b: bases) { 11.174 + if (s.startsWith(b)) { 11.175 + String tail = s.substring(b.length()); 11.176 + for (String t: tails) { 11.177 + if (tail.equals(t)) 11.178 + return true; 11.179 + } 11.180 + } 11.181 + } 11.182 + return false; 11.183 + } 11.184 + 11.185 + Set<String> knownRequired = new TreeSet<String>(Arrays.asList( 11.186 + // See Resolve.getErrorKey 11.187 + "compiler.err.cant.resolve.args", 11.188 + "compiler.err.cant.resolve.args.params", 11.189 + "compiler.err.cant.resolve.location.args", 11.190 + "compiler.err.cant.resolve.location.args.params", 11.191 + // JavaCompiler, reports #errors and #warnings 11.192 + "compiler.misc.count.error", 11.193 + "compiler.misc.count.error.plural", 11.194 + "compiler.misc.count.warn", 11.195 + "compiler.misc.count.warn.plural", 11.196 + // Used for LintCategory 11.197 + "compiler.warn.lintOption", 11.198 + // Other 11.199 + "compiler.misc.base.membership" // (sic) 11.200 + )); 11.201 + 11.202 + 11.203 + Set<String> needToInvestigate = new TreeSet<String>(Arrays.asList( 11.204 + "compiler.err.cant.read.file", // UNUSED 11.205 + "compiler.err.illegal.self.ref", // UNUSED 11.206 + "compiler.err.io.exception", // UNUSED 11.207 + "compiler.err.limit.pool.in.class", // UNUSED 11.208 + "compiler.err.name.reserved.for.internal.use", // UNUSED 11.209 + "compiler.err.no.match.entry", // UNUSED 11.210 + "compiler.err.not.within.bounds.explain", // UNUSED 11.211 + "compiler.err.signature.doesnt.match.intf", // UNUSED 11.212 + "compiler.err.signature.doesnt.match.supertype", // UNUSED 11.213 + "compiler.err.type.var.more.than.once", // UNUSED 11.214 + "compiler.err.type.var.more.than.once.in.result", // UNUSED 11.215 + "compiler.misc.ccf.found.later.version", // UNUSED 11.216 + "compiler.misc.non.denotable.type", // UNUSED 11.217 + "compiler.misc.unnamed.package", // should be required, CR 6964147 11.218 + "compiler.misc.verbose.retro", // UNUSED 11.219 + "compiler.misc.verbose.retro.with", // UNUSED 11.220 + "compiler.misc.verbose.retro.with.list", // UNUSED 11.221 + "compiler.warn.proc.type.already.exists", // TODO in JavacFiler 11.222 + "javac.err.invalid.arg", // UNUSED ?? 11.223 + "javac.opt.arg.class", // UNUSED ?? 11.224 + "javac.opt.arg.pathname", // UNUSED ?? 11.225 + "javac.opt.moreinfo", // option commented out 11.226 + "javac.opt.nogj", // UNUSED 11.227 + "javac.opt.printflat", // option commented out 11.228 + "javac.opt.printsearch", // option commented out 11.229 + "javac.opt.prompt", // option commented out 11.230 + "javac.opt.retrofit", // UNUSED 11.231 + "javac.opt.s", // option commented out 11.232 + "javac.opt.scramble", // option commented out 11.233 + "javac.opt.scrambleall" // option commented out 11.234 + )); 11.235 + 11.236 + /** 11.237 + * For all strings in the code that look like they might be fragments of 11.238 + * a resource key, verify that a key exists. 11.239 + */ 11.240 + void findMissingKeys(Set<String> codeStrings, Set<String> resourceKeys) { 11.241 + for (String cs: codeStrings) { 11.242 + if (cs.matches("[A-Za-z][^.]*\\..*")) { 11.243 + // ignore filenames (i.e. in SourceFile attribute 11.244 + if (cs.matches(".*\\.java")) 11.245 + continue; 11.246 + // ignore package and class names 11.247 + if (cs.matches("(com|java|javax|sun)\\.[A-Za-z.]+")) 11.248 + continue; 11.249 + // explicit known exceptions 11.250 + if (noResourceRequired.contains(cs)) 11.251 + continue; 11.252 + // look for matching resource 11.253 + if (hasMatch(resourceKeys, cs)) 11.254 + continue; 11.255 + error("no match for \"" + cs + "\""); 11.256 + } 11.257 + } 11.258 + } 11.259 + // where 11.260 + private Set<String> noResourceRequired = new HashSet<String>(Arrays.asList( 11.261 + // system properties 11.262 + "application.home", // in Paths.java 11.263 + "env.class.path", 11.264 + "line.separator", 11.265 + "user.dir", 11.266 + // file names 11.267 + "ct.sym", 11.268 + "rt.jar", 11.269 + "tools.jar", 11.270 + // -XD option names 11.271 + "process.packages", 11.272 + "ignore.symbol.file", 11.273 + // prefix/embedded strings 11.274 + "compiler.", 11.275 + "compiler.misc.", 11.276 + "count.", 11.277 + "illegal.", 11.278 + "javac.", 11.279 + "verbose." 11.280 + )); 11.281 + 11.282 + /** 11.283 + * Look for a resource that ends in this string fragment. 11.284 + */ 11.285 + boolean hasMatch(Set<String> resourceKeys, String s) { 11.286 + for (String rk: resourceKeys) { 11.287 + if (rk.endsWith(s)) 11.288 + return true; 11.289 + } 11.290 + return false; 11.291 + } 11.292 + 11.293 + /** 11.294 + * Get the set of strings from (most of) the javac classfiles. 11.295 + */ 11.296 + Set<String> getCodeStrings() throws IOException { 11.297 + Set<String> results = new TreeSet<String>(); 11.298 + JavaCompiler c = ToolProvider.getSystemJavaCompiler(); 11.299 + JavaFileManager fm = c.getStandardFileManager(null, null, null); 11.300 + String[] pkgs = { 11.301 + "javax.annotation.processing", 11.302 + "javax.lang.model", 11.303 + "javax.tools", 11.304 + "com.sun.source", 11.305 + "com.sun.tools.javac" 11.306 + }; 11.307 + for (String pkg: pkgs) { 11.308 + for (JavaFileObject fo: fm.list(StandardLocation.PLATFORM_CLASS_PATH, 11.309 + pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) { 11.310 + String name = fo.getName(); 11.311 + // ignore resource files, and files which are not really part of javac 11.312 + if (name.contains("resources") 11.313 + || name.contains("Launcher.class") 11.314 + || name.contains("CreateSymbols.class")) 11.315 + continue; 11.316 + scan(fo, results); 11.317 + } 11.318 + } 11.319 + return results; 11.320 + } 11.321 + 11.322 + /** 11.323 + * Get the set of strings from a class file. 11.324 + * Only strings that look like they might be a resource key are returned. 11.325 + */ 11.326 + void scan(JavaFileObject fo, Set<String> results) throws IOException { 11.327 + InputStream in = fo.openInputStream(); 11.328 + try { 11.329 + ClassFile cf = ClassFile.read(in); 11.330 + for (ConstantPool.CPInfo cpinfo: cf.constant_pool.entries()) { 11.331 + if (cpinfo.getTag() == ConstantPool.CONSTANT_Utf8) { 11.332 + String v = ((ConstantPool.CONSTANT_Utf8_info) cpinfo).value; 11.333 + if (v.matches("[A-Za-z0-9-_.]+")) 11.334 + results.add(v); 11.335 + } 11.336 + } 11.337 + } catch (ConstantPoolException ignore) { 11.338 + } finally { 11.339 + in.close(); 11.340 + } 11.341 + } 11.342 + 11.343 + /** 11.344 + * Get the set of keys from the javac resource bundles. 11.345 + */ 11.346 + Set<String> getResourceKeys() { 11.347 + Set<String> results = new TreeSet<String>(); 11.348 + for (String name : new String[]{"javac", "compiler"}) { 11.349 + ResourceBundle b = 11.350 + ResourceBundle.getBundle("com.sun.tools.javac.resources." + name); 11.351 + results.addAll(b.keySet()); 11.352 + } 11.353 + return results; 11.354 + } 11.355 + 11.356 + /** 11.357 + * Report an error. 11.358 + */ 11.359 + void error(String msg) { 11.360 + System.err.println("Error: " + msg); 11.361 + errors++; 11.362 + } 11.363 + 11.364 + int errors; 11.365 +}
12.1 --- a/test/tools/javac/generics/6946618/T6946618c.java Thu Jul 15 20:11:54 2010 -0700 12.2 +++ b/test/tools/javac/generics/6946618/T6946618c.java Tue Jul 20 22:22:32 2010 -0700 12.3 @@ -1,6 +1,6 @@ 12.4 /* 12.5 * @test /nodynamiccopyright/ 12.6 - * @bug 6946618 12.7 + * @bug 6946618 6968497 12.8 * @summary sqe test fails: javac/generics/NewOnTypeParm in pit jdk7 b91 in all platforms. 12.9 * @author mcimadamore 12.10 * @compile/fail/ref=T6946618c.out -XDrawDiagnostics T6946618c.java
13.1 --- a/test/tools/javac/generics/6946618/T6946618c.out Thu Jul 15 20:11:54 2010 -0700 13.2 +++ b/test/tools/javac/generics/6946618/T6946618c.out Tue Jul 20 22:22:32 2010 -0700 13.3 @@ -1,4 +1,4 @@ 13.4 -T6946618c.java:13:24: compiler.err.type.found.req: ? extends java.lang.String, class or interface without bounds 13.5 -T6946618c.java:14:24: compiler.err.type.found.req: ? super java.lang.String, class or interface without bounds 13.6 -T6946618c.java:15:24: compiler.err.type.found.req: ?, class or interface without bounds 13.7 +T6946618c.java:13:24: compiler.err.type.found.req: ? extends java.lang.String, (compiler.misc.type.req.exact) 13.8 +T6946618c.java:14:24: compiler.err.type.found.req: ? super java.lang.String, (compiler.misc.type.req.exact) 13.9 +T6946618c.java:15:24: compiler.err.type.found.req: ?, (compiler.misc.type.req.exact) 13.10 3 errors
14.1 --- a/test/tools/javac/literals/BadUnderscoreLiterals.6.out Thu Jul 15 20:11:54 2010 -0700 14.2 +++ b/test/tools/javac/literals/BadUnderscoreLiterals.6.out Tue Jul 20 22:22:32 2010 -0700 14.3 @@ -1,4 +1,4 @@ 14.4 -BadUnderscoreLiterals.java:14:17: compiler.err.unsupported.underscore: 1.6 14.5 +BadUnderscoreLiterals.java:14:17: compiler.err.unsupported.underscore.lit: 1.6 14.6 BadUnderscoreLiterals.java:18:15: compiler.err.illegal.underscore 14.7 BadUnderscoreLiterals.java:22:19: compiler.err.illegal.underscore 14.8 BadUnderscoreLiterals.java:25:14: compiler.err.unsupported.binary.lit: 1.6