8006582: Test for parameter names feature

Reviewed-by: jjg, darcy, emc
This commit is contained in:
Peter Jensen 2013-02-20 15:47:14 -08:00
parent 898ada48bb
commit 556f6dfebb
15 changed files with 1472 additions and 3 deletions

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters AnnotationTest.java
* @run main Tester AnnotationTest
*/
import java.lang.annotation.*;
/** Test that annotations do not interfere with recording of parameter names */
class AnnotationTest {
@Repeatable(Annos.class)
@interface Anno {
Class f() default int.class;
}
@interface Annos { Anno[] value(); String foo() default "hello"; }
interface I {
int m(@Anno @Anno int i, @Anno int ji);
}
public AnnotationTest(@Anno @Anno I i, @Anno int ji) { }
public @Anno String foo(@Anno @Anno I i, int ji) { return null; }
}

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters AnonymousClass.java
* @run main Tester AnonymousClass
*/
class AnonymousClass {
interface I<T> {
T m();
T m(T x, T yx);
}
private class Inner implements I<String> {
public Inner() { }
public Inner(String arg, String barg) { }
public String m() { return "0"; }
public String m(String s, String ts) { return "0"; }
}
public static class Sinner implements I<Long> {
public Sinner() { }
public Sinner(Long arg, Long barg) { }
public Long m() { return 0L; }
public Long m(Long s, Long ts) { return s + ts; }
}
/** Inner class in constructor context */
public AnonymousClass(final Long a, Long ba) {
new I<Long>() {
public Long m() { return null; }
public Long m(Long i, Long ji) { return i + ji; }
}.m(a, ba);
new Inner() {
public String m() { return null; }
public String m(String i, String ji) { return i + ji; }
}.m(a.toString(), ba.toString());
new Inner(a.toString(), ba.toString()) {
public String m() { return null; }
public String m(String i, String ji) { return i + ji; }
}.m(a.toString(), ba.toString());
new Sinner() {
public Long m() { return null; }
public Long m(Long i, Long ji) { return i + ji; }
}.m(a, ba);
new Sinner(a, ba) {
public Long m() { return null; }
public Long m(Long i, Long ji) { return i + ji; }
}.m(a, ba);
}
/** Inner class in method context */
public void foo(final Long a, Long ba) {
new I<Long>() {
public Long m() { return null; }
public Long m(Long i, Long ji) { return i + ji; }
}.m(a, ba);
new Inner() {
public String m() { return null; }
public String m(String i, String ji) { return i + ji; }
}.m(a.toString(), ba.toString());
new Inner(a.toString(), ba.toString()) {
public String m() { return null; }
public String m(String i, String ji) { return i + ji; }
}.m(a.toString(), ba.toString());
new Sinner() {
public Long m() { return null; }
public Long m(Long i, Long ji) { return i + ji; }
}.m(a, ba);
new Sinner(a, ba) {
public Long m() { return null; }
public Long m(Long i, Long ji) { return i + ji; }
}.m(a, ba);
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.sun.tools.classfile.*;
/**
* Trivial {@code Attribute.Visitor} implementation, to make it easy to
* write visitors for specific attributes.
*/
class AttributeVisitor<R, P> implements Attribute.Visitor<R, P> {
public R visitBootstrapMethods(BootstrapMethods_attribute attr, P p) { return null; }
public R visitDefault(DefaultAttribute attr, P p) { return null; }
public R visitAnnotationDefault(AnnotationDefault_attribute attr, P p) { return null; }
public R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p) { return null; }
public R visitCode(Code_attribute attr, P p) { return null; }
public R visitCompilationID(CompilationID_attribute attr, P p) { return null; }
public R visitConstantValue(ConstantValue_attribute attr, P p) { return null; }
public R visitDeprecated(Deprecated_attribute attr, P p) { return null; }
public R visitEnclosingMethod(EnclosingMethod_attribute attr, P p) { return null; }
public R visitExceptions(Exceptions_attribute attr, P p) { return null; }
public R visitInnerClasses(InnerClasses_attribute attr, P p) { return null; }
public R visitLineNumberTable(LineNumberTable_attribute attr, P p) { return null; }
public R visitLocalVariableTable(LocalVariableTable_attribute attr, P p) { return null; }
public R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p) { return null; }
public R visitMethodParameters(MethodParameters_attribute attr, P p) { return null; }
public R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p) { return null; }
public R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p) { return null; }
public R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p) { return null; }
public R visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, P p) { return null; }
public R visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, P p) { return null; }
public R visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, P p) { return null; }
public R visitSignature(Signature_attribute attr, P p) { return null; }
public R visitSourceDebugExtension(SourceDebugExtension_attribute attr, P p) { return null; }
public R visitSourceFile(SourceFile_attribute attr, P p) { return null; }
public R visitSourceID(SourceID_attribute attr, P p) { return null; }
public R visitStackMap(StackMap_attribute attr, P p) { return null; }
public R visitStackMapTable(StackMapTable_attribute attr, P p) { return null; }
public R visitSynthetic(Synthetic_attribute attr, P p) { return null; }
}

View file

@ -0,0 +1,387 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.sun.tools.classfile.*;
import java.io.*;
import javax.lang.model.element.*;
import java.util.*;
/**
* The {@code ClassFileVisitor} reads a class file using the
* {@code com.sun.tools.classfile} library. It iterates over the methods
* in a class, and checks MethodParameters attributes against JLS
* requirements, as well as assumptions about the javac implementations.
* <p>
* It enforces the following rules:
* <ul>
* <li>All non-synthetic methods with arguments must have the
* MethodParameters attribute. </li>
* <li>At most one MethodParameters attribute per method.</li>
* <li>An empty MethodParameters attribute is not allowed (i.e. no
* attribute for methods taking no parameters).</li>
* <li>The number of recorded parameter names much equal the number
* of parameters, including any implicit or synthetic parameters generated
* by the compiler.</li>
* <li>Although the spec allow recording parameters with no name, the javac
* implementation is assumed to record a name for all parameters. That is,
* the Methodparameters attribute must record a non-zero, valid constant
* pool index for each parameter.</li>
* <li>Check presence, expected names (e.g. this$N, $enum$name, ...) and flags
* (e.g. ACC_SYNTHETIC, ACC_MANDATED) for compiler generated parameters.</li>
* <li>Names of explicit parameters must reflect the names in the Java source.
* This is checked by assuming a design pattern where any name is permitted
* for the first explicit parameter. For subsequent parameters the following
* rule is checked: <i>param[n] == ++param[n-1].charAt(0) + param[n-1]</i>
* </ul>
*/
class ClassFileVisitor extends Tester.Visitor {
Tester tester;
public String cname;
public boolean isEnum;
public boolean isInterface;
public boolean isInner;
public boolean isPublic;
public boolean isStatic;
public boolean isAnon;
public ClassFile classFile;
public ClassFileVisitor(Tester tester) {
super(tester);
}
public void error(String msg) {
super.error("classfile: " + msg);
}
public void warn(String msg) {
super.warn("classfile: " + msg);
}
/**
* Read the class and determine some key characteristics, like if it's
* an enum, or inner class, etc.
*/
void visitClass(final String cname, final File cfile, final StringBuilder sb)
throws Exception {
this.cname = cname;
classFile = ClassFile.read(cfile);
isEnum = classFile.access_flags.is(AccessFlags.ACC_ENUM);
isInterface = classFile.access_flags.is(AccessFlags.ACC_INTERFACE);
isPublic = classFile.access_flags.is(AccessFlags.ACC_PUBLIC);
isInner = false;
isStatic = true;
isAnon = false;
Attribute attr = classFile.getAttribute("InnerClasses");
if (attr != null) attr.accept(new InnerClassVisitor(), null);
isAnon = isInner & isAnon;
sb.append(isStatic ? "static " : "")
.append(isPublic ? "public " : "")
.append(isEnum ? "enum " : isInterface ? "interface " : "class ")
.append(cname).append(" -- ")
.append(isInner? "inner " : "" )
.append(isAnon ? "anon" : "")
.append("\n");;
for (Method method : classFile.methods) {
new MethodVisitor().visitMethod(method, sb);
}
}
/**
* Used to visit InnerClasses_attribute of a class,
* to determne if this class is an local class, and anonymous
* inner class or a none-static member class. These types of
* classes all have an containing class instances field that
* requires an implicit or synthetic constructor argument.
*/
class InnerClassVisitor extends AttributeVisitor<Void, Void> {
public Void visitInnerClasses(InnerClasses_attribute iattr, Void v) {
try{
for (InnerClasses_attribute.Info info : iattr.classes) {
if (info.getInnerClassInfo(classFile.constant_pool) == null) continue;
String in = info.getInnerClassInfo(classFile.constant_pool).getName();
if (in == null || !cname.equals(in)) continue;
isInner = true;
isAnon = null == info.getInnerName(classFile.constant_pool);
isStatic = info.inner_class_access_flags.is(AccessFlags.ACC_STATIC);
break;
}
} catch(Exception e) {
throw new IllegalStateException(e);
}
return null;
}
}
/**
* Check the MethodParameters attribute of a method.
*/
class MethodVisitor extends AttributeVisitor<Void, StringBuilder> {
public String mName;
public Descriptor mDesc;
public int mParams;
public int mAttrs;
public int mNumParams;
public boolean mSynthetic;
public boolean mIsConstructor;
public String prefix;
void visitMethod(Method method, StringBuilder sb) throws Exception {
mName = method.getName(classFile.constant_pool);
mDesc = method.descriptor;
mParams = mDesc.getParameterCount(classFile.constant_pool);
mAttrs = method.attributes.attrs.length;
mNumParams = -1; // no MethodParameters attribute found
mSynthetic = method.access_flags.is(AccessFlags.ACC_SYNTHETIC);
mIsConstructor = mName.equals("<init>");
prefix = cname + "." + mName + "() - ";
sb.append(cname).append(".").append(mName).append("(");
for (Attribute a : method.attributes) {
a.accept(this, sb);
}
if (mNumParams == -1) {
if (mSynthetic) {
sb.append("<none>)!!");
} else {
sb.append("<none>)");
}
}
sb.append("\n");
// IMPL: methods with arguments must have a MethodParameters
// attribute, except possibly some synthetic methods.
if (mNumParams == -1 && mParams > 0 && ! mSynthetic) {
error(prefix + "missing MethodParameters attribute");
}
}
public Void visitMethodParameters(MethodParameters_attribute mp,
StringBuilder sb) {
// SPEC: At most one MethodParameters attribute allowed
if (mNumParams != -1) {
error(prefix + "Multiple MethodParameters attributes");
return null;
}
mNumParams = mp.method_parameter_table_length;
// SPEC: An empty attribute is not allowed!
if (mNumParams == 0) {
error(prefix + "0 length MethodParameters attribute");
return null;
}
// SPEC: one name per parameter.
if (mNumParams != mParams) {
error(prefix + "found " + mNumParams +
" parameters, expected " + mParams);
return null;
}
// IMPL: Whether MethodParameters attributes will be generated
// for some synthetics is unresolved. For now, assume no.
if (mSynthetic) {
warn(prefix + "synthetic has MethodParameter attribute");
}
String sep = "";
String userParam = null;
for (int x = 0; x < mNumParams; x++) {
// IMPL: Assume all parameters are named, something.
int cpi = mp.method_parameter_table[x].name_index;
if (cpi == 0) {
error(prefix + "name expected, param[" + x + "]");
return null;
}
// SPEC: a non 0 index, must be valid!
String param = null;
try {
param = classFile.constant_pool.getUTF8Value(cpi);
sb.append(sep).append(param);
sep = ", ";
} catch(ConstantPoolException e) {
error(prefix + "invalid index " + cpi + " for param["
+ x + "]");
return null;
}
// Check availability, flags and special names
int check = checkParam(mp, param, x, sb);
if (check < 0) {
return null;
}
// TEST: check test assumptions about parameter name.
// Expected names are calculated starting with the
// 2nd explicit (user given) parameter.
// param[n] == ++param[n-1].charAt(0) + param[n-1]
String expect = null;
if (userParam != null) {
char c = userParam.charAt(0);
expect = (++c) + userParam;
}
if (check > 0) {
userParam = param;
}
if (expect != null && !param.equals(expect)) {
error(prefix + "param[" + x + "]='"
+ param + "' expected '" + expect + "'");
return null;
}
}
if (mSynthetic) {
sb.append(")!!");
} else {
sb.append(")");
}
return null;
}
/*
* Check a parameter for conformity to JLS and javac specific
* assumptions.
* Return -1, if an error is detected. Otherwise, return 0, if
* the parameter is compiler generated, or 1 for an (presumably)
* explicitly declared parameter.
*/
int checkParam(MethodParameters_attribute mp, String param, int index,
StringBuilder sb) {
boolean synthetic = (mp.method_parameter_table[index].flags
& AccessFlags.ACC_SYNTHETIC) != 0;
boolean mandated = (mp.method_parameter_table[index].flags
& AccessFlags.ACC_MANDATED) != 0;
// Setup expectations for flags and special names
String expect = null;
boolean allowMandated = false;
boolean allowSynthetic = false;
if (mSynthetic || synthetic) {
// not an implementation gurantee, but okay for now
expect = "arg" + index; // default
}
if (mIsConstructor) {
if (isEnum) {
if (index == 0) {
expect = "\\$enum\\$name";
allowSynthetic = true;
} else if(index == 1) {
expect = "\\$enum\\$ordinal";
allowSynthetic = true;
}
} else if (index == 0) {
if (isAnon) {
allowMandated = true;
expect = "this\\$[0-n]*";
} else if (isInner && !isStatic) {
allowMandated = true;
if (!isPublic) {
// some but not all non-public inner classes
// have synthetic argument. For now we give
// the test a bit of slack and allow either.
allowSynthetic = true;
}
expect = "this\\$[0-n]*";
}
} else if (isAnon) {
// not an implementation gurantee, but okay for now
expect = "x[0-n]*";
}
} else if (isEnum && mNumParams == 1 && index == 0 && mName.equals("valueOf")) {
expect = "name";
allowMandated = true;
}
if (mandated) sb.append("!");
if (synthetic) sb.append("!!");
// IMPL: our rules a somewhat fuzzy, sometimes allowing both mandated
// and synthetic. However, a parameters cannot be both.
if (mandated && synthetic) {
error(prefix + "param[" + index + "] == \"" + param
+ "\" ACC_SYNTHETIC and ACC_MANDATED");
return -1;
}
// ... but must be either, if both "allowed".
if (!(mandated || synthetic) && allowMandated && allowSynthetic) {
error(prefix + "param[" + index + "] == \"" + param
+ "\" expected ACC_MANDATED or ACC_SYNTHETIC");
return -1;
}
// ... if only one is "allowed", we meant "required".
if (!mandated && allowMandated && !allowSynthetic) {
error(prefix + "param[" + index + "] == \"" + param
+ "\" expected ACC_MANDATED");
return -1;
}
if (!synthetic && !allowMandated && allowSynthetic) {
error(prefix + "param[" + index + "] == \"" + param
+ "\" expected ACC_SYNTHETIC");
return -1;
}
// ... and not "allowed", means prohibited.
if (mandated && !allowMandated) {
error(prefix + "param[" + index + "] == \"" + param
+ "\" unexpected, is ACC_MANDATED");
return -1;
}
if (synthetic && !allowSynthetic) {
error(prefix + "param[" + index + "] == \"" + param
+ "\" unexpected, is ACC_SYNTHETIC");
return -1;
}
// Test special name expectations
if (expect != null) {
if (param.matches(expect)) {
return 0;
}
error(prefix + "param[" + index + "]='" + param +
"' expected '" + expect + "'");
return -1;
}
// No further checking for synthetic methods.
if (mSynthetic) {
return 0;
}
// Otherwise, do check test parameter naming convention.
return 1;
}
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters Constructors.java
* @run main Tester Constructors
*/
public class Constructors {
public Constructors() {}
Constructors(final Object a, final String... ba) { }
protected Constructors(Object a, final Object ba, final String... cba) { }
private Constructors(int a, Object ba, final Object cba, final String... dcba) { }
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters EnumTest.java
* @run main Tester EnumTest
*/
/** Test that parameter names are recorded for enum methods */
enum EnumTest {
E1(0), E2(1, "x"), E3(2, "x", "y"), E4;
EnumTest() { }
EnumTest(int a, String... ba) { }
boolean ok(int c, String... dc) { return true; }
int valueOf(EnumTest A, EnumTest BA) { return 0; }
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters InstanceMethods.java
* @run main Tester InstanceMethods
*/
public class InstanceMethods {
public void empty() {}
final void def(Object a, final Object ba, final String... cba) { }
final public void pub(Object d, final Object ed, final String... fed) { }
protected boolean prot(Object g, final Object hg, final String... ihg) { return true; }
private boolean priv(Object j, final Object kj, final String... lkj) { return true; }
void def(int A, Object BA, final Object CBA, final String... DCBA) { }
public void pub(int B, Object CB, final Object DCB, final String... EDCB) { }
final protected boolean prot(int C, Object DC, final Object EDC, final String... FEDC) { return true; }
final private boolean priv(int D, Object ED, final Object FED, final String... GFED) { return true; }
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters LambdaTest.java
* @run main Tester LambdaTest
*/
/**
* Parameter names are not recorded for lambdas. This test verifies
* that there are no MethodParameters attribute for lambdas.
*/
class LambdaTest {
interface I {
int m(int x);
}
static int foo(I i) { return i.m(0); }
static {
foo((int x1) -> { return foo((int x2) -> { return x1 + x2; }); });
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters LocalClassTest.java
* @run main Tester LocalClassTest
*/
class LocalClassTest {
void foo() {
class Local_default_constructor {
public void foo() {}
public void foo(int m, int nm) {}
}
class Local_has_constructor {
public Local_has_constructor() {}
public Local_has_constructor(int a, int ba) {}
public void foo() {}
public void foo(int m, int nm) {}
}
new LocalClassTest().foo();
}
}

View file

@ -0,0 +1,86 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters MemberClassTest.java
* @run main Tester MemberClassTest
*/
class MemberClassTest {
interface I {
Long m();
Long m(Long x, Long yx);
}
public class Member implements I {
public class Member_Member {
public Member_Member() {}
public Member_Member(String x, String yx) {}
}
public Member() { }
public Member(Long a, Long ba) { }
public Long m() { return 0L; }
public Long m(Long s, Long ts) { return 0L; }
}
static class Static_Member implements I {
public class Static_Member_Member {
public Static_Member_Member() {}
public Static_Member_Member(String x, String yx) {}
}
public static class Static_Member_Static_Member {
public Static_Member_Static_Member() {}
public Static_Member_Static_Member(String x, String yx) {}
}
public Static_Member() { }
public Static_Member(Long arg, Long barg) { }
public Long m() { return 0L; }
public Long m(Long s, Long ts) { return s + ts; }
}
public MemberClassTest() {
}
public MemberClassTest(final Long a, Long ba) {
}
public void foo() {
new I() {
class Anonymous_Member {
public Anonymous_Member() {}
public Anonymous_Member(String x, String yx) {}
}
public Long m() { return 0L; }
public Long m(Long s, Long ts) { return s + ts; }
}.m();
}
}

View file

@ -0,0 +1,270 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.*;
import java.util.*;
import java.net.*;
import java.lang.reflect.*;
/**
* Test MethodParameter attributs by reflection API
*/
public class ReflectionVisitor extends Tester.Visitor {
public ReflectionVisitor(Tester tester) {
super(tester);
}
public void error(String msg) {
super.error("reflection: " + msg);
}
public void warn(String msg) {
super.warn("reflection: " + msg);
}
boolean isEnum;
boolean isInterface;
boolean isAnon;
boolean isLocal;
boolean isMember;
boolean isStatic;
boolean isPublic;
Class clazz;
StringBuilder sb;
/**
* Read class using {@code ClassFile}, and generate a list of methods
* with parameter names as available in the MethodParameters attribute.
*/
void visitClass(final String cl, final File cfile, final StringBuilder sb)
throws Exception {
this.sb = sb;
clazz = Class.forName(cl);
isEnum = clazz.isEnum();
isInterface = clazz.isInterface();
isAnon = clazz.isAnonymousClass();
isLocal = clazz.isLocalClass();
isMember = clazz.isMemberClass();
isStatic = ((clazz.getModifiers() & Modifier.STATIC) != 0);
isPublic = ((clazz.getModifiers() & Modifier.PUBLIC) != 0);
sb.append(isStatic ? "static " : "")
.append(isPublic ? "public " : "")
.append(isEnum ? "enum " : isInterface ? "interface " : "class ")
.append(cl).append(" -- ")
.append(isMember? "member " : "" )
.append(isLocal? "local " : "" )
.append(isAnon ? "anon" : "")
.append("\n");
for (Constructor c : clazz.getDeclaredConstructors()) {
testConstructor(c);
}
for (Method m :clazz.getDeclaredMethods()) {
testMethod(m);
}
}
void testConstructor(Constructor c) {
String prefix = clazz.getName() + "." + c.getName() + "() - ";
// Parameters must match parameter types
Parameter params[] = c.getParameters();
int paramTypes = c.getParameterTypes().length;
if (paramTypes != params.length) {
error(prefix + "number of parameter types (" + paramTypes
+ ") != number of parameters (" + params.length + ")");
return;
}
sb.append(clazz.getName()).append(".").append("<init>").append("(");
String sep = "";
// Some paramters are expected
if (params.length < 2 && isEnum) {
error(prefix + "enum constuctor, two arguments expected");
} else if (params.length < 1 && (isAnon || isLocal ||
(isMember && !isStatic ))) {
error(prefix + "class constuctor,expected implicit argument");
}
int i = -1;
String param = null;
for (Parameter p : c.getParameters()) {
i++;
String pname = p.getName();
sb.append(sep).append(pname);
if (p.isImplicit()) sb.append("!");
if (p.isSynthetic()) sb.append("!!");
sep = ", ";
// Set expectations
String expect = null;
boolean allowImplicit = false;
boolean allowSynthetic = false;
if (isEnum) {
if (i == 0) {
expect = "\\$enum\\$name";
allowSynthetic = true;
} else if(i == 1) {
expect = "\\$enum\\$ordinal";
allowSynthetic = true;
}
} else if (i == 0) {
if (isAnon) {
allowImplicit = true;
} else if (isLocal) {
allowImplicit = true;
expect = "this\\$[0-n]*";
} else if ((isMember && !isStatic)) {
allowImplicit = true;
if (!isPublic) {
// some but not all non-public inner classes
// have synthetic argument. For now we give
// the test a bit of slack and allow either.
allowSynthetic = true;
}
expect = "this\\$[0-n]*";
}
} else if (isAnon) {
// not an implementation gurantee, but okay for now
expect = "x[0-n]*";
}
// Check expected flags
if (p.isSynthetic() && p.isImplicit()) {
error(prefix + "param[" + i + "]='" + pname +
"' both isImplicit() and isSynthetic()");
break;
}
if (allowImplicit && allowSynthetic &&
!(p.isSynthetic() || p.isImplicit())) {
error(prefix + "param[" + i + "]='" + pname +
"' isImplicit() or isSynthetic() expected");
break;
}
if (allowImplicit && !allowSynthetic && !p.isImplicit()) {
error(prefix + "param[" + i + "]='" + pname +
"' isImplicit() expected");
break;
}
if (!allowImplicit && allowSynthetic && !p.isSynthetic()) {
error(prefix + "param[" + i + "]='" + pname +
"' isSynthetic() expected");
break;
}
if (!allowImplicit && p.isImplicit()) {
error(prefix + "param[" + i + "]='" + pname +
"' isImplicit() unexpected");
break;
}
if (!allowSynthetic && p.isSynthetic()) {
error(prefix + "param[" + i + "]='" + pname +
"' isSynthetic() unexpected");
break;
}
// Check expected names
if (expect != null) {
if (pname.matches(expect)) continue;
error(prefix + "param[" + i + "]='" + pname +
"' expected '" + expect + "'");
break;
}
// Test naming convention for explicit parameters.
boolean fidelity = !isAnon;
if (param != null && fidelity) {
char ch = param.charAt(0);
expect = (++ch) + param;
}
if (pname != null && fidelity) {
param = pname;
}
if (expect != null && !expect.equals(pname)) {
error(prefix + "param[" + i + "]='" + pname +
"' expected '" + expect + "'");
break;
}
}
if (c.isSynthetic()) {
sb.append(")!!\n");
} else {
sb.append(")\n");
}
}
void testMethod(Method m) {
String prefix = clazz.getName() + "." + m.getName() + "() - ";
// Parameters must match parameter types
int paramTypes = m.getParameterTypes().length;
int params = m.getParameters().length;
if (paramTypes != params) {
error(prefix + "number of parameter types (" + paramTypes
+ ") != number of parameters (" + params + ")");
return;
}
sb.append(clazz.getName()).append(".").append(m.getName()).append("(");
String sep = "";
String param = null;
int i = -1;
// For methods we expect all parameters to follow
// the test-case design pattern, except synthetic methods.
for (Parameter p : m.getParameters()) {
i++;
if (param == null) {
param = p.getName();
sb.append(sep).append(param);
} else {
char c = param.charAt(0);
String expect = m.isSynthetic() ? ("arg" + i) : ((++c) + param);
param = p.getName();
sb.append(sep).append(param);
if (!expect.equals(param)) {
error(prefix + "param[" + i + "]='"
+ param + "' expected '" + expect + "'");
break;
}
}
sep = ", ";
}
if (m.isSynthetic()) {
sb.append(")!!\n");
} else {
sb.append(")\n");
}
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters StaticMethods.java
* @run main Tester StaticMethods
*/
public class StaticMethods {
static public void empty() {}
static final void def(Object a, final Object ba, final String... cba) { }
static final public void pub(Object d, final Object ed, final String... fed) { }
static protected boolean prot(Object g, final Object hg, final String... ihg) { return true; }
static private boolean priv(Object j, final Object kj, final String... lkj) { return true; }
static void def(int a, Object ba, final Object cba, final String... dcba) { }
static public void pub(int a, Object ba, final Object cba , final String... dcba) { }
static final protected boolean prot(int aa, Object baa, final Object cbaa, final String... dcbaa) { return true; }
static final private boolean priv(int abc, Object babc, final Object cbabc, final String... dcbabc) { return true; }
}

View file

@ -0,0 +1,162 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.*;
import java.util.*;
import java.lang.reflect.Constructor;
/**
* Test driver for MethodParameters testing.
* <p>
* The intended use of this driver is to run it, giving the name of
* a single class compiled with -parameters as argument. The driver
* will test the specified class, and any nested classes it finds.
* <p>
* Each class is tested in two way. By refelction, and by directly
* checking MethodParameters attributes in the classfile. The checking
* is done using two visitor classes {@link ClassFileVisitor} and
* {@link ReflectionVisitor}.
* <p>
* The {@code ReflectionVisitor} test logically belongs with library tests.
* we wish to reuse the same test-cases, so both test are committed together,
* under langtools. The tests, may be duplicated in the jdk repository.
*/
public class Tester {
final static File classesdir = new File(System.getProperty("test.classes", "."));
/**
* The visitor classes that does the actual checking are referenced
* statically, to force compilations, without having to reference
* them in individual test cases.
* <p>
* This makes it easy to change the set of visitors, without
* complicating the design with dynamic discovery and compilation
* of visitor classes.
*/
static final Class visitors[] = {
ClassFileVisitor.class,
ReflectionVisitor.class
};
/**
* Test-driver expect a single classname as argument.
*/
public static void main(String... args) throws Exception {
if (args.length != 1) {
throw new Error("A single class name is expected as argument");
}
final String pattern = args[0] + ".*\\.class";
File files[] = classesdir.listFiles(new FileFilter() {
public boolean accept(File f) {
return f.getName().matches(pattern);
}
});
if (files.length == 0) {
File file = new File(classesdir, args[0] + ".class");
throw new Error(file.getPath() + " not found");
}
new Tester(args[0], files).run();
}
public Tester(String name, File files[]) {
this.classname = name;
this.files = files;
}
void run() throws Exception {
// Test with each visitor
for (Class<Visitor> vclass : visitors) {
try {
String vname = vclass.getName();
Constructor c = vclass.getConstructor(Tester.class);
info("\nRun " + vname + " for " + classname + "\n");
StringBuilder sb = new StringBuilder();
for (File f : files) {
String fname = f.getName();
fname = fname.substring(0, fname.length() - 6);
Visitor v = (Visitor) c.newInstance(this);
try {
v.visitClass(fname, f, sb);
} catch(Exception e) {
error("Uncaught exception in visitClass()");
e.printStackTrace();
}
}
info(sb.toString());
} catch(ReflectiveOperationException e) {
warn("Class " + vclass.getName() + " ignored, not a Visitor");
continue;
}
}
if(0 != warnings)
System.err.println("Test generated " + warnings + " warnings");
if(0 != errors)
throw new Exception("Tester test failed with " +
errors + " errors");
}
abstract static class Visitor {
Tester tester;
File classesdir;
public Visitor(Tester tester) {
this.tester = tester;
}
abstract void visitClass(final String classname, final File cfile,
final StringBuilder sb) throws Exception;
public void error(String msg) {
tester.error(msg);
}
public void warn(String msg) {
tester.warn(msg);
}
}
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
void warn(String msg) {
System.err.println("Warning: " + msg);
warnings++;
}
void info(String msg) {
System.out.println(msg);
}
int errors;
int warnings;
String classname;
File files[];
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006582
* @summary javac should generate method parameters correctly.
* @build Tester
* @compile -parameters UncommonParamNames.java
* @run main Tester UncommonParamNames
*/
/** Test uncommon parameter names */
class UncommonParamNames {
public UncommonParamNames(int _x) { }
public UncommonParamNames(short $1) { }
public UncommonParamNames(long \u0061) { }
public UncommonParamNames(char zero\u0000zero\u0000) { }
public UncommonParamNames(String zero\u0000zero\u0000seven\u0007) { }
public UncommonParamNames(Object zero\u0000zero\u0000eight\u0008) { }
public UncommonParamNames(Object aLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName,
Object baLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName,
Object cbaLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName) { }
public UncommonParamNames(int a, int ba, int cba, int dcba, int edcba, int fedcba, int gfedcba,
int hgfedcba, int ihgfedcba, int jihgfedcba, int kjihgfedcba, int lkjihgfedcba,
int mlkjihgfedcba, int nmlkjihgfedcba, int onmlkjihgfedcba, int ponmlkjihgfedcba,
int qponmlkjihgfedcba, int rqponmlkjihgfedcba, int srqponmlkjihgfedcba,
int tsrqponmlkjihgfedcba, int utsrqponmlkjihgfedcba, int vutsrqponmlkjihgfedcba,
int wvutsrqponmlkjihgfedcba, int xwvutsrqponmlkjihgfedcba,
int yxwvutsrqponmlkjihgfedcba, int zyxwvutsrqponmlkjihgfedcba) { }
public void foo(int _x) { }
public void foo(short $1) { }
public void foo(long \u0061) { }
public void foo(char zero\u0000zero\u0000) { }
public void foo(String zero\u0000zero\u0000seven\u0007) { }
public void foo(Object zero\u0000zero\u0000eight\u0008) { }
public void foo(Object aLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName,
Object baLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName,
Object cbaLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName) { }
public void foo(int a, int ba, int cba, int dcba, int edcba, int fedcba, int gfedcba,
int hgfedcba, int ihgfedcba, int jihgfedcba, int kjihgfedcba, int lkjihgfedcba,
int mlkjihgfedcba, int nmlkjihgfedcba, int onmlkjihgfedcba, int ponmlkjihgfedcba,
int qponmlkjihgfedcba, int rqponmlkjihgfedcba, int srqponmlkjihgfedcba,
int tsrqponmlkjihgfedcba, int utsrqponmlkjihgfedcba, int vutsrqponmlkjihgfedcba,
int wvutsrqponmlkjihgfedcba, int xwvutsrqponmlkjihgfedcba,
int yxwvutsrqponmlkjihgfedcba, int zyxwvutsrqponmlkjihgfedcba) { }
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,7 +37,7 @@ import java.io.*;
import javax.lang.model.element.*;
import java.util.*;
public class MethodParameters {
public class MethodParametersTest {
static final String Foo_name = "Foo";
static final String Foo_contents =
@ -66,7 +66,7 @@ public class MethodParameters {
static final File classesdir = new File("methodparameters");
public static void main(String... args) throws Exception {
new MethodParameters().run();
new MethodParametersTest().run();
}
void run() throws Exception {