1 /* 2 * Copyright (c) 2019, 2020, 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 8071961 27 * @summary Verify expected default constructor warnings are producted or not produced 28 * @library /tools/lib 29 * @modules jdk.compiler/com.sun.tools.javac.api 30 * jdk.compiler/com.sun.tools.javac.main 31 * @build toolbox.ToolBox toolbox.JavacTask toolbox.TestRunner 32 * @run main DefaultCtorWarningToolBox 33 */ 34 35 import java.io.IOException; 36 import java.nio.file.Path; 37 import java.nio.file.Paths; 38 import java.util.Arrays; 39 import java.util.List; 40 41 import java.io.InputStream; 42 import java.nio.file.Files; 43 import java.util.EnumSet; 44 import javax.tools.JavaFileManager; 45 import javax.tools.JavaFileObject; 46 import javax.tools.StandardLocation; 47 import javax.tools.ToolProvider; 48 import toolbox.JavacTask; 49 import toolbox.Task; 50 import toolbox.Task.Expect; 51 import toolbox.TestRunner; 52 import toolbox.ToolBox; 53 54 public class DefaultCtorWarningToolBox extends TestRunner { 55 56 private final ToolBox tb = new ToolBox(); 57 private final String fileSep = System.getProperty("file.separator"); 58 59 public DefaultCtorWarningToolBox() { 60 super(System.err); 61 } 62 63 public static void main(String... args) throws Exception { 64 new DefaultCtorWarningToolBox().runTests(); 65 } 66 67 @Test 68 public void testWithAndWithOutLint(Path base) throws IOException { 69 Path src = base.resolve("src"); 70 71 tb.writeJavaFiles(src, 72 MOD_INFO_SRC, 73 PKG1_BAR_SRC, PKG1_FOO_SRC, 74 PKG2_BAZ_SRC, PKG2_QUUX_SRC, 75 PKG3_CORGE_SRC, PKG3_GRAULT_SRC 76 ); 77 Path classes = base.resolve("classes"); 78 tb.createDirectories(classes); 79 80 List<String> log; 81 List<String> expected = List.of(""); 82 83 // Warning disabled, no messages expected 84 log = new JavacTask(tb) 85 .options("-Xlint:-missing-explicit-ctor", "-Werror") 86 .outdir(classes) 87 .files(tb.findJavaFiles(src)) 88 .run(Expect.SUCCESS) 89 .writeAll() 90 .getOutputLines(Task.OutputKind.DIRECT); 91 92 if (!expected.equals(log)) { 93 throw new AssertionError("Unexpected output: " + log); 94 } 95 96 expected = 97 List.of("Foo.java:4:8: compiler.warn.missing-explicit-ctor: pkg1.Foo, pkg1, mod", 98 "Foo.java:12:12: compiler.warn.missing-explicit-ctor: pkg1.Foo.FooNest, pkg1, mod", 99 "Foo.java:16:19: compiler.warn.missing-explicit-ctor: pkg1.Foo.StaticFooNest, pkg1, mod", 100 "Foo.java:25:15: compiler.warn.missing-explicit-ctor: pkg1.Foo.ProtectedFooNest, pkg1, mod", 101 "Foo.java:27:19: compiler.warn.missing-explicit-ctor: pkg1.Foo.ProtectedFooNest.ProtectedFooNestNest, pkg1, mod", 102 "5 warnings"); 103 104 // Warning enable, 105 log = new JavacTask(tb) 106 .options("-Xlint:missing-explicit-ctor", "-XDrawDiagnostics") 107 .outdir(classes) 108 .files(tb.findJavaFiles(src)) 109 .run(Expect.SUCCESS) 110 .writeAll() 111 .getOutputLines(Task.OutputKind.DIRECT); 112 113 if (!expected.equals(log)) { 114 throw new AssertionError("Unexpected output: " + log); 115 } 116 } 117 118 protected void runTests() throws Exception { 119 runTests(m -> new Object[] { Paths.get(m.getName()).toAbsolutePath() }); 120 } 121 122 private static final String MOD_INFO_SRC = 123 """ 124 module mod { 125 exports pkg1; 126 // Do *not* export pkg2. 127 exports pkg3 to java.base; 128 } 129 """; 130 131 private static final String PKG1_BAR_SRC = 132 """ 133 package pkg1; 134 135 // Neither the top-level class nor the nested classes should generate 136 // a warning since Bar is not public. 137 138 // No explicit constructor; use a default. 139 class Bar { 140 141 // No explicit constructor; use a default. 142 public class BarNest { 143 } 144 145 // No explicit constructor; use a default. 146 public static class StaticBaryNest { 147 } 148 149 // No explicit constructor; use a default. 150 protected class ProtectedBarNest { 151 } 152 153 // Package-access classes 154 155 // No explicit constructor; use a default. 156 /*package*/ class PkgBarNest { 157 } 158 159 // No explicit constructor; use a default. 160 /*package*/ static class PkgStaticBarNest { 161 } 162 // Private classes 163 164 // No explicit constructor; use a default. 165 private class PrvBarNest { 166 } 167 168 // No explicit constructor; use a default. 169 private static class PrvStaticBarNest { 170 } 171 } 172 """; 173 174 private static final String PKG1_FOO_SRC = 175 """ 176 package pkg1; 177 178 // No explicit constructor; use a default. 179 public class Foo { 180 181 /* 182 * Of the nexted classes, only FooNest and StaticFooNest should 183 * generate warnings. 184 */ 185 186 // No explicit constructor; use a default. 187 public class FooNest { 188 } 189 190 // No explicit constructor; use a default. 191 public static class StaticFooNest { 192 } 193 194 // No explicit constructor; use a default. 195 @SuppressWarnings("missing-explicit-ctor") 196 public static class SuppressedStaticFooNest { 197 } 198 199 // No explicit constructor; use a default. 200 protected class ProtectedFooNest { 201 // No explicit constructor; use a default. 202 protected class ProtectedFooNestNest {} 203 } 204 205 // Package-access classes 206 207 // No explicit constructor; use a default. 208 /*package*/ class PkgFooNest { 209 // No explicit constructor; use a default. 210 protected class PkgFooNestNest {} 211 } 212 213 // No explicit constructor; use a default. 214 /*package*/ static class PkgStaticFooNest { 215 } 216 // Private classes 217 218 // No explicit constructor; use a default. 219 private class PrvFooNest { 220 // No explicit constructor; use a default. 221 protected class PrvFooNestNest {} 222 } 223 224 // No explicit constructor; use a default. 225 private static class PrvStaticFooNest { 226 } 227 } 228 """; 229 230 private static final String PKG2_BAZ_SRC = 231 """ 232 package pkg2; 233 234 // None of these classes should generate warnings since pkg2 is not 235 // exported unconditionally. 236 237 // No explicit constructor; use a default. 238 public class Baz { 239 240 // No explicit constructor; use a default. 241 public class FooNest { 242 } 243 244 // No explicit constructor; use a default. 245 public static class StaticFooNest { 246 } 247 248 // Package-access classes 249 250 // No explicit constructor; use a default. 251 /*package*/ class PkgFooNest { 252 } 253 254 // No explicit constructor; use a default. 255 /*package*/ static class PkgStaticFooNest { 256 } 257 // Private classes 258 259 // No explicit constructor; use a default. 260 private class PrvFooNest { 261 } 262 263 // No explicit constructor; use a default. 264 private static class PrvStaticFooNest { 265 } 266 } 267 """; 268 269 private static final String PKG2_QUUX_SRC = 270 """ 271 package pkg2; 272 273 // Neither the top-level class nor the nested classes should generate 274 // a warning since Bar is not public. 275 276 // No explicit constructor; use a default. 277 class Quux { 278 279 // No explicit constructor; use a default. 280 public class FooNest { 281 } 282 283 // No explicit constructor; use a default. 284 public static class StaticFooNest { 285 } 286 287 // Package-access classes 288 289 // No explicit constructor; use a default. 290 /*package*/ class PkgFooNest { 291 } 292 293 // No explicit constructor; use a default. 294 /*package*/ static class PkgStaticFooNest { 295 } 296 // Private classes 297 298 // No explicit constructor; use a default. 299 private class PrvFooNest { 300 } 301 302 // No explicit constructor; use a default. 303 private static class PrvStaticFooNest { 304 } 305 } 306 """; 307 308 private static final String PKG3_CORGE_SRC = 309 """ 310 package pkg3; 311 312 // None of these classes should generate warnings since pkg3 is not 313 // exported unconditionally. 314 315 // No explicit constructor; use a default. 316 public class Corge { 317 318 // No explicit constructor; use a default. 319 public class FooNest { 320 } 321 322 // No explicit constructor; use a default. 323 public static class StaticFooNest { 324 } 325 326 // Package-access classes 327 328 // No explicit constructor; use a default. 329 /*package*/ class PkgFooNest { 330 } 331 332 // No explicit constructor; use a default. 333 /*package*/ static class PkgStaticFooNest { 334 } 335 // Private classes 336 337 // No explicit constructor; use a default. 338 private class PrvFooNest { 339 } 340 341 // No explicit constructor; use a default. 342 private static class PrvStaticFooNest { 343 } 344 } 345 """; 346 347 private static final String PKG3_GRAULT_SRC = 348 """ 349 package pkg3; 350 351 // None of these classes should generate warnings since pkg3 is not 352 // exported unconditionally. 353 354 // No explicit constructor; use a default. 355 class Grault { 356 357 // No explicit constructor; use a default. 358 public class FooNest { 359 } 360 361 // No explicit constructor; use a default. 362 public static class StaticFooNest { 363 } 364 365 // Package-access classes 366 367 // No explicit constructor; use a default. 368 /*package*/ class PkgFooNest { 369 } 370 371 // No explicit constructor; use a default. 372 /*package*/ static class PkgStaticFooNest { 373 } 374 // Private classes 375 376 // No explicit constructor; use a default. 377 private class PrvFooNest { 378 } 379 380 // No explicit constructor; use a default. 381 private static class PrvStaticFooNest { 382 } 383 } 384 """; 385 }