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