--- 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 '<' it could be an unbound
* method reference or a binary expression. To disambiguate, look for a
- * matching '>' and see if the subsequent terminal is either '.' or '#'.
+ * matching '>' 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 '<' it could be an unbound
* method reference or a binary expression. To disambiguate, look for a
- * matching '>' and see if the subsequent terminal is either '.' or '#'.
+ * matching '>' and see if the subsequent terminal is either '.' or '::'.
*/
@SuppressWarnings("fallthrough")
ParensResult analyzeParens() {