Wed, 20 Feb 2013 15:47:14 -0800
8006582: Test for parameter names feature
Reviewed-by: jjg, darcy, emc
1.1 --- a/test/tools/javac/MethodParameters.java Tue Feb 19 20:53:35 2013 -0800 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,344 +0,0 @@ 1.4 -/* 1.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 - * 1.8 - * This code is free software; you can redistribute it and/or modify it 1.9 - * under the terms of the GNU General Public License version 2 only, as 1.10 - * published by the Free Software Foundation. 1.11 - * 1.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 - * version 2 for more details (a copy is included in the LICENSE file that 1.16 - * accompanied this code). 1.17 - * 1.18 - * You should have received a copy of the GNU General Public License version 1.19 - * 2 along with this work; if not, write to the Free Software Foundation, 1.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 - * 1.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 - * or visit www.oracle.com if you need additional information or have any 1.24 - * questions. 1.25 - */ 1.26 - 1.27 -/* 1.28 - * @test 1.29 - * @bug 8004727 1.30 - * @summary javac should generate method parameters correctly. 1.31 - */ 1.32 -// key: opt.arg.parameters 1.33 -import com.sun.tools.classfile.*; 1.34 -import com.sun.tools.javac.file.JavacFileManager; 1.35 -import com.sun.tools.javac.main.Main; 1.36 -import com.sun.tools.javac.util.Context; 1.37 -import com.sun.tools.javac.util.Name; 1.38 -import com.sun.tools.javac.util.Names; 1.39 -import java.io.*; 1.40 -import javax.lang.model.element.*; 1.41 -import java.util.*; 1.42 - 1.43 -public class MethodParameters { 1.44 - 1.45 - static final String Foo_name = "Foo"; 1.46 - static final String Foo_contents = 1.47 - "public class Foo {\n" + 1.48 - " Foo() {}\n" + 1.49 - " void foo0() {}\n" + 1.50 - " void foo2(int j, int k) {}\n" + 1.51 - "}"; 1.52 - static final String Bar_name = "Bar"; 1.53 - static final String Bar_contents = 1.54 - "public class Bar {\n" + 1.55 - " Bar(int i) {}" + 1.56 - " Foo foo() { return new Foo(); }\n" + 1.57 - "}"; 1.58 - static final String Baz_name = "Baz"; 1.59 - static final String Baz_contents = 1.60 - "public class Baz {\n" + 1.61 - " int baz;" + 1.62 - " Baz(int i) {}" + 1.63 - "}"; 1.64 - static final String Qux_name = "Qux"; 1.65 - static final String Qux_contents = 1.66 - "public class Qux extends Baz {\n" + 1.67 - " Qux(int i) { super(i); }" + 1.68 - "}"; 1.69 - static final File classesdir = new File("methodparameters"); 1.70 - 1.71 - public static void main(String... args) throws Exception { 1.72 - new MethodParameters().run(); 1.73 - } 1.74 - 1.75 - void run() throws Exception { 1.76 - classesdir.mkdir(); 1.77 - final File Foo_java = 1.78 - writeFile(classesdir, Foo_name + ".java", Foo_contents); 1.79 - final File Bar_java = 1.80 - writeFile(classesdir, Bar_name + ".java", Bar_contents); 1.81 - final File Baz_java = 1.82 - writeFile(classesdir, Baz_name + ".java", Baz_contents); 1.83 - System.err.println("Test compile with -parameter"); 1.84 - compile("-parameters", "-d", classesdir.getPath(), Foo_java.getPath()); 1.85 - // First test: make sure javac doesn't choke to death on 1.86 - // MethodParameter attributes 1.87 - System.err.println("Test compile with classfile containing MethodParameter attributes"); 1.88 - compile("-parameters", "-d", classesdir.getPath(), 1.89 - "-cp", classesdir.getPath(), Bar_java.getPath()); 1.90 - System.err.println("Examine class foo"); 1.91 - checkFoo(); 1.92 - checkBar(); 1.93 - System.err.println("Test debug information conflict"); 1.94 - compile("-g", "-parameters", "-d", classesdir.getPath(), 1.95 - "-cp", classesdir.getPath(), Baz_java.getPath()); 1.96 - System.err.println("Introducing debug information conflict"); 1.97 - Baz_java.delete(); 1.98 - modifyBaz(false); 1.99 - System.err.println("Checking language model"); 1.100 - inspectBaz(); 1.101 - System.err.println("Permuting attributes"); 1.102 - modifyBaz(true); 1.103 - System.err.println("Checking language model"); 1.104 - inspectBaz(); 1.105 - 1.106 - if(0 != errors) 1.107 - throw new Exception("MethodParameters test failed with " + 1.108 - errors + " errors"); 1.109 - } 1.110 - 1.111 - void inspectBaz() throws Exception { 1.112 - final File Qux_java = 1.113 - writeFile(classesdir, Qux_name + ".java", Qux_contents); 1.114 - final String[] args = { "-XDsave-parameter-names", "-d", 1.115 - classesdir.getPath(), 1.116 - "-cp", classesdir.getPath(), 1.117 - Qux_java.getPath() }; 1.118 - final StringWriter sw = new StringWriter(); 1.119 - final PrintWriter pw = new PrintWriter(sw); 1.120 - 1.121 - // We need to be able to crack open javac and look at its data 1.122 - // structures. We'll rig up a compiler instance, but keep its 1.123 - // Context, thus allowing us to get at the ClassReader. 1.124 - Context context = new Context(); 1.125 - Main comp = new Main("javac", pw); 1.126 - JavacFileManager.preRegister(context); 1.127 - 1.128 - // Compile Qux, which uses Baz. 1.129 - comp.compile(args, context); 1.130 - pw.close(); 1.131 - final String out = sw.toString(); 1.132 - if (out.length() > 0) 1.133 - System.err.println(out); 1.134 - 1.135 - // Now get the class reader, construct a name for Baz, and load it. 1.136 - com.sun.tools.javac.jvm.ClassReader cr = 1.137 - com.sun.tools.javac.jvm.ClassReader.instance(context); 1.138 - Name name = Names.instance(context).fromString(Baz_name); 1.139 - 1.140 - // Now walk down the language model and check the name of the 1.141 - // parameter. 1.142 - final Element baz = cr.loadClass(name); 1.143 - for (Element e : baz.getEnclosedElements()) { 1.144 - if (e instanceof ExecutableElement) { 1.145 - final ExecutableElement ee = (ExecutableElement) e; 1.146 - final List<? extends VariableElement> params = 1.147 - ee.getParameters(); 1.148 - if (1 != params.size()) 1.149 - throw new Exception("Classfile Baz badly formed: wrong number of methods"); 1.150 - final VariableElement param = params.get(0); 1.151 - if (!param.getSimpleName().contentEquals("baz")) { 1.152 - errors++; 1.153 - System.err.println("javac did not correctly resolve the metadata conflict, parameter's name reads as " + param.getSimpleName()); 1.154 - } else 1.155 - System.err.println("javac did correctly resolve the metadata conflict"); 1.156 - } 1.157 - } 1.158 - } 1.159 - 1.160 - void modifyBaz(boolean flip) throws Exception { 1.161 - final File Baz_class = new File(classesdir, Baz_name + ".class"); 1.162 - final ClassFile baz = ClassFile.read(Baz_class); 1.163 - final int ind = baz.constant_pool.getUTF8Index("baz"); 1.164 - MethodParameters_attribute mpattr = null; 1.165 - int mpind = 0; 1.166 - Code_attribute cattr = null; 1.167 - int cind = 0; 1.168 - 1.169 - // Find the indexes of the MethodParameters and the Code attributes 1.170 - if (baz.methods.length != 1) 1.171 - throw new Exception("Classfile Baz badly formed: wrong number of methods"); 1.172 - if (!baz.methods[0].getName(baz.constant_pool).equals("<init>")) 1.173 - throw new Exception("Classfile Baz badly formed: method has name " + 1.174 - baz.methods[0].getName(baz.constant_pool)); 1.175 - for (int i = 0; i < baz.methods[0].attributes.attrs.length; i++) { 1.176 - if (baz.methods[0].attributes.attrs[i] instanceof 1.177 - MethodParameters_attribute) { 1.178 - mpattr = (MethodParameters_attribute) 1.179 - baz.methods[0].attributes.attrs[i]; 1.180 - mpind = i; 1.181 - } else if (baz.methods[0].attributes.attrs[i] instanceof 1.182 - Code_attribute) { 1.183 - cattr = (Code_attribute) baz.methods[0].attributes.attrs[i]; 1.184 - cind = i; 1.185 - } 1.186 - } 1.187 - if (null == mpattr) 1.188 - throw new Exception("Classfile Baz badly formed: no method parameters info"); 1.189 - if (null == cattr) 1.190 - throw new Exception("Classfile Baz badly formed: no local variable table"); 1.191 - 1.192 - int flags = mpattr.method_parameter_table[0].flags; 1.193 - 1.194 - // Alter the MethodParameters attribute, changing the name of 1.195 - // the parameter from i to baz. This requires Black Magic... 1.196 - // 1.197 - // The (well-designed) classfile library (correctly) does not 1.198 - // allow us to mess around with the attribute data structures, 1.199 - // or arbitrarily generate new ones. 1.200 - // 1.201 - // Instead, we install a new subclass of Attribute that 1.202 - // hijacks the Visitor pattern and outputs the sequence of 1.203 - // bytes that we want. This only works in this particular 1.204 - // instance, because we know we'll only every see one kind of 1.205 - // visitor. 1.206 - // 1.207 - // If anyone ever changes the makeup of the Baz class, or 1.208 - // tries to install some kind of visitor that gets run prior 1.209 - // to serialization, this will break. 1.210 - baz.methods[0].attributes.attrs[mpind] = 1.211 - new Attribute(mpattr.attribute_name_index, 1.212 - mpattr.attribute_length) { 1.213 - public <R, D> R accept(Visitor<R, D> visitor, D data) { 1.214 - if (data instanceof ByteArrayOutputStream) { 1.215 - ByteArrayOutputStream out = 1.216 - (ByteArrayOutputStream) data; 1.217 - out.write(1); 1.218 - out.write((ind >> 8) & 0xff); 1.219 - out.write(ind & 0xff); 1.220 - out.write((flags >> 24) & 0xff); 1.221 - out.write((flags >> 16) & 0xff); 1.222 - out.write((flags >> 8) & 0xff); 1.223 - out.write(flags & 0xff); 1.224 - } else 1.225 - throw new RuntimeException("Output stream is of type " + data.getClass() + ", which is not handled by this test. Update the test and it should work."); 1.226 - return null; 1.227 - } 1.228 - }; 1.229 - 1.230 - // Flip the code and method attributes. This is for checking 1.231 - // that order doesn't matter. 1.232 - if (flip) { 1.233 - baz.methods[0].attributes.attrs[mpind] = cattr; 1.234 - baz.methods[0].attributes.attrs[cind] = mpattr; 1.235 - } 1.236 - 1.237 - new ClassWriter().write(baz, Baz_class); 1.238 - } 1.239 - 1.240 - // Run a bunch of structural tests on foo to make sure it looks right. 1.241 - void checkFoo() throws Exception { 1.242 - final File Foo_class = new File(classesdir, Foo_name + ".class"); 1.243 - final ClassFile foo = ClassFile.read(Foo_class); 1.244 - for (int i = 0; i < foo.methods.length; i++) { 1.245 - System.err.println("Examine method Foo." + foo.methods[i].getName(foo.constant_pool)); 1.246 - if (foo.methods[i].getName(foo.constant_pool).equals("foo2")) { 1.247 - for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) 1.248 - if (foo.methods[i].attributes.attrs[j] instanceof 1.249 - MethodParameters_attribute) { 1.250 - MethodParameters_attribute mp = 1.251 - (MethodParameters_attribute) 1.252 - foo.methods[i].attributes.attrs[j]; 1.253 - System.err.println("Foo.foo2 should have 2 parameters: j and k"); 1.254 - if (2 != mp.method_parameter_table_length) 1.255 - error("expected 2 method parameter entries in foo2, got " + 1.256 - mp.method_parameter_table_length); 1.257 - else if (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("j")) 1.258 - error("expected first parameter to foo2 to be \"j\", got \"" + 1.259 - foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) + 1.260 - "\" instead"); 1.261 - else if (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index).equals("k")) 1.262 - error("expected first parameter to foo2 to be \"k\", got \"" + 1.263 - foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index) + 1.264 - "\" instead"); 1.265 - } 1.266 - } 1.267 - else if (foo.methods[i].getName(foo.constant_pool).equals("<init>")) { 1.268 - for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) { 1.269 - if (foo.methods[i].attributes.attrs[j] instanceof 1.270 - MethodParameters_attribute) 1.271 - error("Zero-argument constructor shouldn't have MethodParameters"); 1.272 - } 1.273 - } 1.274 - else if (foo.methods[i].getName(foo.constant_pool).equals("foo0")) { 1.275 - for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) 1.276 - if (foo.methods[i].attributes.attrs[j] instanceof 1.277 - MethodParameters_attribute) 1.278 - error("Zero-argument method shouldn't have MethodParameters"); 1.279 - } 1.280 - else 1.281 - error("Unknown method " + foo.methods[i].getName(foo.constant_pool) + " showed up in class Foo"); 1.282 - } 1.283 - } 1.284 - 1.285 - // Run a bunch of structural tests on Bar to make sure it looks right. 1.286 - void checkBar() throws Exception { 1.287 - final File Bar_class = new File(classesdir, Bar_name + ".class"); 1.288 - final ClassFile bar = ClassFile.read(Bar_class); 1.289 - for (int i = 0; i < bar.methods.length; i++) { 1.290 - System.err.println("Examine method Bar." + bar.methods[i].getName(bar.constant_pool)); 1.291 - if (bar.methods[i].getName(bar.constant_pool).equals("<init>")) { 1.292 - for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++) 1.293 - if (bar.methods[i].attributes.attrs[j] instanceof 1.294 - MethodParameters_attribute) { 1.295 - MethodParameters_attribute mp = 1.296 - (MethodParameters_attribute) 1.297 - bar.methods[i].attributes.attrs[j]; 1.298 - System.err.println("Bar constructor should have 1 parameter: i"); 1.299 - if (1 != mp.method_parameter_table_length) 1.300 - error("expected 1 method parameter entries in constructor, got " + 1.301 - mp.method_parameter_table_length); 1.302 - else if (!bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("i")) 1.303 - error("expected first parameter to foo2 to be \"i\", got \"" + 1.304 - bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) + 1.305 - "\" instead"); 1.306 - } 1.307 - } 1.308 - else if (bar.methods[i].getName(bar.constant_pool).equals("foo")) { 1.309 - for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++) { 1.310 - if (bar.methods[i].attributes.attrs[j] instanceof 1.311 - MethodParameters_attribute) 1.312 - error("Zero-argument constructor shouldn't have MethodParameters"); 1.313 - } 1.314 - } 1.315 - } 1.316 - } 1.317 - 1.318 - String compile(String... args) throws Exception { 1.319 - System.err.println("compile: " + Arrays.asList(args)); 1.320 - StringWriter sw = new StringWriter(); 1.321 - PrintWriter pw = new PrintWriter(sw); 1.322 - int rc = com.sun.tools.javac.Main.compile(args, pw); 1.323 - pw.close(); 1.324 - String out = sw.toString(); 1.325 - if (out.length() > 0) 1.326 - System.err.println(out); 1.327 - if (rc != 0) 1.328 - error("compilation failed, rc=" + rc); 1.329 - return out; 1.330 - } 1.331 - 1.332 - File writeFile(File dir, String path, String body) throws IOException { 1.333 - File f = new File(dir, path); 1.334 - f.getParentFile().mkdirs(); 1.335 - FileWriter out = new FileWriter(f); 1.336 - out.write(body); 1.337 - out.close(); 1.338 - return f; 1.339 - } 1.340 - 1.341 - void error(String msg) { 1.342 - System.err.println("Error: " + msg); 1.343 - errors++; 1.344 - } 1.345 - 1.346 - int errors; 1.347 -}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/MethodParameters/AnnotationTest.java Wed Feb 20 15:47:14 2013 -0800 2.3 @@ -0,0 +1,54 @@ 2.4 +/* 2.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +/* 2.28 + * @test 2.29 + * @bug 8006582 2.30 + * @summary javac should generate method parameters correctly. 2.31 + * @build Tester 2.32 + * @compile -parameters AnnotationTest.java 2.33 + * @run main Tester AnnotationTest 2.34 + */ 2.35 + 2.36 +import java.lang.annotation.*; 2.37 + 2.38 +/** Test that annotations do not interfere with recording of parameter names */ 2.39 +class AnnotationTest { 2.40 + 2.41 + @Repeatable(Annos.class) 2.42 + @interface Anno { 2.43 + Class f() default int.class; 2.44 + } 2.45 + 2.46 + @interface Annos { Anno[] value(); String foo() default "hello"; } 2.47 + 2.48 + interface I { 2.49 + int m(@Anno @Anno int i, @Anno int ji); 2.50 + } 2.51 + 2.52 + public AnnotationTest(@Anno @Anno I i, @Anno int ji) { } 2.53 + public @Anno String foo(@Anno @Anno I i, int ji) { return null; } 2.54 +} 2.55 + 2.56 + 2.57 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/MethodParameters/AnonymousClass.java Wed Feb 20 15:47:14 2013 -0800 3.3 @@ -0,0 +1,104 @@ 3.4 +/* 3.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/* 3.28 + * @test 3.29 + * @bug 8006582 3.30 + * @summary javac should generate method parameters correctly. 3.31 + * @build Tester 3.32 + * @compile -parameters AnonymousClass.java 3.33 + * @run main Tester AnonymousClass 3.34 + */ 3.35 + 3.36 +class AnonymousClass { 3.37 + 3.38 + interface I<T> { 3.39 + T m(); 3.40 + T m(T x, T yx); 3.41 + } 3.42 + 3.43 + private class Inner implements I<String> { 3.44 + public Inner() { } 3.45 + public Inner(String arg, String barg) { } 3.46 + public String m() { return "0"; } 3.47 + public String m(String s, String ts) { return "0"; } 3.48 + } 3.49 + 3.50 + public static class Sinner implements I<Long> { 3.51 + public Sinner() { } 3.52 + public Sinner(Long arg, Long barg) { } 3.53 + public Long m() { return 0L; } 3.54 + public Long m(Long s, Long ts) { return s + ts; } 3.55 + } 3.56 + 3.57 + /** Inner class in constructor context */ 3.58 + public AnonymousClass(final Long a, Long ba) { 3.59 + new I<Long>() { 3.60 + public Long m() { return null; } 3.61 + public Long m(Long i, Long ji) { return i + ji; } 3.62 + }.m(a, ba); 3.63 + new Inner() { 3.64 + public String m() { return null; } 3.65 + public String m(String i, String ji) { return i + ji; } 3.66 + }.m(a.toString(), ba.toString()); 3.67 + new Inner(a.toString(), ba.toString()) { 3.68 + public String m() { return null; } 3.69 + public String m(String i, String ji) { return i + ji; } 3.70 + }.m(a.toString(), ba.toString()); 3.71 + new Sinner() { 3.72 + public Long m() { return null; } 3.73 + public Long m(Long i, Long ji) { return i + ji; } 3.74 + }.m(a, ba); 3.75 + new Sinner(a, ba) { 3.76 + public Long m() { return null; } 3.77 + public Long m(Long i, Long ji) { return i + ji; } 3.78 + }.m(a, ba); 3.79 + } 3.80 + 3.81 + /** Inner class in method context */ 3.82 + public void foo(final Long a, Long ba) { 3.83 + new I<Long>() { 3.84 + public Long m() { return null; } 3.85 + public Long m(Long i, Long ji) { return i + ji; } 3.86 + }.m(a, ba); 3.87 + new Inner() { 3.88 + public String m() { return null; } 3.89 + public String m(String i, String ji) { return i + ji; } 3.90 + }.m(a.toString(), ba.toString()); 3.91 + new Inner(a.toString(), ba.toString()) { 3.92 + public String m() { return null; } 3.93 + public String m(String i, String ji) { return i + ji; } 3.94 + }.m(a.toString(), ba.toString()); 3.95 + new Sinner() { 3.96 + public Long m() { return null; } 3.97 + public Long m(Long i, Long ji) { return i + ji; } 3.98 + }.m(a, ba); 3.99 + new Sinner(a, ba) { 3.100 + public Long m() { return null; } 3.101 + public Long m(Long i, Long ji) { return i + ji; } 3.102 + }.m(a, ba); 3.103 + } 3.104 +} 3.105 + 3.106 + 3.107 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/MethodParameters/AttributeVisitor.java Wed Feb 20 15:47:14 2013 -0800 4.3 @@ -0,0 +1,59 @@ 4.4 +/* 4.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +import com.sun.tools.classfile.*; 4.28 + 4.29 +/** 4.30 + * Trivial {@code Attribute.Visitor} implementation, to make it easy to 4.31 + * write visitors for specific attributes. 4.32 + */ 4.33 +class AttributeVisitor<R, P> implements Attribute.Visitor<R, P> { 4.34 + public R visitBootstrapMethods(BootstrapMethods_attribute attr, P p) { return null; } 4.35 + public R visitDefault(DefaultAttribute attr, P p) { return null; } 4.36 + public R visitAnnotationDefault(AnnotationDefault_attribute attr, P p) { return null; } 4.37 + public R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p) { return null; } 4.38 + public R visitCode(Code_attribute attr, P p) { return null; } 4.39 + public R visitCompilationID(CompilationID_attribute attr, P p) { return null; } 4.40 + public R visitConstantValue(ConstantValue_attribute attr, P p) { return null; } 4.41 + public R visitDeprecated(Deprecated_attribute attr, P p) { return null; } 4.42 + public R visitEnclosingMethod(EnclosingMethod_attribute attr, P p) { return null; } 4.43 + public R visitExceptions(Exceptions_attribute attr, P p) { return null; } 4.44 + public R visitInnerClasses(InnerClasses_attribute attr, P p) { return null; } 4.45 + public R visitLineNumberTable(LineNumberTable_attribute attr, P p) { return null; } 4.46 + public R visitLocalVariableTable(LocalVariableTable_attribute attr, P p) { return null; } 4.47 + public R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p) { return null; } 4.48 + public R visitMethodParameters(MethodParameters_attribute attr, P p) { return null; } 4.49 + public R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p) { return null; } 4.50 + public R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p) { return null; } 4.51 + public R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p) { return null; } 4.52 + public R visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, P p) { return null; } 4.53 + public R visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, P p) { return null; } 4.54 + public R visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, P p) { return null; } 4.55 + public R visitSignature(Signature_attribute attr, P p) { return null; } 4.56 + public R visitSourceDebugExtension(SourceDebugExtension_attribute attr, P p) { return null; } 4.57 + public R visitSourceFile(SourceFile_attribute attr, P p) { return null; } 4.58 + public R visitSourceID(SourceID_attribute attr, P p) { return null; } 4.59 + public R visitStackMap(StackMap_attribute attr, P p) { return null; } 4.60 + public R visitStackMapTable(StackMapTable_attribute attr, P p) { return null; } 4.61 + public R visitSynthetic(Synthetic_attribute attr, P p) { return null; } 4.62 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/MethodParameters/ClassFileVisitor.java Wed Feb 20 15:47:14 2013 -0800 5.3 @@ -0,0 +1,387 @@ 5.4 +/* 5.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +import com.sun.tools.classfile.*; 5.28 +import java.io.*; 5.29 +import javax.lang.model.element.*; 5.30 +import java.util.*; 5.31 + 5.32 +/** 5.33 + * The {@code ClassFileVisitor} reads a class file using the 5.34 + * {@code com.sun.tools.classfile} library. It iterates over the methods 5.35 + * in a class, and checks MethodParameters attributes against JLS 5.36 + * requirements, as well as assumptions about the javac implementations. 5.37 + * <p> 5.38 + * It enforces the following rules: 5.39 + * <ul> 5.40 + * <li>All non-synthetic methods with arguments must have the 5.41 + * MethodParameters attribute. </li> 5.42 + * <li>At most one MethodParameters attribute per method.</li> 5.43 + * <li>An empty MethodParameters attribute is not allowed (i.e. no 5.44 + * attribute for methods taking no parameters).</li> 5.45 + * <li>The number of recorded parameter names much equal the number 5.46 + * of parameters, including any implicit or synthetic parameters generated 5.47 + * by the compiler.</li> 5.48 + * <li>Although the spec allow recording parameters with no name, the javac 5.49 + * implementation is assumed to record a name for all parameters. That is, 5.50 + * the Methodparameters attribute must record a non-zero, valid constant 5.51 + * pool index for each parameter.</li> 5.52 + * <li>Check presence, expected names (e.g. this$N, $enum$name, ...) and flags 5.53 + * (e.g. ACC_SYNTHETIC, ACC_MANDATED) for compiler generated parameters.</li> 5.54 + * <li>Names of explicit parameters must reflect the names in the Java source. 5.55 + * This is checked by assuming a design pattern where any name is permitted 5.56 + * for the first explicit parameter. For subsequent parameters the following 5.57 + * rule is checked: <i>param[n] == ++param[n-1].charAt(0) + param[n-1]</i> 5.58 + * </ul> 5.59 + */ 5.60 +class ClassFileVisitor extends Tester.Visitor { 5.61 + 5.62 + Tester tester; 5.63 + 5.64 + public String cname; 5.65 + public boolean isEnum; 5.66 + public boolean isInterface; 5.67 + public boolean isInner; 5.68 + public boolean isPublic; 5.69 + public boolean isStatic; 5.70 + public boolean isAnon; 5.71 + public ClassFile classFile; 5.72 + 5.73 + 5.74 + public ClassFileVisitor(Tester tester) { 5.75 + super(tester); 5.76 + } 5.77 + 5.78 + public void error(String msg) { 5.79 + super.error("classfile: " + msg); 5.80 + } 5.81 + 5.82 + public void warn(String msg) { 5.83 + super.warn("classfile: " + msg); 5.84 + } 5.85 + 5.86 + /** 5.87 + * Read the class and determine some key characteristics, like if it's 5.88 + * an enum, or inner class, etc. 5.89 + */ 5.90 + void visitClass(final String cname, final File cfile, final StringBuilder sb) 5.91 + throws Exception { 5.92 + this.cname = cname; 5.93 + classFile = ClassFile.read(cfile); 5.94 + isEnum = classFile.access_flags.is(AccessFlags.ACC_ENUM); 5.95 + isInterface = classFile.access_flags.is(AccessFlags.ACC_INTERFACE); 5.96 + isPublic = classFile.access_flags.is(AccessFlags.ACC_PUBLIC); 5.97 + isInner = false; 5.98 + isStatic = true; 5.99 + isAnon = false; 5.100 + 5.101 + Attribute attr = classFile.getAttribute("InnerClasses"); 5.102 + if (attr != null) attr.accept(new InnerClassVisitor(), null); 5.103 + isAnon = isInner & isAnon; 5.104 + 5.105 + sb.append(isStatic ? "static " : "") 5.106 + .append(isPublic ? "public " : "") 5.107 + .append(isEnum ? "enum " : isInterface ? "interface " : "class ") 5.108 + .append(cname).append(" -- ") 5.109 + .append(isInner? "inner " : "" ) 5.110 + .append(isAnon ? "anon" : "") 5.111 + .append("\n");; 5.112 + 5.113 + for (Method method : classFile.methods) { 5.114 + new MethodVisitor().visitMethod(method, sb); 5.115 + } 5.116 + } 5.117 + 5.118 + /** 5.119 + * Used to visit InnerClasses_attribute of a class, 5.120 + * to determne if this class is an local class, and anonymous 5.121 + * inner class or a none-static member class. These types of 5.122 + * classes all have an containing class instances field that 5.123 + * requires an implicit or synthetic constructor argument. 5.124 + */ 5.125 + class InnerClassVisitor extends AttributeVisitor<Void, Void> { 5.126 + public Void visitInnerClasses(InnerClasses_attribute iattr, Void v) { 5.127 + try{ 5.128 + for (InnerClasses_attribute.Info info : iattr.classes) { 5.129 + if (info.getInnerClassInfo(classFile.constant_pool) == null) continue; 5.130 + String in = info.getInnerClassInfo(classFile.constant_pool).getName(); 5.131 + if (in == null || !cname.equals(in)) continue; 5.132 + isInner = true; 5.133 + isAnon = null == info.getInnerName(classFile.constant_pool); 5.134 + isStatic = info.inner_class_access_flags.is(AccessFlags.ACC_STATIC); 5.135 + break; 5.136 + } 5.137 + } catch(Exception e) { 5.138 + throw new IllegalStateException(e); 5.139 + } 5.140 + return null; 5.141 + } 5.142 + } 5.143 + 5.144 + /** 5.145 + * Check the MethodParameters attribute of a method. 5.146 + */ 5.147 + class MethodVisitor extends AttributeVisitor<Void, StringBuilder> { 5.148 + 5.149 + public String mName; 5.150 + public Descriptor mDesc; 5.151 + public int mParams; 5.152 + public int mAttrs; 5.153 + public int mNumParams; 5.154 + public boolean mSynthetic; 5.155 + public boolean mIsConstructor; 5.156 + public String prefix; 5.157 + 5.158 + void visitMethod(Method method, StringBuilder sb) throws Exception { 5.159 + 5.160 + mName = method.getName(classFile.constant_pool); 5.161 + mDesc = method.descriptor; 5.162 + mParams = mDesc.getParameterCount(classFile.constant_pool); 5.163 + mAttrs = method.attributes.attrs.length; 5.164 + mNumParams = -1; // no MethodParameters attribute found 5.165 + mSynthetic = method.access_flags.is(AccessFlags.ACC_SYNTHETIC); 5.166 + mIsConstructor = mName.equals("<init>"); 5.167 + prefix = cname + "." + mName + "() - "; 5.168 + 5.169 + sb.append(cname).append(".").append(mName).append("("); 5.170 + 5.171 + for (Attribute a : method.attributes) { 5.172 + a.accept(this, sb); 5.173 + } 5.174 + if (mNumParams == -1) { 5.175 + if (mSynthetic) { 5.176 + sb.append("<none>)!!"); 5.177 + } else { 5.178 + sb.append("<none>)"); 5.179 + } 5.180 + } 5.181 + sb.append("\n"); 5.182 + 5.183 + // IMPL: methods with arguments must have a MethodParameters 5.184 + // attribute, except possibly some synthetic methods. 5.185 + if (mNumParams == -1 && mParams > 0 && ! mSynthetic) { 5.186 + error(prefix + "missing MethodParameters attribute"); 5.187 + } 5.188 + } 5.189 + 5.190 + public Void visitMethodParameters(MethodParameters_attribute mp, 5.191 + StringBuilder sb) { 5.192 + 5.193 + // SPEC: At most one MethodParameters attribute allowed 5.194 + if (mNumParams != -1) { 5.195 + error(prefix + "Multiple MethodParameters attributes"); 5.196 + return null; 5.197 + } 5.198 + 5.199 + mNumParams = mp.method_parameter_table_length; 5.200 + 5.201 + // SPEC: An empty attribute is not allowed! 5.202 + if (mNumParams == 0) { 5.203 + error(prefix + "0 length MethodParameters attribute"); 5.204 + return null; 5.205 + } 5.206 + 5.207 + // SPEC: one name per parameter. 5.208 + if (mNumParams != mParams) { 5.209 + error(prefix + "found " + mNumParams + 5.210 + " parameters, expected " + mParams); 5.211 + return null; 5.212 + } 5.213 + 5.214 + // IMPL: Whether MethodParameters attributes will be generated 5.215 + // for some synthetics is unresolved. For now, assume no. 5.216 + if (mSynthetic) { 5.217 + warn(prefix + "synthetic has MethodParameter attribute"); 5.218 + } 5.219 + 5.220 + String sep = ""; 5.221 + String userParam = null; 5.222 + for (int x = 0; x < mNumParams; x++) { 5.223 + 5.224 + // IMPL: Assume all parameters are named, something. 5.225 + int cpi = mp.method_parameter_table[x].name_index; 5.226 + if (cpi == 0) { 5.227 + error(prefix + "name expected, param[" + x + "]"); 5.228 + return null; 5.229 + } 5.230 + 5.231 + // SPEC: a non 0 index, must be valid! 5.232 + String param = null; 5.233 + try { 5.234 + param = classFile.constant_pool.getUTF8Value(cpi); 5.235 + sb.append(sep).append(param); 5.236 + sep = ", "; 5.237 + } catch(ConstantPoolException e) { 5.238 + error(prefix + "invalid index " + cpi + " for param[" 5.239 + + x + "]"); 5.240 + return null; 5.241 + } 5.242 + 5.243 + 5.244 + // Check availability, flags and special names 5.245 + int check = checkParam(mp, param, x, sb); 5.246 + if (check < 0) { 5.247 + return null; 5.248 + } 5.249 + 5.250 + // TEST: check test assumptions about parameter name. 5.251 + // Expected names are calculated starting with the 5.252 + // 2nd explicit (user given) parameter. 5.253 + // param[n] == ++param[n-1].charAt(0) + param[n-1] 5.254 + String expect = null; 5.255 + if (userParam != null) { 5.256 + char c = userParam.charAt(0); 5.257 + expect = (++c) + userParam; 5.258 + } 5.259 + if (check > 0) { 5.260 + userParam = param; 5.261 + } 5.262 + if (expect != null && !param.equals(expect)) { 5.263 + error(prefix + "param[" + x + "]='" 5.264 + + param + "' expected '" + expect + "'"); 5.265 + return null; 5.266 + } 5.267 + } 5.268 + if (mSynthetic) { 5.269 + sb.append(")!!"); 5.270 + } else { 5.271 + sb.append(")"); 5.272 + } 5.273 + return null; 5.274 + } 5.275 + 5.276 + /* 5.277 + * Check a parameter for conformity to JLS and javac specific 5.278 + * assumptions. 5.279 + * Return -1, if an error is detected. Otherwise, return 0, if 5.280 + * the parameter is compiler generated, or 1 for an (presumably) 5.281 + * explicitly declared parameter. 5.282 + */ 5.283 + int checkParam(MethodParameters_attribute mp, String param, int index, 5.284 + StringBuilder sb) { 5.285 + 5.286 + boolean synthetic = (mp.method_parameter_table[index].flags 5.287 + & AccessFlags.ACC_SYNTHETIC) != 0; 5.288 + boolean mandated = (mp.method_parameter_table[index].flags 5.289 + & AccessFlags.ACC_MANDATED) != 0; 5.290 + 5.291 + // Setup expectations for flags and special names 5.292 + String expect = null; 5.293 + boolean allowMandated = false; 5.294 + boolean allowSynthetic = false; 5.295 + if (mSynthetic || synthetic) { 5.296 + // not an implementation gurantee, but okay for now 5.297 + expect = "arg" + index; // default 5.298 + } 5.299 + if (mIsConstructor) { 5.300 + if (isEnum) { 5.301 + if (index == 0) { 5.302 + expect = "\\$enum\\$name"; 5.303 + allowSynthetic = true; 5.304 + } else if(index == 1) { 5.305 + expect = "\\$enum\\$ordinal"; 5.306 + allowSynthetic = true; 5.307 + } 5.308 + } else if (index == 0) { 5.309 + if (isAnon) { 5.310 + allowMandated = true; 5.311 + expect = "this\\$[0-n]*"; 5.312 + } else if (isInner && !isStatic) { 5.313 + allowMandated = true; 5.314 + if (!isPublic) { 5.315 + // some but not all non-public inner classes 5.316 + // have synthetic argument. For now we give 5.317 + // the test a bit of slack and allow either. 5.318 + allowSynthetic = true; 5.319 + } 5.320 + expect = "this\\$[0-n]*"; 5.321 + } 5.322 + } else if (isAnon) { 5.323 + // not an implementation gurantee, but okay for now 5.324 + expect = "x[0-n]*"; 5.325 + } 5.326 + } else if (isEnum && mNumParams == 1 && index == 0 && mName.equals("valueOf")) { 5.327 + expect = "name"; 5.328 + allowMandated = true; 5.329 + } 5.330 + if (mandated) sb.append("!"); 5.331 + if (synthetic) sb.append("!!"); 5.332 + 5.333 + // IMPL: our rules a somewhat fuzzy, sometimes allowing both mandated 5.334 + // and synthetic. However, a parameters cannot be both. 5.335 + if (mandated && synthetic) { 5.336 + error(prefix + "param[" + index + "] == \"" + param 5.337 + + "\" ACC_SYNTHETIC and ACC_MANDATED"); 5.338 + return -1; 5.339 + } 5.340 + // ... but must be either, if both "allowed". 5.341 + if (!(mandated || synthetic) && allowMandated && allowSynthetic) { 5.342 + error(prefix + "param[" + index + "] == \"" + param 5.343 + + "\" expected ACC_MANDATED or ACC_SYNTHETIC"); 5.344 + return -1; 5.345 + } 5.346 + 5.347 + // ... if only one is "allowed", we meant "required". 5.348 + if (!mandated && allowMandated && !allowSynthetic) { 5.349 + error(prefix + "param[" + index + "] == \"" + param 5.350 + + "\" expected ACC_MANDATED"); 5.351 + return -1; 5.352 + } 5.353 + if (!synthetic && !allowMandated && allowSynthetic) { 5.354 + error(prefix + "param[" + index + "] == \"" + param 5.355 + + "\" expected ACC_SYNTHETIC"); 5.356 + return -1; 5.357 + } 5.358 + 5.359 + // ... and not "allowed", means prohibited. 5.360 + if (mandated && !allowMandated) { 5.361 + error(prefix + "param[" + index + "] == \"" + param 5.362 + + "\" unexpected, is ACC_MANDATED"); 5.363 + return -1; 5.364 + } 5.365 + if (synthetic && !allowSynthetic) { 5.366 + error(prefix + "param[" + index + "] == \"" + param 5.367 + + "\" unexpected, is ACC_SYNTHETIC"); 5.368 + return -1; 5.369 + } 5.370 + 5.371 + // Test special name expectations 5.372 + if (expect != null) { 5.373 + if (param.matches(expect)) { 5.374 + return 0; 5.375 + } 5.376 + error(prefix + "param[" + index + "]='" + param + 5.377 + "' expected '" + expect + "'"); 5.378 + return -1; 5.379 + } 5.380 + 5.381 + // No further checking for synthetic methods. 5.382 + if (mSynthetic) { 5.383 + return 0; 5.384 + } 5.385 + 5.386 + // Otherwise, do check test parameter naming convention. 5.387 + return 1; 5.388 + } 5.389 + } 5.390 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/MethodParameters/Constructors.java Wed Feb 20 15:47:14 2013 -0800 6.3 @@ -0,0 +1,41 @@ 6.4 +/* 6.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/* 6.28 + * @test 6.29 + * @bug 8006582 6.30 + * @summary javac should generate method parameters correctly. 6.31 + * @build Tester 6.32 + * @compile -parameters Constructors.java 6.33 + * @run main Tester Constructors 6.34 + */ 6.35 + 6.36 +public class Constructors { 6.37 + public Constructors() {} 6.38 + Constructors(final Object a, final String... ba) { } 6.39 + protected Constructors(Object a, final Object ba, final String... cba) { } 6.40 + private Constructors(int a, Object ba, final Object cba, final String... dcba) { } 6.41 +} 6.42 + 6.43 + 6.44 +
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javac/MethodParameters/EnumTest.java Wed Feb 20 15:47:14 2013 -0800 7.3 @@ -0,0 +1,45 @@ 7.4 +/* 7.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. 7.11 + * 7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.15 + * version 2 for more details (a copy is included in the LICENSE file that 7.16 + * accompanied this code). 7.17 + * 7.18 + * You should have received a copy of the GNU General Public License version 7.19 + * 2 along with this work; if not, write to the Free Software Foundation, 7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.21 + * 7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 7.23 + * or visit www.oracle.com if you need additional information or have any 7.24 + * questions. 7.25 + */ 7.26 + 7.27 +/* 7.28 + * @test 7.29 + * @bug 8006582 7.30 + * @summary javac should generate method parameters correctly. 7.31 + * @build Tester 7.32 + * @compile -parameters EnumTest.java 7.33 + * @run main Tester EnumTest 7.34 + */ 7.35 + 7.36 +/** Test that parameter names are recorded for enum methods */ 7.37 +enum EnumTest { 7.38 + E1(0), E2(1, "x"), E3(2, "x", "y"), E4; 7.39 + 7.40 + EnumTest() { } 7.41 + EnumTest(int a, String... ba) { } 7.42 + boolean ok(int c, String... dc) { return true; } 7.43 + 7.44 + int valueOf(EnumTest A, EnumTest BA) { return 0; } 7.45 +} 7.46 + 7.47 + 7.48 +
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/tools/javac/MethodParameters/InstanceMethods.java Wed Feb 20 15:47:14 2013 -0800 8.3 @@ -0,0 +1,46 @@ 8.4 +/* 8.5 + * Copyright (c) 2013, 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 + * @test 8.29 + * @bug 8006582 8.30 + * @summary javac should generate method parameters correctly. 8.31 + * @build Tester 8.32 + * @compile -parameters InstanceMethods.java 8.33 + * @run main Tester InstanceMethods 8.34 + */ 8.35 + 8.36 +public class InstanceMethods { 8.37 + public void empty() {} 8.38 + final void def(Object a, final Object ba, final String... cba) { } 8.39 + final public void pub(Object d, final Object ed, final String... fed) { } 8.40 + protected boolean prot(Object g, final Object hg, final String... ihg) { return true; } 8.41 + private boolean priv(Object j, final Object kj, final String... lkj) { return true; } 8.42 + void def(int A, Object BA, final Object CBA, final String... DCBA) { } 8.43 + public void pub(int B, Object CB, final Object DCB, final String... EDCB) { } 8.44 + final protected boolean prot(int C, Object DC, final Object EDC, final String... FEDC) { return true; } 8.45 + final private boolean priv(int D, Object ED, final Object FED, final String... GFED) { return true; } 8.46 +} 8.47 + 8.48 + 8.49 +
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/tools/javac/MethodParameters/LambdaTest.java Wed Feb 20 15:47:14 2013 -0800 9.3 @@ -0,0 +1,51 @@ 9.4 +/* 9.5 + * Copyright (c) 2013, 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 8006582 9.30 + * @summary javac should generate method parameters correctly. 9.31 + * @build Tester 9.32 + * @compile -parameters LambdaTest.java 9.33 + * @run main Tester LambdaTest 9.34 + */ 9.35 + 9.36 +/** 9.37 + * Parameter names are not recorded for lambdas. This test verifies 9.38 + * that there are no MethodParameters attribute for lambdas. 9.39 + */ 9.40 +class LambdaTest { 9.41 + 9.42 + interface I { 9.43 + int m(int x); 9.44 + } 9.45 + 9.46 + static int foo(I i) { return i.m(0); } 9.47 + 9.48 + static { 9.49 + foo((int x1) -> { return foo((int x2) -> { return x1 + x2; }); }); 9.50 + } 9.51 +} 9.52 + 9.53 + 9.54 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/tools/javac/MethodParameters/LocalClassTest.java Wed Feb 20 15:47:14 2013 -0800 10.3 @@ -0,0 +1,50 @@ 10.4 +/* 10.5 + * Copyright (c) 2013, 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 +/* 10.28 + * @test 10.29 + * @bug 8006582 10.30 + * @summary javac should generate method parameters correctly. 10.31 + * @build Tester 10.32 + * @compile -parameters LocalClassTest.java 10.33 + * @run main Tester LocalClassTest 10.34 + */ 10.35 + 10.36 +class LocalClassTest { 10.37 + void foo() { 10.38 + class Local_default_constructor { 10.39 + public void foo() {} 10.40 + public void foo(int m, int nm) {} 10.41 + } 10.42 + class Local_has_constructor { 10.43 + public Local_has_constructor() {} 10.44 + public Local_has_constructor(int a, int ba) {} 10.45 + public void foo() {} 10.46 + public void foo(int m, int nm) {} 10.47 + } 10.48 + new LocalClassTest().foo(); 10.49 + } 10.50 +} 10.51 + 10.52 + 10.53 +
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/tools/javac/MethodParameters/MemberClassTest.java Wed Feb 20 15:47:14 2013 -0800 11.3 @@ -0,0 +1,86 @@ 11.4 +/* 11.5 + * Copyright (c) 2013, 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 8006582 11.30 + * @summary javac should generate method parameters correctly. 11.31 + * @build Tester 11.32 + * @compile -parameters MemberClassTest.java 11.33 + * @run main Tester MemberClassTest 11.34 + */ 11.35 + 11.36 +class MemberClassTest { 11.37 + 11.38 + interface I { 11.39 + Long m(); 11.40 + Long m(Long x, Long yx); 11.41 + } 11.42 + 11.43 + public class Member implements I { 11.44 + public class Member_Member { 11.45 + public Member_Member() {} 11.46 + public Member_Member(String x, String yx) {} 11.47 + } 11.48 + 11.49 + public Member() { } 11.50 + public Member(Long a, Long ba) { } 11.51 + public Long m() { return 0L; } 11.52 + public Long m(Long s, Long ts) { return 0L; } 11.53 + } 11.54 + 11.55 + static class Static_Member implements I { 11.56 + public class Static_Member_Member { 11.57 + public Static_Member_Member() {} 11.58 + public Static_Member_Member(String x, String yx) {} 11.59 + } 11.60 + 11.61 + public static class Static_Member_Static_Member { 11.62 + public Static_Member_Static_Member() {} 11.63 + public Static_Member_Static_Member(String x, String yx) {} 11.64 + } 11.65 + public Static_Member() { } 11.66 + public Static_Member(Long arg, Long barg) { } 11.67 + public Long m() { return 0L; } 11.68 + public Long m(Long s, Long ts) { return s + ts; } 11.69 + } 11.70 + 11.71 + public MemberClassTest() { 11.72 + } 11.73 + public MemberClassTest(final Long a, Long ba) { 11.74 + } 11.75 + 11.76 + public void foo() { 11.77 + 11.78 + new I() { 11.79 + 11.80 + class Anonymous_Member { 11.81 + public Anonymous_Member() {} 11.82 + public Anonymous_Member(String x, String yx) {} 11.83 + } 11.84 + 11.85 + public Long m() { return 0L; } 11.86 + public Long m(Long s, Long ts) { return s + ts; } 11.87 + }.m(); 11.88 + } 11.89 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/test/tools/javac/MethodParameters/ReflectionVisitor.java Wed Feb 20 15:47:14 2013 -0800 12.3 @@ -0,0 +1,270 @@ 12.4 +/* 12.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.7 + * 12.8 + * This code is free software; you can redistribute it and/or modify it 12.9 + * under the terms of the GNU General Public License version 2 only, as 12.10 + * published by the Free Software Foundation. 12.11 + * 12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12.15 + * version 2 for more details (a copy is included in the LICENSE file that 12.16 + * accompanied this code). 12.17 + * 12.18 + * You should have received a copy of the GNU General Public License version 12.19 + * 2 along with this work; if not, write to the Free Software Foundation, 12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 12.21 + * 12.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 12.23 + * or visit www.oracle.com if you need additional information or have any 12.24 + * questions. 12.25 + */ 12.26 + 12.27 +import java.io.*; 12.28 +import java.util.*; 12.29 +import java.net.*; 12.30 +import java.lang.reflect.*; 12.31 + 12.32 +/** 12.33 + * Test MethodParameter attributs by reflection API 12.34 + */ 12.35 +public class ReflectionVisitor extends Tester.Visitor { 12.36 + 12.37 + public ReflectionVisitor(Tester tester) { 12.38 + super(tester); 12.39 + } 12.40 + 12.41 + public void error(String msg) { 12.42 + super.error("reflection: " + msg); 12.43 + } 12.44 + 12.45 + public void warn(String msg) { 12.46 + super.warn("reflection: " + msg); 12.47 + } 12.48 + 12.49 + boolean isEnum; 12.50 + boolean isInterface; 12.51 + boolean isAnon; 12.52 + boolean isLocal; 12.53 + boolean isMember; 12.54 + boolean isStatic; 12.55 + boolean isPublic; 12.56 + Class clazz; 12.57 + StringBuilder sb; 12.58 + 12.59 + /** 12.60 + * Read class using {@code ClassFile}, and generate a list of methods 12.61 + * with parameter names as available in the MethodParameters attribute. 12.62 + */ 12.63 + void visitClass(final String cl, final File cfile, final StringBuilder sb) 12.64 + throws Exception { 12.65 + 12.66 + this.sb = sb; 12.67 + clazz = Class.forName(cl); 12.68 + isEnum = clazz.isEnum(); 12.69 + isInterface = clazz.isInterface(); 12.70 + isAnon = clazz.isAnonymousClass(); 12.71 + isLocal = clazz.isLocalClass(); 12.72 + isMember = clazz.isMemberClass(); 12.73 + isStatic = ((clazz.getModifiers() & Modifier.STATIC) != 0); 12.74 + isPublic = ((clazz.getModifiers() & Modifier.PUBLIC) != 0); 12.75 + 12.76 + sb.append(isStatic ? "static " : "") 12.77 + .append(isPublic ? "public " : "") 12.78 + .append(isEnum ? "enum " : isInterface ? "interface " : "class ") 12.79 + .append(cl).append(" -- ") 12.80 + .append(isMember? "member " : "" ) 12.81 + .append(isLocal? "local " : "" ) 12.82 + .append(isAnon ? "anon" : "") 12.83 + .append("\n"); 12.84 + 12.85 + for (Constructor c : clazz.getDeclaredConstructors()) { 12.86 + testConstructor(c); 12.87 + } 12.88 + 12.89 + for (Method m :clazz.getDeclaredMethods()) { 12.90 + 12.91 + testMethod(m); 12.92 + } 12.93 + } 12.94 + 12.95 + void testConstructor(Constructor c) { 12.96 + 12.97 + String prefix = clazz.getName() + "." + c.getName() + "() - "; 12.98 + 12.99 + // Parameters must match parameter types 12.100 + Parameter params[] = c.getParameters(); 12.101 + int paramTypes = c.getParameterTypes().length; 12.102 + if (paramTypes != params.length) { 12.103 + error(prefix + "number of parameter types (" + paramTypes 12.104 + + ") != number of parameters (" + params.length + ")"); 12.105 + return; 12.106 + } 12.107 + 12.108 + sb.append(clazz.getName()).append(".").append("<init>").append("("); 12.109 + String sep = ""; 12.110 + 12.111 + // Some paramters are expected 12.112 + if (params.length < 2 && isEnum) { 12.113 + error(prefix + "enum constuctor, two arguments expected"); 12.114 + } else if (params.length < 1 && (isAnon || isLocal || 12.115 + (isMember && !isStatic ))) { 12.116 + error(prefix + "class constuctor,expected implicit argument"); 12.117 + } 12.118 + 12.119 + int i = -1; 12.120 + String param = null; 12.121 + for (Parameter p : c.getParameters()) { 12.122 + i++; 12.123 + String pname = p.getName(); 12.124 + sb.append(sep).append(pname); 12.125 + if (p.isImplicit()) sb.append("!"); 12.126 + if (p.isSynthetic()) sb.append("!!"); 12.127 + sep = ", "; 12.128 + 12.129 + // Set expectations 12.130 + String expect = null; 12.131 + boolean allowImplicit = false; 12.132 + boolean allowSynthetic = false; 12.133 + if (isEnum) { 12.134 + if (i == 0) { 12.135 + expect = "\\$enum\\$name"; 12.136 + allowSynthetic = true; 12.137 + } else if(i == 1) { 12.138 + expect = "\\$enum\\$ordinal"; 12.139 + allowSynthetic = true; 12.140 + } 12.141 + } else if (i == 0) { 12.142 + if (isAnon) { 12.143 + allowImplicit = true; 12.144 + } else if (isLocal) { 12.145 + allowImplicit = true; 12.146 + expect = "this\\$[0-n]*"; 12.147 + } else if ((isMember && !isStatic)) { 12.148 + allowImplicit = true; 12.149 + if (!isPublic) { 12.150 + // some but not all non-public inner classes 12.151 + // have synthetic argument. For now we give 12.152 + // the test a bit of slack and allow either. 12.153 + allowSynthetic = true; 12.154 + } 12.155 + expect = "this\\$[0-n]*"; 12.156 + } 12.157 + } else if (isAnon) { 12.158 + // not an implementation gurantee, but okay for now 12.159 + expect = "x[0-n]*"; 12.160 + } 12.161 + 12.162 + // Check expected flags 12.163 + if (p.isSynthetic() && p.isImplicit()) { 12.164 + error(prefix + "param[" + i + "]='" + pname + 12.165 + "' both isImplicit() and isSynthetic()"); 12.166 + break; 12.167 + } 12.168 + if (allowImplicit && allowSynthetic && 12.169 + !(p.isSynthetic() || p.isImplicit())) { 12.170 + error(prefix + "param[" + i + "]='" + pname + 12.171 + "' isImplicit() or isSynthetic() expected"); 12.172 + break; 12.173 + } 12.174 + 12.175 + if (allowImplicit && !allowSynthetic && !p.isImplicit()) { 12.176 + error(prefix + "param[" + i + "]='" + pname + 12.177 + "' isImplicit() expected"); 12.178 + break; 12.179 + } 12.180 + if (!allowImplicit && allowSynthetic && !p.isSynthetic()) { 12.181 + error(prefix + "param[" + i + "]='" + pname + 12.182 + "' isSynthetic() expected"); 12.183 + break; 12.184 + } 12.185 + 12.186 + if (!allowImplicit && p.isImplicit()) { 12.187 + error(prefix + "param[" + i + "]='" + pname + 12.188 + "' isImplicit() unexpected"); 12.189 + break; 12.190 + } 12.191 + 12.192 + if (!allowSynthetic && p.isSynthetic()) { 12.193 + error(prefix + "param[" + i + "]='" + pname + 12.194 + "' isSynthetic() unexpected"); 12.195 + break; 12.196 + } 12.197 + 12.198 + // Check expected names 12.199 + if (expect != null) { 12.200 + if (pname.matches(expect)) continue; 12.201 + error(prefix + "param[" + i + "]='" + pname + 12.202 + "' expected '" + expect + "'"); 12.203 + break; 12.204 + } 12.205 + 12.206 + // Test naming convention for explicit parameters. 12.207 + boolean fidelity = !isAnon; 12.208 + if (param != null && fidelity) { 12.209 + char ch = param.charAt(0); 12.210 + expect = (++ch) + param; 12.211 + } 12.212 + 12.213 + if (pname != null && fidelity) { 12.214 + param = pname; 12.215 + } 12.216 + 12.217 + if (expect != null && !expect.equals(pname)) { 12.218 + error(prefix + "param[" + i + "]='" + pname + 12.219 + "' expected '" + expect + "'"); 12.220 + break; 12.221 + } 12.222 + } 12.223 + if (c.isSynthetic()) { 12.224 + sb.append(")!!\n"); 12.225 + } else { 12.226 + sb.append(")\n"); 12.227 + } 12.228 + } 12.229 + 12.230 + void testMethod(Method m) { 12.231 + 12.232 + String prefix = clazz.getName() + "." + m.getName() + "() - "; 12.233 + 12.234 + // Parameters must match parameter types 12.235 + int paramTypes = m.getParameterTypes().length; 12.236 + int params = m.getParameters().length; 12.237 + if (paramTypes != params) { 12.238 + error(prefix + "number of parameter types (" + paramTypes 12.239 + + ") != number of parameters (" + params + ")"); 12.240 + return; 12.241 + } 12.242 + 12.243 + sb.append(clazz.getName()).append(".").append(m.getName()).append("("); 12.244 + String sep = ""; 12.245 + String param = null; 12.246 + int i = -1; 12.247 + // For methods we expect all parameters to follow 12.248 + // the test-case design pattern, except synthetic methods. 12.249 + for (Parameter p : m.getParameters()) { 12.250 + i++; 12.251 + if (param == null) { 12.252 + param = p.getName(); 12.253 + sb.append(sep).append(param); 12.254 + } else { 12.255 + char c = param.charAt(0); 12.256 + String expect = m.isSynthetic() ? ("arg" + i) : ((++c) + param); 12.257 + param = p.getName(); 12.258 + sb.append(sep).append(param); 12.259 + if (!expect.equals(param)) { 12.260 + error(prefix + "param[" + i + "]='" 12.261 + + param + "' expected '" + expect + "'"); 12.262 + break; 12.263 + } 12.264 + } 12.265 + sep = ", "; 12.266 + } 12.267 + if (m.isSynthetic()) { 12.268 + sb.append(")!!\n"); 12.269 + } else { 12.270 + sb.append(")\n"); 12.271 + } 12.272 + } 12.273 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/test/tools/javac/MethodParameters/StaticMethods.java Wed Feb 20 15:47:14 2013 -0800 13.3 @@ -0,0 +1,46 @@ 13.4 +/* 13.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 13.7 + * 13.8 + * This code is free software; you can redistribute it and/or modify it 13.9 + * under the terms of the GNU General Public License version 2 only, as 13.10 + * published by the Free Software Foundation. 13.11 + * 13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13.15 + * version 2 for more details (a copy is included in the LICENSE file that 13.16 + * accompanied this code). 13.17 + * 13.18 + * You should have received a copy of the GNU General Public License version 13.19 + * 2 along with this work; if not, write to the Free Software Foundation, 13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 13.21 + * 13.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 13.23 + * or visit www.oracle.com if you need additional information or have any 13.24 + * questions. 13.25 + */ 13.26 + 13.27 +/* 13.28 + * @test 13.29 + * @bug 8006582 13.30 + * @summary javac should generate method parameters correctly. 13.31 + * @build Tester 13.32 + * @compile -parameters StaticMethods.java 13.33 + * @run main Tester StaticMethods 13.34 + */ 13.35 + 13.36 +public class StaticMethods { 13.37 + static public void empty() {} 13.38 + static final void def(Object a, final Object ba, final String... cba) { } 13.39 + static final public void pub(Object d, final Object ed, final String... fed) { } 13.40 + static protected boolean prot(Object g, final Object hg, final String... ihg) { return true; } 13.41 + static private boolean priv(Object j, final Object kj, final String... lkj) { return true; } 13.42 + static void def(int a, Object ba, final Object cba, final String... dcba) { } 13.43 + static public void pub(int a, Object ba, final Object cba , final String... dcba) { } 13.44 + static final protected boolean prot(int aa, Object baa, final Object cbaa, final String... dcbaa) { return true; } 13.45 + static final private boolean priv(int abc, Object babc, final Object cbabc, final String... dcbabc) { return true; } 13.46 +} 13.47 + 13.48 + 13.49 +
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/test/tools/javac/MethodParameters/Tester.java Wed Feb 20 15:47:14 2013 -0800 14.3 @@ -0,0 +1,162 @@ 14.4 +/* 14.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.7 + * 14.8 + * This code is free software; you can redistribute it and/or modify it 14.9 + * under the terms of the GNU General Public License version 2 only, as 14.10 + * published by the Free Software Foundation. 14.11 + * 14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14.15 + * version 2 for more details (a copy is included in the LICENSE file that 14.16 + * accompanied this code). 14.17 + * 14.18 + * You should have received a copy of the GNU General Public License version 14.19 + * 2 along with this work; if not, write to the Free Software Foundation, 14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 14.21 + * 14.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 14.23 + * or visit www.oracle.com if you need additional information or have any 14.24 + * questions. 14.25 + */ 14.26 + 14.27 +import java.io.*; 14.28 +import java.util.*; 14.29 +import java.lang.reflect.Constructor; 14.30 + 14.31 +/** 14.32 + * Test driver for MethodParameters testing. 14.33 + * <p> 14.34 + * The intended use of this driver is to run it, giving the name of 14.35 + * a single class compiled with -parameters as argument. The driver 14.36 + * will test the specified class, and any nested classes it finds. 14.37 + * <p> 14.38 + * Each class is tested in two way. By refelction, and by directly 14.39 + * checking MethodParameters attributes in the classfile. The checking 14.40 + * is done using two visitor classes {@link ClassFileVisitor} and 14.41 + * {@link ReflectionVisitor}. 14.42 + * <p> 14.43 + * The {@code ReflectionVisitor} test logically belongs with library tests. 14.44 + * we wish to reuse the same test-cases, so both test are committed together, 14.45 + * under langtools. The tests, may be duplicated in the jdk repository. 14.46 + */ 14.47 +public class Tester { 14.48 + 14.49 + final static File classesdir = new File(System.getProperty("test.classes", ".")); 14.50 + 14.51 + /** 14.52 + * The visitor classes that does the actual checking are referenced 14.53 + * statically, to force compilations, without having to reference 14.54 + * them in individual test cases. 14.55 + * <p> 14.56 + * This makes it easy to change the set of visitors, without 14.57 + * complicating the design with dynamic discovery and compilation 14.58 + * of visitor classes. 14.59 + */ 14.60 + static final Class visitors[] = { 14.61 + ClassFileVisitor.class, 14.62 + ReflectionVisitor.class 14.63 + }; 14.64 + 14.65 + /** 14.66 + * Test-driver expect a single classname as argument. 14.67 + */ 14.68 + public static void main(String... args) throws Exception { 14.69 + if (args.length != 1) { 14.70 + throw new Error("A single class name is expected as argument"); 14.71 + } 14.72 + final String pattern = args[0] + ".*\\.class"; 14.73 + File files[] = classesdir.listFiles(new FileFilter() { 14.74 + public boolean accept(File f) { 14.75 + return f.getName().matches(pattern); 14.76 + } 14.77 + }); 14.78 + if (files.length == 0) { 14.79 + File file = new File(classesdir, args[0] + ".class"); 14.80 + throw new Error(file.getPath() + " not found"); 14.81 + } 14.82 + 14.83 + new Tester(args[0], files).run(); 14.84 + } 14.85 + 14.86 + public Tester(String name, File files[]) { 14.87 + this.classname = name; 14.88 + this.files = files; 14.89 + } 14.90 + 14.91 + void run() throws Exception { 14.92 + 14.93 + // Test with each visitor 14.94 + for (Class<Visitor> vclass : visitors) { 14.95 + try { 14.96 + String vname = vclass.getName(); 14.97 + Constructor c = vclass.getConstructor(Tester.class); 14.98 + 14.99 + info("\nRun " + vname + " for " + classname + "\n"); 14.100 + StringBuilder sb = new StringBuilder(); 14.101 + for (File f : files) { 14.102 + String fname = f.getName(); 14.103 + fname = fname.substring(0, fname.length() - 6); 14.104 + Visitor v = (Visitor) c.newInstance(this); 14.105 + try { 14.106 + v.visitClass(fname, f, sb); 14.107 + } catch(Exception e) { 14.108 + error("Uncaught exception in visitClass()"); 14.109 + e.printStackTrace(); 14.110 + } 14.111 + } 14.112 + info(sb.toString()); 14.113 + } catch(ReflectiveOperationException e) { 14.114 + warn("Class " + vclass.getName() + " ignored, not a Visitor"); 14.115 + continue; 14.116 + } 14.117 + } 14.118 + 14.119 + if(0 != warnings) 14.120 + System.err.println("Test generated " + warnings + " warnings"); 14.121 + 14.122 + if(0 != errors) 14.123 + throw new Exception("Tester test failed with " + 14.124 + errors + " errors"); 14.125 + } 14.126 + 14.127 + abstract static class Visitor { 14.128 + Tester tester; 14.129 + File classesdir; 14.130 + 14.131 + public Visitor(Tester tester) { 14.132 + this.tester = tester; 14.133 + } 14.134 + 14.135 + abstract void visitClass(final String classname, final File cfile, 14.136 + final StringBuilder sb) throws Exception; 14.137 + 14.138 + public void error(String msg) { 14.139 + tester.error(msg); 14.140 + } 14.141 + 14.142 + public void warn(String msg) { 14.143 + tester.warn(msg); 14.144 + } 14.145 + } 14.146 + 14.147 + void error(String msg) { 14.148 + System.err.println("Error: " + msg); 14.149 + errors++; 14.150 + } 14.151 + 14.152 + void warn(String msg) { 14.153 + System.err.println("Warning: " + msg); 14.154 + warnings++; 14.155 + } 14.156 + 14.157 + void info(String msg) { 14.158 + System.out.println(msg); 14.159 + } 14.160 + 14.161 + int errors; 14.162 + int warnings; 14.163 + String classname; 14.164 + File files[]; 14.165 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/test/tools/javac/MethodParameters/UncommonParamNames.java Wed Feb 20 15:47:14 2013 -0800 15.3 @@ -0,0 +1,68 @@ 15.4 +/* 15.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.7 + * 15.8 + * This code is free software; you can redistribute it and/or modify it 15.9 + * under the terms of the GNU General Public License version 2 only, as 15.10 + * published by the Free Software Foundation. 15.11 + * 15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15.15 + * version 2 for more details (a copy is included in the LICENSE file that 15.16 + * accompanied this code). 15.17 + * 15.18 + * You should have received a copy of the GNU General Public License version 15.19 + * 2 along with this work; if not, write to the Free Software Foundation, 15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 15.21 + * 15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 15.23 + * or visit www.oracle.com if you need additional information or have any 15.24 + * questions. 15.25 + */ 15.26 + 15.27 +/* 15.28 + * @test 15.29 + * @bug 8006582 15.30 + * @summary javac should generate method parameters correctly. 15.31 + * @build Tester 15.32 + * @compile -parameters UncommonParamNames.java 15.33 + * @run main Tester UncommonParamNames 15.34 + */ 15.35 + 15.36 +/** Test uncommon parameter names */ 15.37 +class UncommonParamNames { 15.38 + public UncommonParamNames(int _x) { } 15.39 + public UncommonParamNames(short $1) { } 15.40 + public UncommonParamNames(long \u0061) { } 15.41 + public UncommonParamNames(char zero\u0000zero\u0000) { } 15.42 + public UncommonParamNames(String zero\u0000zero\u0000seven\u0007) { } 15.43 + public UncommonParamNames(Object zero\u0000zero\u0000eight\u0008) { } 15.44 + public UncommonParamNames(Object aLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName, 15.45 + Object baLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName, 15.46 + Object cbaLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName) { } 15.47 + public UncommonParamNames(int a, int ba, int cba, int dcba, int edcba, int fedcba, int gfedcba, 15.48 + int hgfedcba, int ihgfedcba, int jihgfedcba, int kjihgfedcba, int lkjihgfedcba, 15.49 + int mlkjihgfedcba, int nmlkjihgfedcba, int onmlkjihgfedcba, int ponmlkjihgfedcba, 15.50 + int qponmlkjihgfedcba, int rqponmlkjihgfedcba, int srqponmlkjihgfedcba, 15.51 + int tsrqponmlkjihgfedcba, int utsrqponmlkjihgfedcba, int vutsrqponmlkjihgfedcba, 15.52 + int wvutsrqponmlkjihgfedcba, int xwvutsrqponmlkjihgfedcba, 15.53 + int yxwvutsrqponmlkjihgfedcba, int zyxwvutsrqponmlkjihgfedcba) { } 15.54 + 15.55 + public void foo(int _x) { } 15.56 + public void foo(short $1) { } 15.57 + public void foo(long \u0061) { } 15.58 + public void foo(char zero\u0000zero\u0000) { } 15.59 + public void foo(String zero\u0000zero\u0000seven\u0007) { } 15.60 + public void foo(Object zero\u0000zero\u0000eight\u0008) { } 15.61 + public void foo(Object aLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName, 15.62 + Object baLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName, 15.63 + Object cbaLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName) { } 15.64 + public void foo(int a, int ba, int cba, int dcba, int edcba, int fedcba, int gfedcba, 15.65 + int hgfedcba, int ihgfedcba, int jihgfedcba, int kjihgfedcba, int lkjihgfedcba, 15.66 + int mlkjihgfedcba, int nmlkjihgfedcba, int onmlkjihgfedcba, int ponmlkjihgfedcba, 15.67 + int qponmlkjihgfedcba, int rqponmlkjihgfedcba, int srqponmlkjihgfedcba, 15.68 + int tsrqponmlkjihgfedcba, int utsrqponmlkjihgfedcba, int vutsrqponmlkjihgfedcba, 15.69 + int wvutsrqponmlkjihgfedcba, int xwvutsrqponmlkjihgfedcba, 15.70 + int yxwvutsrqponmlkjihgfedcba, int zyxwvutsrqponmlkjihgfedcba) { } 15.71 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/test/tools/javac/MethodParametersTest.java Wed Feb 20 15:47:14 2013 -0800 16.3 @@ -0,0 +1,344 @@ 16.4 +/* 16.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 16.7 + * 16.8 + * This code is free software; you can redistribute it and/or modify it 16.9 + * under the terms of the GNU General Public License version 2 only, as 16.10 + * published by the Free Software Foundation. 16.11 + * 16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16.15 + * version 2 for more details (a copy is included in the LICENSE file that 16.16 + * accompanied this code). 16.17 + * 16.18 + * You should have received a copy of the GNU General Public License version 16.19 + * 2 along with this work; if not, write to the Free Software Foundation, 16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 16.21 + * 16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 16.23 + * or visit www.oracle.com if you need additional information or have any 16.24 + * questions. 16.25 + */ 16.26 + 16.27 +/* 16.28 + * @test 16.29 + * @bug 8004727 16.30 + * @summary javac should generate method parameters correctly. 16.31 + */ 16.32 +// key: opt.arg.parameters 16.33 +import com.sun.tools.classfile.*; 16.34 +import com.sun.tools.javac.file.JavacFileManager; 16.35 +import com.sun.tools.javac.main.Main; 16.36 +import com.sun.tools.javac.util.Context; 16.37 +import com.sun.tools.javac.util.Name; 16.38 +import com.sun.tools.javac.util.Names; 16.39 +import java.io.*; 16.40 +import javax.lang.model.element.*; 16.41 +import java.util.*; 16.42 + 16.43 +public class MethodParametersTest { 16.44 + 16.45 + static final String Foo_name = "Foo"; 16.46 + static final String Foo_contents = 16.47 + "public class Foo {\n" + 16.48 + " Foo() {}\n" + 16.49 + " void foo0() {}\n" + 16.50 + " void foo2(int j, int k) {}\n" + 16.51 + "}"; 16.52 + static final String Bar_name = "Bar"; 16.53 + static final String Bar_contents = 16.54 + "public class Bar {\n" + 16.55 + " Bar(int i) {}" + 16.56 + " Foo foo() { return new Foo(); }\n" + 16.57 + "}"; 16.58 + static final String Baz_name = "Baz"; 16.59 + static final String Baz_contents = 16.60 + "public class Baz {\n" + 16.61 + " int baz;" + 16.62 + " Baz(int i) {}" + 16.63 + "}"; 16.64 + static final String Qux_name = "Qux"; 16.65 + static final String Qux_contents = 16.66 + "public class Qux extends Baz {\n" + 16.67 + " Qux(int i) { super(i); }" + 16.68 + "}"; 16.69 + static final File classesdir = new File("methodparameters"); 16.70 + 16.71 + public static void main(String... args) throws Exception { 16.72 + new MethodParametersTest().run(); 16.73 + } 16.74 + 16.75 + void run() throws Exception { 16.76 + classesdir.mkdir(); 16.77 + final File Foo_java = 16.78 + writeFile(classesdir, Foo_name + ".java", Foo_contents); 16.79 + final File Bar_java = 16.80 + writeFile(classesdir, Bar_name + ".java", Bar_contents); 16.81 + final File Baz_java = 16.82 + writeFile(classesdir, Baz_name + ".java", Baz_contents); 16.83 + System.err.println("Test compile with -parameter"); 16.84 + compile("-parameters", "-d", classesdir.getPath(), Foo_java.getPath()); 16.85 + // First test: make sure javac doesn't choke to death on 16.86 + // MethodParameter attributes 16.87 + System.err.println("Test compile with classfile containing MethodParameter attributes"); 16.88 + compile("-parameters", "-d", classesdir.getPath(), 16.89 + "-cp", classesdir.getPath(), Bar_java.getPath()); 16.90 + System.err.println("Examine class foo"); 16.91 + checkFoo(); 16.92 + checkBar(); 16.93 + System.err.println("Test debug information conflict"); 16.94 + compile("-g", "-parameters", "-d", classesdir.getPath(), 16.95 + "-cp", classesdir.getPath(), Baz_java.getPath()); 16.96 + System.err.println("Introducing debug information conflict"); 16.97 + Baz_java.delete(); 16.98 + modifyBaz(false); 16.99 + System.err.println("Checking language model"); 16.100 + inspectBaz(); 16.101 + System.err.println("Permuting attributes"); 16.102 + modifyBaz(true); 16.103 + System.err.println("Checking language model"); 16.104 + inspectBaz(); 16.105 + 16.106 + if(0 != errors) 16.107 + throw new Exception("MethodParameters test failed with " + 16.108 + errors + " errors"); 16.109 + } 16.110 + 16.111 + void inspectBaz() throws Exception { 16.112 + final File Qux_java = 16.113 + writeFile(classesdir, Qux_name + ".java", Qux_contents); 16.114 + final String[] args = { "-XDsave-parameter-names", "-d", 16.115 + classesdir.getPath(), 16.116 + "-cp", classesdir.getPath(), 16.117 + Qux_java.getPath() }; 16.118 + final StringWriter sw = new StringWriter(); 16.119 + final PrintWriter pw = new PrintWriter(sw); 16.120 + 16.121 + // We need to be able to crack open javac and look at its data 16.122 + // structures. We'll rig up a compiler instance, but keep its 16.123 + // Context, thus allowing us to get at the ClassReader. 16.124 + Context context = new Context(); 16.125 + Main comp = new Main("javac", pw); 16.126 + JavacFileManager.preRegister(context); 16.127 + 16.128 + // Compile Qux, which uses Baz. 16.129 + comp.compile(args, context); 16.130 + pw.close(); 16.131 + final String out = sw.toString(); 16.132 + if (out.length() > 0) 16.133 + System.err.println(out); 16.134 + 16.135 + // Now get the class reader, construct a name for Baz, and load it. 16.136 + com.sun.tools.javac.jvm.ClassReader cr = 16.137 + com.sun.tools.javac.jvm.ClassReader.instance(context); 16.138 + Name name = Names.instance(context).fromString(Baz_name); 16.139 + 16.140 + // Now walk down the language model and check the name of the 16.141 + // parameter. 16.142 + final Element baz = cr.loadClass(name); 16.143 + for (Element e : baz.getEnclosedElements()) { 16.144 + if (e instanceof ExecutableElement) { 16.145 + final ExecutableElement ee = (ExecutableElement) e; 16.146 + final List<? extends VariableElement> params = 16.147 + ee.getParameters(); 16.148 + if (1 != params.size()) 16.149 + throw new Exception("Classfile Baz badly formed: wrong number of methods"); 16.150 + final VariableElement param = params.get(0); 16.151 + if (!param.getSimpleName().contentEquals("baz")) { 16.152 + errors++; 16.153 + System.err.println("javac did not correctly resolve the metadata conflict, parameter's name reads as " + param.getSimpleName()); 16.154 + } else 16.155 + System.err.println("javac did correctly resolve the metadata conflict"); 16.156 + } 16.157 + } 16.158 + } 16.159 + 16.160 + void modifyBaz(boolean flip) throws Exception { 16.161 + final File Baz_class = new File(classesdir, Baz_name + ".class"); 16.162 + final ClassFile baz = ClassFile.read(Baz_class); 16.163 + final int ind = baz.constant_pool.getUTF8Index("baz"); 16.164 + MethodParameters_attribute mpattr = null; 16.165 + int mpind = 0; 16.166 + Code_attribute cattr = null; 16.167 + int cind = 0; 16.168 + 16.169 + // Find the indexes of the MethodParameters and the Code attributes 16.170 + if (baz.methods.length != 1) 16.171 + throw new Exception("Classfile Baz badly formed: wrong number of methods"); 16.172 + if (!baz.methods[0].getName(baz.constant_pool).equals("<init>")) 16.173 + throw new Exception("Classfile Baz badly formed: method has name " + 16.174 + baz.methods[0].getName(baz.constant_pool)); 16.175 + for (int i = 0; i < baz.methods[0].attributes.attrs.length; i++) { 16.176 + if (baz.methods[0].attributes.attrs[i] instanceof 16.177 + MethodParameters_attribute) { 16.178 + mpattr = (MethodParameters_attribute) 16.179 + baz.methods[0].attributes.attrs[i]; 16.180 + mpind = i; 16.181 + } else if (baz.methods[0].attributes.attrs[i] instanceof 16.182 + Code_attribute) { 16.183 + cattr = (Code_attribute) baz.methods[0].attributes.attrs[i]; 16.184 + cind = i; 16.185 + } 16.186 + } 16.187 + if (null == mpattr) 16.188 + throw new Exception("Classfile Baz badly formed: no method parameters info"); 16.189 + if (null == cattr) 16.190 + throw new Exception("Classfile Baz badly formed: no local variable table"); 16.191 + 16.192 + int flags = mpattr.method_parameter_table[0].flags; 16.193 + 16.194 + // Alter the MethodParameters attribute, changing the name of 16.195 + // the parameter from i to baz. This requires Black Magic... 16.196 + // 16.197 + // The (well-designed) classfile library (correctly) does not 16.198 + // allow us to mess around with the attribute data structures, 16.199 + // or arbitrarily generate new ones. 16.200 + // 16.201 + // Instead, we install a new subclass of Attribute that 16.202 + // hijacks the Visitor pattern and outputs the sequence of 16.203 + // bytes that we want. This only works in this particular 16.204 + // instance, because we know we'll only every see one kind of 16.205 + // visitor. 16.206 + // 16.207 + // If anyone ever changes the makeup of the Baz class, or 16.208 + // tries to install some kind of visitor that gets run prior 16.209 + // to serialization, this will break. 16.210 + baz.methods[0].attributes.attrs[mpind] = 16.211 + new Attribute(mpattr.attribute_name_index, 16.212 + mpattr.attribute_length) { 16.213 + public <R, D> R accept(Visitor<R, D> visitor, D data) { 16.214 + if (data instanceof ByteArrayOutputStream) { 16.215 + ByteArrayOutputStream out = 16.216 + (ByteArrayOutputStream) data; 16.217 + out.write(1); 16.218 + out.write((ind >> 8) & 0xff); 16.219 + out.write(ind & 0xff); 16.220 + out.write((flags >> 24) & 0xff); 16.221 + out.write((flags >> 16) & 0xff); 16.222 + out.write((flags >> 8) & 0xff); 16.223 + out.write(flags & 0xff); 16.224 + } else 16.225 + throw new RuntimeException("Output stream is of type " + data.getClass() + ", which is not handled by this test. Update the test and it should work."); 16.226 + return null; 16.227 + } 16.228 + }; 16.229 + 16.230 + // Flip the code and method attributes. This is for checking 16.231 + // that order doesn't matter. 16.232 + if (flip) { 16.233 + baz.methods[0].attributes.attrs[mpind] = cattr; 16.234 + baz.methods[0].attributes.attrs[cind] = mpattr; 16.235 + } 16.236 + 16.237 + new ClassWriter().write(baz, Baz_class); 16.238 + } 16.239 + 16.240 + // Run a bunch of structural tests on foo to make sure it looks right. 16.241 + void checkFoo() throws Exception { 16.242 + final File Foo_class = new File(classesdir, Foo_name + ".class"); 16.243 + final ClassFile foo = ClassFile.read(Foo_class); 16.244 + for (int i = 0; i < foo.methods.length; i++) { 16.245 + System.err.println("Examine method Foo." + foo.methods[i].getName(foo.constant_pool)); 16.246 + if (foo.methods[i].getName(foo.constant_pool).equals("foo2")) { 16.247 + for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) 16.248 + if (foo.methods[i].attributes.attrs[j] instanceof 16.249 + MethodParameters_attribute) { 16.250 + MethodParameters_attribute mp = 16.251 + (MethodParameters_attribute) 16.252 + foo.methods[i].attributes.attrs[j]; 16.253 + System.err.println("Foo.foo2 should have 2 parameters: j and k"); 16.254 + if (2 != mp.method_parameter_table_length) 16.255 + error("expected 2 method parameter entries in foo2, got " + 16.256 + mp.method_parameter_table_length); 16.257 + else if (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("j")) 16.258 + error("expected first parameter to foo2 to be \"j\", got \"" + 16.259 + foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) + 16.260 + "\" instead"); 16.261 + else if (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index).equals("k")) 16.262 + error("expected first parameter to foo2 to be \"k\", got \"" + 16.263 + foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index) + 16.264 + "\" instead"); 16.265 + } 16.266 + } 16.267 + else if (foo.methods[i].getName(foo.constant_pool).equals("<init>")) { 16.268 + for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) { 16.269 + if (foo.methods[i].attributes.attrs[j] instanceof 16.270 + MethodParameters_attribute) 16.271 + error("Zero-argument constructor shouldn't have MethodParameters"); 16.272 + } 16.273 + } 16.274 + else if (foo.methods[i].getName(foo.constant_pool).equals("foo0")) { 16.275 + for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) 16.276 + if (foo.methods[i].attributes.attrs[j] instanceof 16.277 + MethodParameters_attribute) 16.278 + error("Zero-argument method shouldn't have MethodParameters"); 16.279 + } 16.280 + else 16.281 + error("Unknown method " + foo.methods[i].getName(foo.constant_pool) + " showed up in class Foo"); 16.282 + } 16.283 + } 16.284 + 16.285 + // Run a bunch of structural tests on Bar to make sure it looks right. 16.286 + void checkBar() throws Exception { 16.287 + final File Bar_class = new File(classesdir, Bar_name + ".class"); 16.288 + final ClassFile bar = ClassFile.read(Bar_class); 16.289 + for (int i = 0; i < bar.methods.length; i++) { 16.290 + System.err.println("Examine method Bar." + bar.methods[i].getName(bar.constant_pool)); 16.291 + if (bar.methods[i].getName(bar.constant_pool).equals("<init>")) { 16.292 + for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++) 16.293 + if (bar.methods[i].attributes.attrs[j] instanceof 16.294 + MethodParameters_attribute) { 16.295 + MethodParameters_attribute mp = 16.296 + (MethodParameters_attribute) 16.297 + bar.methods[i].attributes.attrs[j]; 16.298 + System.err.println("Bar constructor should have 1 parameter: i"); 16.299 + if (1 != mp.method_parameter_table_length) 16.300 + error("expected 1 method parameter entries in constructor, got " + 16.301 + mp.method_parameter_table_length); 16.302 + else if (!bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("i")) 16.303 + error("expected first parameter to foo2 to be \"i\", got \"" + 16.304 + bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) + 16.305 + "\" instead"); 16.306 + } 16.307 + } 16.308 + else if (bar.methods[i].getName(bar.constant_pool).equals("foo")) { 16.309 + for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++) { 16.310 + if (bar.methods[i].attributes.attrs[j] instanceof 16.311 + MethodParameters_attribute) 16.312 + error("Zero-argument constructor shouldn't have MethodParameters"); 16.313 + } 16.314 + } 16.315 + } 16.316 + } 16.317 + 16.318 + String compile(String... args) throws Exception { 16.319 + System.err.println("compile: " + Arrays.asList(args)); 16.320 + StringWriter sw = new StringWriter(); 16.321 + PrintWriter pw = new PrintWriter(sw); 16.322 + int rc = com.sun.tools.javac.Main.compile(args, pw); 16.323 + pw.close(); 16.324 + String out = sw.toString(); 16.325 + if (out.length() > 0) 16.326 + System.err.println(out); 16.327 + if (rc != 0) 16.328 + error("compilation failed, rc=" + rc); 16.329 + return out; 16.330 + } 16.331 + 16.332 + File writeFile(File dir, String path, String body) throws IOException { 16.333 + File f = new File(dir, path); 16.334 + f.getParentFile().mkdirs(); 16.335 + FileWriter out = new FileWriter(f); 16.336 + out.write(body); 16.337 + out.close(); 16.338 + return f; 16.339 + } 16.340 + 16.341 + void error(String msg) { 16.342 + System.err.println("Error: " + msg); 16.343 + errors++; 16.344 + } 16.345 + 16.346 + int errors; 16.347 +}