1 /* 2 * Copyright (c) 2021, 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 8260593 27 * @summary Verify that a temporary storage variable is or is not used as needed when pattern matching. 28 * @enablePreview 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 LocalVariableReuse.java 38 * @run main LocalVariableReuse 39 */ 40 41 import combo.ComboInstance; 42 import combo.ComboParameter; 43 import combo.ComboTask; 44 import combo.ComboTestHelper; 45 import java.io.IOException; 46 import javax.tools.JavaFileObject; 47 import toolbox.ToolBox; 48 49 public class LocalVariableReuse extends ComboInstance<LocalVariableReuse> { 50 protected ToolBox tb; 51 52 LocalVariableReuse() { 53 super(); 54 tb = new ToolBox(); 55 } 56 57 public static void main(String... args) throws Exception { 58 new ComboTestHelper<LocalVariableReuse>() 59 .withDimension("CODE", (x, code) -> x.code = code, Code.values()) 60 .run(LocalVariableReuse::new); 61 } 62 63 private Code code; 64 65 private static final String MAIN_TEMPLATE = 66 """ 67 public class Test { 68 #{CODE} 69 } 70 """; 71 72 @Override 73 protected void doWork() throws Throwable { 74 ComboTask task = newCompilationTask() 75 .withSourceFromTemplate(MAIN_TEMPLATE, pname -> switch (pname) { 76 case "CODE" -> code; 77 default -> throw new UnsupportedOperationException(pname); 78 }); 79 80 task.withOption("-printsource"); 81 task.generate(result -> { 82 for (JavaFileObject out : result.get()) { 83 try { 84 String actualDesugared = out.getCharContent(false).toString(); 85 boolean hasTempVar = actualDesugared.contains("$temp"); 86 if (hasTempVar != code.useTemporaryVariable) { 87 throw new AssertionError("Expected temporary variable: " + code.useTemporaryVariable + 88 ", but got: " + actualDesugared); 89 } 90 } catch (IOException ex) { 91 throw new AssertionError(ex); 92 } 93 } 94 }); 95 } 96 97 public enum Code implements ComboParameter { 98 LOCAL_VARIABLE( 99 """ 100 private boolean test() { 101 Object o = null; 102 return o instanceof String s && s.length() > 0; 103 } 104 """, false), 105 PARAMETER( 106 """ 107 private boolean test(Object o) { 108 return o instanceof String s && s.length() > 0; 109 } 110 """, false), 111 LAMBDA_PARAMETER( 112 """ 113 private void test(Object o) { 114 I i = o -> o instanceof String s && s.length() > 0; 115 interface I { 116 public boolean run(Object o); 117 } 118 """, false), 119 EXCEPTION( 120 """ 121 private boolean test() { 122 try { 123 throw new Exception(); 124 } catch (Exception o) { 125 return o instanceof RuntimeException re && re.getMessage() != null; 126 } 127 } 128 """, false), 129 RESOURCE( 130 """ 131 private boolean test() throws Exception { 132 try (AutoCloseable r = null) { 133 return r instanceof java.io.InputStream in && in.read() != (-1); 134 } catch (Exception o) { 135 } 136 } 137 """, false), 138 FIELD(""" 139 private Object o; 140 private boolean test() { 141 return o instanceof String s && s.length() > 0; 142 } 143 """, 144 true), 145 FINAL_FIELD(""" 146 private final Object o; 147 private boolean test() { 148 return o instanceof String s && s.length() > 0; 149 } 150 """, 151 true), 152 ARRAY_ACCESS(""" 153 private boolean test() { 154 Object[] o = null; 155 return o[0] instanceof String s && s.length() > 0; 156 } 157 """, 158 true), 159 METHOD_INVOCATION(""" 160 private boolean test() { 161 return get() instanceof String s && s.length() > 0; 162 } 163 private Object get() { 164 return null; 165 } 166 """, 167 true), 168 ; 169 private final String body; 170 private final boolean useTemporaryVariable; 171 172 private Code(String body, boolean useTemporaryVariable) { 173 this.body = body; 174 this.useTemporaryVariable = useTemporaryVariable; 175 } 176 177 @Override 178 public String expand(String optParameter) { 179 return body; 180 } 181 } 182 183 }