test/tools/javac/MethodParameters/ReflectionVisitor.java

Mon, 16 Oct 2017 16:07:48 +0800

author
aoqi
date
Mon, 16 Oct 2017 16:07:48 +0800
changeset 2893
ca5783d9a597
parent 2733
7974f6da2d76
parent 2525
2eb010b6cb22
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 import java.io.*;
    25 import java.lang.reflect.*;
    27 /**
    28  * Test MethodParameter attributs by reflection API
    29  */
    30 public class ReflectionVisitor extends Tester.Visitor {
    32     public ReflectionVisitor(Tester tester) {
    33         super(tester);
    34     }
    36     public void error(String msg) {
    37         super.error("reflection: " + msg);
    38     }
    40     public void warn(String msg) {
    41         super.warn("reflection: " + msg);
    42     }
    44     boolean isEnum;
    45     boolean isInterface;
    46     boolean isAnon;
    47     boolean isLocal;
    48     boolean isMember;
    49     boolean isStatic;
    50     boolean isPublic;
    51     boolean isFinal;
    52     Class clazz;
    53     StringBuilder sb;
    55     /**
    56      * Read class using {@code ClassFile}, and generate a list of methods
    57      * with parameter names as available in the MethodParameters attribute.
    58      */
    59     void visitClass(final String cl, final File cfile, final StringBuilder sb)
    60         throws Exception {
    62         this.sb = sb;
    63         clazz = Class.forName(cl);
    64         isEnum = clazz.isEnum();
    65         isInterface = clazz.isInterface();
    66         isAnon = clazz.isAnonymousClass();
    67         isLocal = clazz.isLocalClass();
    68         isMember = clazz.isMemberClass();
    69         isStatic = ((clazz.getModifiers() & Modifier.STATIC) != 0);
    70         isPublic = ((clazz.getModifiers() & Modifier.PUBLIC) != 0);
    72         sb.append(isStatic ? "static " : "")
    73             .append(isPublic ? "public " : "")
    74             .append(isEnum ? "enum " : isInterface ? "interface " : "class ")
    75             .append(cl).append(" -- ")
    76             .append(isMember? "inner" : "" )
    77             .append(isLocal? "inner" : "" )
    78             .append(isAnon ?  "anon" : "")
    79             .append("\n");
    81         for (Constructor c : clazz.getDeclaredConstructors()) {
    82             testConstructor(c);
    83         }
    85         for (Method m :clazz.getDeclaredMethods()) {
    86             testMethod(m);
    87         }
    88     }
    90     void testConstructor(Constructor c) {
    92         String prefix = clazz.getName() + "." + c.getName() + "() - ";
    94         // Parameters must match parameter types
    95         Parameter params[] = c.getParameters();
    96         int paramTypes =  c.getParameterTypes().length;
    97         if (paramTypes != params.length) {
    98             error(prefix + "number of parameter types (" + paramTypes
    99                   + ") != number of parameters (" + params.length + ")");
   100             return;
   101         }
   103         sb.append(clazz.getName()).append(".").append("<init>").append("(");
   104         String sep = "";
   106         // Some paramters are expected
   107         if (params.length < 2 && isEnum) {
   108             error(prefix + "enum constuctor, two arguments expected");
   109         } else if (params.length < 1 && (isAnon || isLocal ||
   110                                          (isMember && !isStatic ))) {
   111             error(prefix + "class constuctor,expected implicit argument");
   112         }
   114         int i = -1;
   115         String param = null;
   116         for (Parameter p : c.getParameters()) {
   117             i++;
   118             String pname = p.getName();
   119             int pmodifier = p.getModifiers();
   120             isFinal = false;
   121             if (Modifier.isFinal(pmodifier)) {
   122                 isFinal = true;
   123                 pname = "final " + pname;
   124             }
   125             sb.append(sep).append(pname);
   126             if (p.isImplicit()) sb.append("/*implicit*/");
   127             if (p.isSynthetic()) sb.append("/*synthetic*/");
   128             sep = ", ";
   130             // Set expectations
   131             String expect = null;
   132             boolean allowImplicit = false;
   133             boolean allowSynthetic = false;
   134             if (isEnum) {
   135                 if (i == 0) {
   136                     expect = "\\$enum\\$name";
   137                     allowSynthetic = true;
   138                 } else if(i == 1) {
   139                     expect = "\\$enum\\$ordinal";
   140                     allowSynthetic = true;
   141                 }
   142             } else if (i == 0) {
   143                 if (isAnon) {
   144                     expect = "this\\$[0-9]+";
   145                     allowImplicit = true;
   146                     if (isFinal)
   147                         expect = "final this\\$[0-9]+";
   148                 } else if (isLocal) {
   149                     expect = "this\\$[0-9]+";
   150                     allowImplicit = true;
   151                     if (isFinal)
   152                         expect = "final this\\$[0-9]+";
   153                 } else if ((isMember && !isStatic)) {
   154                     expect = "this\\$[0-9]+";
   155                     allowImplicit = true;
   156                     if (!isPublic) {
   157                         // some but not all non-public inner classes
   158                         // have synthetic argument. For now we give
   159                         // the test a bit of slack and allow either.
   160                         allowSynthetic = true;
   161                     }
   162                     if (isFinal)
   163                         expect = "final this\\$[0-9]+";
   164                 }
   165             }
   167             // Check expected flags
   168             if (p.isSynthetic() && p.isImplicit()) {
   169                 error(prefix + "param[" + i + "]='" + pname +
   170                       "' both isImplicit() and isSynthetic()");
   171                 break;
   172             }
   173             if (allowImplicit && allowSynthetic &&
   174                 !(p.isSynthetic() || p.isImplicit())) {
   175                 error(prefix + "param[" + i + "]='" + pname +
   176                       "' isImplicit() or isSynthetic() expected");
   177                 break;
   178             }
   180             if (allowImplicit && !allowSynthetic && !p.isImplicit()) {
   181                 error(prefix + "param[" + i + "]='" + pname +
   182                       "' isImplicit() expected");
   183                 break;
   184             }
   185             if (!allowImplicit && allowSynthetic && !p.isSynthetic()) {
   186                 error(prefix + "param[" + i + "]='" + pname +
   187                       "' isSynthetic() expected");
   188                 break;
   189             }
   191             if (!allowImplicit && p.isImplicit()) {
   192                 error(prefix + "param[" + i + "]='" + pname +
   193                       "' isImplicit() unexpected");
   194                 break;
   195             }
   197             if (!allowSynthetic && p.isSynthetic()) {
   198                 error(prefix + "param[" + i + "]='" + pname +
   199                       "' isSynthetic() unexpected");
   200                 break;
   201             }
   203             // Check expected names
   204             if (expect != null) {
   205                 if (pname.matches(expect))  continue;
   206                 error(prefix + "param[" + i + "]='" + pname +
   207                       "' expected '" + expect + "'");
   208                 break;
   209             }
   211             // Test naming convention for explicit parameters.
   212             boolean fidelity = !isAnon;
   213             if (param != null && fidelity) {
   214                 char ch = param.charAt(0);
   215                 expect =  (++ch) + param;
   216             }
   217             if (isFinal && expect != null) {
   218                 expect = "final " + expect;
   219             }
   220             if (pname != null && fidelity) {
   221                 if (isFinal) {
   222                     param = pname.substring(6);
   223                 } else {
   224                 param = pname;
   225             }
   226             }
   227             if (expect != null && !expect.equals(pname)) {
   228                 error(prefix + "param[" + i + "]='" + pname +
   229                       "' expected '" + expect + "'");
   230                 break;
   231             }
   232         }
   233         if  (c.isSynthetic()) {
   234             sb.append(")/*synthetic*/\n");
   235         } else {
   236             sb.append(")\n");
   237         }
   238     }
   240     void testMethod(Method m) {
   242         String prefix = clazz.getName() + "." + m.getName() + "() - ";
   244         // Parameters must match parameter types
   245         int paramTypes =  m.getParameterTypes().length;
   246         int params = m.getParameters().length;
   247         if (paramTypes != params) {
   248             error(prefix + "number of parameter types (" + paramTypes
   249                   + ") != number of parameters (" + params + ")");
   250             return;
   251         }
   253         sb.append(clazz.getName()).append(".").append(m.getName()).append("(");
   254         String sep = "";
   255         String param = null;
   256         int i = -1;
   257         // For methods we expect all parameters to follow
   258         // the test-case design pattern, except synthetic methods.
   259         for (Parameter p : m.getParameters()) {
   260             i++;
   261             isFinal = false;
   262             int pmodifier = p.getModifiers();
   263             if (param == null) {
   264                 param = p.getName();
   265                 if (Modifier.isFinal(pmodifier)) {
   266                     isFinal = true;
   267                     param = "final " + param;
   268                 }
   269                 sb.append(sep).append(param);
   270             } else  {
   271                 char c = param.charAt(0);
   272                 String expect =  m.isSynthetic() ? ("arg" + i) : ((++c) + param);
   273                 param = p.getName();
   274                 if (Modifier.isFinal(pmodifier)) {
   275                     isFinal = true;
   276                     expect = "final " + expect;
   277                     param = "final " + param;
   278                 }
   279                 sb.append(sep).append(param);
   280                 if (!m.isBridge() && !m.getName().startsWith("lambda$") && !expect.equals(param)) {
   281                     error(prefix + "param[" + i + "]='"
   282                           + param + "' expected '" + expect + "'");
   283                     break;
   284                 }
   285             }
   286             if(isFinal)
   287                 param = param.substring(6);
   288             if (p.isImplicit()) {
   289                 sb.append("/*implicit*/");
   290             }
   291             if (p.isSynthetic()) {
   292                 sb.append("/*synthetic*/");
   293             }
   294             sep = ", ";
   295         }
   296         if  (m.isSynthetic()) {
   297             sb.append(")/*synthetic*/\n");
   298         } else {
   299             sb.append(")\n");
   300         }
   301     }
   302 }

mercurial