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