1.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Jun 26 12:22:40 2009 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Jun 26 18:51:39 2009 -0700 1.3 @@ -75,6 +75,42 @@ 1.4 /** The name table. */ 1.5 private Names names; 1.6 1.7 + // Because of javac's limited lookahead, some contexts are ambiguous in 1.8 + // the presence of type annotations even though they are not ambiguous 1.9 + // in the absence of type annotations. Consider this code: 1.10 + // void m(String [] m) { } 1.11 + // void m(String ... m) { } 1.12 + // After parsing "String", javac calls bracketsOpt which immediately 1.13 + // returns if the next character is not '['. Similarly, javac can see 1.14 + // if the next token is ... and in that case parse an ellipsis. But in 1.15 + // the presence of type annotations: 1.16 + // void m(String @A [] m) { } 1.17 + // void m(String @A ... m) { } 1.18 + // no finite lookahead is enough to determine whether to read array 1.19 + // levels or an ellipsis. Furthermore, if you call bracketsOpt, then 1.20 + // bracketsOpt first reads all the leading annotations and only then 1.21 + // discovers that it needs to fail. bracketsOpt needs a way to push 1.22 + // back the extra annotations that it read. (But, bracketsOpt should 1.23 + // not *always* be allowed to push back extra annotations that it finds 1.24 + // -- in most contexts, any such extra annotation is an error. 1.25 + // Another similar case occurs with arrays and receiver annotations: 1.26 + // String b() @Array [] @Receiver { } 1.27 + // String b() @Receiver { } 1.28 + // 1.29 + // The following two variables permit type annotations that have 1.30 + // already been read to be stored for later use. Alternate 1.31 + // implementations are possible but would cause much larger changes to 1.32 + // the parser. 1.33 + /** Type annotations that have already been read but have not yet been used. **/ 1.34 + private List<JCTypeAnnotation> typeAnnotationsPushedBack = null; 1.35 + /** 1.36 + * If the parser notices extra annotations, then it either immediately 1.37 + * issues an error (if this variable is false) or places the extra 1.38 + * annotations in variable typeAnnotationsPushedBack (if this variable 1.39 + * is true). 1.40 + */ 1.41 + private boolean permitTypeAnnotationsPushBack = false; 1.42 + 1.43 /** Construct a parser from a given scanner, tree factory and log. 1.44 */ 1.45 protected JavacParser(ParserFactory fac, 1.46 @@ -95,13 +131,19 @@ 1.47 this.allowForeach = source.allowForeach(); 1.48 this.allowStaticImport = source.allowStaticImport(); 1.49 this.allowAnnotations = source.allowAnnotations(); 1.50 + this.allowTypeAnnotations = source.allowTypeAnnotations(); 1.51 this.keepDocComments = keepDocComments; 1.52 if (keepDocComments) 1.53 docComments = new HashMap<JCTree,String>(); 1.54 this.keepLineMap = keepLineMap; 1.55 this.errorTree = F.Erroneous(); 1.56 + this.debugJSR308 = fac.options.get("TA:parser") != null; 1.57 } 1.58 1.59 + /** Switch: debug output for type-annotations operations 1.60 + */ 1.61 + boolean debugJSR308; 1.62 + 1.63 /** Switch: Should generics be recognized? 1.64 */ 1.65 boolean allowGenerics; 1.66 @@ -130,6 +172,10 @@ 1.67 */ 1.68 boolean allowAnnotations; 1.69 1.70 + /** Switch: should we recognize type annotations? 1.71 + */ 1.72 + boolean allowTypeAnnotations; 1.73 + 1.74 /** Switch: should we keep docComments? 1.75 */ 1.76 boolean keepDocComments; 1.77 @@ -558,7 +604,33 @@ 1.78 return term(EXPR); 1.79 } 1.80 1.81 + /** 1.82 + * parses (optional) type annotations followed by a type. If the 1.83 + * annotations are present before the type and are not consumed during array 1.84 + * parsing, this method returns a {@link JCAnnotatedType} consisting of 1.85 + * these annotations and the underlying type. Otherwise, it returns the 1.86 + * underlying type. 1.87 + * 1.88 + * <p> 1.89 + * 1.90 + * Note that this method sets {@code mode} to {@code TYPE} first, before 1.91 + * parsing annotations. 1.92 + */ 1.93 public JCExpression parseType() { 1.94 + List<JCTypeAnnotation> annotations = typeAnnotationsOpt(); 1.95 + return parseType(annotations); 1.96 + } 1.97 + 1.98 + public JCExpression parseType(List<JCTypeAnnotation> annotations) { 1.99 + JCExpression result = unannotatedType(); 1.100 + 1.101 + if (!annotations.isEmpty()) 1.102 + result = F.AnnotatedType(annotations, result); 1.103 + 1.104 + return result; 1.105 + } 1.106 + 1.107 + public JCExpression unannotatedType() { 1.108 return term(TYPE); 1.109 } 1.110 1.111 @@ -792,8 +864,8 @@ 1.112 * | [TypeArguments] THIS [Arguments] 1.113 * | [TypeArguments] SUPER SuperSuffix 1.114 * | NEW [TypeArguments] Creator 1.115 - * | Ident { "." Ident } 1.116 - * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) 1.117 + * | [Annotations] Ident { "." Ident } 1.118 + * [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) 1.119 * | Arguments 1.120 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) 1.121 * ] 1.122 @@ -942,23 +1014,62 @@ 1.123 typeArgs = null; 1.124 } else return illegal(); 1.125 break; 1.126 + case MONKEYS_AT: 1.127 + 1.128 + // only annotated targetting class literals or cast types are valid 1.129 + List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt(); 1.130 + if (typeAnnos.isEmpty()) { 1.131 + // else there would be no '@' 1.132 + throw new AssertionError("type annos is empty"); 1.133 + } 1.134 + 1.135 + JCExpression expr = term3(); 1.136 + 1.137 + // Type annotations: If term3 just parsed a non-type, expect a 1.138 + // class literal (and issue a syntax error if there is no class 1.139 + // literal). Otherwise, create a JCAnnotatedType. 1.140 + if ((mode & TYPE) == 0) { 1.141 + if (expr.getTag() != JCTree.SELECT) 1.142 + return illegal(typeAnnos.head.pos); 1.143 + JCFieldAccess sel = (JCFieldAccess)expr; 1.144 + if (sel.name != names._class) 1.145 + return illegal(); 1.146 + else { 1.147 + sel.selected = F.AnnotatedType(typeAnnos, sel.selected); 1.148 + t = expr; 1.149 + } 1.150 + } else { 1.151 + // type annotation targeting a cast 1.152 + t = toP(F.at(S.pos()).AnnotatedType(typeAnnos, expr)); 1.153 + } 1.154 + break; 1.155 case IDENTIFIER: case ASSERT: case ENUM: 1.156 if (typeArgs != null) return illegal(); 1.157 t = toP(F.at(S.pos()).Ident(ident())); 1.158 loop: while (true) { 1.159 pos = S.pos(); 1.160 + final List<JCTypeAnnotation> annos = typeAnnotationsOpt(); 1.161 + 1.162 + // need to report an error later if LBRACKET is for array 1.163 + // index access rather than array creation level 1.164 + if (!annos.isEmpty() && S.token() != LBRACKET && S.token() != ELLIPSIS) 1.165 + return illegal(annos.head.pos); 1.166 switch (S.token()) { 1.167 case LBRACKET: 1.168 S.nextToken(); 1.169 + 1.170 if (S.token() == RBRACKET) { 1.171 + 1.172 S.nextToken(); 1.173 - t = bracketsOpt(t); 1.174 + 1.175 + t = bracketsOpt(t, annos); 1.176 t = toP(F.at(pos).TypeArray(t)); 1.177 t = bracketsSuffix(t); 1.178 } else { 1.179 if ((mode & EXPR) != 0) { 1.180 mode = EXPR; 1.181 JCExpression t1 = term(); 1.182 + if (!annos.isEmpty()) t = illegal(annos.head.pos); 1.183 t = to(F.at(pos).Indexed(t, t1)); 1.184 } 1.185 accept(RBRACKET); 1.186 @@ -1011,6 +1122,10 @@ 1.187 // typeArgs saved for next loop iteration. 1.188 t = toP(F.at(pos).Select(t, ident())); 1.189 break; 1.190 + case ELLIPSIS: 1.191 + assert this.permitTypeAnnotationsPushBack; 1.192 + typeAnnotationsPushedBack = annos; 1.193 + break loop; 1.194 default: 1.195 break loop; 1.196 } 1.197 @@ -1049,14 +1164,18 @@ 1.198 if (typeArgs != null) illegal(); 1.199 while (true) { 1.200 int pos1 = S.pos(); 1.201 + 1.202 + final List<JCTypeAnnotation> annos = typeAnnotationsOpt(); 1.203 + 1.204 if (S.token() == LBRACKET) { 1.205 S.nextToken(); 1.206 + 1.207 if ((mode & TYPE) != 0) { 1.208 int oldmode = mode; 1.209 mode = TYPE; 1.210 if (S.token() == RBRACKET) { 1.211 S.nextToken(); 1.212 - t = bracketsOpt(t); 1.213 + t = bracketsOpt(t, annos); 1.214 t = toP(F.at(pos1).TypeArray(t)); 1.215 return t; 1.216 } 1.217 @@ -1091,6 +1210,13 @@ 1.218 typeArgs = null; 1.219 } 1.220 } else { 1.221 + if (!annos.isEmpty()) { 1.222 + illegal(0); 1.223 + if (permitTypeAnnotationsPushBack) 1.224 + typeAnnotationsPushedBack = annos; 1.225 + else 1.226 + return illegal(annos.head.pos); 1.227 + } 1.228 break; 1.229 } 1.230 } 1.231 @@ -1100,6 +1226,7 @@ 1.232 S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t)); 1.233 S.nextToken(); 1.234 } 1.235 + 1.236 return toP(t); 1.237 } 1.238 1.239 @@ -1232,22 +1359,24 @@ 1.240 } 1.241 1.242 /** TypeArgument = Type 1.243 - * | "?" 1.244 - * | "?" EXTENDS Type {"&" Type} 1.245 - * | "?" SUPER Type 1.246 + * | [Annotations] "?" 1.247 + * | [Annotations] "?" EXTENDS Type {"&" Type} 1.248 + * | [Annotations] "?" SUPER Type 1.249 */ 1.250 JCExpression typeArgument() { 1.251 - if (S.token() != QUES) return parseType(); 1.252 + List<JCTypeAnnotation> annotations = typeAnnotationsOpt(); 1.253 + if (S.token() != QUES) return parseType(annotations); 1.254 int pos = S.pos(); 1.255 S.nextToken(); 1.256 + JCExpression result; 1.257 if (S.token() == EXTENDS) { 1.258 TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS)); 1.259 S.nextToken(); 1.260 - return F.at(pos).Wildcard(t, parseType()); 1.261 + result = F.at(pos).Wildcard(t, parseType()); 1.262 } else if (S.token() == SUPER) { 1.263 TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER)); 1.264 S.nextToken(); 1.265 - return F.at(pos).Wildcard(t, parseType()); 1.266 + result = F.at(pos).Wildcard(t, parseType()); 1.267 } else if (S.token() == IDENTIFIER) { 1.268 //error recovery 1.269 reportSyntaxError(S.prevEndPos(), "expected3", 1.270 @@ -1255,11 +1384,14 @@ 1.271 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 1.272 JCExpression wc = toP(F.at(pos).Wildcard(t, null)); 1.273 JCIdent id = toP(F.at(S.pos()).Ident(ident())); 1.274 - return F.at(pos).Erroneous(List.<JCTree>of(wc, id)); 1.275 + result = F.at(pos).Erroneous(List.<JCTree>of(wc, id)); 1.276 } else { 1.277 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 1.278 - return toP(F.at(pos).Wildcard(t, null)); 1.279 + result = toP(F.at(pos).Wildcard(t, null)); 1.280 } 1.281 + if (!annotations.isEmpty()) 1.282 + result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result)); 1.283 + return result; 1.284 } 1.285 1.286 JCTypeApply typeArguments(JCExpression t) { 1.287 @@ -1268,21 +1400,47 @@ 1.288 return toP(F.at(pos).TypeApply(t, args)); 1.289 } 1.290 1.291 - /** BracketsOpt = {"[" "]"} 1.292 + /** 1.293 + * BracketsOpt = { [Annotations] "[" "]" } 1.294 + * 1.295 + * <p> 1.296 + * 1.297 + * <code>annotations</code> is the list of annotations targeting 1.298 + * the expression <code>t</code>. 1.299 */ 1.300 - private JCExpression bracketsOpt(JCExpression t) { 1.301 + private JCExpression bracketsOpt(JCExpression t, 1.302 + List<JCTypeAnnotation> annotations) { 1.303 + List<JCTypeAnnotation> nextLevelAnnotations = typeAnnotationsOpt(); 1.304 + 1.305 if (S.token() == LBRACKET) { 1.306 int pos = S.pos(); 1.307 S.nextToken(); 1.308 - t = bracketsOptCont(t, pos); 1.309 - F.at(pos); 1.310 + 1.311 + JCExpression orig = t; 1.312 + t = bracketsOptCont(t, pos, nextLevelAnnotations); 1.313 + } else if (!nextLevelAnnotations.isEmpty()) { 1.314 + if (permitTypeAnnotationsPushBack) { 1.315 + this.typeAnnotationsPushedBack = nextLevelAnnotations; 1.316 + } else 1.317 + return illegal(nextLevelAnnotations.head.pos); 1.318 } 1.319 + 1.320 + int apos = S.pos(); 1.321 + if (!annotations.isEmpty()) 1.322 + t = F.at(apos).AnnotatedType(annotations, t); 1.323 return t; 1.324 } 1.325 1.326 - private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) { 1.327 + /** BracketsOpt = {"[" TypeAnnotations "]"} 1.328 + */ 1.329 + private JCExpression bracketsOpt(JCExpression t) { 1.330 + return bracketsOpt(t, List.<JCTypeAnnotation>nil()); 1.331 + } 1.332 + 1.333 + private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos, 1.334 + List<JCTypeAnnotation> annotations) { 1.335 accept(RBRACKET); 1.336 - t = bracketsOpt(t); 1.337 + t = bracketsOpt(t, annotations); 1.338 return toP(F.at(pos).TypeArray(t)); 1.339 } 1.340 1.341 @@ -1316,18 +1474,29 @@ 1.342 return t; 1.343 } 1.344 1.345 - /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) 1.346 + /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) 1.347 */ 1.348 JCExpression creator(int newpos, List<JCExpression> typeArgs) { 1.349 + 1.350 + List<JCTypeAnnotation> newAnnotations = typeAnnotationsOpt(); 1.351 + 1.352 switch (S.token()) { 1.353 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 1.354 case DOUBLE: case BOOLEAN: 1.355 - if (typeArgs == null) 1.356 - return arrayCreatorRest(newpos, basicType()); 1.357 + if (typeArgs == null) { 1.358 + if (newAnnotations.isEmpty()) 1.359 + return arrayCreatorRest(newpos, basicType()); 1.360 + else 1.361 + return arrayCreatorRest(newpos, F.AnnotatedType(newAnnotations, basicType())); 1.362 + } 1.363 break; 1.364 default: 1.365 } 1.366 JCExpression t = qualident(); 1.367 + // handle type annotations for non primitive arrays 1.368 + if (!newAnnotations.isEmpty()) 1.369 + t = F.AnnotatedType(newAnnotations, t); 1.370 + 1.371 int oldmode = mode; 1.372 mode = TYPE; 1.373 if (S.token() == LT) { 1.374 @@ -1344,7 +1513,7 @@ 1.375 } 1.376 } 1.377 mode = oldmode; 1.378 - if (S.token() == LBRACKET) { 1.379 + if (S.token() == LBRACKET || S.token() == MONKEYS_AT) { 1.380 JCExpression e = arrayCreatorRest(newpos, t); 1.381 if (typeArgs != null) { 1.382 int pos = newpos; 1.383 @@ -1360,7 +1529,12 @@ 1.384 } 1.385 return e; 1.386 } else if (S.token() == LPAREN) { 1.387 - return classCreatorRest(newpos, null, typeArgs, t); 1.388 + JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t); 1.389 + if (newClass.def != null) { 1.390 + assert newClass.def.mods.annotations.isEmpty(); 1.391 + newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations); 1.392 + } 1.393 + return newClass; 1.394 } else { 1.395 reportSyntaxError(S.pos(), "expected2", 1.396 LPAREN, LBRACKET); 1.397 @@ -1380,40 +1554,73 @@ 1.398 return classCreatorRest(newpos, encl, typeArgs, t); 1.399 } 1.400 1.401 - /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer 1.402 - * | Expression "]" {"[" Expression "]"} BracketsOpt ) 1.403 + /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer 1.404 + * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt ) 1.405 */ 1.406 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { 1.407 + 1.408 + List<JCTypeAnnotation> topAnnos = List.nil(); 1.409 + if (elemtype.getTag() == JCTree.ANNOTATED_TYPE) { 1.410 + JCAnnotatedType atype = (JCAnnotatedType) elemtype; 1.411 + topAnnos = atype.annotations; 1.412 + elemtype = atype.underlyingType; 1.413 + } 1.414 + 1.415 + List<JCTypeAnnotation> annos = typeAnnotationsOpt(); 1.416 + 1.417 accept(LBRACKET); 1.418 + 1.419 if (S.token() == RBRACKET) { 1.420 accept(RBRACKET); 1.421 - elemtype = bracketsOpt(elemtype); 1.422 + 1.423 + elemtype = bracketsOpt(elemtype, annos); 1.424 + 1.425 if (S.token() == LBRACE) { 1.426 - return arrayInitializer(newpos, elemtype); 1.427 + JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype); 1.428 + 1.429 + na.annotations = topAnnos; 1.430 + 1.431 + return na; 1.432 } else { 1.433 return syntaxError(S.pos(), "array.dimension.missing"); 1.434 } 1.435 } else { 1.436 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>(); 1.437 + 1.438 + // maintain array dimension type annotations 1.439 + ListBuffer<List<JCTypeAnnotation>> dimAnnotations = ListBuffer.lb(); 1.440 + dimAnnotations.append(annos); 1.441 + 1.442 dims.append(parseExpression()); 1.443 accept(RBRACKET); 1.444 - while (S.token() == LBRACKET) { 1.445 + while (S.token() == LBRACKET 1.446 + || (S.token() == MONKEYS_AT)) { 1.447 + List<JCTypeAnnotation> maybeDimAnnos = typeAnnotationsOpt(); 1.448 int pos = S.pos(); 1.449 S.nextToken(); 1.450 if (S.token() == RBRACKET) { 1.451 - elemtype = bracketsOptCont(elemtype, pos); 1.452 + elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); 1.453 } else { 1.454 - dims.append(parseExpression()); 1.455 - accept(RBRACKET); 1.456 + if (S.token() == RBRACKET) { // no dimension 1.457 + elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); 1.458 + } else { 1.459 + dimAnnotations.append(maybeDimAnnos); 1.460 + dims.append(parseExpression()); 1.461 + accept(RBRACKET); 1.462 + } 1.463 } 1.464 } 1.465 - return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); 1.466 + 1.467 + JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); 1.468 + na.annotations = topAnnos; 1.469 + na.dimAnnotations = dimAnnotations.toList(); 1.470 + return na; 1.471 } 1.472 } 1.473 1.474 /** ClassCreatorRest = Arguments [ClassBody] 1.475 */ 1.476 - JCExpression classCreatorRest(int newpos, 1.477 + JCNewClass classCreatorRest(int newpos, 1.478 JCExpression encl, 1.479 List<JCExpression> typeArgs, 1.480 JCExpression t) 1.481 @@ -1860,17 +2067,32 @@ 1.482 new ListBuffer<JCExpressionStatement>()).toList(); 1.483 } 1.484 1.485 + enum AnnotationKind { DEFAULT_ANNO, TYPE_ANNO }; 1.486 + 1.487 /** AnnotationsOpt = { '@' Annotation } 1.488 */ 1.489 - List<JCAnnotation> annotationsOpt() { 1.490 + List<JCAnnotation> annotationsOpt(AnnotationKind kind) { 1.491 if (S.token() != MONKEYS_AT) return List.nil(); // optimization 1.492 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>(); 1.493 + int prevmode = mode; 1.494 while (S.token() == MONKEYS_AT) { 1.495 int pos = S.pos(); 1.496 S.nextToken(); 1.497 - buf.append(annotation(pos)); 1.498 + buf.append(annotation(pos, kind)); 1.499 } 1.500 - return buf.toList(); 1.501 + lastmode = mode; 1.502 + mode = prevmode; 1.503 + List<JCAnnotation> annotations = buf.toList(); 1.504 + 1.505 + if (debugJSR308 && kind == AnnotationKind.TYPE_ANNO) 1.506 + System.out.println("TA: parsing " + annotations 1.507 + + " in " + log.currentSourceFile()); 1.508 + return annotations; 1.509 + } 1.510 + 1.511 + List<JCTypeAnnotation> typeAnnotationsOpt() { 1.512 + List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.TYPE_ANNO); 1.513 + return List.convert(JCTypeAnnotation.class, annotations); 1.514 } 1.515 1.516 /** ModifiersOpt = { Modifier } 1.517 @@ -1915,7 +2137,7 @@ 1.518 if (flag == Flags.ANNOTATION) { 1.519 checkAnnotations(); 1.520 if (S.token() != INTERFACE) { 1.521 - JCAnnotation ann = annotation(lastPos); 1.522 + JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO); 1.523 // if first modifier is an annotation, set pos to annotation's. 1.524 if (flags == 0 && annotations.isEmpty()) 1.525 pos = ann.pos; 1.526 @@ -1946,12 +2168,18 @@ 1.527 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] 1.528 * @param pos position of "@" token 1.529 */ 1.530 - JCAnnotation annotation(int pos) { 1.531 + JCAnnotation annotation(int pos, AnnotationKind kind) { 1.532 // accept(AT); // AT consumed by caller 1.533 checkAnnotations(); 1.534 + if (kind == AnnotationKind.TYPE_ANNO) 1.535 + checkTypeAnnotations(); 1.536 JCTree ident = qualident(); 1.537 List<JCExpression> fieldValues = annotationFieldValuesOpt(); 1.538 - JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); 1.539 + JCAnnotation ann; 1.540 + if (kind == AnnotationKind.DEFAULT_ANNO) 1.541 + ann = F.at(pos).Annotation(ident, fieldValues); 1.542 + else 1.543 + ann = F.at(pos).TypeAnnotation(ident, fieldValues); 1.544 storeEnd(ann, S.prevEndPos()); 1.545 return ann; 1.546 } 1.547 @@ -2003,7 +2231,7 @@ 1.548 case MONKEYS_AT: 1.549 pos = S.pos(); 1.550 S.nextToken(); 1.551 - return annotation(pos); 1.552 + return annotation(pos, AnnotationKind.DEFAULT_ANNO); 1.553 case LBRACE: 1.554 pos = S.pos(); 1.555 accept(LBRACE); 1.556 @@ -2357,7 +2585,7 @@ 1.557 S.resetDeprecatedFlag(); 1.558 } 1.559 int pos = S.pos(); 1.560 - List<JCAnnotation> annotations = annotationsOpt(); 1.561 + List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.DEFAULT_ANNO); 1.562 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 1.563 List<JCExpression> typeArgs = typeArgumentsOpt(); 1.564 int identPos = S.pos(); 1.565 @@ -2460,16 +2688,23 @@ 1.566 if (typarams.length() > 0 && mods.pos == Position.NOPOS) { 1.567 mods.pos = pos; 1.568 } 1.569 + 1.570 + List<JCAnnotation> annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO); 1.571 + 1.572 Token token = S.token(); 1.573 Name name = S.name(); 1.574 pos = S.pos(); 1.575 JCExpression type; 1.576 boolean isVoid = S.token() == VOID; 1.577 if (isVoid) { 1.578 + if (annosAfterParams.nonEmpty()) 1.579 + illegal(annosAfterParams.head.pos); 1.580 type = to(F.at(pos).TypeIdent(TypeTags.VOID)); 1.581 S.nextToken(); 1.582 } else { 1.583 - type = parseType(); 1.584 + mods.annotations = mods.annotations.appendList(annosAfterParams); 1.585 + // method returns types are un-annotated types 1.586 + type = unannotatedType(); 1.587 } 1.588 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { 1.589 if (isInterface || name != className) 1.590 @@ -2505,15 +2740,15 @@ 1.591 } 1.592 1.593 /** MethodDeclaratorRest = 1.594 - * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 1.595 + * FormalParameters BracketsOpt [Annotations] [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 1.596 * VoidMethodDeclaratorRest = 1.597 - * FormalParameters [Throws TypeList] ( MethodBody | ";") 1.598 + * FormalParameters [Annotations] [Throws TypeList] ( MethodBody | ";") 1.599 * InterfaceMethodDeclaratorRest = 1.600 - * FormalParameters BracketsOpt [THROWS TypeList] ";" 1.601 + * FormalParameters BracketsOpt [Annotations] [THROWS TypeList] ";" 1.602 * VoidInterfaceMethodDeclaratorRest = 1.603 - * FormalParameters [THROWS TypeList] ";" 1.604 + * FormalParameters [Annotations] [THROWS TypeList] ";" 1.605 * ConstructorDeclaratorRest = 1.606 - * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody 1.607 + * "(" FormalParameterListOpt ")" [Annotations] [THROWS TypeList] MethodBody 1.608 */ 1.609 JCTree methodDeclaratorRest(int pos, 1.610 JCModifiers mods, 1.611 @@ -2523,7 +2758,22 @@ 1.612 boolean isInterface, boolean isVoid, 1.613 String dc) { 1.614 List<JCVariableDecl> params = formalParameters(); 1.615 - if (!isVoid) type = bracketsOpt(type); 1.616 + 1.617 + List<JCTypeAnnotation> receiverAnnotations; 1.618 + if (!isVoid) { 1.619 + // need to distinguish between receiver anno and array anno 1.620 + // look at typeAnnotationsPushedBack comment 1.621 + this.permitTypeAnnotationsPushBack = true; 1.622 + type = methodReturnArrayRest(type); 1.623 + this.permitTypeAnnotationsPushBack = false; 1.624 + if (typeAnnotationsPushedBack == null) 1.625 + receiverAnnotations = List.nil(); 1.626 + else 1.627 + receiverAnnotations = typeAnnotationsPushedBack; 1.628 + typeAnnotationsPushedBack = null; 1.629 + } else 1.630 + receiverAnnotations = typeAnnotationsOpt(); 1.631 + 1.632 List<JCExpression> thrown = List.nil(); 1.633 if (S.token() == THROWS) { 1.634 S.nextToken(); 1.635 @@ -2552,20 +2802,51 @@ 1.636 } 1.637 JCMethodDecl result = 1.638 toP(F.at(pos).MethodDef(mods, name, type, typarams, 1.639 - params, thrown, 1.640 + params, receiverAnnotations, thrown, 1.641 body, defaultValue)); 1.642 attach(result, dc); 1.643 return result; 1.644 } 1.645 1.646 - /** QualidentList = Qualident {"," Qualident} 1.647 + /** Parses the array levels after the format parameters list, and append 1.648 + * them to the return type, while preseving the order of type annotations 1.649 + */ 1.650 + private JCExpression methodReturnArrayRest(JCExpression type) { 1.651 + if (type.getTag() != JCTree.TYPEARRAY) 1.652 + return bracketsOpt(type); 1.653 + 1.654 + JCArrayTypeTree baseArray = (JCArrayTypeTree)type; 1.655 + while (TreeInfo.typeIn(baseArray.elemtype) instanceof JCArrayTypeTree) 1.656 + baseArray = (JCArrayTypeTree)TreeInfo.typeIn(baseArray.elemtype); 1.657 + 1.658 + if (baseArray.elemtype.getTag() == JCTree.ANNOTATED_TYPE) { 1.659 + JCAnnotatedType at = (JCAnnotatedType)baseArray.elemtype; 1.660 + at.underlyingType = bracketsOpt(at.underlyingType); 1.661 + } else { 1.662 + baseArray.elemtype = bracketsOpt(baseArray.elemtype); 1.663 + } 1.664 + 1.665 + return type; 1.666 + } 1.667 + 1.668 + /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident} 1.669 */ 1.670 List<JCExpression> qualidentList() { 1.671 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 1.672 - ts.append(qualident()); 1.673 + 1.674 + List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt(); 1.675 + if (!typeAnnos.isEmpty()) 1.676 + ts.append(F.AnnotatedType(typeAnnos, qualident())); 1.677 + else 1.678 + ts.append(qualident()); 1.679 while (S.token() == COMMA) { 1.680 S.nextToken(); 1.681 - ts.append(qualident()); 1.682 + 1.683 + typeAnnos = typeAnnotationsOpt(); 1.684 + if (!typeAnnos.isEmpty()) 1.685 + ts.append(F.AnnotatedType(typeAnnos, qualident())); 1.686 + else 1.687 + ts.append(qualident()); 1.688 } 1.689 return ts.toList(); 1.690 } 1.691 @@ -2589,12 +2870,13 @@ 1.692 } 1.693 } 1.694 1.695 - /** TypeParameter = TypeVariable [TypeParameterBound] 1.696 + /** TypeParameter = [Annotations] TypeVariable [TypeParameterBound] 1.697 * TypeParameterBound = EXTENDS Type {"&" Type} 1.698 * TypeVariable = Ident 1.699 */ 1.700 JCTypeParameter typeParameter() { 1.701 int pos = S.pos(); 1.702 + List<JCTypeAnnotation> annos = typeAnnotationsOpt(); 1.703 Name name = ident(); 1.704 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); 1.705 if (S.token() == EXTENDS) { 1.706 @@ -2605,7 +2887,7 @@ 1.707 bounds.append(parseType()); 1.708 } 1.709 } 1.710 - return toP(F.at(pos).TypeParameter(name, bounds.toList())); 1.711 + return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos)); 1.712 } 1.713 1.714 /** FormalParameters = "(" [ FormalParameterList ] ")" 1.715 @@ -2639,12 +2921,31 @@ 1.716 */ 1.717 JCVariableDecl formalParameter() { 1.718 JCModifiers mods = optFinal(Flags.PARAMETER); 1.719 + // need to distinguish between vararg annos and array annos 1.720 + // look at typeAnnotaitonsPushedBack comment 1.721 + this.permitTypeAnnotationsPushBack = true; 1.722 JCExpression type = parseType(); 1.723 + this.permitTypeAnnotationsPushBack = false; 1.724 + 1.725 if (S.token() == ELLIPSIS) { 1.726 + List<JCTypeAnnotation> varargsAnnos = typeAnnotationsPushedBack; 1.727 + typeAnnotationsPushedBack = null; 1.728 checkVarargs(); 1.729 mods.flags |= Flags.VARARGS; 1.730 + // insert var arg type annotations 1.731 + if (varargsAnnos != null && varargsAnnos.nonEmpty()) 1.732 + type = F.at(S.pos()).AnnotatedType(varargsAnnos, type); 1.733 type = to(F.at(S.pos()).TypeArray(type)); 1.734 + 1.735 S.nextToken(); 1.736 + } else { 1.737 + // if not a var arg, then typeAnnotationsPushedBack should be null 1.738 + if (typeAnnotationsPushedBack != null 1.739 + && !typeAnnotationsPushedBack.isEmpty()) { 1.740 + reportSyntaxError(typeAnnotationsPushedBack.head.pos, 1.741 + "illegal.start.of.type"); 1.742 + } 1.743 + typeAnnotationsPushedBack = null; 1.744 } 1.745 return variableDeclaratorId(mods, type); 1.746 } 1.747 @@ -2829,4 +3130,10 @@ 1.748 allowAnnotations = true; 1.749 } 1.750 } 1.751 + void checkTypeAnnotations() { 1.752 + if (!allowTypeAnnotations) { 1.753 + log.error(S.pos(), "type.annotations.not.supported.in.source", source.name); 1.754 + allowTypeAnnotations = true; 1.755 + } 1.756 + } 1.757 }