8004727: Add compiler support for parameter reflection

Sat, 29 Dec 2012 17:33:17 -0800

author
jjg
date
Sat, 29 Dec 2012 17:33:17 -0800
changeset 1473
31780dd06ec7
parent 1472
0c244701188e
child 1474
383bc0fbd759

8004727: Add compiler support for parameter reflection
Reviewed-by: jjg
Contributed-by: eric.mccorkle@oracle.com

src/share/classes/com/sun/tools/classfile/Attribute.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/classfile/ClassWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Symbol.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/jvm/ClassReader.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/main/Option.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/resources/javac.properties file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/Names.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/AttributeWriter.java file | annotate | diff | comparison | revisions
test/tools/javac/MethodParameters.java file | annotate | diff | comparison | revisions
test/tools/javap/MethodParameters.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/classfile/Attribute.java	Fri Dec 28 22:25:21 2012 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/classfile/Attribute.java	Sat Dec 29 17:33:17 2012 -0800
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -51,6 +51,7 @@
    1.11      public static final String LineNumberTable          = "LineNumberTable";
    1.12      public static final String LocalVariableTable       = "LocalVariableTable";
    1.13      public static final String LocalVariableTypeTable   = "LocalVariableTypeTable";
    1.14 +    public static final String MethodParameters         = "MethodParameters";
    1.15      public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
    1.16      public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
    1.17      public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
    1.18 @@ -113,6 +114,7 @@
    1.19              standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class);
    1.20  
    1.21              if (!compat) { // old javap does not recognize recent attributes
    1.22 +                standardAttributes.put(MethodParameters, MethodParameters_attribute.class);
    1.23                  standardAttributes.put(CompilationID, CompilationID_attribute.class);
    1.24                  standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class);
    1.25                  standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
    1.26 @@ -171,6 +173,7 @@
    1.27          R visitLineNumberTable(LineNumberTable_attribute attr, P p);
    1.28          R visitLocalVariableTable(LocalVariableTable_attribute attr, P p);
    1.29          R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p);
    1.30 +        R visitMethodParameters(MethodParameters_attribute attr, P p);
    1.31          R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p);
    1.32          R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
    1.33          R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
     2.1 --- a/src/share/classes/com/sun/tools/classfile/ClassWriter.java	Fri Dec 28 22:25:21 2012 -0800
     2.2 +++ b/src/share/classes/com/sun/tools/classfile/ClassWriter.java	Sat Dec 29 17:33:17 2012 -0800
     2.3 @@ -1,6 +1,6 @@
     2.4  
     2.5  /*
     2.6 - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
     2.7 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
     2.8   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.9   *
    2.10   * This code is free software; you can redistribute it and/or modify it
    2.11 @@ -479,6 +479,15 @@
    2.12              out.writeShort(entry.index);
    2.13          }
    2.14  
    2.15 +        public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) {
    2.16 +            out.writeByte(attr.method_parameter_table.length);
    2.17 +            for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {
    2.18 +                out.writeShort(e.name_index);
    2.19 +                out.writeInt(e.flags);
    2.20 +            }
    2.21 +            return null;
    2.22 +        }
    2.23 +
    2.24          public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
    2.25              annotationWriter.write(attr.annotations, out);
    2.26              return null;
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java	Sat Dec 29 17:33:17 2012 -0800
     3.3 @@ -0,0 +1,87 @@
     3.4 +/*
     3.5 + * Copyright (c) 2012, 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.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +
    3.29 +package com.sun.tools.classfile;
    3.30 +
    3.31 +import java.io.IOException;
    3.32 +
    3.33 +/**
    3.34 + * See JVMS, section 4.8.13.
    3.35 + *
    3.36 + *  <p><b>This is NOT part of any supported API.
    3.37 + *  If you write code that depends on this, you do so at your own risk.
    3.38 + *  This code and its internal interfaces are subject to change or
    3.39 + *  deletion without notice.</b>
    3.40 + */
    3.41 +public class MethodParameters_attribute extends Attribute {
    3.42 +
    3.43 +    public final int method_parameter_table_length;
    3.44 +    public final Entry[] method_parameter_table;
    3.45 +
    3.46 +    MethodParameters_attribute(ClassReader cr,
    3.47 +                              int name_index,
    3.48 +                              int length)
    3.49 +        throws IOException {
    3.50 +        super(name_index, length);
    3.51 +
    3.52 +        method_parameter_table_length = cr.readUnsignedByte();
    3.53 +        method_parameter_table = new Entry[method_parameter_table_length];
    3.54 +        for (int i = 0; i < method_parameter_table_length; i++)
    3.55 +            method_parameter_table[i] = new Entry(cr);
    3.56 +    }
    3.57 +
    3.58 +    public MethodParameters_attribute(ConstantPool constant_pool,
    3.59 +                                      Entry[] method_parameter_table)
    3.60 +        throws ConstantPoolException {
    3.61 +        this(constant_pool.getUTF8Index(Attribute.MethodParameters),
    3.62 +             method_parameter_table);
    3.63 +    }
    3.64 +
    3.65 +    public MethodParameters_attribute(int name_index,
    3.66 +                                      Entry[] method_parameter_table) {
    3.67 +        super(name_index, 1 + method_parameter_table.length * Entry.length());
    3.68 +        this.method_parameter_table_length = method_parameter_table.length;
    3.69 +        this.method_parameter_table = method_parameter_table;
    3.70 +    }
    3.71 +
    3.72 +    public <R, D> R accept(Visitor<R, D> visitor, D data) {
    3.73 +        return visitor.visitMethodParameters(this, data);
    3.74 +    }
    3.75 +
    3.76 +    public static class Entry {
    3.77 +        Entry(ClassReader cr) throws IOException {
    3.78 +            name_index = cr.readUnsignedShort();
    3.79 +            flags = cr.readInt();
    3.80 +        }
    3.81 +
    3.82 +        public static int length() {
    3.83 +            return 6;
    3.84 +        }
    3.85 +
    3.86 +        public final int name_index;
    3.87 +        public final int flags;
    3.88 +    }
    3.89 +
    3.90 +}
     4.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Dec 28 22:25:21 2012 -0800
     4.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Sat Dec 29 17:33:17 2012 -0800
     4.3 @@ -1283,8 +1283,9 @@
     4.4                  List<Name> paramNames = savedParameterNames;
     4.5                  savedParameterNames = null;
     4.6                  // discard the provided names if the list of names is the wrong size.
     4.7 -                if (paramNames == null || paramNames.size() != type.getParameterTypes().size())
     4.8 +                if (paramNames == null || paramNames.size() != type.getParameterTypes().size()) {
     4.9                      paramNames = List.nil();
    4.10 +                }
    4.11                  ListBuffer<VarSymbol> buf = new ListBuffer<VarSymbol>();
    4.12                  List<Name> remaining = paramNames;
    4.13                  // assert: remaining and paramNames are both empty or both
     5.1 --- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Dec 28 22:25:21 2012 -0800
     5.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Sat Dec 29 17:33:17 2012 -0800
     5.3 @@ -217,6 +217,13 @@
     5.4       */
     5.5      boolean haveParameterNameIndices;
     5.6  
     5.7 +    /** Set this to false every time we start reading a method
     5.8 +     * and are saving parameter names.  Set it to true when we see
     5.9 +     * MethodParameters, if it's set when we see a LocalVariableTable,
    5.10 +     * then we ignore the parameter names from the LVT.
    5.11 +     */
    5.12 +    boolean sawMethodParameters;
    5.13 +
    5.14      /**
    5.15       * The set of attribute names for which warnings have been generated for the current class
    5.16       */
    5.17 @@ -984,7 +991,7 @@
    5.18              new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
    5.19                  protected void read(Symbol sym, int attrLen) {
    5.20                      int newbp = bp + attrLen;
    5.21 -                    if (saveParameterNames) {
    5.22 +                    if (saveParameterNames && !sawMethodParameters) {
    5.23                          // Pick up parameter names from the variable table.
    5.24                          // Parameter names are not explicitly identified as such,
    5.25                          // but all parameter name entries in the LocalVariableTable
    5.26 @@ -1017,6 +1024,25 @@
    5.27                  }
    5.28              },
    5.29  
    5.30 +            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
    5.31 +                protected void read(Symbol sym, int attrlen) {
    5.32 +                    int newbp = bp + attrlen;
    5.33 +                    if (saveParameterNames) {
    5.34 +                        sawMethodParameters = true;
    5.35 +                        int numEntries = nextByte();
    5.36 +                        parameterNameIndices = new int[numEntries];
    5.37 +                        haveParameterNameIndices = true;
    5.38 +                        for (int i = 0; i < numEntries; i++) {
    5.39 +                            int nameIndex = nextChar();
    5.40 +                            int flags = nextInt();
    5.41 +                            parameterNameIndices[i] = nameIndex;
    5.42 +                        }
    5.43 +                    }
    5.44 +                    bp = newbp;
    5.45 +                }
    5.46 +            },
    5.47 +
    5.48 +
    5.49              new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
    5.50                  protected void read(Symbol sym, int attrLen) {
    5.51                      ClassSymbol c = (ClassSymbol) sym;
    5.52 @@ -1826,6 +1852,7 @@
    5.53          } else
    5.54              Arrays.fill(parameterNameIndices, 0);
    5.55          haveParameterNameIndices = false;
    5.56 +        sawMethodParameters = false;
    5.57      }
    5.58  
    5.59      /**
    5.60 @@ -1845,12 +1872,16 @@
    5.61          // if no names were found in the class file, there's nothing more to do
    5.62          if (!haveParameterNameIndices)
    5.63              return;
    5.64 -
    5.65 -        int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
    5.66 -        // the code in readMethod may have skipped the first parameter when
    5.67 -        // setting up the MethodType. If so, we make a corresponding allowance
    5.68 -        // here for the position of the first parameter.  Note that this
    5.69 -        // assumes the skipped parameter has a width of 1 -- i.e. it is not
    5.70 +        // If we get parameter names from MethodParameters, then we
    5.71 +        // don't need to skip.
    5.72 +        int firstParam = 0;
    5.73 +        if (!sawMethodParameters) {
    5.74 +            firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
    5.75 +            // the code in readMethod may have skipped the first
    5.76 +            // parameter when setting up the MethodType. If so, we
    5.77 +            // make a corresponding allowance here for the position of
    5.78 +            // the first parameter.  Note that this assumes the
    5.79 +            // skipped parameter has a width of 1 -- i.e. it is not
    5.80          // a double width type (long or double.)
    5.81          if (sym.name == names.init && currentOwner.hasOuterInstance()) {
    5.82              // Sometimes anonymous classes don't have an outer
    5.83 @@ -1861,17 +1892,20 @@
    5.84          }
    5.85  
    5.86          if (sym.type != jvmType) {
    5.87 -            // reading the method attributes has caused the symbol's type to
    5.88 -            // be changed. (i.e. the Signature attribute.)  This may happen if
    5.89 -            // there are hidden (synthetic) parameters in the descriptor, but
    5.90 -            // not in the Signature.  The position of these hidden parameters
    5.91 -            // is unspecified; for now, assume they are at the beginning, and
    5.92 -            // so skip over them. The primary case for this is two hidden
    5.93 -            // parameters passed into Enum constructors.
    5.94 +                // reading the method attributes has caused the
    5.95 +                // symbol's type to be changed. (i.e. the Signature
    5.96 +                // attribute.)  This may happen if there are hidden
    5.97 +                // (synthetic) parameters in the descriptor, but not
    5.98 +                // in the Signature.  The position of these hidden
    5.99 +                // parameters is unspecified; for now, assume they are
   5.100 +                // at the beginning, and so skip over them. The
   5.101 +                // primary case for this is two hidden parameters
   5.102 +                // passed into Enum constructors.
   5.103              int skip = Code.width(jvmType.getParameterTypes())
   5.104                      - Code.width(sym.type.getParameterTypes());
   5.105              firstParam += skip;
   5.106          }
   5.107 +        }
   5.108          List<Name> paramNames = List.nil();
   5.109          int index = firstParam;
   5.110          for (Type t: sym.type.getParameterTypes()) {
     6.1 --- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Dec 28 22:25:21 2012 -0800
     6.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Sat Dec 29 17:33:17 2012 -0800
     6.3 @@ -725,6 +725,28 @@
     6.4          return acount;
     6.5      }
     6.6  
     6.7 +    /**
     6.8 +     * Write method parameter names attribute.
     6.9 +     */
    6.10 +    int writeMethodParametersAttr(MethodSymbol m) {
    6.11 +        if (m.params != null && 0 != m.params.length()) {
    6.12 +            int attrIndex = writeAttr(names.MethodParameters);
    6.13 +            databuf.appendByte(m.params.length());
    6.14 +            for (VarSymbol s : m.params) {
    6.15 +                // TODO: expand to cover synthesized, once we figure out
    6.16 +                // how to represent that.
    6.17 +                final int flags = (int) s.flags() & (FINAL | SYNTHETIC);
    6.18 +                // output parameter info
    6.19 +                databuf.appendChar(pool.put(s.name));
    6.20 +                databuf.appendInt(flags);
    6.21 +            }
    6.22 +            endAttr(attrIndex);
    6.23 +            return 1;
    6.24 +        } else
    6.25 +            return 0;
    6.26 +    }
    6.27 +
    6.28 +
    6.29      /** Write method parameter annotations;
    6.30       *  return number of attributes written.
    6.31       */
    6.32 @@ -1034,6 +1056,8 @@
    6.33              endAttr(alenIdx);
    6.34              acount++;
    6.35          }
    6.36 +        if (options.isSet(PARAMETERS))
    6.37 +            acount += writeMethodParametersAttr(m);
    6.38          acount += writeMemberAttrs(m);
    6.39          acount += writeParameterAttrs(m);
    6.40          endAttrs(acountIdx, acount);
     7.1 --- a/src/share/classes/com/sun/tools/javac/main/Option.java	Fri Dec 28 22:25:21 2012 -0800
     7.2 +++ b/src/share/classes/com/sun/tools/javac/main/Option.java	Sat Dec 29 17:33:17 2012 -0800
     7.3 @@ -176,6 +176,8 @@
     7.4  
     7.5      PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER),
     7.6  
     7.7 +    PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC),
     7.8 +
     7.9      D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER),
    7.10  
    7.11      S("-s", "opt.arg.directory", "opt.sourceDest", STANDARD, FILEMANAGER),
     8.1 --- a/src/share/classes/com/sun/tools/javac/resources/javac.properties	Fri Dec 28 22:25:21 2012 -0800
     8.2 +++ b/src/share/classes/com/sun/tools/javac/resources/javac.properties	Sat Dec 29 17:33:17 2012 -0800
     8.3 @@ -55,6 +55,8 @@
     8.4      Specify where to find annotation processors
     8.5  javac.opt.processor=\
     8.6      Names of the annotation processors to run; bypasses default discovery process
     8.7 +javac.opt.parameters=\
     8.8 +    Generate metadata for reflection on method parameters
     8.9  javac.opt.proc.none.only=\
    8.10      Control whether annotation processing and/or compilation is done.
    8.11  javac.opt.d=\
     9.1 --- a/src/share/classes/com/sun/tools/javac/util/Names.java	Fri Dec 28 22:25:21 2012 -0800
     9.2 +++ b/src/share/classes/com/sun/tools/javac/util/Names.java	Sat Dec 29 17:33:17 2012 -0800
     9.3 @@ -132,6 +132,7 @@
     9.4      public final Name LineNumberTable;
     9.5      public final Name LocalVariableTable;
     9.6      public final Name LocalVariableTypeTable;
     9.7 +    public final Name MethodParameters;
     9.8      public final Name RuntimeInvisibleAnnotations;
     9.9      public final Name RuntimeInvisibleParameterAnnotations;
    9.10      public final Name RuntimeInvisibleTypeAnnotations;
    9.11 @@ -265,6 +266,7 @@
    9.12          LineNumberTable = fromString("LineNumberTable");
    9.13          LocalVariableTable = fromString("LocalVariableTable");
    9.14          LocalVariableTypeTable = fromString("LocalVariableTypeTable");
    9.15 +        MethodParameters = fromString("MethodParameters");
    9.16          RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
    9.17          RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
    9.18          RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
    10.1 --- a/src/share/classes/com/sun/tools/javap/AttributeWriter.java	Fri Dec 28 22:25:21 2012 -0800
    10.2 +++ b/src/share/classes/com/sun/tools/javap/AttributeWriter.java	Sat Dec 29 17:33:17 2012 -0800
    10.3 @@ -1,5 +1,5 @@
    10.4  /*
    10.5 - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
    10.6 + * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
    10.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.8   *
    10.9   * This code is free software; you can redistribute it and/or modify it
   10.10 @@ -46,6 +46,7 @@
   10.11  import com.sun.tools.classfile.LineNumberTable_attribute;
   10.12  import com.sun.tools.classfile.LocalVariableTable_attribute;
   10.13  import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
   10.14 +import com.sun.tools.classfile.MethodParameters_attribute;
   10.15  import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
   10.16  import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
   10.17  import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
   10.18 @@ -386,6 +387,28 @@
   10.19          return null;
   10.20      }
   10.21  
   10.22 +    private static final String format = "%-31s%s";
   10.23 +
   10.24 +    public Void visitMethodParameters(MethodParameters_attribute attr,
   10.25 +                                      Void ignore) {
   10.26 +
   10.27 +        final String header = String.format(format, "Name", "Flags");
   10.28 +        println("MethodParameters:");
   10.29 +        indent(+1);
   10.30 +        println(header);
   10.31 +        for (MethodParameters_attribute.Entry entry :
   10.32 +                 attr.method_parameter_table) {
   10.33 +            String flagstr =
   10.34 +                (0 != (entry.flags & ACC_FINAL) ? " final" : "") +
   10.35 +                (0 != (entry.flags & ACC_SYNTHETIC) ? " synthetic" : "");
   10.36 +            println(String.format(format,
   10.37 +                                  constantWriter.stringValue(entry.name_index),
   10.38 +                                  flagstr));
   10.39 +        }
   10.40 +        indent(-1);
   10.41 +        return null;
   10.42 +    }
   10.43 +
   10.44      public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) {
   10.45          println("RuntimeVisibleAnnotations:");
   10.46          indent(+1);
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/test/tools/javac/MethodParameters.java	Sat Dec 29 17:33:17 2012 -0800
    11.3 @@ -0,0 +1,343 @@
    11.4 +/*
    11.5 + * Copyright (c) 2012, 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 + * @summary javac should generate method parameters correctly.
   11.30 + */
   11.31 +// key: opt.arg.parameters
   11.32 +import com.sun.tools.classfile.*;
   11.33 +import com.sun.tools.javac.file.JavacFileManager;
   11.34 +import com.sun.tools.javac.main.Main;
   11.35 +import com.sun.tools.javac.util.Context;
   11.36 +import com.sun.tools.javac.util.Name;
   11.37 +import com.sun.tools.javac.util.Names;
   11.38 +import java.io.*;
   11.39 +import javax.lang.model.element.*;
   11.40 +import java.util.*;
   11.41 +
   11.42 +public class MethodParameters {
   11.43 +
   11.44 +    static final String Foo_name = "Foo";
   11.45 +    static final String Foo_contents =
   11.46 +        "public class Foo {\n" +
   11.47 +        "  Foo() {}\n" +
   11.48 +        "  void foo0() {}\n" +
   11.49 +        "  void foo2(int j, int k) {}\n" +
   11.50 +        "}";
   11.51 +    static final String Bar_name = "Bar";
   11.52 +    static final String Bar_contents =
   11.53 +        "public class Bar {\n" +
   11.54 +        "  Bar(int i) {}" +
   11.55 +        "  Foo foo() { return new Foo(); }\n" +
   11.56 +        "}";
   11.57 +    static final String Baz_name = "Baz";
   11.58 +    static final String Baz_contents =
   11.59 +        "public class Baz {\n" +
   11.60 +        "  int baz;" +
   11.61 +        "  Baz(int i) {}" +
   11.62 +        "}";
   11.63 +    static final String Qux_name = "Qux";
   11.64 +    static final String Qux_contents =
   11.65 +        "public class Qux extends Baz {\n" +
   11.66 +        "  Qux(int i) { super(i); }" +
   11.67 +        "}";
   11.68 +    static final File classesdir = new File("methodparameters");
   11.69 +
   11.70 +    public static void main(String... args) throws Exception {
   11.71 +        new MethodParameters().run();
   11.72 +    }
   11.73 +
   11.74 +    void run() throws Exception {
   11.75 +        classesdir.mkdir();
   11.76 +        final File Foo_java =
   11.77 +            writeFile(classesdir, Foo_name + ".java", Foo_contents);
   11.78 +        final File Bar_java =
   11.79 +            writeFile(classesdir, Bar_name + ".java", Bar_contents);
   11.80 +        final File Baz_java =
   11.81 +            writeFile(classesdir, Baz_name + ".java", Baz_contents);
   11.82 +        System.err.println("Test compile with -parameter");
   11.83 +        compile("-parameters", "-d", classesdir.getPath(), Foo_java.getPath());
   11.84 +        // First test: make sure javac doesn't choke to death on
   11.85 +        // MethodParameter attributes
   11.86 +        System.err.println("Test compile with classfile containing MethodParameter attributes");
   11.87 +        compile("-parameters", "-d", classesdir.getPath(),
   11.88 +                "-cp", classesdir.getPath(), Bar_java.getPath());
   11.89 +        System.err.println("Examine class foo");
   11.90 +        checkFoo();
   11.91 +        checkBar();
   11.92 +        System.err.println("Test debug information conflict");
   11.93 +        compile("-g", "-parameters", "-d", classesdir.getPath(),
   11.94 +                "-cp", classesdir.getPath(), Baz_java.getPath());
   11.95 +        System.err.println("Introducing debug information conflict");
   11.96 +        Baz_java.delete();
   11.97 +        modifyBaz(false);
   11.98 +        System.err.println("Checking language model");
   11.99 +        inspectBaz();
  11.100 +        System.err.println("Permuting attributes");
  11.101 +        modifyBaz(true);
  11.102 +        System.err.println("Checking language model");
  11.103 +        inspectBaz();
  11.104 +
  11.105 +        if(0 != errors)
  11.106 +            throw new Exception("MethodParameters test failed with " +
  11.107 +                                errors + " errors");
  11.108 +    }
  11.109 +
  11.110 +    void inspectBaz() throws Exception {
  11.111 +        final File Qux_java =
  11.112 +            writeFile(classesdir, Qux_name + ".java", Qux_contents);
  11.113 +        final String[] args = { "-XDsave-parameter-names", "-d",
  11.114 +                                classesdir.getPath(),
  11.115 +                                "-cp", classesdir.getPath(),
  11.116 +                                Qux_java.getPath() };
  11.117 +        final StringWriter sw = new StringWriter();
  11.118 +        final PrintWriter pw = new PrintWriter(sw);
  11.119 +
  11.120 +        // We need to be able to crack open javac and look at its data
  11.121 +        // structures.  We'll rig up a compiler instance, but keep its
  11.122 +        // Context, thus allowing us to get at the ClassReader.
  11.123 +        Context context = new Context();
  11.124 +        Main comp =  new Main("javac", pw);
  11.125 +        JavacFileManager.preRegister(context);
  11.126 +
  11.127 +        // Compile Qux, which uses Baz.
  11.128 +        comp.compile(args, context);
  11.129 +        pw.close();
  11.130 +        final String out = sw.toString();
  11.131 +        if (out.length() > 0)
  11.132 +            System.err.println(out);
  11.133 +
  11.134 +        // Now get the class reader, construct a name for Baz, and load it.
  11.135 +        com.sun.tools.javac.jvm.ClassReader cr =
  11.136 +            com.sun.tools.javac.jvm.ClassReader.instance(context);
  11.137 +        Name name = Names.instance(context).fromString(Baz_name);
  11.138 +
  11.139 +        // Now walk down the language model and check the name of the
  11.140 +        // parameter.
  11.141 +        final Element baz = cr.loadClass(name);
  11.142 +        for (Element e : baz.getEnclosedElements()) {
  11.143 +            if (e instanceof ExecutableElement) {
  11.144 +                final ExecutableElement ee = (ExecutableElement) e;
  11.145 +                final List<? extends VariableElement> params =
  11.146 +                    ee.getParameters();
  11.147 +                if (1 != params.size())
  11.148 +                    throw new Exception("Classfile Baz badly formed: wrong number of methods");
  11.149 +                final VariableElement param = params.get(0);
  11.150 +                if (!param.getSimpleName().contentEquals("baz")) {
  11.151 +                    errors++;
  11.152 +                    System.err.println("javac did not correctly resolve the metadata conflict, parameter's name reads as " + param.getSimpleName());
  11.153 +                } else
  11.154 +                    System.err.println("javac did correctly resolve the metadata conflict");
  11.155 +            }
  11.156 +        }
  11.157 +    }
  11.158 +
  11.159 +    void modifyBaz(boolean flip) throws Exception {
  11.160 +        final File Baz_class = new File(classesdir, Baz_name + ".class");
  11.161 +        final ClassFile baz = ClassFile.read(Baz_class);
  11.162 +        final int ind = baz.constant_pool.getUTF8Index("baz");
  11.163 +        MethodParameters_attribute mpattr = null;
  11.164 +        int mpind = 0;
  11.165 +        Code_attribute cattr = null;
  11.166 +        int cind = 0;
  11.167 +
  11.168 +        // Find the indexes of the MethodParameters and the Code attributes
  11.169 +        if (baz.methods.length != 1)
  11.170 +            throw new Exception("Classfile Baz badly formed: wrong number of methods");
  11.171 +        if (!baz.methods[0].getName(baz.constant_pool).equals("<init>"))
  11.172 +            throw new Exception("Classfile Baz badly formed: method has name " +
  11.173 +                                baz.methods[0].getName(baz.constant_pool));
  11.174 +        for (int i = 0; i < baz.methods[0].attributes.attrs.length; i++) {
  11.175 +            if (baz.methods[0].attributes.attrs[i] instanceof
  11.176 +                MethodParameters_attribute) {
  11.177 +                mpattr = (MethodParameters_attribute)
  11.178 +                    baz.methods[0].attributes.attrs[i];
  11.179 +                mpind = i;
  11.180 +            } else if (baz.methods[0].attributes.attrs[i] instanceof
  11.181 +                       Code_attribute) {
  11.182 +                cattr = (Code_attribute) baz.methods[0].attributes.attrs[i];
  11.183 +                cind = i;
  11.184 +            }
  11.185 +        }
  11.186 +        if (null == mpattr)
  11.187 +            throw new Exception("Classfile Baz badly formed: no method parameters info");
  11.188 +        if (null == cattr)
  11.189 +            throw new Exception("Classfile Baz badly formed: no local variable table");
  11.190 +
  11.191 +        int flags = mpattr.method_parameter_table[0].flags;
  11.192 +
  11.193 +        // Alter the MethodParameters attribute, changing the name of
  11.194 +        // the parameter from i to baz.  This requires Black Magic...
  11.195 +        //
  11.196 +        // The (well-designed) classfile library (correctly) does not
  11.197 +        // allow us to mess around with the attribute data structures,
  11.198 +        // or arbitrarily generate new ones.
  11.199 +        //
  11.200 +        // Instead, we install a new subclass of Attribute that
  11.201 +        // hijacks the Visitor pattern and outputs the sequence of
  11.202 +        // bytes that we want.  This only works in this particular
  11.203 +        // instance, because we know we'll only every see one kind of
  11.204 +        // visitor.
  11.205 +        //
  11.206 +        // If anyone ever changes the makeup of the Baz class, or
  11.207 +        // tries to install some kind of visitor that gets run prior
  11.208 +        // to serialization, this will break.
  11.209 +        baz.methods[0].attributes.attrs[mpind] =
  11.210 +            new Attribute(mpattr.attribute_name_index,
  11.211 +                          mpattr.attribute_length) {
  11.212 +                public <R, D> R accept(Visitor<R, D> visitor, D data) {
  11.213 +                    if (data instanceof ByteArrayOutputStream) {
  11.214 +                        ByteArrayOutputStream out =
  11.215 +                            (ByteArrayOutputStream) data;
  11.216 +                        out.write(1);
  11.217 +                        out.write((ind >> 8) & 0xff);
  11.218 +                        out.write(ind & 0xff);
  11.219 +                        out.write((flags >> 24) & 0xff);
  11.220 +                        out.write((flags >> 16) & 0xff);
  11.221 +                        out.write((flags >> 8) & 0xff);
  11.222 +                        out.write(flags & 0xff);
  11.223 +                    } else
  11.224 +                        throw new RuntimeException("Output stream is of type " + data.getClass() + ", which is not handled by this test.  Update the test and it should work.");
  11.225 +                    return null;
  11.226 +                }
  11.227 +            };
  11.228 +
  11.229 +        // Flip the code and method attributes.  This is for checking
  11.230 +        // that order doesn't matter.
  11.231 +        if (flip) {
  11.232 +            baz.methods[0].attributes.attrs[mpind] = cattr;
  11.233 +            baz.methods[0].attributes.attrs[cind] = mpattr;
  11.234 +        }
  11.235 +
  11.236 +        new ClassWriter().write(baz, Baz_class);
  11.237 +    }
  11.238 +
  11.239 +    // Run a bunch of structural tests on foo to make sure it looks right.
  11.240 +    void checkFoo() throws Exception {
  11.241 +        final File Foo_class = new File(classesdir, Foo_name + ".class");
  11.242 +        final ClassFile foo = ClassFile.read(Foo_class);
  11.243 +        for (int i = 0; i < foo.methods.length; i++) {
  11.244 +            System.err.println("Examine method Foo." + foo.methods[i].getName(foo.constant_pool));
  11.245 +            if (foo.methods[i].getName(foo.constant_pool).equals("foo2")) {
  11.246 +                for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++)
  11.247 +                    if (foo.methods[i].attributes.attrs[j] instanceof
  11.248 +                        MethodParameters_attribute) {
  11.249 +                        MethodParameters_attribute mp =
  11.250 +                            (MethodParameters_attribute)
  11.251 +                            foo.methods[i].attributes.attrs[j];
  11.252 +                        System.err.println("Foo.foo2 should have 2 parameters: j and k");
  11.253 +                        if (2 != mp.method_parameter_table_length)
  11.254 +                            error("expected 2 method parameter entries in foo2, got " +
  11.255 +                                  mp.method_parameter_table_length);
  11.256 +                        else if (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("j"))
  11.257 +                            error("expected first parameter to foo2 to be \"j\", got \"" +
  11.258 +                                  foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) +
  11.259 +                                  "\" instead");
  11.260 +                        else if  (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index).equals("k"))
  11.261 +                            error("expected first parameter to foo2 to be \"k\", got \"" +
  11.262 +                                  foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index) +
  11.263 +                                  "\" instead");
  11.264 +                    }
  11.265 +            }
  11.266 +            else if (foo.methods[i].getName(foo.constant_pool).equals("<init>")) {
  11.267 +                for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) {
  11.268 +                    if (foo.methods[i].attributes.attrs[j] instanceof
  11.269 +                        MethodParameters_attribute)
  11.270 +                        error("Zero-argument constructor shouldn't have MethodParameters");
  11.271 +                }
  11.272 +            }
  11.273 +            else if (foo.methods[i].getName(foo.constant_pool).equals("foo0")) {
  11.274 +                for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++)
  11.275 +                    if (foo.methods[i].attributes.attrs[j] instanceof
  11.276 +                        MethodParameters_attribute)
  11.277 +                        error("Zero-argument method shouldn't have MethodParameters");
  11.278 +            }
  11.279 +            else
  11.280 +                error("Unknown method " + foo.methods[i].getName(foo.constant_pool) + " showed up in class Foo");
  11.281 +        }
  11.282 +    }
  11.283 +
  11.284 +    // Run a bunch of structural tests on Bar to make sure it looks right.
  11.285 +    void checkBar() throws Exception {
  11.286 +        final File Bar_class = new File(classesdir, Bar_name + ".class");
  11.287 +        final ClassFile bar = ClassFile.read(Bar_class);
  11.288 +        for (int i = 0; i < bar.methods.length; i++) {
  11.289 +            System.err.println("Examine method Bar." + bar.methods[i].getName(bar.constant_pool));
  11.290 +            if (bar.methods[i].getName(bar.constant_pool).equals("<init>")) {
  11.291 +                for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++)
  11.292 +                    if (bar.methods[i].attributes.attrs[j] instanceof
  11.293 +                        MethodParameters_attribute) {
  11.294 +                        MethodParameters_attribute mp =
  11.295 +                            (MethodParameters_attribute)
  11.296 +                            bar.methods[i].attributes.attrs[j];
  11.297 +                        System.err.println("Bar constructor should have 1 parameter: i");
  11.298 +                        if (1 != mp.method_parameter_table_length)
  11.299 +                            error("expected 1 method parameter entries in constructor, got " +
  11.300 +                                  mp.method_parameter_table_length);
  11.301 +                        else if (!bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("i"))
  11.302 +                            error("expected first parameter to foo2 to be \"i\", got \"" +
  11.303 +                                  bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) +
  11.304 +                                  "\" instead");
  11.305 +                    }
  11.306 +            }
  11.307 +            else if (bar.methods[i].getName(bar.constant_pool).equals("foo")) {
  11.308 +                for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++) {
  11.309 +                    if (bar.methods[i].attributes.attrs[j] instanceof
  11.310 +                        MethodParameters_attribute)
  11.311 +                        error("Zero-argument constructor shouldn't have MethodParameters");
  11.312 +                }
  11.313 +            }
  11.314 +        }
  11.315 +    }
  11.316 +
  11.317 +    String compile(String... args) throws Exception {
  11.318 +        System.err.println("compile: " + Arrays.asList(args));
  11.319 +        StringWriter sw = new StringWriter();
  11.320 +        PrintWriter pw = new PrintWriter(sw);
  11.321 +        int rc = com.sun.tools.javac.Main.compile(args, pw);
  11.322 +        pw.close();
  11.323 +        String out = sw.toString();
  11.324 +        if (out.length() > 0)
  11.325 +            System.err.println(out);
  11.326 +        if (rc != 0)
  11.327 +            error("compilation failed, rc=" + rc);
  11.328 +        return out;
  11.329 +    }
  11.330 +
  11.331 +    File writeFile(File dir, String path, String body) throws IOException {
  11.332 +        File f = new File(dir, path);
  11.333 +        f.getParentFile().mkdirs();
  11.334 +        FileWriter out = new FileWriter(f);
  11.335 +        out.write(body);
  11.336 +        out.close();
  11.337 +        return f;
  11.338 +    }
  11.339 +
  11.340 +    void error(String msg) {
  11.341 +        System.err.println("Error: " + msg);
  11.342 +        errors++;
  11.343 +    }
  11.344 +
  11.345 +    int errors;
  11.346 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/test/tools/javap/MethodParameters.java	Sat Dec 29 17:33:17 2012 -0800
    12.3 @@ -0,0 +1,165 @@
    12.4 +/*
    12.5 + * Copyright (c) 2010, 2012, 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 +/*
   12.28 + * @test
   12.29 + * @summary javac should generate method parameters correctly.
   12.30 + */
   12.31 +
   12.32 +import java.io.*;
   12.33 +import java.util.*;
   12.34 +
   12.35 +public class MethodParameters {
   12.36 +
   12.37 +    static final String Foo_name = "Foo";
   12.38 +    static final String Foo_contents =
   12.39 +        ("public class Foo {\n" +
   12.40 +         "  Foo() {}\n" +
   12.41 +         "  Foo(int i) {}\n" +
   12.42 +         "  void foo0() {}\n" +
   12.43 +         "  void foo2(int j, int k) {}\n" +
   12.44 +         "}").replaceAll(" +", " ");
   12.45 +    static final String Init0_expected =
   12.46 +        ("  Foo();\n" +
   12.47 +         "    flags: \n" +
   12.48 +         "    Code:\n" +
   12.49 +         "      stack=1, locals=1, args_size=1\n" +
   12.50 +         "         0: aload_0       \n" +
   12.51 +         "         1: invokespecial #1                  // Method java/lang/Object.\"<init>\":()V\n" +
   12.52 +         "         4: return        \n" +
   12.53 +         "      LineNumberTable:\n" +
   12.54 +         "        line 2: 0").replaceAll(" +", " ");
   12.55 +    static final String Init1_expected =
   12.56 +        ("  Foo(int);\n" +
   12.57 +         "    flags: \n" +
   12.58 +         "    Code:\n" +
   12.59 +         "      stack=1, locals=2, args_size=2\n" +
   12.60 +         "         0: aload_0       \n" +
   12.61 +         "         1: invokespecial #1                  // Method java/lang/Object.\"<init>\":()V\n" +
   12.62 +         "         4: return        \n" +
   12.63 +         "      LineNumberTable:\n" +
   12.64 +         "        line 3: 0\n" +
   12.65 +         "    MethodParameters:\n" +
   12.66 +         "      Name                                Flags\n" +
   12.67 +         "      i").replaceAll(" +", " ");
   12.68 +    static final String foo0_expected =
   12.69 +        ("  void foo0();\n" +
   12.70 +         "    flags: \n" +
   12.71 +         "    Code:\n" +
   12.72 +         "      stack=0, locals=1, args_size=1\n" +
   12.73 +         "         0: return        \n" +
   12.74 +         "      LineNumberTable:\n" +
   12.75 +         "        line 4: 0").replaceAll(" +", " ");
   12.76 +    static final String foo2_expected =
   12.77 +        ("  void foo2(int, int);\n" +
   12.78 +         "    flags: \n" +
   12.79 +         "    Code:\n" +
   12.80 +         "      stack=0, locals=3, args_size=3\n" +
   12.81 +         "         0: return        \n" +
   12.82 +         "      LineNumberTable:\n" +
   12.83 +         "        line 5: 0\n" +
   12.84 +         "    MethodParameters:\n" +
   12.85 +         "      Name                                Flags\n" +
   12.86 +         "      j                              \n" +
   12.87 +         "      k").replaceAll(" +", " ");
   12.88 +
   12.89 +    static final File classesdir = new File("methodparameters");
   12.90 +    static final String separator = System.getProperty("line.separator");
   12.91 +
   12.92 +    public static void main(String... args) throws Exception {
   12.93 +        new MethodParameters().run();
   12.94 +    }
   12.95 +
   12.96 +    void run() throws Exception {
   12.97 +        classesdir.mkdir();
   12.98 +        final File Foo_java =
   12.99 +            writeFile(classesdir, Foo_name + ".java", Foo_contents);
  12.100 +        compile("-parameters", "-d", classesdir.getPath(), Foo_java.getPath());
  12.101 +        System.out.println("Run javap");
  12.102 +        String output =
  12.103 +            javap("-c", "-verbose", "-classpath",
  12.104 +                  classesdir.getPath(), Foo_name);
  12.105 +        String normalized =
  12.106 +            output.replaceAll(separator, "\n").replaceAll(" +", " ");
  12.107 +
  12.108 +        if (!normalized.contains(Init0_expected))
  12.109 +            error("Bad output for zero-parameter constructor.  Expected\n" +
  12.110 +                  Init0_expected + "\n" + "but got\n" + normalized);
  12.111 +        if (!normalized.contains(Init1_expected))
  12.112 +           error("Bad output for one-parameter constructor.  Expected\n" +
  12.113 +                 Init1_expected + "\n" + "but got\n" + normalized);
  12.114 +        if (!normalized.contains(foo0_expected))
  12.115 +           error("Bad output for zero-parameter method.  Expected\n" +
  12.116 +                 foo0_expected + "\n" + "but got\n" + normalized);
  12.117 +        if (!normalized.contains(foo2_expected))
  12.118 +           error("Bad output for two-parameter method  Expected\n" +
  12.119 +                 foo2_expected + "\n" + "but got\n" + normalized);
  12.120 +
  12.121 +        if (0 != errors)
  12.122 +            throw new Exception("MethodParameters test failed with " +
  12.123 +                                errors + " errors");
  12.124 +    }
  12.125 +
  12.126 +    String javap(String... args) {
  12.127 +        StringWriter sw = new StringWriter();
  12.128 +        PrintWriter out = new PrintWriter(sw);
  12.129 +        //sun.tools.javap.Main.entry(args);
  12.130 +        int rc = com.sun.tools.javap.Main.run(args, out);
  12.131 +        if (rc != 0)
  12.132 +            throw new Error("javap failed. rc=" + rc);
  12.133 +        out.close();
  12.134 +        System.out.println(sw);
  12.135 +        return sw.toString();
  12.136 +    }
  12.137 +
  12.138 +    String compile(String... args) throws Exception {
  12.139 +        System.err.println("compile: " + Arrays.asList(args));
  12.140 +        StringWriter sw = new StringWriter();
  12.141 +        PrintWriter pw = new PrintWriter(sw);
  12.142 +        int rc = com.sun.tools.javac.Main.compile(args, pw);
  12.143 +        pw.close();
  12.144 +        String out = sw.toString();
  12.145 +        if (out.length() > 0)
  12.146 +            System.err.println(out);
  12.147 +        if (rc != 0)
  12.148 +            error("compilation failed, rc=" + rc);
  12.149 +        return out;
  12.150 +    }
  12.151 +
  12.152 +    File writeFile(File dir, String path, String body) throws IOException {
  12.153 +        File f = new File(dir, path);
  12.154 +        f.getParentFile().mkdirs();
  12.155 +        FileWriter out = new FileWriter(f);
  12.156 +        out.write(body);
  12.157 +        out.close();
  12.158 +        return f;
  12.159 +    }
  12.160 +
  12.161 +    void error(String msg) {
  12.162 +        System.err.println("Error: " + msg);
  12.163 +        errors++;
  12.164 +    }
  12.165 +
  12.166 +    int errors;
  12.167 +
  12.168 +}

mercurial