1 /* 2 * Copyright (c) 2019, 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 8226585 27 * @summary Verify behavior w.r.t. preview feature API errors and warnings 28 * @library /tools/lib /tools/javac/lib 29 * @modules 30 * java.base/jdk.internal 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 --enable-preview -source ${jdk.version} PreviewErrors.java 38 * @run main/othervm --enable-preview PreviewErrors 39 */ 40 41 import java.io.IOException; 42 import java.nio.file.Files; 43 import java.nio.file.Path; 44 import java.nio.file.Paths; 45 46 import combo.ComboInstance; 47 import combo.ComboParameter; 48 import combo.ComboTask; 49 import combo.ComboTestHelper; 50 import java.util.Arrays; 51 import java.util.Set; 52 import java.util.stream.Collectors; 53 import javax.tools.Diagnostic; 54 55 import jdk.internal.PreviewFeature; 56 57 import toolbox.JavacTask; 58 import toolbox.ToolBox; 59 60 public class PreviewErrors extends ComboInstance<PreviewErrors> { 61 62 protected ToolBox tb; 63 PreviewErrors()64 PreviewErrors() { 65 super(); 66 tb = new ToolBox(); 67 } 68 main(String... args)69 public static void main(String... args) throws Exception { 70 new ComboTestHelper<PreviewErrors>() 71 .withDimension("ESSENTIAL", (x, essential) -> x.essential = essential, EssentialAPI.values()) 72 .withDimension("PREVIEW", (x, preview) -> x.preview = preview, Preview.values()) 73 .withDimension("LINT", (x, lint) -> x.lint = lint, Lint.values()) 74 .withDimension("SUPPRESS", (x, suppress) -> x.suppress = suppress, Suppress.values()) 75 .withDimension("FROM", (x, from) -> x.from = from, PreviewFrom.values()) 76 .run(PreviewErrors::new); 77 } 78 79 private EssentialAPI essential; 80 private Preview preview; 81 private Lint lint; 82 private Suppress suppress; 83 private PreviewFrom from; 84 85 @Override doWork()86 public void doWork() throws IOException { 87 Path base = Paths.get("."); 88 Path src = base.resolve("src"); 89 Path srcJavaBase = src.resolve("java.base"); 90 Path classes = base.resolve("classes"); 91 Path classesJavaBase = classes.resolve("java.base"); 92 93 Files.createDirectories(classesJavaBase); 94 95 String previewAPI = """ 96 package preview.api; 97 public class Extra { 98 @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.${preview} 99 ${essential}) 100 public static void test() { } 101 @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.${preview} 102 ${essential}) 103 public static class Clazz {} 104 } 105 """.replace("${preview}", PreviewFeature.Feature.values()[0].name()) 106 .replace("${essential}", essential.expand(null)); 107 108 if (from == PreviewFrom.CLASS) { 109 tb.writeJavaFiles(srcJavaBase, previewAPI); 110 111 new JavacTask(tb) 112 .outdir(classesJavaBase) 113 .options("--patch-module", "java.base=" + srcJavaBase.toString()) 114 .files(tb.findJavaFiles(srcJavaBase)) 115 .run() 116 .writeAll(); 117 } 118 119 ComboTask task = newCompilationTask() 120 .withSourceFromTemplate(""" 121 package test; 122 public class Test { 123 #{SUPPRESS} 124 public void test() { 125 preview.api.Extra.test(); 126 preview.api.Extra.Clazz c; 127 } 128 } 129 """) 130 .withOption("-XDrawDiagnostics") 131 .withOption("-source") 132 .withOption(String.valueOf(Runtime.version().feature())); 133 134 if (from == PreviewFrom.CLASS) { 135 task.withOption("--patch-module") 136 .withOption("java.base=" + classesJavaBase.toString()) 137 .withOption("--add-exports") 138 .withOption("java.base/preview.api=ALL-UNNAMED"); 139 } else { 140 task.withSourceFromTemplate("Extra", previewAPI) 141 .withOption("--add-exports") 142 .withOption("java.base/jdk.internal=ALL-UNNAMED"); 143 } 144 145 if (preview.expand(null)!= null) { 146 task = task.withOption(preview.expand(null)); 147 } 148 149 if (lint.expand(null) != null) { 150 task = task.withOption(lint.expand(null)); 151 } 152 153 task.generate(result -> { 154 Set<String> actual = Arrays.stream(Diagnostic.Kind.values()) 155 .flatMap(kind -> result.diagnosticsForKind(kind).stream()) 156 .map(d -> d.getLineNumber() + ":" + d.getColumnNumber() + ":" + d.getCode()) 157 .collect(Collectors.toSet()); 158 Set<String> expected; 159 boolean ok; 160 if (essential == EssentialAPI.YES) { 161 if (preview == Preview.YES) { 162 if (suppress == Suppress.YES) { 163 expected = Set.of(); 164 } else if (lint == Lint.ENABLE_PREVIEW) { 165 expected = Set.of("5:26:compiler.warn.is.preview", "6:26:compiler.warn.is.preview"); 166 } else { 167 expected = Set.of("-1:-1:compiler.note.preview.filename", 168 "-1:-1:compiler.note.preview.recompile"); 169 } 170 ok = true; 171 } else { 172 expected = Set.of("5:26:compiler.err.is.preview", "6:26:compiler.err.is.preview"); 173 ok = false; 174 } 175 } else { 176 if (suppress == Suppress.YES) { 177 expected = Set.of(); 178 } else if ((preview == Preview.YES && (lint == Lint.NONE || lint == Lint.DISABLE_PREVIEW)) || 179 (preview == Preview.NO && lint == Lint.DISABLE_PREVIEW)) { 180 expected = Set.of("-1:-1:compiler.note.preview.filename", 181 "-1:-1:compiler.note.preview.recompile"); 182 } else { 183 expected = Set.of("5:26:compiler.warn.is.preview", "6:26:compiler.warn.is.preview"); 184 } 185 ok = true; 186 } 187 if (ok) { 188 if (!result.get().iterator().hasNext()) { 189 throw new IllegalStateException("Did not succeed as expected." + actual); 190 } 191 } else { 192 if (result.get().iterator().hasNext()) { 193 throw new IllegalStateException("Succeed unexpectedly."); 194 } 195 } 196 if (!expected.equals(actual)) { 197 throw new IllegalStateException("Unexpected output for " + essential + ", " + preview + ", " + lint + ", " + suppress + ", " + from + ": actual: \"" + actual + "\", expected: \"" + expected + "\""); 198 } 199 }); 200 } 201 202 public enum EssentialAPI implements ComboParameter { 203 YES(", essentialAPI=true"), 204 NO(", essentialAPI=false"); 205 206 private final String code; 207 EssentialAPI(String code)208 private EssentialAPI(String code) { 209 this.code = code; 210 } 211 expand(String optParameter)212 public String expand(String optParameter) { 213 return code; 214 } 215 } 216 217 public enum Preview implements ComboParameter { 218 YES("--enable-preview"), 219 NO(null); 220 221 private final String opt; 222 Preview(String opt)223 private Preview(String opt) { 224 this.opt = opt; 225 } 226 expand(String optParameter)227 public String expand(String optParameter) { 228 return opt; 229 } 230 } 231 232 public enum Lint implements ComboParameter { 233 NONE(null), 234 ENABLE_PREVIEW("-Xlint:preview"), 235 DISABLE_PREVIEW("-Xlint:-preview"); 236 237 private final String opt; 238 Lint(String opt)239 private Lint(String opt) { 240 this.opt = opt; 241 } 242 expand(String optParameter)243 public String expand(String optParameter) { 244 return opt; 245 } 246 } 247 248 public enum Suppress implements ComboParameter { 249 YES("@SuppressWarnings(\"preview\")"), 250 NO(""); 251 252 private final String code; 253 Suppress(String code)254 private Suppress(String code) { 255 this.code = code; 256 } 257 expand(String optParameter)258 public String expand(String optParameter) { 259 return code; 260 } 261 } 262 263 public enum PreviewFrom implements ComboParameter { 264 CLASS, 265 SOURCE; 266 PreviewFrom()267 private PreviewFrom() { 268 } 269 expand(String optParameter)270 public String expand(String optParameter) { 271 throw new IllegalStateException(); 272 } 273 } 274 } 275