MethodReferenceParserTest.java revision 1481:954541f13717
1/*
2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 7115052
27 * @bug 8003280
28 * @summary Add lambda tests
29 *  Add parser support for method references
30 * @library ../lib
31 * @build JavacTestingAbstractThreadedTest
32 * @run main MethodReferenceParserTest
33 */
34
35import java.net.URI;
36import java.util.Arrays;
37import javax.tools.Diagnostic;
38import javax.tools.JavaFileObject;
39import javax.tools.SimpleJavaFileObject;
40import com.sun.source.util.JavacTask;
41
42public class MethodReferenceParserTest
43    extends JavacTestingAbstractThreadedTest
44    implements Runnable {
45
46    enum ReferenceKind {
47        METHOD_REF("#Q::#Gm"),
48        CONSTRUCTOR_REF("#Q::#Gnew"),
49        FALSE_REF("min < max"),
50        ERR_SUPER("#Q::#Gsuper"),
51        ERR_METH0("#Q::#Gm()"),
52        ERR_METH1("#Q::#Gm(X)"),
53        ERR_CONSTR0("#Q::#Gnew()"),
54        ERR_CONSTR1("#Q::#Gnew(X)");
55
56        String referenceTemplate;
57
58        ReferenceKind(String referenceTemplate) {
59            this.referenceTemplate = referenceTemplate;
60        }
61
62        String getReferenceString(QualifierKind qk, GenericKind gk) {
63            return referenceTemplate
64                    .replaceAll("#Q", qk.qualifier)
65                    .replaceAll("#G", gk.typeParameters);
66        }
67
68        boolean erroneous() {
69            switch (this) {
70                case ERR_SUPER:
71                case ERR_METH0:
72                case ERR_METH1:
73                case ERR_CONSTR0:
74                case ERR_CONSTR1:
75                    return true;
76                default: return false;
77            }
78        }
79    }
80
81    enum ContextKind {
82        ASSIGN("SAM s = #E;"),
83        METHOD("m(#E, i);");
84
85        String contextTemplate;
86
87        ContextKind(String contextTemplate) {
88            this.contextTemplate = contextTemplate;
89        }
90
91        String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk,
92                GenericKind gk, SubExprKind sk) {
93            return contextTemplate.replaceAll("#E", ek.expressionString(rk, qk, gk, sk));
94        }
95    }
96
97    enum GenericKind {
98        NONE(""),
99        ONE("<X>"),
100        TWO("<X,Y>");
101
102        String typeParameters;
103
104        GenericKind(String typeParameters) {
105            this.typeParameters = typeParameters;
106        }
107    }
108
109    enum QualifierKind {
110        THIS("this"),
111        SUPER("super"),
112        NEW("new Foo()"),
113        METHOD("m()"),
114        FIELD("a.f"),
115        UBOUND_SIMPLE("A"),
116        UNBOUND_ARRAY1("int[]"),
117        UNBOUND_ARRAY2("A<G>[][]"),
118        UNBOUND_GENERIC1("A<X>"),
119        UNBOUND_GENERIC2("A<X, Y>"),
120        UNBOUND_GENERIC3("A<? extends X, ? super Y>"),
121        UNBOUND_GENERIC4("A<int[], short[][]>"),
122        NESTED_GENERIC1("A<A<X,Y>, A<X,Y>>"),
123        NESTED_GENERIC2("A<A<A<X,Y>,A<X,Y>>, A<A<X,Y>,A<X,Y>>>");
124
125        String qualifier;
126
127        QualifierKind(String qualifier) {
128            this.qualifier = qualifier;
129        }
130    }
131
132    enum ExprKind {
133        NONE("#R::S"),
134        SINGLE_PAREN1("(#R#S)"),
135        SINGLE_PAREN2("(#R)#S"),
136        DOUBLE_PAREN1("((#R#S))"),
137        DOUBLE_PAREN2("((#R)#S)"),
138        DOUBLE_PAREN3("((#R))#S");
139
140        String expressionTemplate;
141
142        ExprKind(String expressionTemplate) {
143            this.expressionTemplate = expressionTemplate;
144        }
145
146        String expressionString(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) {
147            return expressionTemplate
148                    .replaceAll("#R", rk.getReferenceString(qk, gk))
149                    .replaceAll("#S", sk.subExpression);
150        }
151    }
152
153    enum SubExprKind {
154        NONE(""),
155        SELECT_FIELD(".f"),
156        SELECT_METHOD(".f()"),
157        SELECT_NEW(".new Foo()"),
158        POSTINC("++"),
159        POSTDEC("--");
160
161        String subExpression;
162
163        SubExprKind(String subExpression) {
164            this.subExpression = subExpression;
165        }
166    }
167
168    public static void main(String... args) throws Exception {
169        for (ReferenceKind rk : ReferenceKind.values()) {
170            for (QualifierKind qk : QualifierKind.values()) {
171                for (GenericKind gk : GenericKind.values()) {
172                    for (SubExprKind sk : SubExprKind.values()) {
173                        for (ExprKind ek : ExprKind.values()) {
174                            for (ContextKind ck : ContextKind.values()) {
175                                pool.execute(new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck));
176                            }
177                        }
178                    }
179                }
180            }
181        }
182
183        checkAfterExec();
184    }
185
186    ReferenceKind rk;
187    QualifierKind qk;
188    GenericKind gk;
189    SubExprKind sk;
190    ExprKind ek;
191    ContextKind ck;
192    JavaSource source;
193    DiagnosticChecker diagChecker;
194
195    MethodReferenceParserTest(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk, ExprKind ek, ContextKind ck) {
196        this.rk = rk;
197        this.qk = qk;
198        this.gk = gk;
199        this.sk = sk;
200        this.ek = ek;
201        this.ck = ck;
202        this.source = new JavaSource();
203        this.diagChecker = new DiagnosticChecker();
204    }
205
206    class JavaSource extends SimpleJavaFileObject {
207
208        String template = "class Test {\n" +
209                          "   void test() {\n" +
210                          "      #C\n" +
211                          "   }" +
212                          "}";
213
214        String source;
215
216        public JavaSource() {
217            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
218            source = template.replaceAll("#C", ck.contextString(ek, rk, qk, gk, sk));
219        }
220
221        @Override
222        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
223            return source;
224        }
225    }
226
227    @Override
228    public void run() {
229        JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
230                null, null, Arrays.asList(source));
231        try {
232            ct.parse();
233        } catch (Throwable ex) {
234            processException(ex);
235            return;
236        }
237        check();
238    }
239
240    void check() {
241        checkCount.incrementAndGet();
242
243        if (diagChecker.errorFound != rk.erroneous()) {
244            throw new Error("invalid diagnostics for source:\n" +
245                source.getCharContent(true) +
246                "\nFound error: " + diagChecker.errorFound +
247                "\nExpected error: " + rk.erroneous());
248        }
249    }
250
251    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
252
253        boolean errorFound;
254
255        public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
256            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
257                errorFound = true;
258            }
259        }
260    }
261
262}
263