1/*
2 * Copyright (c) 2013, 2016, 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 8013576 8129962
27 * @summary Add stat support to LambdaToMethod
28 * @library /tools/javac/lib
29 * @modules jdk.compiler/com.sun.tools.javac.api
30 *          jdk.compiler/com.sun.tools.javac.code
31 *          jdk.compiler/com.sun.tools.javac.comp
32 *          jdk.compiler/com.sun.tools.javac.main
33 *          jdk.compiler/com.sun.tools.javac.tree
34 *          jdk.compiler/com.sun.tools.javac.util
35 * @build combo.ComboTestHelper
36 * @run main TestLambdaToMethodStats
37 */
38
39import java.io.IOException;
40
41import javax.tools.Diagnostic;
42import javax.tools.JavaFileObject;
43
44import com.sun.tools.javac.api.ClientCodeWrapper;
45
46import com.sun.tools.javac.util.List;
47import combo.ComboInstance;
48import combo.ComboParameter;
49import combo.ComboTask.Result;
50import combo.ComboTestHelper;
51
52public class TestLambdaToMethodStats extends ComboInstance<TestLambdaToMethodStats> {
53
54    enum ExprKind implements ComboParameter {
55        LAMBDA("()->null"),
56        MREF1("this::g"),
57        MREF2("this::h");
58
59        String exprStr;
60
61        ExprKind(String exprStr) {
62            this.exprStr = exprStr;
63        }
64
65        @Override
66        public String expand(String optParameter) {
67            return exprStr;
68        }
69    }
70
71    enum TargetKind implements ComboParameter {
72        IMPLICIT(""),
73        SERIALIZABLE("(A & java.io.Serializable)");
74
75        String targetStr;
76
77        TargetKind(String targetStr) {
78            this.targetStr = targetStr;
79        }
80
81        @Override
82        public String expand(String optParameter) {
83            return targetStr;
84        }
85    }
86
87    enum DiagnosticKind {
88        LAMBDA_STAT("compiler.note.lambda.stat", true, false),
89        MREF_STAT("compiler.note.mref.stat", false, false),
90        MREF_STAT1("compiler.note.mref.stat.1", false, true);
91
92        String code;
93        boolean lambda;
94        boolean bridge;
95
96        DiagnosticKind(String code, boolean lambda, boolean bridge) {
97            this.code = code;
98            this.lambda = lambda;
99            this.bridge = bridge;
100        }
101    }
102
103    public static void main(String... args) throws Exception {
104        new ComboTestHelper<TestLambdaToMethodStats>()
105                .withDimension("EXPR", (x, expr) -> x.ek = expr, ExprKind.values())
106                .withDimension("CAST", (x, target) -> x.tk = target, TargetKind.values())
107                .run(TestLambdaToMethodStats::new);
108    }
109
110    ExprKind ek;
111    TargetKind tk;
112
113    String template = "interface A {\n" +
114            "   Object o();\n" +
115            "}\n" +
116            "class Test {\n" +
117            "   A a = #{CAST}#{EXPR};\n" +
118            "   Object g() { return null; }\n" +
119            "   Object h(Object... o) { return null; }\n" +
120            "}";
121
122    @Override
123    public void doWork() throws IOException {
124        check(newCompilationTask()
125                .withOption("--debug:dumpLambdaToMethodStats")
126                .withSourceFromTemplate(template)
127                .generate());
128    }
129
130    void check(Result<?> res) {
131        DiagnosticKind diag = null;
132        boolean altMetafactory = false;
133        for (DiagnosticKind dk : DiagnosticKind.values()) {
134            List<Diagnostic<? extends JavaFileObject>> jcDiag = res.diagnosticsForKey(dk.code);
135            if (jcDiag.nonEmpty()) {
136                diag = dk;
137                ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
138                        (ClientCodeWrapper.DiagnosticSourceUnwrapper)jcDiag.head;
139                altMetafactory = (Boolean)dsu.d.getArgs()[0];
140                break;
141            }
142        }
143
144        if (diag == null) {
145            fail("No diagnostic found; " + res.compilationInfo());
146        }
147
148        boolean error = diag.lambda !=
149                (ek == ExprKind.LAMBDA);
150
151        error |= diag.bridge !=
152                (ek == ExprKind.MREF2);
153
154        error |= altMetafactory !=
155                (tk == TargetKind.SERIALIZABLE);
156
157        if (error) {
158            fail("Bad stat diagnostic found for source\n" +
159                    "lambda = " + diag.lambda + "\n" +
160                    "bridge = " + diag.bridge + "\n" +
161                    "altMF = " + altMetafactory + "\n" +
162                    res.compilationInfo());
163        }
164    }
165}
166