1 /*
  2  * Copyright (c) 2022, 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 8278834
 27  * @summary Verify pattern matching nested inside initializers of classes nested in methods
 28  *          works correctly.
 29  * @library /tools/lib /tools/javac/lib
 30  * @modules
 31  *      jdk.compiler/com.sun.tools.javac.api
 32  *      jdk.compiler/com.sun.tools.javac.file
 33  *      jdk.compiler/com.sun.tools.javac.main
 34  *      jdk.compiler/com.sun.tools.javac.util
 35  * @build toolbox.ToolBox toolbox.JavacTask
 36  * @build combo.ComboTestHelper
 37  * @compile BindingsInitializer.java
 38  * @run main BindingsInitializer
 39  */
 40 
 41 import combo.ComboInstance;
 42 import combo.ComboParameter;
 43 import combo.ComboTask;
 44 import combo.ComboTestHelper;
 45 import java.nio.file.Path;
 46 import java.nio.file.Paths;
 47 import toolbox.ToolBox;
 48 
 49 public class BindingsInitializer extends ComboInstance<BindingsInitializer> {
 50     protected ToolBox tb;
 51 
 52     BindingsInitializer() {
 53         super();
 54         tb = new ToolBox();
 55     }
 56 
 57     public static void main(String... args) throws Exception {
 58         new ComboTestHelper<BindingsInitializer>()
 59                 .withDimension("OUTER", (x, outer) -> x.outer = outer, Outer.values())
 60                 .withDimension("MIDDLE", (x, middle) -> x.middle = middle, Middle.values())
 61                 .withDimension("INNER", (x, inner) -> x.inner = inner, Inner.values())
 62                 .withDimension("TEST", (x, test) -> x.test = test, Test.values())
 63                 .run(BindingsInitializer::new);
 64     }
 65 
 66     private Outer outer;
 67     private Middle middle;
 68     private Inner inner;
 69     private Test test;
 70 
 71     private static final String MAIN_TEMPLATE =
 72             """
 73             public class Test {
 74                 private static Object obj = "";
 75                 #{OUTER}
 76             }
 77             """;
 78 
 79     @Override
 80     protected void doWork() throws Throwable {
 81         Path base = Paths.get(".");
 82 
 83         ComboTask task = newCompilationTask()
 84                 .withSourceFromTemplate(MAIN_TEMPLATE, pname -> switch (pname) {
 85                         case "OUTER" -> outer;
 86                         case "MIDDLE" -> middle;
 87                         case "INNER" -> inner;
 88                         case "TESST" -> test;
 89                         default -> throw new UnsupportedOperationException(pname);
 90                     });
 91 
 92         task.generate(result -> {
 93             if (result.hasErrors()) {
 94                 throw new AssertionError("Unexpected result: " + result.compilationInfo());
 95             }
 96         });
 97     }
 98 
 99     public enum Outer implements ComboParameter {
100         NONE("#{MIDDLE}"),
101         STATIC_CLASS("static class Nested { #{MIDDLE} }"),
102         CLASS("class Inner { #{MIDDLE} }");
103         private final String code;
104 
105         private Outer(String code) {
106             this.code = code;
107         }
108 
109         @Override
110         public String expand(String optParameter) {
111             return code;
112         }
113     }
114 
115     public enum Middle implements ComboParameter {
116         STATIC_INIT("static { #{INNER} }"),
117         INIT("{ #{INNER} }"),
118         METHOD("void test() { #{INNER} }");
119         private final String code;
120 
121         private Middle(String code) {
122             this.code = code;
123         }
124 
125         @Override
126         public String expand(String optParameter) {
127             return code;
128         }
129     }
130 
131     public enum Inner implements ComboParameter {
132         DIRECT("#{TEST}"),
133         CLASS_STATIC_INIT("class C { static { #{TEST} } }"),
134         CLASS_INIT("class C { { #{TEST} } }"),
135         CLASS_METHOD("class C { void t() { #{TEST} } }"),
136         ANNONYMOUS_CLASS_STATIC_INIT("new Object() { static { #{TEST} } };"),
137         ANNONYMOUS_CLASS_INIT("new Object() { { #{TEST} } };"),
138         ANNONYMOUS_CLASS_METHOD("new Object() { void t() { #{TEST} } };");
139         private final String code;
140 
141         private Inner(String code) {
142             this.code = code;
143         }
144 
145         @Override
146         public String expand(String optParameter) {
147             return code;
148         }
149     }
150 
151     public enum Test implements ComboParameter {
152         TEST("if (obj instanceof String str) System.err.println(str);");
153         private final String code;
154 
155         private Test(String code) {
156             this.code = code;
157         }
158 
159         @Override
160         public String expand(String optParameter) {
161             return code;
162         }
163     }
164 }