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