1/*
2 * Copyright (c) 2012, 2015, 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 8003280
27 * @summary Add lambda tests
28 *  compile crashes on partial lambda expressions
29 * @modules jdk.compiler
30 */
31
32import com.sun.source.util.JavacTask;
33import java.net.URI;
34import java.util.Arrays;
35import javax.tools.Diagnostic;
36import javax.tools.JavaCompiler;
37import javax.tools.JavaFileObject;
38import javax.tools.SimpleJavaFileObject;
39import javax.tools.StandardJavaFileManager;
40import javax.tools.ToolProvider;
41
42
43public class BadLambdaExpr {
44
45    static int checkCount = 0;
46
47    enum ParameterListKind {
48        ZERO_ARY("()"),
49        UNARY("(#P)"),
50        TWO_ARY("(#P, #P)"),
51        THREE_ARY("(#P, #P, #P)");
52
53        String parametersTemplateStr;
54
55        ParameterListKind(String parametersTemplateStr) {
56            this.parametersTemplateStr = parametersTemplateStr;
57        }
58
59        String getParameterString(ParameterKind pk) {
60            return parametersTemplateStr.replaceAll("#P", pk.parameterStr);
61        }
62    }
63
64    enum ParameterKind {
65        IMPLICIT("a"),
66        EXPLIICT("A a");
67
68        String parameterStr;
69
70        ParameterKind(String parameterStr) {
71            this.parameterStr = parameterStr;
72        }
73    }
74
75    enum ArrowKind {
76        NONE(""),
77        SEMI("-"),
78        FULL("->");
79
80        String arrowStr;
81
82        ArrowKind(String arrowStr) {
83            this.arrowStr = arrowStr;
84        }
85    }
86
87    enum ExprKind {
88        NONE("#P#A"),
89        METHOD_CALL("m(#P#A)"),
90        CONSTR_CALL("new Foo(#P#A)");
91
92        String expressionTemplate;
93
94        ExprKind(String expressionTemplate) {
95            this.expressionTemplate = expressionTemplate;
96        }
97
98        String expressionString(ParameterListKind plk, ParameterKind pk,
99                ArrowKind ak) {
100            return expressionTemplate.replaceAll("#P", plk.getParameterString(pk))
101                    .replaceAll("#A", ak.arrowStr);
102        }
103    }
104
105    public static void main(String... args) throws Exception {
106
107        //create default shared JavaCompiler - reused across multiple compilations
108        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
109        try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) {
110
111            for (ParameterListKind plk : ParameterListKind.values()) {
112                for (ParameterKind pk : ParameterKind.values()) {
113                    for (ArrowKind ak : ArrowKind.values()) {
114                        for (ExprKind ek : ExprKind.values()) {
115                            new BadLambdaExpr(plk, pk, ak, ek).run(comp, fm);
116                        }
117                    }
118                }
119            }
120            System.out.println("Total check executed: " + checkCount);
121        }
122    }
123
124    ParameterListKind plk;
125    ParameterKind pk;
126    ArrowKind ak;
127    ExprKind ek;
128    JavaSource source;
129    DiagnosticChecker diagChecker;
130
131    BadLambdaExpr(ParameterListKind plk, ParameterKind pk, ArrowKind ak, ExprKind ek) {
132        this.plk = plk;
133        this.pk = pk;
134        this.ak = ak;
135        this.ek = ek;
136        this.source = new JavaSource();
137        this.diagChecker = new DiagnosticChecker();
138    }
139
140    class JavaSource extends SimpleJavaFileObject {
141
142        String template = "class Test {\n" +
143                          "   SAM s = #E;\n" +
144                          "}";
145
146        String source;
147
148        public JavaSource() {
149            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
150            source = template.replaceAll("#E", ek.expressionString(plk, pk, ak));
151        }
152
153        @Override
154        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
155            return source;
156        }
157    }
158
159    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
160        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
161                null, null, Arrays.asList(source));
162        try {
163            ct.parse();
164        } catch (Throwable ex) {
165            throw new AssertionError("Error thron when parsing the following source:\n" + source.getCharContent(true));
166        }
167        check();
168    }
169
170    void check() {
171        boolean errorExpected =
172                ak != ArrowKind.NONE ||
173                plk != ParameterListKind.UNARY ||
174                pk != ParameterKind.IMPLICIT;
175        if (errorExpected != diagChecker.errorFound) {
176            throw new Error("bad diag for source:\n" +
177                source.getCharContent(true));
178        }
179        checkCount++;
180    }
181
182    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
183
184        boolean errorFound;
185
186        @Override
187        public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
188            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
189                errorFound = true;
190            }
191        }
192    }
193}
194