Mon, 24 Nov 2014 12:49:30 -0500
8029012: parameter_index for type annotation not updated after outer.this added
Summary: Fix javac's handling of type annotations when synthetic parameters are added
Reviewed-by: jjg, mcimadamore
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Nov 20 14:05:39 2014 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Mon Nov 24 12:49:30 2014 -0500 1.3 @@ -2716,9 +2716,10 @@ 1.4 syms.intType, tree.sym); 1.5 ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC; 1.6 1.7 + MethodSymbol m = tree.sym; 1.8 tree.params = tree.params.prepend(ordParam).prepend(nameParam); 1.9 - 1.10 - MethodSymbol m = tree.sym; 1.11 + incrementParamTypeAnnoIndexes(m, 2); 1.12 + 1.13 m.extraParams = m.extraParams.prepend(ordParam.sym); 1.14 m.extraParams = m.extraParams.prepend(nameParam.sym); 1.15 Type olderasure = m.erasure(types); 1.16 @@ -2741,6 +2742,17 @@ 1.17 } 1.18 } 1.19 //where 1.20 + private void incrementParamTypeAnnoIndexes(MethodSymbol m, 1.21 + int amount) { 1.22 + for (final Attribute.TypeCompound anno : m.getRawTypeAttributes()) { 1.23 + // Increment the parameter_index of any existing formal 1.24 + // parameter annotations. 1.25 + if (anno.position.type == TargetType.METHOD_FORMAL_PARAMETER) { 1.26 + anno.position.parameter_index += amount; 1.27 + } 1.28 + } 1.29 + } 1.30 + 1.31 private void visitMethodDefInternal(JCMethodDecl tree) { 1.32 if (tree.name == names.init && 1.33 (currentClass.isInner() || currentClass.isLocal())) { 1.34 @@ -2771,8 +2783,10 @@ 1.35 // Add this$n (if needed) in front of and free variables behind 1.36 // constructor parameter list. 1.37 tree.params = tree.params.appendList(fvdefs); 1.38 - if (currentClass.hasOuterInstance()) 1.39 + if (currentClass.hasOuterInstance()) { 1.40 tree.params = tree.params.prepend(otdef); 1.41 + incrementParamTypeAnnoIndexes(m, 1); 1.42 + } 1.43 1.44 // If this is an initial constructor, i.e., it does not start with 1.45 // this(...), insert initializers for this$n and proxies
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileInspector.java Mon Nov 24 12:49:30 2014 -0500 2.3 @@ -0,0 +1,950 @@ 2.4 +/* 2.5 + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +import java.lang.annotation.*; 2.28 +import java.io.*; 2.29 +import java.net.URL; 2.30 +import java.util.List; 2.31 + 2.32 +import com.sun.tools.classfile.*; 2.33 + 2.34 +/** 2.35 + * A class providing utilities for writing tests that inspect class 2.36 + * files directly, looking for specific type annotations. 2.37 + * 2.38 + * Note: this framework does not currently handle repeating 2.39 + * annotations. 2.40 + */ 2.41 +public class ClassfileInspector { 2.42 + 2.43 + /** 2.44 + * A group of expected annotations to be found in a given class. 2.45 + * If the class name is null, then the template will be applied to 2.46 + * every class. 2.47 + */ 2.48 + public static class Expected { 2.49 + /** 2.50 + * The name of the class. If {@code null} this template will 2.51 + * apply to every class; otherwise, it will only be applied to 2.52 + * the named class. 2.53 + */ 2.54 + public final String classname; 2.55 + 2.56 + /** 2.57 + * The expected class annotations. These will be checked 2.58 + * against the class' attributes. 2.59 + */ 2.60 + public final ExpectedTypeAnnotation[] classAnnos; 2.61 + 2.62 + /** 2.63 + * The expected method annotations. These will be checked 2.64 + * against all methods in the class. 2.65 + */ 2.66 + public final ExpectedMethodTypeAnnotation[] methodAnnos; 2.67 + 2.68 + /** 2.69 + * The expected field annotations. These will be checked 2.70 + * against all fields in the class. 2.71 + */ 2.72 + public final ExpectedFieldTypeAnnotation[] fieldAnnos; 2.73 + 2.74 + /** 2.75 + * Create an {@code Expected} from its components. 2.76 + * 2.77 + * @param classname The name of the class to match, or {@code 2.78 + * null} for all classes. 2.79 + * @param classAnnos The expected class annotations. 2.80 + * @param methodAnnos The expected method annotations. 2.81 + * @param fieldAnnos The expected field annotations. 2.82 + */ 2.83 + public Expected(String classname, 2.84 + ExpectedTypeAnnotation[] classAnnos, 2.85 + ExpectedMethodTypeAnnotation[] methodAnnos, 2.86 + ExpectedFieldTypeAnnotation[] fieldAnnos) { 2.87 + this.classname = classname; 2.88 + this.classAnnos = classAnnos; 2.89 + this.methodAnnos = methodAnnos; 2.90 + this.fieldAnnos = fieldAnnos; 2.91 + } 2.92 + 2.93 + public String toString() { 2.94 + final StringBuilder sb = new StringBuilder(); 2.95 + final String newline = System.lineSeparator(); 2.96 + sb.append("Expected on class ").append(classname); 2.97 + if (null != classAnnos) { 2.98 + sb.append(newline).append("Class annotations:").append(newline); 2.99 + for(ExpectedTypeAnnotation anno : classAnnos) { 2.100 + sb.append(anno).append(newline); 2.101 + } 2.102 + } 2.103 + if (null != methodAnnos) { 2.104 + sb.append(newline).append("Method annotations:").append(newline); 2.105 + for(ExpectedTypeAnnotation anno : methodAnnos) { 2.106 + sb.append(anno).append(newline); 2.107 + } 2.108 + } 2.109 + if (null != fieldAnnos) { 2.110 + sb.append(newline).append("Field annotations:").append(newline); 2.111 + for(ExpectedTypeAnnotation anno : fieldAnnos) { 2.112 + sb.append(anno).append(newline); 2.113 + } 2.114 + } 2.115 + return sb.toString(); 2.116 + } 2.117 + 2.118 + /** 2.119 + * See if this template applies to a class. 2.120 + * 2.121 + * @param classname The classname to check. 2.122 + * @return Whether or not this template should apply. 2.123 + */ 2.124 + public boolean matchClassName(String classname) { 2.125 + return this.classname == null || this.classname.equals(classname); 2.126 + } 2.127 + 2.128 + /** 2.129 + * After applying the template to all classes, check to see if 2.130 + * any of the expected annotations weren't matched. 2.131 + * 2.132 + * @return The number of missed matches. 2.133 + */ 2.134 + public int check() { 2.135 + int count = 0; 2.136 + if (classAnnos != null) { 2.137 + for(ExpectedTypeAnnotation expected : classAnnos) { 2.138 + if (!expected.check()) { 2.139 + count++; 2.140 + } 2.141 + } 2.142 + } 2.143 + if (methodAnnos != null) { 2.144 + for(ExpectedMethodTypeAnnotation expected : methodAnnos) { 2.145 + if (!expected.check()) { 2.146 + count++; 2.147 + } 2.148 + } 2.149 + } 2.150 + if (fieldAnnos != null) { 2.151 + for(ExpectedFieldTypeAnnotation expected : fieldAnnos) { 2.152 + if (!expected.check()) { 2.153 + count++; 2.154 + } 2.155 + } 2.156 + } 2.157 + return count; 2.158 + } 2.159 + } 2.160 + 2.161 + /** 2.162 + * An expected type annotation. This is both a superclass for 2.163 + * method and field type annotations, as well as a class for type 2.164 + * annotations on a class. 2.165 + */ 2.166 + public static class ExpectedTypeAnnotation { 2.167 + private int count = 0; 2.168 + protected final String expectedName; 2.169 + protected final int expectedCount; 2.170 + protected final TypeAnnotation.TargetType targetType; 2.171 + protected final int bound_index; 2.172 + protected final int parameter_index; 2.173 + protected final int type_index; 2.174 + protected final int exception_index; 2.175 + protected final TypeAnnotation.Position.TypePathEntry[] typePath; 2.176 + protected final boolean visibility; 2.177 + 2.178 + /** 2.179 + * Create an {@code ExpectedTypeAnnotation} from its 2.180 + * components. It is usually a better idea to use a {@code 2.181 + * Builder} to do this. 2.182 + * 2.183 + * @param expectedName The expected annotation name. 2.184 + * @param visibility Whether this annotation should be runtime-visible. 2.185 + * @param expectedCount The number of annotations that should 2.186 + * be seen. If 0, this asserts that the 2.187 + * described annotation is not present. 2.188 + * @param targetType The expected target type. 2.189 + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. 2.190 + * @param parameter_index The expected parameter index, or 2.191 + * {@code Integer.MIN_VALUE}. 2.192 + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. 2.193 + * @param exception_index The expected exception index, or 2.194 + * {@code Integer.MIN_VALUE}. 2.195 + * @param typePath The expected type path. 2.196 + */ 2.197 + public ExpectedTypeAnnotation(String expectedName, 2.198 + boolean visibility, 2.199 + int expectedCount, 2.200 + TypeAnnotation.TargetType targetType, 2.201 + int bound_index, 2.202 + int parameter_index, 2.203 + int type_index, 2.204 + int exception_index, 2.205 + TypeAnnotation.Position.TypePathEntry... typePath) { 2.206 + this.expectedName = expectedName; 2.207 + this.visibility = visibility; 2.208 + this.expectedCount = expectedCount; 2.209 + this.targetType = targetType; 2.210 + this.bound_index = bound_index; 2.211 + this.parameter_index = parameter_index; 2.212 + this.type_index = type_index; 2.213 + this.exception_index = exception_index; 2.214 + this.typePath = typePath; 2.215 + } 2.216 + 2.217 + public String toString() { 2.218 + final StringBuilder sb = new StringBuilder(); 2.219 + sb.append("Expected "); 2.220 + sb.append(expectedCount); 2.221 + sb.append(" annotation "); 2.222 + sb.append(expectedName); 2.223 + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); 2.224 + sb.append(targetType); 2.225 + sb.append(", bound_index = "); 2.226 + sb.append(bound_index); 2.227 + sb.append(", parameter_index = "); 2.228 + sb.append(parameter_index); 2.229 + sb.append(", type_index = "); 2.230 + sb.append(type_index); 2.231 + sb.append(", exception_index = "); 2.232 + sb.append(exception_index); 2.233 + sb.append(", type_path = ["); 2.234 + for(int i = 0; i < typePath.length; i++) { 2.235 + if (i != 0) { 2.236 + sb.append(", "); 2.237 + } 2.238 + sb.append(typePath[i]); 2.239 + } 2.240 + sb.append("]"); 2.241 + return sb.toString(); 2.242 + } 2.243 + 2.244 + /** 2.245 + * See if this template matches the given visibility. 2.246 + * 2.247 + * @param Whether or not the annotation is visible at runtime. 2.248 + * @return Whether or not this template matches the visibility. 2.249 + */ 2.250 + public boolean matchVisibility(boolean visibility) { 2.251 + return this.visibility == visibility; 2.252 + } 2.253 + 2.254 + /** 2.255 + * Attempty to match this template against an annotation. If 2.256 + * it does match, then the match count for the template will 2.257 + * be incremented. Otherwise, nothing will be done. 2.258 + * 2.259 + * @param anno The annotation to attempt to match. 2.260 + */ 2.261 + public void matchAnnotation(TypeAnnotation anno) { 2.262 + boolean matches = true; 2.263 + 2.264 + try { 2.265 + matches = anno.constant_pool.getUTF8Info(anno.annotation.type_index).value.equals("L" + expectedName + ";"); 2.266 + } catch(Exception e) { 2.267 + matches = false; 2.268 + } 2.269 + 2.270 + matches = matches && anno.position.type == targetType; 2.271 + matches = matches && anno.position.bound_index == bound_index; 2.272 + matches = matches && anno.position.parameter_index == parameter_index; 2.273 + matches = matches && anno.position.type_index == type_index; 2.274 + matches = matches && anno.position.exception_index == exception_index; 2.275 + matches = matches && anno.position.location.size() == typePath.length; 2.276 + 2.277 + if (matches) { 2.278 + int i = 0; 2.279 + for(TypeAnnotation.Position.TypePathEntry entry : 2.280 + anno.position.location) { 2.281 + matches = matches && typePath[i++].equals(entry); 2.282 + } 2.283 + } 2.284 + 2.285 + if (matches) { 2.286 + count++; 2.287 + } 2.288 + } 2.289 + 2.290 + /** 2.291 + * After all matching, check to see if the expected number of 2.292 + * matches equals the actual number. If not, then print a 2.293 + * failure message and return {@code false}. 2.294 + * 2.295 + * @return Whether or not the expected number of matched 2.296 + * equals the actual number. 2.297 + */ 2.298 + public boolean check() { 2.299 + if (count != expectedCount) { 2.300 + System.err.println(this + ", but saw " + count); 2.301 + return false; 2.302 + } else { 2.303 + return true; 2.304 + } 2.305 + } 2.306 + 2.307 + /** 2.308 + * A builder class for creating {@code 2.309 + * ExpectedTypeAnnotation}s in a more convenient fashion. The 2.310 + * constructor for {@code ExpectedTypeAnnotation} takes a 2.311 + * large number of parameters (by necessity). This class 2.312 + * allows users to construct a {@code ExpectedTypeAnnotation}s 2.313 + * using only the ones they need. 2.314 + */ 2.315 + public static class Builder { 2.316 + protected final String expectedName; 2.317 + protected final int expectedCount; 2.318 + protected final TypeAnnotation.TargetType targetType; 2.319 + protected final boolean visibility; 2.320 + protected int bound_index = Integer.MIN_VALUE; 2.321 + protected int parameter_index = Integer.MIN_VALUE; 2.322 + protected int type_index = Integer.MIN_VALUE; 2.323 + protected int exception_index = Integer.MIN_VALUE; 2.324 + protected TypeAnnotation.Position.TypePathEntry[] typePath = 2.325 + new TypeAnnotation.Position.TypePathEntry[0]; 2.326 + 2.327 + /** 2.328 + * Create a {@code Builder} from the mandatory parameters. 2.329 + * 2.330 + * @param expectedName The expected annotation name. 2.331 + * @param targetType The expected target type. 2.332 + * @param visibility Whether this annotation should be runtime-visible. 2.333 + * @param expectedCount The number of annotations that should be seen. 2.334 + */ 2.335 + public Builder(String expectedName, 2.336 + TypeAnnotation.TargetType targetType, 2.337 + boolean visibility, 2.338 + int expectedCount) { 2.339 + this.expectedName = expectedName; 2.340 + this.visibility = visibility; 2.341 + this.expectedCount = expectedCount; 2.342 + this.targetType = targetType; 2.343 + } 2.344 + 2.345 + /** 2.346 + * Create an {@code ExpectedTypeAnnotation} from all 2.347 + * parameters that have been provided. The default values 2.348 + * will be used for those that have not. 2.349 + * 2.350 + * @return The cretaed {@code ExpectedTypeAnnotation}. 2.351 + */ 2.352 + public ExpectedTypeAnnotation build() { 2.353 + return new ExpectedTypeAnnotation(expectedName, visibility, 2.354 + expectedCount, targetType, 2.355 + bound_index, parameter_index, 2.356 + type_index, exception_index, 2.357 + typePath); 2.358 + } 2.359 + 2.360 + /** 2.361 + * Provide a bound index parameter. 2.362 + * 2.363 + * @param bound_index The bound_index value. 2.364 + */ 2.365 + public Builder setBoundIndex(int bound_index) { 2.366 + this.bound_index = bound_index; 2.367 + return this; 2.368 + } 2.369 + 2.370 + /** 2.371 + * Provide a parameter index parameter. 2.372 + * 2.373 + * @param bound_index The parameter_index value. 2.374 + */ 2.375 + public Builder setParameterIndex(int parameter_index) { 2.376 + this.parameter_index = parameter_index; 2.377 + return this; 2.378 + } 2.379 + 2.380 + /** 2.381 + * Provide a type index parameter. 2.382 + * 2.383 + * @param type_index The type_index value. 2.384 + */ 2.385 + public Builder setTypeIndex(int type_index) { 2.386 + this.type_index = type_index; 2.387 + return this; 2.388 + } 2.389 + 2.390 + /** 2.391 + * Provide an exception index parameter. 2.392 + * 2.393 + * @param exception_index The exception_index value. 2.394 + */ 2.395 + public Builder setExceptionIndex(int exception_index) { 2.396 + this.exception_index = exception_index; 2.397 + return this; 2.398 + } 2.399 + 2.400 + /** 2.401 + * Provide a type path parameter. 2.402 + * 2.403 + * @param typePath The type path value. 2.404 + */ 2.405 + public Builder setTypePath(TypeAnnotation.Position.TypePathEntry[] typePath) { 2.406 + this.typePath = typePath; 2.407 + return this; 2.408 + } 2.409 + } 2.410 + } 2.411 + 2.412 + /** 2.413 + * A type annotation found on a method. 2.414 + */ 2.415 + public static class ExpectedMethodTypeAnnotation extends ExpectedTypeAnnotation { 2.416 + private final String methodname; 2.417 + 2.418 + /** 2.419 + * Create an {@code ExpectedMethodTypeAnnotation} from its 2.420 + * components. It is usually a better idea to use a {@code 2.421 + * Builder} to do this. 2.422 + * 2.423 + * @param methodname The expected method name. 2.424 + * @param expectedName The expected annotation name. 2.425 + * @param visibility Whether this annotation should be runtime-visible. 2.426 + * @param expectedCount The number of annotations that should be seen. 2.427 + * @param targetType The expected target type. 2.428 + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. 2.429 + * @param parameter_index The expected parameter index, or 2.430 + * {@code Integer.MIN_VALUE}. 2.431 + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. 2.432 + * @param exception_index The expected exception index, or 2.433 + * {@code Integer.MIN_VALUE}. 2.434 + * @param typePath The expected type path. 2.435 + */ 2.436 + public ExpectedMethodTypeAnnotation(String methodname, 2.437 + String expectedName, 2.438 + boolean visibility, 2.439 + int expectedCount, 2.440 + TypeAnnotation.TargetType targetType, 2.441 + int bound_index, 2.442 + int parameter_index, 2.443 + int type_index, 2.444 + int exception_index, 2.445 + TypeAnnotation.Position.TypePathEntry... typePath) { 2.446 + super(expectedName, visibility, expectedCount, targetType, bound_index, 2.447 + parameter_index, type_index, exception_index, typePath); 2.448 + this.methodname = methodname; 2.449 + } 2.450 + 2.451 + public String toString() { 2.452 + final StringBuilder sb = new StringBuilder(); 2.453 + sb.append("Expected "); 2.454 + sb.append(expectedCount); 2.455 + sb.append(" annotation "); 2.456 + sb.append(expectedName); 2.457 + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); 2.458 + sb.append(targetType); 2.459 + sb.append(", bound_index = "); 2.460 + sb.append(bound_index); 2.461 + sb.append(", parameter_index = "); 2.462 + sb.append(parameter_index); 2.463 + sb.append(", type_index = "); 2.464 + sb.append(type_index); 2.465 + sb.append(", exception_index = "); 2.466 + sb.append(exception_index); 2.467 + sb.append(", type_path = ["); 2.468 + for(int i = 0; i < typePath.length; i++) { 2.469 + if (i != 0) { 2.470 + sb.append(", "); 2.471 + } 2.472 + sb.append(typePath[i]); 2.473 + } 2.474 + sb.append("]"); 2.475 + sb.append(" on method "); 2.476 + sb.append(methodname); 2.477 + return sb.toString(); 2.478 + } 2.479 + 2.480 + /** 2.481 + * See if this template applies to a method. 2.482 + * 2.483 + * @param methodname The method name to check. 2.484 + * @return Whether or not this template should apply. 2.485 + */ 2.486 + public boolean matchMethodName(String methodname) { 2.487 + return this.methodname.equals(methodname); 2.488 + } 2.489 + 2.490 + /** 2.491 + * A builder class for creating {@code 2.492 + * ExpectedMethodTypeAnnotation}s in a more convenient fashion. The 2.493 + * constructor for {@code ExpectedMethodTypeAnnotation} takes a 2.494 + * large number of parameters (by necessity). This class 2.495 + * allows users to construct a {@code ExpectedMethodTypeAnnotation}s 2.496 + * using only the ones they need. 2.497 + */ 2.498 + public static class Builder extends ExpectedTypeAnnotation.Builder { 2.499 + protected final String methodname; 2.500 + 2.501 + /** 2.502 + * Create a {@code Builder} from the mandatory parameters. 2.503 + * 2.504 + * @param methodname The expected method name. 2.505 + * @param expectedName The expected annotation name. 2.506 + * @param targetType The expected target type. 2.507 + * @param visibility Whether this annotation should be runtime-visible. 2.508 + * @param expectedCount The number of annotations that should be seen. 2.509 + */ 2.510 + public Builder(String methodname, 2.511 + String expectedName, 2.512 + TypeAnnotation.TargetType targetType, 2.513 + boolean visibility, 2.514 + int expectedCount) { 2.515 + super(expectedName, targetType, visibility, expectedCount); 2.516 + this.methodname = methodname; 2.517 + } 2.518 + 2.519 + /** 2.520 + * Create an {@code ExpectedMethodTypeAnnotation} from all 2.521 + * parameters that have been provided. The default values 2.522 + * will be used for those that have not. 2.523 + * 2.524 + * @return The cretaed {@code ExpectedMethodTypeAnnotation}. 2.525 + */ 2.526 + public ExpectedMethodTypeAnnotation build() { 2.527 + return new ExpectedMethodTypeAnnotation(methodname, expectedName, 2.528 + visibility, expectedCount, 2.529 + targetType, bound_index, 2.530 + parameter_index, type_index, 2.531 + exception_index, typePath); 2.532 + } 2.533 + } 2.534 + } 2.535 + 2.536 + /** 2.537 + * A type annotation found on a field. 2.538 + */ 2.539 + public static class ExpectedFieldTypeAnnotation extends ExpectedTypeAnnotation { 2.540 + private final String fieldname; 2.541 + 2.542 + /** 2.543 + * Create an {@code ExpectedFieldTypeAnnotation} from its 2.544 + * components. It is usually a better idea to use a {@code 2.545 + * Builder} to do this. 2.546 + * 2.547 + * @param fieldname The expected field name. 2.548 + * @param expectedName The expected annotation name. 2.549 + * @param visibility Whether this annotation should be runtime-visible. 2.550 + * @param expectedCount The number of annotations that should be seen. 2.551 + * @param targetType The expected target type. 2.552 + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. 2.553 + * @param parameter_index The expected parameter index, or 2.554 + * {@code Integer.MIN_VALUE}. 2.555 + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. 2.556 + * @param exception_index The expected exception index, or 2.557 + * {@code Integer.MIN_VALUE}. 2.558 + * @param typePath The expected type path. 2.559 + */ 2.560 + public ExpectedFieldTypeAnnotation(String fieldname, 2.561 + String expectedName, 2.562 + boolean visibility, 2.563 + int expectedCount, 2.564 + TypeAnnotation.TargetType targetType, 2.565 + int bound_index, 2.566 + int parameter_index, 2.567 + int type_index, 2.568 + int exception_index, 2.569 + TypeAnnotation.Position.TypePathEntry... typePath) { 2.570 + super(expectedName, visibility, expectedCount, targetType, bound_index, 2.571 + parameter_index, type_index, exception_index, typePath); 2.572 + this.fieldname = fieldname; 2.573 + } 2.574 + 2.575 + public String toString() { 2.576 + final StringBuilder sb = new StringBuilder(); 2.577 + sb.append("Expected ").append(expectedCount) 2.578 + .append(" annotation ").append(expectedName) 2.579 + .append(visibility ? ", runtime visibile " : ", runtime invisibile ") 2.580 + .append(targetType) 2.581 + .append(", bound_index = ").append(bound_index) 2.582 + .append(", parameter_index = ").append(parameter_index) 2.583 + .append(", type_index = ").append(type_index) 2.584 + .append(", exception_index = ").append(exception_index) 2.585 + .append(", type_path = ["); 2.586 + 2.587 + for(int i = 0; i < typePath.length; i++) { 2.588 + if (i != 0) { 2.589 + sb.append(", "); 2.590 + } 2.591 + sb.append(typePath[i]); 2.592 + } 2.593 + sb.append("]") 2.594 + .append(" on field ").append(fieldname); 2.595 + return sb.toString(); 2.596 + } 2.597 + 2.598 + /** 2.599 + * See if this template applies to a field. 2.600 + * 2.601 + * @param fieldname The field name to check. 2.602 + * @return Whether or not this template should apply. 2.603 + */ 2.604 + public boolean matchFieldName(String fieldname) { 2.605 + return this.fieldname.equals(fieldname); 2.606 + } 2.607 + 2.608 + /** 2.609 + * A builder class for creating {@code 2.610 + * ExpectedFieldTypeAnnotation}s in a more convenient fashion. The 2.611 + * constructor for {@code ExpectedFieldTypeAnnotation} takes a 2.612 + * large number of parameters (by necessity). This class 2.613 + * allows users to construct a {@code ExpectedFieldTypeAnnotation}s 2.614 + * using only the ones they need. 2.615 + */ 2.616 + public static class Builder extends ExpectedTypeAnnotation.Builder { 2.617 + protected final String fieldname; 2.618 + 2.619 + /** 2.620 + * Create a {@code Builder} from the mandatory parameters. 2.621 + * 2.622 + * @param fieldname The expected field name. 2.623 + * @param expectedName The expected annotation name. 2.624 + * @param targetType The expected target type. 2.625 + * @param visibility Whether this annotation should be runtime-visible. 2.626 + * @param expectedCount The number of annotations that should be seen. 2.627 + */ 2.628 + public Builder(String fieldname, 2.629 + String expectedName, 2.630 + TypeAnnotation.TargetType targetType, 2.631 + boolean visibility, 2.632 + int expectedCount) { 2.633 + super(expectedName, targetType, visibility, expectedCount); 2.634 + this.fieldname = fieldname; 2.635 + } 2.636 + 2.637 + /** 2.638 + * Create an {@code ExpectedFieldTypeAnnotation} from all 2.639 + * parameters that have been provided. The default values 2.640 + * will be used for those that have not. 2.641 + * 2.642 + * @return The cretaed {@code ExpectedFieldTypeAnnotation}. 2.643 + */ 2.644 + public ExpectedFieldTypeAnnotation build() { 2.645 + return new ExpectedFieldTypeAnnotation(fieldname, expectedName, 2.646 + visibility, expectedCount, 2.647 + targetType, bound_index, 2.648 + parameter_index, type_index, 2.649 + exception_index, typePath); 2.650 + } 2.651 + } 2.652 + } 2.653 + 2.654 + private void matchClassTypeAnnotation(ClassFile classfile, 2.655 + ExpectedTypeAnnotation expected) 2.656 + throws ConstantPoolException { 2.657 + for(Attribute attr : classfile.attributes) { 2.658 + attr.accept(typeAnnoMatcher, expected); 2.659 + } 2.660 + } 2.661 + 2.662 + private void matchMethodTypeAnnotation(ClassFile classfile, 2.663 + ExpectedMethodTypeAnnotation expected) 2.664 + throws ConstantPoolException { 2.665 + for(Method meth : classfile.methods) { 2.666 + if (expected.matchMethodName(meth.getName(classfile.constant_pool))) { 2.667 + for(Attribute attr : meth.attributes) { 2.668 + attr.accept(typeAnnoMatcher, expected); 2.669 + } 2.670 + } 2.671 + } 2.672 + } 2.673 + 2.674 + private void matchFieldTypeAnnotation(ClassFile classfile, 2.675 + ExpectedFieldTypeAnnotation expected) 2.676 + throws ConstantPoolException { 2.677 + for(Field field : classfile.fields) { 2.678 + if (expected.matchFieldName(field.getName(classfile.constant_pool))) { 2.679 + for(Attribute attr : field.attributes) { 2.680 + attr.accept(typeAnnoMatcher, expected); 2.681 + } 2.682 + } 2.683 + } 2.684 + } 2.685 + 2.686 + private void matchClassTypeAnnotations(ClassFile classfile, 2.687 + ExpectedTypeAnnotation[] expected) 2.688 + throws ConstantPoolException { 2.689 + for(ExpectedTypeAnnotation one : expected) { 2.690 + matchClassTypeAnnotation(classfile, one); 2.691 + } 2.692 + } 2.693 + 2.694 + private void matchMethodTypeAnnotations(ClassFile classfile, 2.695 + ExpectedMethodTypeAnnotation[] expected) 2.696 + throws ConstantPoolException { 2.697 + for(ExpectedMethodTypeAnnotation one : expected) { 2.698 + matchMethodTypeAnnotation(classfile, one); 2.699 + } 2.700 + } 2.701 + 2.702 + private void matchFieldTypeAnnotations(ClassFile classfile, 2.703 + ExpectedFieldTypeAnnotation[] expected) 2.704 + throws ConstantPoolException { 2.705 + for(ExpectedFieldTypeAnnotation one : expected) { 2.706 + matchFieldTypeAnnotation(classfile, one); 2.707 + } 2.708 + } 2.709 + 2.710 + /** 2.711 + * Run a template on a single {@code ClassFile}. 2.712 + * 2.713 + * @param classfile The {@code ClassFile} on which to run tests. 2.714 + * @param expected The expected annotation template. 2.715 + */ 2.716 + public void run(ClassFile classfile, 2.717 + Expected... expected) 2.718 + throws ConstantPoolException { 2.719 + run(new ClassFile[] { classfile }, expected); 2.720 + } 2.721 + 2.722 + /** 2.723 + * Run a template on multiple {@code ClassFile}s. 2.724 + * 2.725 + * @param classfile The {@code ClassFile}s on which to run tests. 2.726 + * @param expected The expected annotation template. 2.727 + */ 2.728 + public void run(ClassFile[] classfiles, 2.729 + Expected... expected) 2.730 + throws ConstantPoolException { 2.731 + for(ClassFile classfile : classfiles) { 2.732 + for(Expected one : expected) { 2.733 + if (one.matchClassName(classfile.getName())) { 2.734 + if (one.classAnnos != null) 2.735 + matchClassTypeAnnotations(classfile, one.classAnnos); 2.736 + if (one.methodAnnos != null) 2.737 + matchMethodTypeAnnotations(classfile, one.methodAnnos); 2.738 + if (one.fieldAnnos != null) 2.739 + matchFieldTypeAnnotations(classfile, one.fieldAnnos); 2.740 + } 2.741 + } 2.742 + } 2.743 + int count = 0; 2.744 + for (Expected one : expected) { 2.745 + count += one.check(); 2.746 + } 2.747 + 2.748 + if (count != 0) { 2.749 + throw new RuntimeException(count + " errors occurred in test"); 2.750 + } 2.751 + } 2.752 + 2.753 + /** 2.754 + * Get a {@code ClassFile} from its file name. 2.755 + * 2.756 + * @param name The class' file name. 2.757 + * @return The {@code ClassFile} 2.758 + */ 2.759 + public static ClassFile getClassFile(String name) 2.760 + throws IOException, ConstantPoolException { 2.761 + final URL url = ClassfileInspector.class.getResource(name); 2.762 + final InputStream in = url.openStream(); 2.763 + try { 2.764 + return ClassFile.read(in); 2.765 + } finally { 2.766 + in.close(); 2.767 + } 2.768 + } 2.769 + 2.770 + private static final Attribute.Visitor<Void, ExpectedTypeAnnotation> typeAnnoMatcher = 2.771 + new Attribute.Visitor<Void, ExpectedTypeAnnotation>() { 2.772 + 2.773 + @Override 2.774 + public Void visitBootstrapMethods(BootstrapMethods_attribute attr, 2.775 + ExpectedTypeAnnotation expected) { 2.776 + return null; 2.777 + } 2.778 + 2.779 + @Override 2.780 + public Void visitDefault(DefaultAttribute attr, 2.781 + ExpectedTypeAnnotation expected) { 2.782 + return null; 2.783 + } 2.784 + 2.785 + @Override 2.786 + public Void visitAnnotationDefault(AnnotationDefault_attribute attr, 2.787 + ExpectedTypeAnnotation expected) { 2.788 + return null; 2.789 + } 2.790 + 2.791 + @Override 2.792 + public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, 2.793 + ExpectedTypeAnnotation expected) { 2.794 + return null; 2.795 + } 2.796 + 2.797 + @Override 2.798 + public Void visitCode(Code_attribute attr, 2.799 + ExpectedTypeAnnotation expected) { 2.800 + return null; 2.801 + } 2.802 + 2.803 + @Override 2.804 + public Void visitCompilationID(CompilationID_attribute attr, 2.805 + ExpectedTypeAnnotation expected) { 2.806 + return null; 2.807 + } 2.808 + 2.809 + @Override 2.810 + public Void visitConstantValue(ConstantValue_attribute attr, 2.811 + ExpectedTypeAnnotation expected) { 2.812 + return null; 2.813 + } 2.814 + 2.815 + @Override 2.816 + public Void visitDeprecated(Deprecated_attribute attr, 2.817 + ExpectedTypeAnnotation expected) { 2.818 + return null; 2.819 + } 2.820 + 2.821 + @Override 2.822 + public Void visitEnclosingMethod(EnclosingMethod_attribute attr, 2.823 + ExpectedTypeAnnotation expected) { 2.824 + return null; 2.825 + } 2.826 + 2.827 + @Override 2.828 + public Void visitExceptions(Exceptions_attribute attr, 2.829 + ExpectedTypeAnnotation expected) { 2.830 + return null; 2.831 + } 2.832 + 2.833 + @Override 2.834 + public Void visitInnerClasses(InnerClasses_attribute attr, 2.835 + ExpectedTypeAnnotation expected) { 2.836 + return null; 2.837 + } 2.838 + 2.839 + @Override 2.840 + public Void visitLineNumberTable(LineNumberTable_attribute attr, 2.841 + ExpectedTypeAnnotation expected) { 2.842 + return null; 2.843 + } 2.844 + 2.845 + @Override 2.846 + public Void visitLocalVariableTable(LocalVariableTable_attribute attr, 2.847 + ExpectedTypeAnnotation expected) { 2.848 + return null; 2.849 + } 2.850 + 2.851 + @Override 2.852 + public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, 2.853 + ExpectedTypeAnnotation expected) { 2.854 + return null; 2.855 + } 2.856 + 2.857 + @Override 2.858 + public Void visitMethodParameters(MethodParameters_attribute attr, 2.859 + ExpectedTypeAnnotation expected) { 2.860 + return null; 2.861 + } 2.862 + 2.863 + @Override 2.864 + public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, 2.865 + ExpectedTypeAnnotation expected) { 2.866 + return null; 2.867 + } 2.868 + 2.869 + @Override 2.870 + public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, 2.871 + ExpectedTypeAnnotation expected) { 2.872 + return null; 2.873 + } 2.874 + 2.875 + @Override 2.876 + public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, 2.877 + ExpectedTypeAnnotation expected) { 2.878 + return null; 2.879 + } 2.880 + 2.881 + @Override 2.882 + public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, 2.883 + ExpectedTypeAnnotation expected) { 2.884 + return null; 2.885 + } 2.886 + 2.887 + @Override 2.888 + public Void visitSignature(Signature_attribute attr, 2.889 + ExpectedTypeAnnotation expected) { 2.890 + return null; 2.891 + } 2.892 + 2.893 + @Override 2.894 + public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, 2.895 + ExpectedTypeAnnotation expected) { 2.896 + return null; 2.897 + } 2.898 + 2.899 + @Override 2.900 + public Void visitSourceFile(SourceFile_attribute attr, 2.901 + ExpectedTypeAnnotation expected) { 2.902 + return null; 2.903 + } 2.904 + 2.905 + @Override 2.906 + public Void visitSourceID(SourceID_attribute attr, 2.907 + ExpectedTypeAnnotation expected) { 2.908 + return null; 2.909 + } 2.910 + 2.911 + @Override 2.912 + public Void visitStackMap(StackMap_attribute attr, 2.913 + ExpectedTypeAnnotation expected) { 2.914 + return null; 2.915 + } 2.916 + 2.917 + @Override 2.918 + public Void visitStackMapTable(StackMapTable_attribute attr, 2.919 + ExpectedTypeAnnotation expected) { 2.920 + return null; 2.921 + } 2.922 + 2.923 + @Override 2.924 + public Void visitSynthetic(Synthetic_attribute attr, 2.925 + ExpectedTypeAnnotation expected) { 2.926 + return null; 2.927 + } 2.928 + 2.929 + @Override 2.930 + public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, 2.931 + ExpectedTypeAnnotation expected) { 2.932 + if (expected.matchVisibility(true)) { 2.933 + for(TypeAnnotation anno : attr.annotations) { 2.934 + expected.matchAnnotation(anno); 2.935 + } 2.936 + } 2.937 + 2.938 + return null; 2.939 + } 2.940 + 2.941 + @Override 2.942 + public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, 2.943 + ExpectedTypeAnnotation expected) { 2.944 + if (expected.matchVisibility(false)) { 2.945 + for(TypeAnnotation anno : attr.annotations) { 2.946 + expected.matchAnnotation(anno); 2.947 + } 2.948 + } 2.949 + 2.950 + return null; 2.951 + } 2.952 + }; 2.953 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java Mon Nov 24 12:49:30 2014 -0500 3.3 @@ -0,0 +1,130 @@ 3.4 +/* 3.5 + * Copyright (c) 2014, 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. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/* 3.28 + * @test SyntheticParameters 3.29 + * @summary Test generation of annotations on inner class parameters. 3.30 + * @build ClassfileInspector 3.31 + * @run main SyntheticParameters 3.32 + */ 3.33 + 3.34 +import java.io.*; 3.35 +import java.lang.annotation.*; 3.36 + 3.37 +import com.sun.tools.classfile.*; 3.38 + 3.39 +public class SyntheticParameters extends ClassfileInspector { 3.40 + 3.41 + private static final String Inner_class = "SyntheticParameters$Inner.class"; 3.42 + private static final String Foo_class = "SyntheticParameters$Foo.class"; 3.43 + private static final Expected Inner_expected = 3.44 + new Expected("SyntheticParameters$Inner", 3.45 + null, 3.46 + new ExpectedMethodTypeAnnotation[] { 3.47 + (ExpectedMethodTypeAnnotation) 3.48 + // Assert there is no annotation on the 3.49 + // this$0 parameter. 3.50 + new ExpectedMethodTypeAnnotation.Builder( 3.51 + "<init>", 3.52 + "A", 3.53 + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, 3.54 + false, 3.55 + 0).setParameterIndex(0).build(), 3.56 + (ExpectedMethodTypeAnnotation) 3.57 + // Assert there is an annotation on the 3.58 + // first parameter. 3.59 + new ExpectedMethodTypeAnnotation.Builder( 3.60 + "<init>", 3.61 + "A", 3.62 + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, 3.63 + false, 3.64 + 1).setParameterIndex(1).build(), 3.65 + (ExpectedMethodTypeAnnotation) 3.66 + new ExpectedMethodTypeAnnotation.Builder( 3.67 + "foo", 3.68 + "A", 3.69 + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, 3.70 + false, 3.71 + 1).setParameterIndex(0).build(), 3.72 + (ExpectedMethodTypeAnnotation) 3.73 + new ExpectedMethodTypeAnnotation.Builder( 3.74 + "foo", 3.75 + "A", 3.76 + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, 3.77 + false, 3.78 + 0).setParameterIndex(1).build() 3.79 + }, 3.80 + null); 3.81 + private static final Expected Foo_expected = 3.82 + new Expected("SyntheticParameters$Foo", 3.83 + null, 3.84 + new ExpectedMethodTypeAnnotation[] { 3.85 + (ExpectedMethodTypeAnnotation) 3.86 + // Assert there is no annotation on the 3.87 + // $enum$name parameter. 3.88 + new ExpectedMethodTypeAnnotation.Builder( 3.89 + "<init>", 3.90 + "A", 3.91 + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, 3.92 + false, 3.93 + 0).setParameterIndex(0).build(), 3.94 + (ExpectedMethodTypeAnnotation) 3.95 + // Assert there is no annotation on the 3.96 + // $enum$ordinal parameter. 3.97 + new ExpectedMethodTypeAnnotation.Builder( 3.98 + "<init>", 3.99 + "A", 3.100 + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, 3.101 + false, 3.102 + 0).setParameterIndex(1).build(), 3.103 + (ExpectedMethodTypeAnnotation) 3.104 + // Assert there is an annotation on the 3.105 + // first parameter. 3.106 + new ExpectedMethodTypeAnnotation.Builder( 3.107 + "<init>", 3.108 + "A", 3.109 + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, 3.110 + false, 3.111 + 1).setParameterIndex(2).build() 3.112 + }, 3.113 + null); 3.114 + 3.115 + public static void main(String... args) throws Exception { 3.116 + new SyntheticParameters().run( 3.117 + new ClassFile[] { getClassFile(Inner_class), getClassFile(Foo_class) }, 3.118 + new Expected[] { Inner_expected, Foo_expected }); 3.119 + } 3.120 + 3.121 + public class Inner { 3.122 + public Inner(@A int a) {} 3.123 + public void foo(@A int a, int b) {} 3.124 + } 3.125 + 3.126 + public static enum Foo { 3.127 + ONE(null); 3.128 + Foo(@A Object a) {} 3.129 + } 3.130 +} 3.131 + 3.132 +@Target({ElementType.TYPE_USE}) 3.133 +@interface A {}
4.1 --- a/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Thu Nov 20 14:05:39 2014 -0800 4.2 +++ b/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Mon Nov 24 12:49:30 2014 -0500 4.3 @@ -46,7 +46,7 @@ 4.4 @TADescriptions({ 4.5 @TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {1, 0}), 4.6 @TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0}), 4.7 - @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) 4.8 + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) 4.9 }) 4.10 @TestClass("Test$Inner") 4.11 public String innerClass() { 4.12 @@ -61,7 +61,7 @@ 4.13 @TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0}), 4.14 @TADescription(annotation = "TC", type = METHOD_RECEIVER), 4.15 @TADescription(annotation = "TD", type = METHOD_RETURN, genericLocation = {1, 0}), 4.16 - @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) 4.17 + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) 4.18 }) 4.19 @TestClass("Test$Inner") 4.20 public String innerClass2() { 4.21 @@ -77,7 +77,7 @@ 4.22 @TADescription(annotation = "TC", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}), 4.23 @TADescription(annotation = "TD", type = METHOD_RECEIVER, genericLocation = {1, 0}), 4.24 @TADescription(annotation = "TE", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}), 4.25 - @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) 4.26 + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) 4.27 }) 4.28 @TestClass("Outer$Middle$Inner") 4.29 public String innerClass3() {