langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
changeset 3149 0cd06d598d6f
parent 2723 b659ca23d5f5
child 3151 41800a86aad3
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Jun 26 12:22:40 2009 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Jun 26 18:51:39 2009 -0700
@@ -75,6 +75,42 @@
     /** The name table. */
     private Names names;
 
+    // Because of javac's limited lookahead, some contexts are ambiguous in
+    // the presence of type annotations even though they are not ambiguous
+    // in the absence of type annotations.  Consider this code:
+    //   void m(String [] m) { }
+    //   void m(String ... m) { }
+    // After parsing "String", javac calls bracketsOpt which immediately
+    // returns if the next character is not '['.  Similarly, javac can see
+    // if the next token is ... and in that case parse an ellipsis.  But in
+    // the presence of type annotations:
+    //   void m(String @A [] m) { }
+    //   void m(String @A ... m) { }
+    // no finite lookahead is enough to determine whether to read array
+    // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
+    // bracketsOpt first reads all the leading annotations and only then
+    // discovers that it needs to fail.  bracketsOpt needs a way to push
+    // back the extra annotations that it read.  (But, bracketsOpt should
+    // not *always* be allowed to push back extra annotations that it finds
+    // -- in most contexts, any such extra annotation is an error.
+    // Another similar case occurs with arrays and receiver annotations:
+    //   String b() @Array [] @Receiver { }
+    //   String b() @Receiver { }
+    //
+    // The following two variables permit type annotations that have
+    // already been read to be stored for later use.  Alternate
+    // implementations are possible but would cause much larger changes to
+    // the parser.
+    /** Type annotations that have already been read but have not yet been used. **/
+    private List<JCTypeAnnotation> typeAnnotationsPushedBack = null;
+    /**
+     * If the parser notices extra annotations, then it either immediately
+     * issues an error (if this variable is false) or places the extra
+     * annotations in variable typeAnnotationsPushedBack (if this variable
+     * is true).
+     */
+    private boolean permitTypeAnnotationsPushBack = false;
+
     /** Construct a parser from a given scanner, tree factory and log.
      */
     protected JavacParser(ParserFactory fac,
@@ -95,13 +131,19 @@
         this.allowForeach = source.allowForeach();
         this.allowStaticImport = source.allowStaticImport();
         this.allowAnnotations = source.allowAnnotations();
+        this.allowTypeAnnotations = source.allowTypeAnnotations();
         this.keepDocComments = keepDocComments;
         if (keepDocComments)
             docComments = new HashMap<JCTree,String>();
         this.keepLineMap = keepLineMap;
         this.errorTree = F.Erroneous();
+        this.debugJSR308 = fac.options.get("TA:parser") != null;
     }
 
+    /** Switch: debug output for type-annotations operations
+     */
+    boolean debugJSR308;
+
     /** Switch: Should generics be recognized?
      */
     boolean allowGenerics;
@@ -130,6 +172,10 @@
      */
     boolean allowAnnotations;
 
+    /** Switch: should we recognize type annotations?
+     */
+    boolean allowTypeAnnotations;
+
     /** Switch: should we keep docComments?
      */
     boolean keepDocComments;
@@ -558,7 +604,33 @@
         return term(EXPR);
     }
 
+    /**
+     * parses (optional) type annotations followed by a type. If the
+     * annotations are present before the type and are not consumed during array
+     * parsing, this method returns a {@link JCAnnotatedType} consisting of
+     * these annotations and the underlying type. Otherwise, it returns the
+     * underlying type.
+     *
+     * <p>
+     *
+     * Note that this method sets {@code mode} to {@code TYPE} first, before
+     * parsing annotations.
+     */
     public JCExpression parseType() {
+        List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
+        return parseType(annotations);
+    }
+
+    public JCExpression parseType(List<JCTypeAnnotation> annotations) {
+        JCExpression result = unannotatedType();
+
+        if (!annotations.isEmpty())
+            result = F.AnnotatedType(annotations, result);
+
+        return result;
+    }
+
+    public JCExpression unannotatedType() {
         return term(TYPE);
     }
 
@@ -792,8 +864,8 @@
      *                 | [TypeArguments] THIS [Arguments]
      *                 | [TypeArguments] SUPER SuperSuffix
      *                 | NEW [TypeArguments] Creator
-     *                 | Ident { "." Ident }
-     *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
+     *                 | [Annotations] Ident { "." Ident }
+     *                   [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
      *                   | Arguments
      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
      *                   ]
@@ -942,23 +1014,62 @@
                 typeArgs = null;
             } else return illegal();
             break;
+        case MONKEYS_AT:
+
+            // only annotated targetting class literals or cast types are valid
+            List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
+            if (typeAnnos.isEmpty()) {
+                // else there would be no '@'
+                throw new AssertionError("type annos is empty");
+            }
+
+            JCExpression expr = term3();
+
+            // Type annotations: If term3 just parsed a non-type, expect a
+            // class literal (and issue a syntax error if there is no class
+            // literal). Otherwise, create a JCAnnotatedType.
+            if ((mode & TYPE) == 0) {
+                if (expr.getTag() != JCTree.SELECT)
+                    return illegal(typeAnnos.head.pos);
+                JCFieldAccess sel = (JCFieldAccess)expr;
+                if (sel.name != names._class)
+                    return illegal();
+                else {
+                    sel.selected = F.AnnotatedType(typeAnnos, sel.selected);
+                    t = expr;
+                }
+            } else {
+                // type annotation targeting a cast
+                t = toP(F.at(S.pos()).AnnotatedType(typeAnnos, expr));
+            }
+            break;
         case IDENTIFIER: case ASSERT: case ENUM:
             if (typeArgs != null) return illegal();
             t = toP(F.at(S.pos()).Ident(ident()));
             loop: while (true) {
                 pos = S.pos();
+                final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
+
+                // need to report an error later if LBRACKET is for array
+                // index access rather than array creation level
+                if (!annos.isEmpty() && S.token() != LBRACKET && S.token() != ELLIPSIS)
+                    return illegal(annos.head.pos);
                 switch (S.token()) {
                 case LBRACKET:
                     S.nextToken();
+
                     if (S.token() == RBRACKET) {
+
                         S.nextToken();
-                        t = bracketsOpt(t);
+
+                        t = bracketsOpt(t, annos);
                         t = toP(F.at(pos).TypeArray(t));
                         t = bracketsSuffix(t);
                     } else {
                         if ((mode & EXPR) != 0) {
                             mode = EXPR;
                             JCExpression t1 = term();
+                            if (!annos.isEmpty()) t = illegal(annos.head.pos);
                             t = to(F.at(pos).Indexed(t, t1));
                         }
                         accept(RBRACKET);
@@ -1011,6 +1122,10 @@
                     // typeArgs saved for next loop iteration.
                     t = toP(F.at(pos).Select(t, ident()));
                     break;
+                case ELLIPSIS:
+                    assert this.permitTypeAnnotationsPushBack;
+                    typeAnnotationsPushedBack = annos;
+                    break loop;
                 default:
                     break loop;
                 }
@@ -1049,14 +1164,18 @@
         if (typeArgs != null) illegal();
         while (true) {
             int pos1 = S.pos();
+
+            final List<JCTypeAnnotation> annos = typeAnnotationsOpt();
+
             if (S.token() == LBRACKET) {
                 S.nextToken();
+
                 if ((mode & TYPE) != 0) {
                     int oldmode = mode;
                     mode = TYPE;
                     if (S.token() == RBRACKET) {
                         S.nextToken();
-                        t = bracketsOpt(t);
+                        t = bracketsOpt(t, annos);
                         t = toP(F.at(pos1).TypeArray(t));
                         return t;
                     }
@@ -1091,6 +1210,13 @@
                     typeArgs = null;
                 }
             } else {
+                if (!annos.isEmpty()) {
+                    illegal(0);
+                    if (permitTypeAnnotationsPushBack)
+                        typeAnnotationsPushedBack = annos;
+                    else
+                        return illegal(annos.head.pos);
+                }
                 break;
             }
         }
@@ -1100,6 +1226,7 @@
                   S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
             S.nextToken();
         }
+
         return toP(t);
     }
 
@@ -1232,22 +1359,24 @@
     }
 
     /** TypeArgument = Type
-     *               | "?"
-     *               | "?" EXTENDS Type {"&" Type}
-     *               | "?" SUPER Type
+     *               | [Annotations] "?"
+     *               | [Annotations] "?" EXTENDS Type {"&" Type}
+     *               | [Annotations] "?" SUPER Type
      */
     JCExpression typeArgument() {
-        if (S.token() != QUES) return parseType();
+        List<JCTypeAnnotation> annotations = typeAnnotationsOpt();
+        if (S.token() != QUES) return parseType(annotations);
         int pos = S.pos();
         S.nextToken();
+        JCExpression result;
         if (S.token() == EXTENDS) {
             TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
             S.nextToken();
-            return F.at(pos).Wildcard(t, parseType());
+            result = F.at(pos).Wildcard(t, parseType());
         } else if (S.token() == SUPER) {
             TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
             S.nextToken();
-            return F.at(pos).Wildcard(t, parseType());
+            result = F.at(pos).Wildcard(t, parseType());
         } else if (S.token() == IDENTIFIER) {
             //error recovery
             reportSyntaxError(S.prevEndPos(), "expected3",
@@ -1255,11 +1384,14 @@
             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
-            return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
+            result = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
         } else {
             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
-            return toP(F.at(pos).Wildcard(t, null));
+            result = toP(F.at(pos).Wildcard(t, null));
         }
+        if (!annotations.isEmpty())
+            result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
+        return result;
     }
 
     JCTypeApply typeArguments(JCExpression t) {
@@ -1268,21 +1400,47 @@
         return toP(F.at(pos).TypeApply(t, args));
     }
 
-    /** BracketsOpt = {"[" "]"}
+    /**
+     * BracketsOpt = { [Annotations] "[" "]" }
+     *
+     * <p>
+     *
+     * <code>annotations</code> is the list of annotations targeting
+     * the expression <code>t</code>.
      */
-    private JCExpression bracketsOpt(JCExpression t) {
+    private JCExpression bracketsOpt(JCExpression t,
+            List<JCTypeAnnotation> annotations) {
+        List<JCTypeAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
+
         if (S.token() == LBRACKET) {
             int pos = S.pos();
             S.nextToken();
-            t = bracketsOptCont(t, pos);
-            F.at(pos);
+
+            JCExpression orig = t;
+            t = bracketsOptCont(t, pos, nextLevelAnnotations);
+        } else if (!nextLevelAnnotations.isEmpty()) {
+            if (permitTypeAnnotationsPushBack) {
+                this.typeAnnotationsPushedBack = nextLevelAnnotations;
+            } else
+                return illegal(nextLevelAnnotations.head.pos);
         }
+
+        int apos = S.pos();
+        if (!annotations.isEmpty())
+            t = F.at(apos).AnnotatedType(annotations, t);
         return t;
     }
 
-    private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
+    /** BracketsOpt = {"[" TypeAnnotations "]"}
+     */
+    private JCExpression bracketsOpt(JCExpression t) {
+        return bracketsOpt(t, List.<JCTypeAnnotation>nil());
+    }
+
+    private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos,
+            List<JCTypeAnnotation> annotations) {
         accept(RBRACKET);
-        t = bracketsOpt(t);
+        t = bracketsOpt(t, annotations);
         return toP(F.at(pos).TypeArray(t));
     }
 
@@ -1316,18 +1474,29 @@
         return t;
     }
 
-    /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
+    /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
      */
     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
+
+        List<JCTypeAnnotation> newAnnotations = typeAnnotationsOpt();
+
         switch (S.token()) {
         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
         case DOUBLE: case BOOLEAN:
-            if (typeArgs == null)
-                return arrayCreatorRest(newpos, basicType());
+            if (typeArgs == null) {
+                if (newAnnotations.isEmpty())
+                    return arrayCreatorRest(newpos, basicType());
+                else
+                    return arrayCreatorRest(newpos, F.AnnotatedType(newAnnotations, basicType()));
+            }
             break;
         default:
         }
         JCExpression t = qualident();
+        // handle type annotations for non primitive arrays
+        if (!newAnnotations.isEmpty())
+            t = F.AnnotatedType(newAnnotations, t);
+
         int oldmode = mode;
         mode = TYPE;
         if (S.token() == LT) {
@@ -1344,7 +1513,7 @@
             }
         }
         mode = oldmode;
-        if (S.token() == LBRACKET) {
+        if (S.token() == LBRACKET || S.token() == MONKEYS_AT) {
             JCExpression e = arrayCreatorRest(newpos, t);
             if (typeArgs != null) {
                 int pos = newpos;
@@ -1360,7 +1529,12 @@
             }
             return e;
         } else if (S.token() == LPAREN) {
-            return classCreatorRest(newpos, null, typeArgs, t);
+            JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t);
+            if (newClass.def != null) {
+                assert newClass.def.mods.annotations.isEmpty();
+                newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations);
+            }
+            return newClass;
         } else {
             reportSyntaxError(S.pos(), "expected2",
                                LPAREN, LBRACKET);
@@ -1380,40 +1554,73 @@
         return classCreatorRest(newpos, encl, typeArgs, t);
     }
 
-    /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
-     *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
+    /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
+     *                         | Expression "]" {[Annotations]  "[" Expression "]"} BracketsOpt )
      */
     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
+
+        List<JCTypeAnnotation> topAnnos = List.nil();
+        if (elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
+            JCAnnotatedType atype = (JCAnnotatedType) elemtype;
+            topAnnos = atype.annotations;
+            elemtype = atype.underlyingType;
+        }
+
+        List<JCTypeAnnotation> annos = typeAnnotationsOpt();
+
         accept(LBRACKET);
+
         if (S.token() == RBRACKET) {
             accept(RBRACKET);
-            elemtype = bracketsOpt(elemtype);
+
+            elemtype = bracketsOpt(elemtype, annos);
+
             if (S.token() == LBRACE) {
-                return arrayInitializer(newpos, elemtype);
+                JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
+
+                na.annotations = topAnnos;
+
+                return na;
             } else {
                 return syntaxError(S.pos(), "array.dimension.missing");
             }
         } else {
             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
+
+            // maintain array dimension type annotations
+            ListBuffer<List<JCTypeAnnotation>> dimAnnotations = ListBuffer.lb();
+            dimAnnotations.append(annos);
+
             dims.append(parseExpression());
             accept(RBRACKET);
-            while (S.token() == LBRACKET) {
+            while (S.token() == LBRACKET
+                    || (S.token() == MONKEYS_AT)) {
+                List<JCTypeAnnotation> maybeDimAnnos = typeAnnotationsOpt();
                 int pos = S.pos();
                 S.nextToken();
                 if (S.token() == RBRACKET) {
-                    elemtype = bracketsOptCont(elemtype, pos);
+                    elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
                 } else {
-                    dims.append(parseExpression());
-                    accept(RBRACKET);
+                    if (S.token() == RBRACKET) { // no dimension
+                        elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
+                    } else {
+                        dimAnnotations.append(maybeDimAnnos);
+                        dims.append(parseExpression());
+                        accept(RBRACKET);
+                    }
                 }
             }
-            return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
+
+            JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
+            na.annotations = topAnnos;
+            na.dimAnnotations = dimAnnotations.toList();
+            return na;
         }
     }
 
     /** ClassCreatorRest = Arguments [ClassBody]
      */
-    JCExpression classCreatorRest(int newpos,
+    JCNewClass classCreatorRest(int newpos,
                                   JCExpression encl,
                                   List<JCExpression> typeArgs,
                                   JCExpression t)
@@ -1860,17 +2067,32 @@
                                         new ListBuffer<JCExpressionStatement>()).toList();
     }
 
+    enum AnnotationKind { DEFAULT_ANNO, TYPE_ANNO };
+
     /** AnnotationsOpt = { '@' Annotation }
      */
-    List<JCAnnotation> annotationsOpt() {
+    List<JCAnnotation> annotationsOpt(AnnotationKind kind) {
         if (S.token() != MONKEYS_AT) return List.nil(); // optimization
         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
+        int prevmode = mode;
         while (S.token() == MONKEYS_AT) {
             int pos = S.pos();
             S.nextToken();
-            buf.append(annotation(pos));
+            buf.append(annotation(pos, kind));
         }
-        return buf.toList();
+        lastmode = mode;
+        mode = prevmode;
+        List<JCAnnotation> annotations = buf.toList();
+
+        if (debugJSR308 && kind == AnnotationKind.TYPE_ANNO)
+            System.out.println("TA: parsing " + annotations
+                    + " in " + log.currentSourceFile());
+        return annotations;
+    }
+
+    List<JCTypeAnnotation> typeAnnotationsOpt() {
+        List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.TYPE_ANNO);
+        return List.convert(JCTypeAnnotation.class, annotations);
     }
 
     /** ModifiersOpt = { Modifier }
@@ -1915,7 +2137,7 @@
             if (flag == Flags.ANNOTATION) {
                 checkAnnotations();
                 if (S.token() != INTERFACE) {
-                JCAnnotation ann = annotation(lastPos);
+                JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO);
                 // if first modifier is an annotation, set pos to annotation's.
                 if (flags == 0 && annotations.isEmpty())
                     pos = ann.pos;
@@ -1946,12 +2168,18 @@
     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
      * @param pos position of "@" token
      */
-    JCAnnotation annotation(int pos) {
+    JCAnnotation annotation(int pos, AnnotationKind kind) {
         // accept(AT); // AT consumed by caller
         checkAnnotations();
+        if (kind == AnnotationKind.TYPE_ANNO)
+            checkTypeAnnotations();
         JCTree ident = qualident();
         List<JCExpression> fieldValues = annotationFieldValuesOpt();
-        JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
+        JCAnnotation ann;
+        if (kind == AnnotationKind.DEFAULT_ANNO)
+            ann = F.at(pos).Annotation(ident, fieldValues);
+        else
+            ann = F.at(pos).TypeAnnotation(ident, fieldValues);
         storeEnd(ann, S.prevEndPos());
         return ann;
     }
@@ -2003,7 +2231,7 @@
         case MONKEYS_AT:
             pos = S.pos();
             S.nextToken();
-            return annotation(pos);
+            return annotation(pos, AnnotationKind.DEFAULT_ANNO);
         case LBRACE:
             pos = S.pos();
             accept(LBRACE);
@@ -2357,7 +2585,7 @@
             S.resetDeprecatedFlag();
         }
         int pos = S.pos();
-        List<JCAnnotation> annotations = annotationsOpt();
+        List<JCAnnotation> annotations = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
         List<JCExpression> typeArgs = typeArgumentsOpt();
         int identPos = S.pos();
@@ -2460,16 +2688,23 @@
                 if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
                     mods.pos = pos;
                 }
+
+                List<JCAnnotation> annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO);
+
                 Token token = S.token();
                 Name name = S.name();
                 pos = S.pos();
                 JCExpression type;
                 boolean isVoid = S.token() == VOID;
                 if (isVoid) {
+                    if (annosAfterParams.nonEmpty())
+                        illegal(annosAfterParams.head.pos);
                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
                     S.nextToken();
                 } else {
-                    type = parseType();
+                    mods.annotations = mods.annotations.appendList(annosAfterParams);
+                    // method returns types are un-annotated types
+                    type = unannotatedType();
                 }
                 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
                     if (isInterface || name != className)
@@ -2505,15 +2740,15 @@
     }
 
     /** MethodDeclaratorRest =
-     *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
+     *      FormalParameters BracketsOpt [Annotations] [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
      *  VoidMethodDeclaratorRest =
-     *      FormalParameters [Throws TypeList] ( MethodBody | ";")
+     *      FormalParameters [Annotations] [Throws TypeList] ( MethodBody | ";")
      *  InterfaceMethodDeclaratorRest =
-     *      FormalParameters BracketsOpt [THROWS TypeList] ";"
+     *      FormalParameters BracketsOpt [Annotations] [THROWS TypeList] ";"
      *  VoidInterfaceMethodDeclaratorRest =
-     *      FormalParameters [THROWS TypeList] ";"
+     *      FormalParameters [Annotations] [THROWS TypeList] ";"
      *  ConstructorDeclaratorRest =
-     *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
+     *      "(" FormalParameterListOpt ")" [Annotations] [THROWS TypeList] MethodBody
      */
     JCTree methodDeclaratorRest(int pos,
                               JCModifiers mods,
@@ -2523,7 +2758,22 @@
                               boolean isInterface, boolean isVoid,
                               String dc) {
         List<JCVariableDecl> params = formalParameters();
-        if (!isVoid) type = bracketsOpt(type);
+
+        List<JCTypeAnnotation> receiverAnnotations;
+        if (!isVoid) {
+            // need to distinguish between receiver anno and array anno
+            // look at typeAnnotationsPushedBack comment
+            this.permitTypeAnnotationsPushBack = true;
+            type = methodReturnArrayRest(type);
+            this.permitTypeAnnotationsPushBack = false;
+            if (typeAnnotationsPushedBack == null)
+                receiverAnnotations = List.nil();
+            else
+                receiverAnnotations = typeAnnotationsPushedBack;
+            typeAnnotationsPushedBack = null;
+        } else
+            receiverAnnotations = typeAnnotationsOpt();
+
         List<JCExpression> thrown = List.nil();
         if (S.token() == THROWS) {
             S.nextToken();
@@ -2552,20 +2802,51 @@
         }
         JCMethodDecl result =
             toP(F.at(pos).MethodDef(mods, name, type, typarams,
-                                    params, thrown,
+                                    params, receiverAnnotations, thrown,
                                     body, defaultValue));
         attach(result, dc);
         return result;
     }
 
-    /** QualidentList = Qualident {"," Qualident}
+    /** Parses the array levels after the format parameters list, and append
+     * them to the return type, while preseving the order of type annotations
+     */
+    private JCExpression methodReturnArrayRest(JCExpression type) {
+        if (type.getTag() != JCTree.TYPEARRAY)
+            return bracketsOpt(type);
+
+        JCArrayTypeTree baseArray = (JCArrayTypeTree)type;
+        while (TreeInfo.typeIn(baseArray.elemtype) instanceof JCArrayTypeTree)
+            baseArray = (JCArrayTypeTree)TreeInfo.typeIn(baseArray.elemtype);
+
+        if (baseArray.elemtype.getTag() == JCTree.ANNOTATED_TYPE) {
+            JCAnnotatedType at = (JCAnnotatedType)baseArray.elemtype;
+            at.underlyingType = bracketsOpt(at.underlyingType);
+        } else {
+            baseArray.elemtype = bracketsOpt(baseArray.elemtype);
+        }
+
+        return type;
+    }
+
+    /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
      */
     List<JCExpression> qualidentList() {
         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
-        ts.append(qualident());
+
+        List<JCTypeAnnotation> typeAnnos = typeAnnotationsOpt();
+        if (!typeAnnos.isEmpty())
+            ts.append(F.AnnotatedType(typeAnnos, qualident()));
+        else
+            ts.append(qualident());
         while (S.token() == COMMA) {
             S.nextToken();
-            ts.append(qualident());
+
+            typeAnnos = typeAnnotationsOpt();
+            if (!typeAnnos.isEmpty())
+                ts.append(F.AnnotatedType(typeAnnos, qualident()));
+            else
+                ts.append(qualident());
         }
         return ts.toList();
     }
@@ -2589,12 +2870,13 @@
         }
     }
 
-    /** TypeParameter = TypeVariable [TypeParameterBound]
+    /** TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
      *  TypeParameterBound = EXTENDS Type {"&" Type}
      *  TypeVariable = Ident
      */
     JCTypeParameter typeParameter() {
         int pos = S.pos();
+        List<JCTypeAnnotation> annos = typeAnnotationsOpt();
         Name name = ident();
         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
         if (S.token() == EXTENDS) {
@@ -2605,7 +2887,7 @@
                 bounds.append(parseType());
             }
         }
-        return toP(F.at(pos).TypeParameter(name, bounds.toList()));
+        return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
     }
 
     /** FormalParameters = "(" [ FormalParameterList ] ")"
@@ -2639,12 +2921,31 @@
      */
     JCVariableDecl formalParameter() {
         JCModifiers mods = optFinal(Flags.PARAMETER);
+        // need to distinguish between vararg annos and array annos
+        // look at typeAnnotaitonsPushedBack comment
+        this.permitTypeAnnotationsPushBack = true;
         JCExpression type = parseType();
+        this.permitTypeAnnotationsPushBack = false;
+
         if (S.token() == ELLIPSIS) {
+            List<JCTypeAnnotation> varargsAnnos = typeAnnotationsPushedBack;
+            typeAnnotationsPushedBack = null;
             checkVarargs();
             mods.flags |= Flags.VARARGS;
+            // insert var arg type annotations
+            if (varargsAnnos != null && varargsAnnos.nonEmpty())
+                type = F.at(S.pos()).AnnotatedType(varargsAnnos, type);
             type = to(F.at(S.pos()).TypeArray(type));
+
             S.nextToken();
+        } else {
+            // if not a var arg, then typeAnnotationsPushedBack should be null
+            if (typeAnnotationsPushedBack != null
+                    && !typeAnnotationsPushedBack.isEmpty()) {
+                reportSyntaxError(typeAnnotationsPushedBack.head.pos,
+                        "illegal.start.of.type");
+            }
+            typeAnnotationsPushedBack = null;
         }
         return variableDeclaratorId(mods, type);
     }
@@ -2829,4 +3130,10 @@
             allowAnnotations = true;
         }
     }
+    void checkTypeAnnotations() {
+        if (!allowTypeAnnotations) {
+            log.error(S.pos(), "type.annotations.not.supported.in.source", source.name);
+            allowTypeAnnotations = true;
+        }
+    }
 }