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