Tue, 31 May 2016 10:20:43 -0700
Merge
strarup@1594 | 1 | /* |
strarup@1594 | 2 | * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. |
strarup@1594 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
strarup@1594 | 4 | * |
strarup@1594 | 5 | * This code is free software; you can redistribute it and/or modify it |
strarup@1594 | 6 | * under the terms of the GNU General Public License version 2 only, as |
strarup@1594 | 7 | * published by the Free Software Foundation. |
strarup@1594 | 8 | * |
strarup@1594 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
strarup@1594 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
strarup@1594 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
strarup@1594 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
strarup@1594 | 13 | * accompanied this code). |
strarup@1594 | 14 | * |
strarup@1594 | 15 | * You should have received a copy of the GNU General Public License version |
strarup@1594 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
strarup@1594 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
strarup@1594 | 18 | * |
strarup@1594 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
strarup@1594 | 20 | * or visit www.oracle.com if you need additional information or have any |
strarup@1594 | 21 | * questions. |
strarup@1594 | 22 | */ |
strarup@1594 | 23 | |
vromero@1792 | 24 | import java.io.*; |
strarup@1594 | 25 | import com.sun.tools.classfile.*; |
strarup@1594 | 26 | |
strarup@1594 | 27 | /** |
strarup@1594 | 28 | * The {@code ClassFileVisitor} reads a class file using the |
strarup@1594 | 29 | * {@code com.sun.tools.classfile} library. It iterates over the methods |
strarup@1594 | 30 | * in a class, and checks MethodParameters attributes against JLS |
strarup@1594 | 31 | * requirements, as well as assumptions about the javac implementations. |
strarup@1594 | 32 | * <p> |
strarup@1594 | 33 | * It enforces the following rules: |
strarup@1594 | 34 | * <ul> |
strarup@1594 | 35 | * <li>All non-synthetic methods with arguments must have the |
strarup@1594 | 36 | * MethodParameters attribute. </li> |
strarup@1594 | 37 | * <li>At most one MethodParameters attribute per method.</li> |
strarup@1594 | 38 | * <li>An empty MethodParameters attribute is not allowed (i.e. no |
strarup@1594 | 39 | * attribute for methods taking no parameters).</li> |
strarup@1594 | 40 | * <li>The number of recorded parameter names much equal the number |
strarup@1594 | 41 | * of parameters, including any implicit or synthetic parameters generated |
strarup@1594 | 42 | * by the compiler.</li> |
strarup@1594 | 43 | * <li>Although the spec allow recording parameters with no name, the javac |
strarup@1594 | 44 | * implementation is assumed to record a name for all parameters. That is, |
strarup@1594 | 45 | * the Methodparameters attribute must record a non-zero, valid constant |
strarup@1594 | 46 | * pool index for each parameter.</li> |
strarup@1594 | 47 | * <li>Check presence, expected names (e.g. this$N, $enum$name, ...) and flags |
strarup@1594 | 48 | * (e.g. ACC_SYNTHETIC, ACC_MANDATED) for compiler generated parameters.</li> |
strarup@1594 | 49 | * <li>Names of explicit parameters must reflect the names in the Java source. |
strarup@1594 | 50 | * This is checked by assuming a design pattern where any name is permitted |
strarup@1594 | 51 | * for the first explicit parameter. For subsequent parameters the following |
strarup@1594 | 52 | * rule is checked: <i>param[n] == ++param[n-1].charAt(0) + param[n-1]</i> |
strarup@1594 | 53 | * </ul> |
strarup@1594 | 54 | */ |
strarup@1594 | 55 | class ClassFileVisitor extends Tester.Visitor { |
strarup@1594 | 56 | |
strarup@1594 | 57 | Tester tester; |
strarup@1594 | 58 | |
strarup@1594 | 59 | public String cname; |
strarup@1594 | 60 | public boolean isEnum; |
strarup@1594 | 61 | public boolean isInterface; |
strarup@1594 | 62 | public boolean isInner; |
strarup@1594 | 63 | public boolean isPublic; |
strarup@1594 | 64 | public boolean isStatic; |
strarup@1594 | 65 | public boolean isAnon; |
strarup@1594 | 66 | public ClassFile classFile; |
strarup@1594 | 67 | |
strarup@1594 | 68 | |
strarup@1594 | 69 | public ClassFileVisitor(Tester tester) { |
strarup@1594 | 70 | super(tester); |
strarup@1594 | 71 | } |
strarup@1594 | 72 | |
strarup@1594 | 73 | public void error(String msg) { |
strarup@1594 | 74 | super.error("classfile: " + msg); |
strarup@1594 | 75 | } |
strarup@1594 | 76 | |
strarup@1594 | 77 | public void warn(String msg) { |
strarup@1594 | 78 | super.warn("classfile: " + msg); |
strarup@1594 | 79 | } |
strarup@1594 | 80 | |
strarup@1594 | 81 | /** |
strarup@1594 | 82 | * Read the class and determine some key characteristics, like if it's |
strarup@1594 | 83 | * an enum, or inner class, etc. |
strarup@1594 | 84 | */ |
mnunez@2137 | 85 | void visitClass(final String cname, final File cfile, final StringBuilder sb) throws Exception { |
strarup@1594 | 86 | this.cname = cname; |
strarup@1594 | 87 | classFile = ClassFile.read(cfile); |
strarup@1594 | 88 | isEnum = classFile.access_flags.is(AccessFlags.ACC_ENUM); |
strarup@1594 | 89 | isInterface = classFile.access_flags.is(AccessFlags.ACC_INTERFACE); |
strarup@1594 | 90 | isPublic = classFile.access_flags.is(AccessFlags.ACC_PUBLIC); |
strarup@1594 | 91 | isInner = false; |
mnunez@2137 | 92 | isStatic = false; |
strarup@1594 | 93 | isAnon = false; |
strarup@1594 | 94 | |
strarup@1594 | 95 | Attribute attr = classFile.getAttribute("InnerClasses"); |
strarup@1594 | 96 | if (attr != null) attr.accept(new InnerClassVisitor(), null); |
strarup@1594 | 97 | isAnon = isInner & isAnon; |
strarup@1594 | 98 | |
strarup@1594 | 99 | sb.append(isStatic ? "static " : "") |
strarup@1594 | 100 | .append(isPublic ? "public " : "") |
strarup@1594 | 101 | .append(isEnum ? "enum " : isInterface ? "interface " : "class ") |
mnunez@2137 | 102 | .append(cname).append(" -- "); |
mnunez@2137 | 103 | if (isInner) { |
mnunez@2137 | 104 | sb.append(isAnon ? "anon" : "inner"); |
mnunez@2137 | 105 | } |
mnunez@2137 | 106 | sb.append("\n"); |
strarup@1594 | 107 | |
strarup@1594 | 108 | for (Method method : classFile.methods) { |
strarup@1594 | 109 | new MethodVisitor().visitMethod(method, sb); |
strarup@1594 | 110 | } |
strarup@1594 | 111 | } |
strarup@1594 | 112 | |
strarup@1594 | 113 | /** |
strarup@1594 | 114 | * Used to visit InnerClasses_attribute of a class, |
strarup@1594 | 115 | * to determne if this class is an local class, and anonymous |
strarup@1594 | 116 | * inner class or a none-static member class. These types of |
strarup@1594 | 117 | * classes all have an containing class instances field that |
strarup@1594 | 118 | * requires an implicit or synthetic constructor argument. |
strarup@1594 | 119 | */ |
strarup@1594 | 120 | class InnerClassVisitor extends AttributeVisitor<Void, Void> { |
strarup@1594 | 121 | public Void visitInnerClasses(InnerClasses_attribute iattr, Void v) { |
strarup@1594 | 122 | try{ |
strarup@1594 | 123 | for (InnerClasses_attribute.Info info : iattr.classes) { |
strarup@1594 | 124 | if (info.getInnerClassInfo(classFile.constant_pool) == null) continue; |
strarup@1594 | 125 | String in = info.getInnerClassInfo(classFile.constant_pool).getName(); |
strarup@1594 | 126 | if (in == null || !cname.equals(in)) continue; |
strarup@1594 | 127 | isInner = true; |
strarup@1594 | 128 | isAnon = null == info.getInnerName(classFile.constant_pool); |
strarup@1594 | 129 | isStatic = info.inner_class_access_flags.is(AccessFlags.ACC_STATIC); |
strarup@1594 | 130 | break; |
strarup@1594 | 131 | } |
strarup@1594 | 132 | } catch(Exception e) { |
strarup@1594 | 133 | throw new IllegalStateException(e); |
strarup@1594 | 134 | } |
strarup@1594 | 135 | return null; |
strarup@1594 | 136 | } |
strarup@1594 | 137 | } |
strarup@1594 | 138 | |
strarup@1594 | 139 | /** |
strarup@1594 | 140 | * Check the MethodParameters attribute of a method. |
strarup@1594 | 141 | */ |
strarup@1594 | 142 | class MethodVisitor extends AttributeVisitor<Void, StringBuilder> { |
strarup@1594 | 143 | |
strarup@1594 | 144 | public String mName; |
strarup@1594 | 145 | public Descriptor mDesc; |
strarup@1594 | 146 | public int mParams; |
strarup@1594 | 147 | public int mAttrs; |
strarup@1594 | 148 | public int mNumParams; |
strarup@1594 | 149 | public boolean mSynthetic; |
jlahoda@2733 | 150 | public boolean mIsLambda; |
strarup@1594 | 151 | public boolean mIsConstructor; |
mnunez@2137 | 152 | public boolean mIsClinit; |
vromero@1792 | 153 | public boolean mIsBridge; |
mnunez@2137 | 154 | public boolean isFinal; |
strarup@1594 | 155 | public String prefix; |
strarup@1594 | 156 | |
strarup@1594 | 157 | void visitMethod(Method method, StringBuilder sb) throws Exception { |
strarup@1594 | 158 | |
strarup@1594 | 159 | mName = method.getName(classFile.constant_pool); |
strarup@1594 | 160 | mDesc = method.descriptor; |
strarup@1594 | 161 | mParams = mDesc.getParameterCount(classFile.constant_pool); |
strarup@1594 | 162 | mAttrs = method.attributes.attrs.length; |
strarup@1594 | 163 | mNumParams = -1; // no MethodParameters attribute found |
strarup@1594 | 164 | mSynthetic = method.access_flags.is(AccessFlags.ACC_SYNTHETIC); |
strarup@1594 | 165 | mIsConstructor = mName.equals("<init>"); |
mnunez@2137 | 166 | mIsClinit = mName.equals("<clinit>"); |
strarup@1594 | 167 | prefix = cname + "." + mName + "() - "; |
vromero@1792 | 168 | mIsBridge = method.access_flags.is(AccessFlags.ACC_BRIDGE); |
jlahoda@2733 | 169 | mIsLambda = mSynthetic && mName.startsWith("lambda$"); |
strarup@1594 | 170 | |
mnunez@2137 | 171 | if (mIsClinit) { |
mnunez@2137 | 172 | sb = new StringBuilder(); // Discard output |
mnunez@2137 | 173 | } |
strarup@1594 | 174 | sb.append(cname).append(".").append(mName).append("("); |
strarup@1594 | 175 | |
strarup@1594 | 176 | for (Attribute a : method.attributes) { |
strarup@1594 | 177 | a.accept(this, sb); |
strarup@1594 | 178 | } |
strarup@1594 | 179 | if (mNumParams == -1) { |
strarup@1594 | 180 | if (mSynthetic) { |
mnunez@2137 | 181 | // We don't generate MethodParameters attribute for synthetic |
mnunez@2137 | 182 | // methods, so we are creating a parameter pattern to match |
mnunez@2137 | 183 | // ReflectionVisitor API output. |
mnunez@2137 | 184 | for (int i = 0; i < mParams; i++) { |
mnunez@2137 | 185 | if (i == 0) |
mnunez@2137 | 186 | sb.append("arg").append(i); |
mnunez@2137 | 187 | else |
mnunez@2137 | 188 | sb.append(", arg").append(i); |
mnunez@2137 | 189 | } |
mnunez@2137 | 190 | sb.append(")/*synthetic*/"); |
strarup@1594 | 191 | } else { |
mnunez@2137 | 192 | sb.append(")"); |
strarup@1594 | 193 | } |
strarup@1594 | 194 | } |
strarup@1594 | 195 | sb.append("\n"); |
strarup@1594 | 196 | |
strarup@1594 | 197 | // IMPL: methods with arguments must have a MethodParameters |
strarup@1594 | 198 | // attribute, except possibly some synthetic methods. |
strarup@1594 | 199 | if (mNumParams == -1 && mParams > 0 && ! mSynthetic) { |
strarup@1594 | 200 | error(prefix + "missing MethodParameters attribute"); |
strarup@1594 | 201 | } |
strarup@1594 | 202 | } |
strarup@1594 | 203 | |
strarup@1594 | 204 | public Void visitMethodParameters(MethodParameters_attribute mp, |
strarup@1594 | 205 | StringBuilder sb) { |
strarup@1594 | 206 | |
strarup@1594 | 207 | // SPEC: At most one MethodParameters attribute allowed |
strarup@1594 | 208 | if (mNumParams != -1) { |
strarup@1594 | 209 | error(prefix + "Multiple MethodParameters attributes"); |
strarup@1594 | 210 | return null; |
strarup@1594 | 211 | } |
strarup@1594 | 212 | |
strarup@1594 | 213 | mNumParams = mp.method_parameter_table_length; |
strarup@1594 | 214 | |
strarup@1594 | 215 | // SPEC: An empty attribute is not allowed! |
strarup@1594 | 216 | if (mNumParams == 0) { |
strarup@1594 | 217 | error(prefix + "0 length MethodParameters attribute"); |
strarup@1594 | 218 | return null; |
strarup@1594 | 219 | } |
strarup@1594 | 220 | |
strarup@1594 | 221 | // SPEC: one name per parameter. |
strarup@1594 | 222 | if (mNumParams != mParams) { |
strarup@1594 | 223 | error(prefix + "found " + mNumParams + |
strarup@1594 | 224 | " parameters, expected " + mParams); |
strarup@1594 | 225 | return null; |
strarup@1594 | 226 | } |
strarup@1594 | 227 | |
strarup@1594 | 228 | // IMPL: Whether MethodParameters attributes will be generated |
strarup@1594 | 229 | // for some synthetics is unresolved. For now, assume no. |
jlahoda@2733 | 230 | if (mSynthetic && !mIsLambda) { |
strarup@1594 | 231 | warn(prefix + "synthetic has MethodParameter attribute"); |
strarup@1594 | 232 | } |
strarup@1594 | 233 | |
strarup@1594 | 234 | String sep = ""; |
strarup@1594 | 235 | String userParam = null; |
strarup@1594 | 236 | for (int x = 0; x < mNumParams; x++) { |
mnunez@2137 | 237 | isFinal = (mp.method_parameter_table[x].flags & AccessFlags.ACC_FINAL) != 0; |
strarup@1594 | 238 | // IMPL: Assume all parameters are named, something. |
strarup@1594 | 239 | int cpi = mp.method_parameter_table[x].name_index; |
strarup@1594 | 240 | if (cpi == 0) { |
strarup@1594 | 241 | error(prefix + "name expected, param[" + x + "]"); |
strarup@1594 | 242 | return null; |
strarup@1594 | 243 | } |
strarup@1594 | 244 | |
strarup@1594 | 245 | // SPEC: a non 0 index, must be valid! |
strarup@1594 | 246 | String param = null; |
strarup@1594 | 247 | try { |
strarup@1594 | 248 | param = classFile.constant_pool.getUTF8Value(cpi); |
mnunez@2137 | 249 | if (isFinal) |
mnunez@2137 | 250 | param = "final " + param; |
strarup@1594 | 251 | sb.append(sep).append(param); |
strarup@1594 | 252 | sep = ", "; |
strarup@1594 | 253 | } catch(ConstantPoolException e) { |
strarup@1594 | 254 | error(prefix + "invalid index " + cpi + " for param[" |
strarup@1594 | 255 | + x + "]"); |
strarup@1594 | 256 | return null; |
strarup@1594 | 257 | } |
strarup@1594 | 258 | |
strarup@1594 | 259 | |
strarup@1594 | 260 | // Check availability, flags and special names |
mnunez@2137 | 261 | int check = checkParam(mp, param, x, sb, isFinal); |
strarup@1594 | 262 | if (check < 0) { |
strarup@1594 | 263 | return null; |
strarup@1594 | 264 | } |
strarup@1594 | 265 | |
strarup@1594 | 266 | // TEST: check test assumptions about parameter name. |
strarup@1594 | 267 | // Expected names are calculated starting with the |
strarup@1594 | 268 | // 2nd explicit (user given) parameter. |
strarup@1594 | 269 | // param[n] == ++param[n-1].charAt(0) + param[n-1] |
strarup@1594 | 270 | String expect = null; |
strarup@1594 | 271 | if (userParam != null) { |
strarup@1594 | 272 | char c = userParam.charAt(0); |
strarup@1594 | 273 | expect = (++c) + userParam; |
strarup@1594 | 274 | } |
mnunez@2137 | 275 | if(isFinal && expect != null) |
mnunez@2137 | 276 | expect = "final " + expect; |
strarup@1594 | 277 | if (check > 0) { |
mnunez@2137 | 278 | if(isFinal) { |
mnunez@2137 | 279 | userParam = param.substring(6); |
mnunez@2137 | 280 | } else { |
strarup@1594 | 281 | userParam = param; |
strarup@1594 | 282 | } |
mnunez@2137 | 283 | } |
strarup@1594 | 284 | if (expect != null && !param.equals(expect)) { |
strarup@1594 | 285 | error(prefix + "param[" + x + "]='" |
strarup@1594 | 286 | + param + "' expected '" + expect + "'"); |
strarup@1594 | 287 | return null; |
strarup@1594 | 288 | } |
strarup@1594 | 289 | } |
strarup@1594 | 290 | if (mSynthetic) { |
mnunez@2137 | 291 | sb.append(")/*synthetic*/"); |
strarup@1594 | 292 | } else { |
strarup@1594 | 293 | sb.append(")"); |
strarup@1594 | 294 | } |
strarup@1594 | 295 | return null; |
strarup@1594 | 296 | } |
strarup@1594 | 297 | |
strarup@1594 | 298 | /* |
strarup@1594 | 299 | * Check a parameter for conformity to JLS and javac specific |
strarup@1594 | 300 | * assumptions. |
strarup@1594 | 301 | * Return -1, if an error is detected. Otherwise, return 0, if |
strarup@1594 | 302 | * the parameter is compiler generated, or 1 for an (presumably) |
strarup@1594 | 303 | * explicitly declared parameter. |
strarup@1594 | 304 | */ |
strarup@1594 | 305 | int checkParam(MethodParameters_attribute mp, String param, int index, |
mnunez@2137 | 306 | StringBuilder sb, boolean isFinal) { |
strarup@1594 | 307 | |
strarup@1594 | 308 | boolean synthetic = (mp.method_parameter_table[index].flags |
strarup@1594 | 309 | & AccessFlags.ACC_SYNTHETIC) != 0; |
strarup@1594 | 310 | boolean mandated = (mp.method_parameter_table[index].flags |
strarup@1594 | 311 | & AccessFlags.ACC_MANDATED) != 0; |
strarup@1594 | 312 | |
strarup@1594 | 313 | // Setup expectations for flags and special names |
strarup@1594 | 314 | String expect = null; |
strarup@1594 | 315 | boolean allowMandated = false; |
strarup@1594 | 316 | boolean allowSynthetic = false; |
strarup@1594 | 317 | if (mSynthetic || synthetic) { |
strarup@1594 | 318 | // not an implementation gurantee, but okay for now |
strarup@1594 | 319 | expect = "arg" + index; // default |
strarup@1594 | 320 | } |
strarup@1594 | 321 | if (mIsConstructor) { |
strarup@1594 | 322 | if (isEnum) { |
strarup@1594 | 323 | if (index == 0) { |
strarup@1594 | 324 | expect = "\\$enum\\$name"; |
strarup@1594 | 325 | allowSynthetic = true; |
strarup@1594 | 326 | } else if(index == 1) { |
strarup@1594 | 327 | expect = "\\$enum\\$ordinal"; |
strarup@1594 | 328 | allowSynthetic = true; |
strarup@1594 | 329 | } |
strarup@1594 | 330 | } else if (index == 0) { |
strarup@1594 | 331 | if (isAnon) { |
mnunez@2137 | 332 | expect = "this\\$[0-9]+"; |
strarup@1594 | 333 | allowMandated = true; |
mnunez@2137 | 334 | if (isFinal) { |
mnunez@2137 | 335 | expect = "final this\\$[0-9]+"; |
mnunez@2137 | 336 | } |
strarup@1594 | 337 | } else if (isInner && !isStatic) { |
mnunez@2137 | 338 | expect = "this\\$[0-9]+"; |
strarup@1594 | 339 | allowMandated = true; |
strarup@1594 | 340 | if (!isPublic) { |
strarup@1594 | 341 | // some but not all non-public inner classes |
strarup@1594 | 342 | // have synthetic argument. For now we give |
strarup@1594 | 343 | // the test a bit of slack and allow either. |
strarup@1594 | 344 | allowSynthetic = true; |
strarup@1594 | 345 | } |
mnunez@2137 | 346 | if (isFinal) { |
mnunez@2137 | 347 | expect = "final this\\$[0-9]+"; |
mnunez@2137 | 348 | } |
strarup@1594 | 349 | } |
strarup@1594 | 350 | } |
strarup@1594 | 351 | } else if (isEnum && mNumParams == 1 && index == 0 && mName.equals("valueOf")) { |
strarup@1594 | 352 | expect = "name"; |
strarup@1594 | 353 | allowMandated = true; |
jlahoda@2733 | 354 | } else if (mIsBridge || mIsLambda) { |
vromero@1792 | 355 | allowSynthetic = true; |
vromero@1792 | 356 | /* you can't expect an special name for bridges' parameters. |
jlahoda@2733 | 357 | * The name of the original parameters are now copied. Likewise |
jlahoda@2733 | 358 | * for a method encoding the lambda expression, names are derived |
jlahoda@2733 | 359 | * from source lambda's parameters and captured enclosing locals. |
vromero@1792 | 360 | */ |
vromero@1792 | 361 | expect = null; |
strarup@1594 | 362 | } |
mnunez@2137 | 363 | if (mandated) sb.append("/*implicit*/"); |
mnunez@2137 | 364 | if (synthetic) sb.append("/*synthetic*/"); |
strarup@1594 | 365 | |
strarup@1594 | 366 | // IMPL: our rules a somewhat fuzzy, sometimes allowing both mandated |
strarup@1594 | 367 | // and synthetic. However, a parameters cannot be both. |
strarup@1594 | 368 | if (mandated && synthetic) { |
strarup@1594 | 369 | error(prefix + "param[" + index + "] == \"" + param |
strarup@1594 | 370 | + "\" ACC_SYNTHETIC and ACC_MANDATED"); |
strarup@1594 | 371 | return -1; |
strarup@1594 | 372 | } |
strarup@1594 | 373 | // ... but must be either, if both "allowed". |
strarup@1594 | 374 | if (!(mandated || synthetic) && allowMandated && allowSynthetic) { |
strarup@1594 | 375 | error(prefix + "param[" + index + "] == \"" + param |
strarup@1594 | 376 | + "\" expected ACC_MANDATED or ACC_SYNTHETIC"); |
strarup@1594 | 377 | return -1; |
strarup@1594 | 378 | } |
strarup@1594 | 379 | |
strarup@1594 | 380 | // ... if only one is "allowed", we meant "required". |
strarup@1594 | 381 | if (!mandated && allowMandated && !allowSynthetic) { |
strarup@1594 | 382 | error(prefix + "param[" + index + "] == \"" + param |
strarup@1594 | 383 | + "\" expected ACC_MANDATED"); |
strarup@1594 | 384 | return -1; |
strarup@1594 | 385 | } |
strarup@1594 | 386 | if (!synthetic && !allowMandated && allowSynthetic) { |
strarup@1594 | 387 | error(prefix + "param[" + index + "] == \"" + param |
strarup@1594 | 388 | + "\" expected ACC_SYNTHETIC"); |
strarup@1594 | 389 | return -1; |
strarup@1594 | 390 | } |
strarup@1594 | 391 | |
strarup@1594 | 392 | // ... and not "allowed", means prohibited. |
strarup@1594 | 393 | if (mandated && !allowMandated) { |
strarup@1594 | 394 | error(prefix + "param[" + index + "] == \"" + param |
strarup@1594 | 395 | + "\" unexpected, is ACC_MANDATED"); |
strarup@1594 | 396 | return -1; |
strarup@1594 | 397 | } |
strarup@1594 | 398 | if (synthetic && !allowSynthetic) { |
strarup@1594 | 399 | error(prefix + "param[" + index + "] == \"" + param |
strarup@1594 | 400 | + "\" unexpected, is ACC_SYNTHETIC"); |
strarup@1594 | 401 | return -1; |
strarup@1594 | 402 | } |
strarup@1594 | 403 | |
strarup@1594 | 404 | // Test special name expectations |
strarup@1594 | 405 | if (expect != null) { |
strarup@1594 | 406 | if (param.matches(expect)) { |
strarup@1594 | 407 | return 0; |
strarup@1594 | 408 | } |
strarup@1594 | 409 | error(prefix + "param[" + index + "]='" + param + |
strarup@1594 | 410 | "' expected '" + expect + "'"); |
strarup@1594 | 411 | return -1; |
strarup@1594 | 412 | } |
strarup@1594 | 413 | |
strarup@1594 | 414 | // No further checking for synthetic methods. |
strarup@1594 | 415 | if (mSynthetic) { |
strarup@1594 | 416 | return 0; |
strarup@1594 | 417 | } |
strarup@1594 | 418 | |
strarup@1594 | 419 | // Otherwise, do check test parameter naming convention. |
strarup@1594 | 420 | return 1; |
strarup@1594 | 421 | } |
strarup@1594 | 422 | } |
strarup@1594 | 423 | } |