langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
changeset 15718 8e54c8e43d38
parent 15711 a975ad2bfe35
child 16296 22c10640a521
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Feb 12 19:25:09 2013 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Feb 12 17:15:29 2013 -0800
@@ -1164,7 +1164,7 @@
             } else return illegal();
             break;
         case MONKEYS_AT:
-            // Only annotated cast types are valid
+            // Only annotated cast types and method references are valid
             List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
             if (typeAnnos.isEmpty()) {
                 // else there would be no '@'
@@ -1175,17 +1175,27 @@
 
             if ((mode & TYPE) == 0) {
                 // Type annotations on class literals no longer legal
-                if (!expr.hasTag(Tag.SELECT)) {
+                switch (expr.getTag()) {
+                case REFERENCE: {
+                    JCMemberReference mref = (JCMemberReference) expr;
+                    mref.expr = toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr));
+                    t = mref;
+                    break;
+                }
+                case SELECT: {
+                    JCFieldAccess sel = (JCFieldAccess) expr;
+
+                    if (sel.name != names._class) {
+                        return illegal();
+                    } else {
+                        log.error(token.pos, "no.annotations.on.dot.class");
+                        return expr;
+                    }
+                }
+                default:
                     return illegal(typeAnnos.head.pos);
                 }
-                JCFieldAccess sel = (JCFieldAccess)expr;
-
-                if (sel.name != names._class) {
-                    return illegal();
-                } else {
-                    log.error(token.pos, "no.annotations.on.dot.class");
-                    return expr;
-                }
+
             } else {
                 // Type annotations targeting a cast
                 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
@@ -1457,18 +1467,40 @@
     /**
      * If we see an identifier followed by a '&lt;' it could be an unbound
      * method reference or a binary expression. To disambiguate, look for a
-     * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
+     * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
      */
     @SuppressWarnings("fallthrough")
     boolean isUnboundMemberRef() {
         int pos = 0, depth = 0;
-        for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
+        outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
             switch (t.kind) {
                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
                 case DOUBLE: case BOOLEAN: case CHAR:
+                case MONKEYS_AT:
                     break;
+
+                case LPAREN:
+                    // skip annotation values
+                    int nesting = 0;
+                    for (; ; pos++) {
+                        TokenKind tk2 = S.token(pos).kind;
+                        switch (tk2) {
+                            case EOF:
+                                return false;
+                            case LPAREN:
+                                nesting++;
+                                break;
+                            case RPAREN:
+                                nesting--;
+                                if (nesting == 0) {
+                                    continue outer;
+                                }
+                                break;
+                        }
+                    }
+
                 case LT:
                     depth++; break;
                 case GTGTGT:
@@ -1494,7 +1526,7 @@
     /**
      * If we see an identifier followed by a '&lt;' it could be an unbound
      * method reference or a binary expression. To disambiguate, look for a
-     * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
+     * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
      */
     @SuppressWarnings("fallthrough")
     ParensResult analyzeParens() {