Thu, 07 Mar 2013 10:04:28 +0000
8009138: javac, equals-hashCode warning tuning
Reviewed-by: mcimadamore
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.util.*;
26 import java.net.*;
27 import java.lang.reflect.*;
29 /**
30 * Test MethodParameter attributs by reflection API
31 */
32 public class ReflectionVisitor extends Tester.Visitor {
34 public ReflectionVisitor(Tester tester) {
35 super(tester);
36 }
38 public void error(String msg) {
39 super.error("reflection: " + msg);
40 }
42 public void warn(String msg) {
43 super.warn("reflection: " + msg);
44 }
46 boolean isEnum;
47 boolean isInterface;
48 boolean isAnon;
49 boolean isLocal;
50 boolean isMember;
51 boolean isStatic;
52 boolean isPublic;
53 Class clazz;
54 StringBuilder sb;
56 /**
57 * Read class using {@code ClassFile}, and generate a list of methods
58 * with parameter names as available in the MethodParameters attribute.
59 */
60 void visitClass(final String cl, final File cfile, final StringBuilder sb)
61 throws Exception {
63 this.sb = sb;
64 clazz = Class.forName(cl);
65 isEnum = clazz.isEnum();
66 isInterface = clazz.isInterface();
67 isAnon = clazz.isAnonymousClass();
68 isLocal = clazz.isLocalClass();
69 isMember = clazz.isMemberClass();
70 isStatic = ((clazz.getModifiers() & Modifier.STATIC) != 0);
71 isPublic = ((clazz.getModifiers() & Modifier.PUBLIC) != 0);
73 sb.append(isStatic ? "static " : "")
74 .append(isPublic ? "public " : "")
75 .append(isEnum ? "enum " : isInterface ? "interface " : "class ")
76 .append(cl).append(" -- ")
77 .append(isMember? "member " : "" )
78 .append(isLocal? "local " : "" )
79 .append(isAnon ? "anon" : "")
80 .append("\n");
82 for (Constructor c : clazz.getDeclaredConstructors()) {
83 testConstructor(c);
84 }
86 for (Method m :clazz.getDeclaredMethods()) {
88 testMethod(m);
89 }
90 }
92 void testConstructor(Constructor c) {
94 String prefix = clazz.getName() + "." + c.getName() + "() - ";
96 // Parameters must match parameter types
97 Parameter params[] = c.getParameters();
98 int paramTypes = c.getParameterTypes().length;
99 if (paramTypes != params.length) {
100 error(prefix + "number of parameter types (" + paramTypes
101 + ") != number of parameters (" + params.length + ")");
102 return;
103 }
105 sb.append(clazz.getName()).append(".").append("<init>").append("(");
106 String sep = "";
108 // Some paramters are expected
109 if (params.length < 2 && isEnum) {
110 error(prefix + "enum constuctor, two arguments expected");
111 } else if (params.length < 1 && (isAnon || isLocal ||
112 (isMember && !isStatic ))) {
113 error(prefix + "class constuctor,expected implicit argument");
114 }
116 int i = -1;
117 String param = null;
118 for (Parameter p : c.getParameters()) {
119 i++;
120 String pname = p.getName();
121 sb.append(sep).append(pname);
122 if (p.isImplicit()) sb.append("!");
123 if (p.isSynthetic()) sb.append("!!");
124 sep = ", ";
126 // Set expectations
127 String expect = null;
128 boolean allowImplicit = false;
129 boolean allowSynthetic = false;
130 if (isEnum) {
131 if (i == 0) {
132 expect = "\\$enum\\$name";
133 allowSynthetic = true;
134 } else if(i == 1) {
135 expect = "\\$enum\\$ordinal";
136 allowSynthetic = true;
137 }
138 } else if (i == 0) {
139 if (isAnon) {
140 allowImplicit = true;
141 } else if (isLocal) {
142 allowImplicit = true;
143 expect = "this\\$[0-n]*";
144 } else if ((isMember && !isStatic)) {
145 allowImplicit = true;
146 if (!isPublic) {
147 // some but not all non-public inner classes
148 // have synthetic argument. For now we give
149 // the test a bit of slack and allow either.
150 allowSynthetic = true;
151 }
152 expect = "this\\$[0-n]*";
153 }
154 } else if (isAnon) {
155 // not an implementation gurantee, but okay for now
156 expect = "x[0-n]*";
157 }
159 // Check expected flags
160 if (p.isSynthetic() && p.isImplicit()) {
161 error(prefix + "param[" + i + "]='" + pname +
162 "' both isImplicit() and isSynthetic()");
163 break;
164 }
165 if (allowImplicit && allowSynthetic &&
166 !(p.isSynthetic() || p.isImplicit())) {
167 error(prefix + "param[" + i + "]='" + pname +
168 "' isImplicit() or isSynthetic() expected");
169 break;
170 }
172 if (allowImplicit && !allowSynthetic && !p.isImplicit()) {
173 error(prefix + "param[" + i + "]='" + pname +
174 "' isImplicit() expected");
175 break;
176 }
177 if (!allowImplicit && allowSynthetic && !p.isSynthetic()) {
178 error(prefix + "param[" + i + "]='" + pname +
179 "' isSynthetic() expected");
180 break;
181 }
183 if (!allowImplicit && p.isImplicit()) {
184 error(prefix + "param[" + i + "]='" + pname +
185 "' isImplicit() unexpected");
186 break;
187 }
189 if (!allowSynthetic && p.isSynthetic()) {
190 error(prefix + "param[" + i + "]='" + pname +
191 "' isSynthetic() unexpected");
192 break;
193 }
195 // Check expected names
196 if (expect != null) {
197 if (pname.matches(expect)) continue;
198 error(prefix + "param[" + i + "]='" + pname +
199 "' expected '" + expect + "'");
200 break;
201 }
203 // Test naming convention for explicit parameters.
204 boolean fidelity = !isAnon;
205 if (param != null && fidelity) {
206 char ch = param.charAt(0);
207 expect = (++ch) + param;
208 }
210 if (pname != null && fidelity) {
211 param = pname;
212 }
214 if (expect != null && !expect.equals(pname)) {
215 error(prefix + "param[" + i + "]='" + pname +
216 "' expected '" + expect + "'");
217 break;
218 }
219 }
220 if (c.isSynthetic()) {
221 sb.append(")!!\n");
222 } else {
223 sb.append(")\n");
224 }
225 }
227 void testMethod(Method m) {
229 String prefix = clazz.getName() + "." + m.getName() + "() - ";
231 // Parameters must match parameter types
232 int paramTypes = m.getParameterTypes().length;
233 int params = m.getParameters().length;
234 if (paramTypes != params) {
235 error(prefix + "number of parameter types (" + paramTypes
236 + ") != number of parameters (" + params + ")");
237 return;
238 }
240 sb.append(clazz.getName()).append(".").append(m.getName()).append("(");
241 String sep = "";
242 String param = null;
243 int i = -1;
244 // For methods we expect all parameters to follow
245 // the test-case design pattern, except synthetic methods.
246 for (Parameter p : m.getParameters()) {
247 i++;
248 if (param == null) {
249 param = p.getName();
250 sb.append(sep).append(param);
251 } else {
252 char c = param.charAt(0);
253 String expect = m.isSynthetic() ? ("arg" + i) : ((++c) + param);
254 param = p.getName();
255 sb.append(sep).append(param);
256 if (!expect.equals(param)) {
257 error(prefix + "param[" + i + "]='"
258 + param + "' expected '" + expect + "'");
259 break;
260 }
261 }
262 sep = ", ";
263 }
264 if (m.isSynthetic()) {
265 sb.append(")!!\n");
266 } else {
267 sb.append(")\n");
268 }
269 }
270 }