7115052: Add parser support for method references

Mon, 28 Nov 2011 16:05:46 +0000

author
mcimadamore
date
Mon, 28 Nov 2011 16:05:46 +0000
changeset 1145
3343b22e2761
parent 1144
9448fe783fd2
child 1146
2584f5358cba
child 1147
abfa0d8ea803

7115052: Add parser support for method references
Summary: Add support for parsing method references to JavacParser
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/code/Source.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/parser/JavacParser.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/parser/Tokens.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/resources/compiler.properties file | annotate | diff | comparison | revisions
test/tools/javac/diags/examples/IllegalChar.java file | annotate | diff | comparison | revisions
test/tools/javac/diags/examples/MethodReferencesNotSupported.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReferenceParserTest.java file | annotate | diff | comparison | revisions
test/tools/javac/quid/T6999438.out file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Source.java	Mon Nov 28 15:56:42 2011 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java	Mon Nov 28 16:05:46 2011 +0000
     1.3 @@ -197,6 +197,9 @@
     1.4      public boolean allowLambda() {
     1.5          return compareTo(JDK1_8) >= 0;
     1.6      }
     1.7 +    public boolean allowMethodReferences() {
     1.8 +        return compareTo(JDK1_8) >= 0;
     1.9 +    }
    1.10      public static SourceVersion toSourceVersion(Source source) {
    1.11          switch(source) {
    1.12          case JDK1_2:
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Nov 28 15:56:42 2011 +0000
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Nov 28 16:05:46 2011 +0000
     2.3 @@ -1980,6 +1980,11 @@
     2.4          throw new UnsupportedOperationException("Lambda expression not supported yet");
     2.5      }
     2.6  
     2.7 +    @Override
     2.8 +    public void visitReference(JCMemberReference that) {
     2.9 +        throw new UnsupportedOperationException("Member references not supported yet");
    2.10 +    }
    2.11 +
    2.12      public void visitParens(JCParens tree) {
    2.13          Type owntype = attribTree(tree.expr, env, pkind, pt);
    2.14          result = check(tree, owntype, pkind, pkind, pt);
     3.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Mon Nov 28 15:56:42 2011 +0000
     3.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Mon Nov 28 16:05:46 2011 +0000
     3.3 @@ -637,6 +637,10 @@
     3.4                          lexError(pos, "unclosed.str.lit");
     3.5                      }
     3.6                      break loop;
     3.7 +                case '#':
     3.8 +                    reader.scanChar();
     3.9 +                    tk = TokenKind.HASH;
    3.10 +                    break loop;
    3.11                  default:
    3.12                      if (isSpecial(reader.ch)) {
    3.13                          scanOperator();
     4.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Nov 28 15:56:42 2011 +0000
     4.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Nov 28 16:05:46 2011 +0000
     4.3 @@ -27,6 +27,8 @@
     4.4  
     4.5  import java.util.*;
     4.6  
     4.7 +import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
     4.8 +
     4.9  import com.sun.tools.javac.code.*;
    4.10  import com.sun.tools.javac.parser.Tokens.*;
    4.11  import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
    4.12 @@ -112,6 +114,8 @@
    4.13          this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
    4.14          this.allowLambda = source.allowLambda() &&
    4.15                  fac.options.isSet("allowLambda");
    4.16 +        this.allowMethodReferences = source.allowMethodReferences() &&
    4.17 +                fac.options.isSet("allowMethodReferences");
    4.18          this.keepDocComments = keepDocComments;
    4.19          docComments = keepDocComments ? new HashMap<JCTree,String>() : null;
    4.20          this.keepLineMap = keepLineMap;
    4.21 @@ -172,6 +176,10 @@
    4.22       */
    4.23      boolean allowLambda;
    4.24  
    4.25 +    /** Switch: should we allow method/constructor references?
    4.26 +     */
    4.27 +    boolean allowMethodReferences;
    4.28 +
    4.29      /** Switch: should we keep docComments?
    4.30       */
    4.31      boolean keepDocComments;
    4.32 @@ -779,7 +787,7 @@
    4.33              top++;
    4.34              topOp = token;
    4.35              nextToken();
    4.36 -            odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
    4.37 +            odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3NoParams();
    4.38              while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
    4.39                  odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
    4.40                                          odStack[top]);
    4.41 @@ -882,6 +890,7 @@
    4.42       *                 | "(" Arguments ")" "->" ( Expression | Block )
    4.43       *                 | Ident "->" ( Expression | Block )
    4.44       *                 | Ident { "." Ident }
    4.45 +     *                 | Expression3 MemberReferenceSuffix
    4.46       *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
    4.47       *                   | Arguments
    4.48       *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
    4.49 @@ -922,7 +931,7 @@
    4.50                      mode = EXPR;
    4.51                      t = literal(names.hyphen, pos);
    4.52                  } else {
    4.53 -                    t = term3();
    4.54 +                    t = term3NoParams();
    4.55                      return F.at(pos).Unary(unoptag(tk), t);
    4.56                  }
    4.57              } else return illegal();
    4.58 @@ -938,8 +947,8 @@
    4.59                      break;
    4.60                  } else {
    4.61                      nextToken();
    4.62 -                    mode = EXPR | TYPE | NOPARAMS;
    4.63 -                    t = term3();
    4.64 +                    mode = EXPR | TYPE;
    4.65 +                    t = term3NoParams();
    4.66                      if ((mode & TYPE) != 0 && token.kind == LT) {
    4.67                          // Could be a cast to a parameterized type
    4.68                          JCTree.Tag op = JCTree.Tag.LT;
    4.69 @@ -1002,7 +1011,7 @@
    4.70                  lastmode = mode;
    4.71                  mode = EXPR;
    4.72                  if ((lastmode & EXPR) == 0) {
    4.73 -                    JCExpression t1 = term3();
    4.74 +                    JCExpression t1 = term3NoParams();
    4.75                      return F.at(pos).TypeCast(t, t1);
    4.76                  } else if ((lastmode & TYPE) != 0) {
    4.77                      switch (token.kind) {
    4.78 @@ -1015,7 +1024,7 @@
    4.79                          case NEW: case IDENTIFIER: case ASSERT: case ENUM:
    4.80                      case BYTE: case SHORT: case CHAR: case INT:
    4.81                      case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
    4.82 -                        JCExpression t1 = term3();
    4.83 +                        JCExpression t1 = term3NoParams();
    4.84                          return F.at(pos).TypeCast(t, t1);
    4.85                      }
    4.86                  }
    4.87 @@ -1134,6 +1143,49 @@
    4.88                          // typeArgs saved for next loop iteration.
    4.89                          t = toP(F.at(pos).Select(t, ident()));
    4.90                          break;
    4.91 +                    case LT:
    4.92 +                        if ((mode & (TYPE | NOPARAMS)) == 0) {
    4.93 +                            //could be an unbound method reference whose qualifier
    4.94 +                            //is a generic type i.e. A<S>#m
    4.95 +                            mode = EXPR | TYPE;
    4.96 +                            JCTree.Tag op = JCTree.Tag.LT;
    4.97 +                            int pos1 = token.pos;
    4.98 +                            nextToken();
    4.99 +                            mode |= EXPR | TYPE | TYPEARG;
   4.100 +                            JCExpression t1 = term3();
   4.101 +                            if ((mode & TYPE) != 0 &&
   4.102 +                                (token.kind == COMMA || token.kind == GT)) {
   4.103 +                                mode = TYPE;
   4.104 +                                ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   4.105 +                                args.append(t1);
   4.106 +                                while (token.kind == COMMA) {
   4.107 +                                    nextToken();
   4.108 +                                    args.append(typeArgument());
   4.109 +                                }
   4.110 +                                accept(GT);
   4.111 +                                t = toP(F.at(pos1).TypeApply(t, args.toList()));
   4.112 +                                checkGenerics();
   4.113 +                                while (token.kind == DOT) {
   4.114 +                                    nextToken();
   4.115 +                                    mode = TYPE;
   4.116 +                                    t = toP(F.at(token.pos).Select(t, ident()));
   4.117 +                                    t = typeArgumentsOpt(t);
   4.118 +                                }
   4.119 +                                if (token.kind != HASH) {
   4.120 +                                    //method reference expected here
   4.121 +                                    t = illegal();
   4.122 +                                }
   4.123 +                                mode = EXPR;
   4.124 +                                break;
   4.125 +                            } else if ((mode & EXPR) != 0) {
   4.126 +                                //rollback - it was a binary expression
   4.127 +                                mode = EXPR;
   4.128 +                                JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
   4.129 +                                t = F.at(pos1).Binary(op, t, e);
   4.130 +                                t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   4.131 +                            }
   4.132 +                        }
   4.133 +                        break loop;
   4.134                      default:
   4.135                          break loop;
   4.136                      }
   4.137 @@ -1173,6 +1225,15 @@
   4.138          return term3Rest(t, typeArgs);
   4.139      }
   4.140  
   4.141 +    JCExpression term3NoParams() {
   4.142 +        try {
   4.143 +            mode |= NOPARAMS;
   4.144 +            return term3();
   4.145 +        } finally {
   4.146 +            mode &= ~NOPARAMS;
   4.147 +        }
   4.148 +    }
   4.149 +
   4.150      JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
   4.151          if (typeArgs != null) illegal();
   4.152          while (true) {
   4.153 @@ -1218,6 +1279,11 @@
   4.154                      t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
   4.155                      typeArgs = null;
   4.156                  }
   4.157 +            } else if ((mode & EXPR) != 0 && token.kind == HASH) {
   4.158 +                mode = EXPR;
   4.159 +                if (typeArgs != null) return illegal();
   4.160 +                accept(HASH);
   4.161 +                t = memberReferenceSuffix(pos1, t);
   4.162              } else {
   4.163                  break;
   4.164              }
   4.165 @@ -1281,6 +1347,9 @@
   4.166          nextToken();
   4.167          if (token.kind == LPAREN || typeArgs != null) {
   4.168              t = arguments(typeArgs, t);
   4.169 +        } else if (token.kind == HASH) {
   4.170 +            if (typeArgs != null) return illegal();
   4.171 +            t = memberReferenceSuffix(t);
   4.172          } else {
   4.173              int pos = token.pos;
   4.174              accept(DOT);
   4.175 @@ -1490,6 +1559,36 @@
   4.176          return t;
   4.177      }
   4.178  
   4.179 +    /**
   4.180 +     * MemberReferenceSuffix = "#" [TypeArguments] Ident
   4.181 +     *                       | "#" [TypeArguments] "new"
   4.182 +     */
   4.183 +    JCExpression memberReferenceSuffix(JCExpression t) {
   4.184 +        int pos1 = token.pos;
   4.185 +        accept(HASH);
   4.186 +        return memberReferenceSuffix(pos1, t);
   4.187 +    }
   4.188 +
   4.189 +    JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
   4.190 +        checkMethodReferences();
   4.191 +        mode = EXPR;
   4.192 +        List<JCExpression> typeArgs = null;
   4.193 +        if (token.kind == LT) {
   4.194 +            typeArgs = typeArguments(false);
   4.195 +        }
   4.196 +        Name refName = null;
   4.197 +        ReferenceMode refMode = null;
   4.198 +        if (token.kind == NEW) {
   4.199 +            refMode = ReferenceMode.NEW;
   4.200 +            refName = names.init;
   4.201 +            nextToken();
   4.202 +        } else {
   4.203 +            refMode = ReferenceMode.INVOKE;
   4.204 +            refName = ident();
   4.205 +        }
   4.206 +        return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
   4.207 +    }
   4.208 +
   4.209      /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
   4.210       */
   4.211      JCExpression creator(int newpos, List<JCExpression> typeArgs) {
   4.212 @@ -3166,6 +3265,12 @@
   4.213              allowLambda = true;
   4.214          }
   4.215      }
   4.216 +    void checkMethodReferences() {
   4.217 +        if (!allowMethodReferences) {
   4.218 +            log.error(token.pos, "method.references.not.supported.in.source", source.name);
   4.219 +            allowMethodReferences = true;
   4.220 +        }
   4.221 +    }
   4.222  
   4.223      /*
   4.224       * a functional source tree and end position mappings
     5.1 --- a/src/share/classes/com/sun/tools/javac/parser/Tokens.java	Mon Nov 28 15:56:42 2011 +0000
     5.2 +++ b/src/share/classes/com/sun/tools/javac/parser/Tokens.java	Mon Nov 28 16:05:46 2011 +0000
     5.3 @@ -177,6 +177,7 @@
     5.4          FALSE("false", Tag.NAMED),
     5.5          NULL("null", Tag.NAMED),
     5.6          ARROW("->"),
     5.7 +        HASH("#"),
     5.8          LPAREN("("),
     5.9          RPAREN(")"),
    5.10          LBRACE("{"),
     6.1 --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Nov 28 15:56:42 2011 +0000
     6.2 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Nov 28 16:05:46 2011 +0000
     6.3 @@ -1950,6 +1950,11 @@
     6.4      lambda expressions are not supported in -source {0}\n\
     6.5      (use -source 8 or higher to enable lambda expressions)
     6.6  
     6.7 +# 0: string
     6.8 +compiler.err.method.references.not.supported.in.source=\
     6.9 +    method references are not supported in -source {0}\n\
    6.10 +    (use -source 8 or higher to enable method references)
    6.11 +
    6.12  ########################################
    6.13  # Diagnostics for verbose resolution
    6.14  # used by Resolve (debug only)
     7.1 --- a/test/tools/javac/diags/examples/IllegalChar.java	Mon Nov 28 15:56:42 2011 +0000
     7.2 +++ b/test/tools/javac/diags/examples/IllegalChar.java	Mon Nov 28 16:05:46 2011 +0000
     7.3 @@ -1,5 +1,5 @@
     7.4  /*
     7.5 - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
     7.6 + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
     7.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.8   *
     7.9   * This code is free software; you can redistribute it and/or modify it
    7.10 @@ -24,5 +24,5 @@
    7.11  // key: compiler.err.illegal.char
    7.12  
    7.13  class IllegalChar {
    7.14 -    int i = #;
    7.15 +    int i = `;
    7.16  }
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/tools/javac/diags/examples/MethodReferencesNotSupported.java	Mon Nov 28 16:05:46 2011 +0000
     8.3 @@ -0,0 +1,29 @@
     8.4 +/*
     8.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.
    8.11 + *
    8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.15 + * version 2 for more details (a copy is included in the LICENSE file that
    8.16 + * accompanied this code).
    8.17 + *
    8.18 + * You should have received a copy of the GNU General Public License version
    8.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.21 + *
    8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.23 + * or visit www.oracle.com if you need additional information or have any
    8.24 + * questions.
    8.25 + */
    8.26 +
    8.27 +// key: compiler.err.method.references.not.supported.in.source
    8.28 +// options: -source 7 -Xlint:-options
    8.29 +
    8.30 +class MethodReferencesNotSupported {
    8.31 +    S s = A#foo;
    8.32 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/tools/javac/lambda/MethodReferenceParserTest.java	Mon Nov 28 16:05:46 2011 +0000
     9.3 @@ -0,0 +1,233 @@
     9.4 +/*
     9.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.
    9.11 + *
    9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.15 + * version 2 for more details (a copy is included in the LICENSE file that
    9.16 + * accompanied this code).
    9.17 + *
    9.18 + * You should have received a copy of the GNU General Public License version
    9.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.21 + *
    9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.23 + * or visit www.oracle.com if you need additional information or have any
    9.24 + * questions.
    9.25 + */
    9.26 +
    9.27 +/*
    9.28 + * @test
    9.29 + * @bug 7115052
    9.30 + * @summary Add parser support for method references
    9.31 + */
    9.32 +
    9.33 +import com.sun.source.util.JavacTask;
    9.34 +import java.net.URI;
    9.35 +import java.util.Arrays;
    9.36 +import javax.tools.Diagnostic;
    9.37 +import javax.tools.JavaCompiler;
    9.38 +import javax.tools.JavaFileObject;
    9.39 +import javax.tools.SimpleJavaFileObject;
    9.40 +import javax.tools.StandardJavaFileManager;
    9.41 +import javax.tools.ToolProvider;
    9.42 +
    9.43 +public class MethodReferenceParserTest {
    9.44 +
    9.45 +    static int checkCount = 0;
    9.46 +
    9.47 +    enum ReferenceKind {
    9.48 +        METHOD_REF("#Q##Gm"),
    9.49 +        CONSTRUCTOR_REF("#Q##Gnew"),
    9.50 +        ERR_SUPER("#Q##Gsuper"),
    9.51 +        ERR_METH0("#Q##Gm()"),
    9.52 +        ERR_METH1("#Q##Gm(X)"),
    9.53 +        ERR_CONSTR0("#Q##Gnew()"),
    9.54 +        ERR_CONSTR1("#Q##Gnew(X)");
    9.55 +
    9.56 +        String referenceTemplate;
    9.57 +
    9.58 +        ReferenceKind(String referenceTemplate) {
    9.59 +            this.referenceTemplate = referenceTemplate;
    9.60 +        }
    9.61 +
    9.62 +        String getReferenceString(QualifierKind qk, GenericKind gk) {
    9.63 +            return referenceTemplate
    9.64 +                    .replaceAll("#Q", qk.qualifier)
    9.65 +                    .replaceAll("#G", gk.typeParameters);
    9.66 +        }
    9.67 +
    9.68 +        boolean erroneous() {
    9.69 +            switch (this) {
    9.70 +                case ERR_SUPER:
    9.71 +                case ERR_METH0:
    9.72 +                case ERR_METH1:
    9.73 +                case ERR_CONSTR0:
    9.74 +                case ERR_CONSTR1:
    9.75 +                    return true;
    9.76 +                default: return false;
    9.77 +            }
    9.78 +        }
    9.79 +    }
    9.80 +
    9.81 +    enum GenericKind {
    9.82 +        NONE(""),
    9.83 +        ONE("<X>"),
    9.84 +        TWO("<X,Y>");
    9.85 +
    9.86 +        String typeParameters;
    9.87 +
    9.88 +        GenericKind(String typeParameters) {
    9.89 +            this.typeParameters = typeParameters;
    9.90 +        }
    9.91 +    }
    9.92 +
    9.93 +    enum QualifierKind {
    9.94 +        THIS("this"),
    9.95 +        SUPER("super"),
    9.96 +        NEW("new Foo()"),
    9.97 +        METHOD("m()"),
    9.98 +        FIELD("a.f"),
    9.99 +        UBOUND_SIMPLE("A"),
   9.100 +        UNBOUND_GENERIC1("A<X>"),
   9.101 +        UNBOUND_GENERIC2("A<X, Y>"),
   9.102 +        UNBOUND_GENERIC3("A<? extends X, ? super Y>");
   9.103 +
   9.104 +        String qualifier;
   9.105 +
   9.106 +        QualifierKind(String qualifier) {
   9.107 +            this.qualifier = qualifier;
   9.108 +        }
   9.109 +    }
   9.110 +
   9.111 +    enum ExprKind {
   9.112 +        NONE("#R#S"),
   9.113 +        SINGLE_PAREN1("(#R#S)"),
   9.114 +        SINGLE_PAREN2("(#R)#S"),
   9.115 +        DOUBLE_PAREN1("((#R#S))"),
   9.116 +        DOUBLE_PAREN2("((#R)#S)"),
   9.117 +        DOUBLE_PAREN3("((#R))#S");
   9.118 +
   9.119 +        String expressionTemplate;
   9.120 +
   9.121 +        ExprKind(String expressionTemplate) {
   9.122 +            this.expressionTemplate = expressionTemplate;
   9.123 +        }
   9.124 +
   9.125 +        String expressionString(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) {
   9.126 +            return expressionTemplate
   9.127 +                    .replaceAll("#R", rk.getReferenceString(qk, gk))
   9.128 +                    .replaceAll("#S", sk.subExpression);
   9.129 +        }
   9.130 +    }
   9.131 +
   9.132 +    enum SubExprKind {
   9.133 +        NONE(""),
   9.134 +        SELECT_FIELD(".f"),
   9.135 +        SELECT_METHOD(".f()"),
   9.136 +        SELECT_NEW(".new Foo()"),
   9.137 +        POSTINC("++"),
   9.138 +        POSTDEC("--");
   9.139 +
   9.140 +        String subExpression;
   9.141 +
   9.142 +        SubExprKind(String subExpression) {
   9.143 +            this.subExpression = subExpression;
   9.144 +        }
   9.145 +    }
   9.146 +
   9.147 +    public static void main(String... args) throws Exception {
   9.148 +
   9.149 +        //create default shared JavaCompiler - reused across multiple compilations
   9.150 +        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
   9.151 +        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
   9.152 +
   9.153 +        for (ReferenceKind rk : ReferenceKind.values()) {
   9.154 +            for (QualifierKind qk : QualifierKind.values()) {
   9.155 +                for (GenericKind gk : GenericKind.values()) {
   9.156 +                    for (SubExprKind sk : SubExprKind.values()) {
   9.157 +                        for (ExprKind ek : ExprKind.values()) {
   9.158 +                            new MethodReferenceParserTest(rk, qk, gk, sk, ek).run(comp, fm);
   9.159 +                        }
   9.160 +                    }
   9.161 +                }
   9.162 +            }
   9.163 +        }
   9.164 +        System.out.println("Total check executed: " + checkCount);
   9.165 +    }
   9.166 +
   9.167 +    ReferenceKind rk;
   9.168 +    QualifierKind qk;
   9.169 +    GenericKind gk;
   9.170 +    SubExprKind sk;
   9.171 +    ExprKind ek;
   9.172 +    JavaSource source;
   9.173 +    DiagnosticChecker diagChecker;
   9.174 +
   9.175 +    MethodReferenceParserTest(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk, ExprKind ek) {
   9.176 +        this.rk = rk;
   9.177 +        this.qk = qk;
   9.178 +        this.gk = gk;
   9.179 +        this.sk = sk;
   9.180 +        this.ek = ek;
   9.181 +        this.source = new JavaSource();
   9.182 +        this.diagChecker = new DiagnosticChecker();
   9.183 +    }
   9.184 +
   9.185 +    class JavaSource extends SimpleJavaFileObject {
   9.186 +
   9.187 +        String template = "class Test {\n" +
   9.188 +                          "   SAM s = #E;\n" +
   9.189 +                          "}";
   9.190 +
   9.191 +        String source;
   9.192 +
   9.193 +        public JavaSource() {
   9.194 +            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   9.195 +            source = template.replaceAll("#E", ek.expressionString(rk, qk, gk, sk));
   9.196 +        }
   9.197 +
   9.198 +        @Override
   9.199 +        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   9.200 +            return source;
   9.201 +        }
   9.202 +    }
   9.203 +
   9.204 +    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
   9.205 +        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
   9.206 +                Arrays.asList("-XDallowMethodReferences"), null, Arrays.asList(source));
   9.207 +        try {
   9.208 +            ct.parse();
   9.209 +        } catch (Throwable ex) {
   9.210 +            throw new AssertionError("Error thrown when parsing the following source:\n" + source.getCharContent(true));
   9.211 +        }
   9.212 +        check();
   9.213 +    }
   9.214 +
   9.215 +    void check() {
   9.216 +        checkCount++;
   9.217 +
   9.218 +        if (diagChecker.errorFound != rk.erroneous()) {
   9.219 +            throw new Error("invalid diagnostics for source:\n" +
   9.220 +                source.getCharContent(true) +
   9.221 +                "\nFound error: " + diagChecker.errorFound +
   9.222 +                "\nExpected error: " + rk.erroneous());
   9.223 +        }
   9.224 +    }
   9.225 +
   9.226 +    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   9.227 +
   9.228 +        boolean errorFound;
   9.229 +
   9.230 +        public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   9.231 +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   9.232 +                errorFound = true;
   9.233 +            }
   9.234 +        }
   9.235 +    }
   9.236 +}
    10.1 --- a/test/tools/javac/quid/T6999438.out	Mon Nov 28 15:56:42 2011 +0000
    10.2 +++ b/test/tools/javac/quid/T6999438.out	Mon Nov 28 16:05:46 2011 +0000
    10.3 @@ -1,4 +1,4 @@
    10.4 -T6999438.java:8:9: compiler.err.illegal.char: 35
    10.5 +T6999438.java:8:8: compiler.err.expected: token.identifier
    10.6  T6999438.java:8:10: compiler.err.illegal.start.of.type
    10.7  T6999438.java:8:25: compiler.err.expected: token.identifier
    10.8  T6999438.java:8:26: compiler.err.expected: ';'

mercurial