EdgeCases.java revision 4054:24fa5d195595
1/* 2 * Copyright (c) 2015, 2017, 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 8154283 8167320 8171098 8172809 8173068 8173117 27 * @summary tests for multi-module mode compilation 28 * @library /tools/lib 29 * @modules 30 * jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.code 32 * jdk.compiler/com.sun.tools.javac.main 33 * jdk.compiler/com.sun.tools.javac.processing 34 * jdk.compiler/com.sun.tools.javac.util 35 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase 36 * @run main EdgeCases 37 */ 38 39import java.io.Writer; 40import java.nio.file.Files; 41import java.nio.file.Path; 42import java.nio.file.Paths; 43import java.util.Arrays; 44import java.util.HashSet; 45import java.util.List; 46import java.util.Objects; 47import java.util.Set; 48 49import javax.annotation.processing.AbstractProcessor; 50import javax.annotation.processing.RoundEnvironment; 51import javax.annotation.processing.SupportedAnnotationTypes; 52import javax.annotation.processing.SupportedOptions; 53import javax.lang.model.SourceVersion; 54import javax.lang.model.element.Element; 55import javax.lang.model.element.ModuleElement; 56import javax.lang.model.element.ModuleElement.RequiresDirective; 57import javax.lang.model.element.PackageElement; 58import javax.lang.model.element.TypeElement; 59import javax.lang.model.util.ElementFilter; 60import javax.lang.model.util.Elements; 61import javax.tools.JavaCompiler; 62import javax.tools.JavaFileObject; 63import javax.tools.StandardJavaFileManager; 64import javax.tools.ToolProvider; 65 66import com.sun.source.tree.CompilationUnitTree; 67//import com.sun.source.util.JavacTask; // conflicts with toolbox.JavacTask 68import com.sun.tools.javac.api.JavacTaskImpl; 69import com.sun.tools.javac.code.Symbol.ModuleSymbol; 70import com.sun.tools.javac.code.Symbol.PackageSymbol; 71import com.sun.tools.javac.code.Symtab; 72import com.sun.tools.javac.processing.JavacProcessingEnvironment; 73import com.sun.tools.javac.util.Context; 74 75import toolbox.JarTask; 76import toolbox.JavacTask; 77import toolbox.Task; 78import toolbox.Task.Expect; 79import toolbox.Task.OutputKind; 80 81public class EdgeCases extends ModuleTestBase { 82 83 public static void main(String... args) throws Exception { 84 new EdgeCases().runTests(); 85 } 86 87 @Test 88 public void testAddExportUndefinedModule(Path base) throws Exception { 89 Path src = base.resolve("src"); 90 tb.writeJavaFiles(src, "package test; import undefPackage.Any; public class Test {}"); 91 Path classes = base.resolve("classes"); 92 tb.createDirectories(classes); 93 94 List<String> log = new JavacTask(tb) 95 .options("--add-exports", "undefModule/undefPackage=ALL-UNNAMED", 96 "-XDrawDiagnostics") 97 .outdir(classes) 98 .files(findJavaFiles(src)) 99 .run(Task.Expect.FAIL) 100 .writeAll() 101 .getOutputLines(Task.OutputKind.DIRECT); 102 103 List<String> expected = Arrays.asList("- compiler.warn.module.for.option.not.found: --add-exports, undefModule", 104 "Test.java:1:34: compiler.err.doesnt.exist: undefPackage", 105 "1 error", "1 warning"); 106 107 if (!expected.equals(log)) 108 throw new Exception("expected output not found: " + log); 109 } 110 111 @Test 112 public void testModuleSymbolOutterMostClass(Path base) throws Exception { 113 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 114 try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { 115 Path moduleSrc = base.resolve("module-src"); 116 Path m1 = moduleSrc.resolve("m1x"); 117 118 tb.writeJavaFiles(m1, "module m1x { }"); 119 120 Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(moduleSrc)); 121 com.sun.source.util.JavacTask task = 122 (com.sun.source.util.JavacTask) compiler.getTask(null, fm, null, null, null, files); 123 124 task.analyze(); 125 126 ModuleSymbol msym = (ModuleSymbol) task.getElements().getModuleElement("m1x"); 127 128 msym.outermostClass(); 129 } 130 } 131 132 @Test 133 public void testParseEnterAnalyze(Path base) throws Exception { 134 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 135 try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { 136 Path moduleSrc = base.resolve("module-src"); 137 Path m1 = moduleSrc.resolve("m1x"); 138 139 tb.writeJavaFiles(m1, "module m1x { }", 140 "package p;", 141 "package p; class T { }"); 142 143 Path classes = base.resolve("classes"); 144 Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(moduleSrc)); 145 List<String> options = Arrays.asList("-d", classes.toString(), "-Xpkginfo:always"); 146 JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, fm, null, options, null, files); 147 148 Iterable<? extends CompilationUnitTree> parsed = task.parse(); 149 Iterable<? extends Element> entered = task.enter(parsed); 150 Iterable<? extends Element> analyzed = task.analyze(entered); 151 Iterable<? extends JavaFileObject> generatedFiles = task.generate(analyzed); 152 153 Set<String> generated = new HashSet<>(); 154 155 for (JavaFileObject jfo : generatedFiles) { 156 generated.add(jfo.getName()); 157 } 158 159 Set<String> expected = new HashSet<>( 160 Arrays.asList(Paths.get("testParseEnterAnalyze", "classes", "p", "package-info.class").toString(), 161 Paths.get("testParseEnterAnalyze", "classes", "module-info.class").toString(), 162 Paths.get("testParseEnterAnalyze", "classes", "p", "T.class").toString()) 163 ); 164 165 if (!Objects.equals(expected, generated)) 166 throw new AssertionError("Incorrect generated files: " + generated); 167 } 168 } 169 170 @Test 171 public void testModuleImplicitModuleBoundaries(Path base) throws Exception { 172 Path src = base.resolve("src"); 173 Path src_m1 = src.resolve("m1x"); 174 tb.writeJavaFiles(src_m1, 175 "module m1x { exports api1; }", 176 "package api1; public class Api1 { public void call() { } }"); 177 Path src_m2 = src.resolve("m2x"); 178 tb.writeJavaFiles(src_m2, 179 "module m2x { requires m1x; exports api2; }", 180 "package api2; public class Api2 { public static api1.Api1 get() { return null; } }"); 181 Path src_m3 = src.resolve("m3x"); 182 tb.writeJavaFiles(src_m3, 183 "module m3x { requires m2x; }", 184 "package test; public class Test { { api2.Api2.get().call(); api2.Api2.get().toString(); } }"); 185 Path classes = base.resolve("classes"); 186 tb.createDirectories(classes); 187 188 String log = new JavacTask(tb) 189 .options("-XDrawDiagnostics", 190 "--module-source-path", src.toString()) 191 .outdir(classes) 192 .files(findJavaFiles(src)) 193 .run(Task.Expect.FAIL) 194 .writeAll() 195 .getOutput(Task.OutputKind.DIRECT); 196 197 if (!log.contains("Test.java:1:52: compiler.err.not.def.access.class.intf.cant.access.reason: call(), api1.Api1, api1, (compiler.misc.not.def.access.does.not.read: m3x, api1, m1x)") || 198 !log.contains("Test.java:1:76: compiler.err.not.def.access.class.intf.cant.access: toString(), java.lang.Object")) 199 throw new Exception("expected output not found"); 200 } 201 202 @Test 203 public void testAssignClassToAutomaticModule(Path base) throws Exception { 204 //check that if a ClassSymbol belongs to an automatic module, it is properly assigned and not 205 //duplicated when being accessed through a classfile. 206 Path automaticSrc = base.resolve("automaticSrc"); 207 tb.writeJavaFiles(automaticSrc, "package api1; public class Api1 {}"); 208 Path automaticClasses = base.resolve("automaticClasses"); 209 tb.createDirectories(automaticClasses); 210 211 String automaticLog = new JavacTask(tb) 212 .outdir(automaticClasses) 213 .files(findJavaFiles(automaticSrc)) 214 .run() 215 .writeAll() 216 .getOutput(Task.OutputKind.DIRECT); 217 218 if (!automaticLog.isEmpty()) 219 throw new Exception("expected output not found: " + automaticLog); 220 221 Path modulePath = base.resolve("module-path"); 222 223 Files.createDirectories(modulePath); 224 225 Path automaticJar = modulePath.resolve("a-1.0.jar"); 226 227 new JarTask(tb, automaticJar) 228 .baseDir(automaticClasses) 229 .files("api1/Api1.class") 230 .run(); 231 232 Path src = base.resolve("src"); 233 Path src_m2 = src.resolve("m2x"); 234 tb.writeJavaFiles(src_m2, 235 "module m2x { requires a; exports api2; }", 236 "package api2; public class Api2 { public static api1.Api1 get() { return null; } }"); 237 Path src_m3 = src.resolve("m3x"); 238 tb.writeJavaFiles(src_m3, 239 "module m3x { requires a; requires m2x; }", 240 "package test; public class Test { { api2.Api2.get(); api1.Api1 a1; } }"); 241 Path classes = base.resolve("classes"); 242 tb.createDirectories(classes); 243 244 new JavacTask(tb) 245 .options("--module-path", modulePath.toString(), 246 "--module-source-path", src.toString()) 247 .outdir(classes) 248 .files(findJavaFiles(src_m2)) 249 .run() 250 .writeAll(); 251 252 new JavacTask(tb) 253 .options("--module-path", modulePath.toString(), 254 "--module-source-path", src.toString()) 255 .outdir(classes) 256 .files(findJavaFiles(src_m3)) 257 .run() 258 .writeAll(); 259 } 260 261 @Test 262 public void testEmptyImplicitModuleInfo(Path base) throws Exception { 263 Path src = base.resolve("src"); 264 Path src_m1 = src.resolve("m1x"); 265 Files.createDirectories(src_m1); 266 try (Writer w = Files.newBufferedWriter(src_m1.resolve("module-info.java"))) {} 267 tb.writeJavaFiles(src_m1, 268 "package test; public class Test {}"); 269 Path classes = base.resolve("classes"); 270 tb.createDirectories(classes); 271 272 List<String> log = new JavacTask(tb) 273 .options("--source-path", src_m1.toString(), 274 "-XDrawDiagnostics") 275 .outdir(classes) 276 .files(findJavaFiles(src_m1.resolve("test"))) 277 .run(Task.Expect.FAIL) 278 .writeAll() 279 .getOutputLines(OutputKind.DIRECT); 280 281 List<String> expected = Arrays.asList( 282 "- compiler.err.cant.access: module-info, (compiler.misc.bad.source.file.header: module-info.java, (compiler.misc.file.does.not.contain.module))", 283 "1 error"); 284 285 if (!expected.equals(log)) { 286 throw new AssertionError("Unexpected output: " + log); 287 } 288 289 tb.writeJavaFiles(src_m1, 290 "module m1x {}"); 291 292 new JavacTask(tb) 293 .options("--source-path", src_m1.toString()) 294 .outdir(classes) 295 .files(findJavaFiles(src_m1.resolve("test"))) 296 .run() 297 .writeAll(); 298 299 } 300 301 @Test 302 public void testClassPackageClash(Path base) throws Exception { 303 Path src = base.resolve("src"); 304 Path src_m1 = src.resolve("m1x"); 305 tb.writeJavaFiles(src_m1, 306 "module m1x { exports test.m1x; }", 307 "package test.m1x;\n" + 308 "public class Test {}\n"); 309 Path src_m2 = src.resolve("m2x"); 310 tb.writeJavaFiles(src_m2, 311 "module m2x { requires m1x; }", 312 "package test;\n" + 313 "public class m1x {}\n"); 314 Path classes = base.resolve("classes"); 315 tb.createDirectories(classes); 316 317 List<String> log = new JavacTask(tb) 318 .options("--module-source-path", src.toString(), 319 "-XDrawDiagnostics") 320 .outdir(classes) 321 .files(findJavaFiles(src)) 322 .run(Task.Expect.FAIL) 323 .writeAll() 324 .getOutputLines(Task.OutputKind.DIRECT); 325 326 List<String> expected = Arrays.asList( 327 "m1x.java:2:8: compiler.err.clash.with.pkg.of.same.name: kindname.class, test.m1x", 328 "1 error" 329 ); 330 331 if (!expected.equals(log)) { 332 throw new IllegalStateException(log.toString()); 333 } 334 } 335 336 @Test 337 public void testImplicitJavaBase(Path base) throws Exception { 338 Path src = base.resolve("src"); 339 Path src_java_base = src.resolve("java.base"); 340 Files.createDirectories(src_java_base); 341 tb.writeJavaFiles(src_java_base, "module java.base { exports java.lang; }"); 342 tb.writeJavaFiles(src_java_base, 343 "package java.lang; public class Object {}"); 344 Path classes = base.resolve("classes"); 345 tb.createDirectories(classes); 346 347 //module-info from source: 348 new JavacTask(tb) 349 .options("-sourcepath", src_java_base.toString()) 350 .outdir(classes) 351 .files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java"))) 352 .run() 353 .writeAll(); 354 355 //module-info from class: 356 if (!Files.exists(classes.resolve("module-info.class"))) { 357 throw new AssertionError("module-info.class not created!"); 358 } 359 360 new JavacTask(tb) 361 .outdir(classes) 362 .files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java"))) 363 .run() 364 .writeAll(); 365 366 //broken module-info.class: 367 Files.newOutputStream(classes.resolve("module-info.class")).close(); 368 369 List<String> log = new JavacTask(tb) 370 .options("-XDrawDiagnostics") 371 .outdir(classes) 372 .files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java"))) 373 .run(Expect.FAIL) 374 .writeAll() 375 .getOutputLines(OutputKind.DIRECT); 376 377 List<String> expected = Arrays.asList( 378 "- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.illegal.start.of.class.file))", 379 "1 error"); 380 381 if (!expected.equals(log)) { 382 throw new AssertionError("Unexpected output: " + log); 383 } 384 385 //broken module-info.java: 386 Files.delete(classes.resolve("module-info.class")); 387 388 try (Writer out = Files.newBufferedWriter(src_java_base.resolve("module-info.java"))) { 389 out.write("class Broken {}"); 390 } 391 392 log = new JavacTask(tb) 393 .options("-sourcepath", src_java_base.toString(), 394 "-XDrawDiagnostics") 395 .outdir(classes) 396 .files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java"))) 397 .run(Expect.FAIL) 398 .writeAll() 399 .getOutputLines(OutputKind.DIRECT); 400 401 expected = Arrays.asList("X"); 402 403 if (expected.equals(log)) { 404 throw new AssertionError("Unexpected output: " + log); 405 } 406 } 407 408 @Test 409 public void testModuleInfoNameMismatchSource(Path base) throws Exception { 410 Path src = base.resolve("src"); 411 Path m1 = src.resolve("m1x"); 412 Files.createDirectories(m1); 413 tb.writeJavaFiles(m1, "module other { }", 414 "package test; public class Test {}"); 415 Path classes = base.resolve("classes"); 416 tb.createDirectories(classes); 417 418 List<String> log = new JavacTask(tb) 419 .options("--module-source-path", src.toString(), 420 "-XDrawDiagnostics") 421 .outdir(classes) 422 .files(findJavaFiles(m1.resolve("test").resolve("Test.java"))) 423 .run(Expect.FAIL) 424 .writeAll() 425 .getOutputLines(OutputKind.DIRECT); 426 427 List<String> expected = Arrays.asList( 428 "module-info.java:1:1: compiler.err.module.name.mismatch: other, m1x", 429 "- compiler.err.cant.access: m1x.module-info, (compiler.misc.cant.resolve.modules)", 430 "2 errors"); 431 432 if (!expected.equals(log)) { 433 throw new AssertionError("Unexpected output: " + log); 434 } 435 } 436 437 @Test 438 public void testModuleInfoNameMismatchClass(Path base) throws Exception { 439 Path src = base.resolve("src"); 440 Files.createDirectories(src); 441 tb.writeJavaFiles(src, "module other { }", 442 "package test; public class Test {}"); 443 Path classes = base.resolve("classes"); 444 Path m1Classes = classes.resolve("m1x"); 445 tb.createDirectories(m1Classes); 446 447 new JavacTask(tb) 448 .outdir(m1Classes) 449 .files(findJavaFiles(src)) 450 .run() 451 .writeAll() 452 .getOutputLines(OutputKind.DIRECT); 453 454 Path src2 = base.resolve("src2"); 455 Files.createDirectories(src2); 456 tb.writeJavaFiles(src2, "module use { requires m1x; }"); 457 458 Path classes2 = base.resolve("classes2"); 459 tb.createDirectories(classes2); 460 461 List<String> log = new JavacTask(tb) 462 .options("--module-path", classes.toString(), 463 "-XDrawDiagnostics") 464 .outdir(classes2) 465 .files(findJavaFiles(src2)) 466 .run(Expect.FAIL) 467 .writeAll() 468 .getOutputLines(OutputKind.DIRECT); 469 470 List<String> expected = Arrays.asList( 471 "- compiler.err.cant.access: m1x.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.name.mismatch: other, m1x))", 472 "1 error"); 473 474 if (!expected.equals(log)) { 475 throw new AssertionError("Unexpected output: " + log); 476 } 477 } 478 479 @Test 480 public void testGetDirectivesComplete(Path base) throws Exception { 481 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 482 JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, null, null, null, null, null); 483 Symtab syms = Symtab.instance(task.getContext()); 484 485 syms.java_base.getDirectives(); 486 } 487 488 @Test 489 public void testPackageInModuleInfo(Path base) throws Exception { 490 Path src = base.resolve("src"); 491 Files.createDirectories(src); 492 tb.writeJavaFiles(src, "package p; module foo { }"); 493 Path classes = base.resolve("classes"); 494 tb.createDirectories(classes); 495 496 List<String> log = new JavacTask(tb) 497 .options("-XDrawDiagnostics", "-XDshould-stop.ifError=FLOW") 498 .outdir(classes) 499 .files(findJavaFiles(src)) 500 .run(Expect.FAIL) 501 .writeAll() 502 .getOutputLines(OutputKind.DIRECT); 503 504 List<String> expected = Arrays.asList( 505 "module-info.java:1:1: compiler.err.no.pkg.in.module-info.java", 506 "1 error"); 507 508 if (!expected.equals(log)) { 509 throw new AssertionError("Unexpected output: " + log); 510 } 511 } 512 513 @Test 514 public void testInvisibleClassVisiblePackageClash(Path base) throws Exception { 515 Path src = base.resolve("src"); 516 Path src_m1 = src.resolve("m1x"); 517 tb.writeJavaFiles(src_m1, 518 "module m1x { }", 519 "package m1x;\n" + 520 "import m1x.a.*; public class Test { A a; }\n", 521 "package m1x.a;\n" + 522 "public class A { }\n"); 523 Path src_m2 = src.resolve("m2x"); 524 tb.writeJavaFiles(src_m2, 525 "module m2x { }", 526 "package m1x;\n" + 527 "public class a { public static class A { } }\n"); 528 Path classes = base.resolve("classes"); 529 tb.createDirectories(classes); 530 531 new JavacTask(tb) 532 .options("--module-source-path", src.toString(), 533 "-XDrawDiagnostics") 534 .outdir(classes) 535 .files(findJavaFiles(src)) 536 .run() 537 .writeAll(); 538 } 539 540 @Test 541 public void testStripUnknownRequired(Path base) throws Exception { 542 Path src = base.resolve("src"); 543 Path src_m1 = src.resolve("m1x"); 544 tb.writeJavaFiles(src_m1, 545 "module m1x { }"); 546 Path src_m2 = src.resolve("m2x"); 547 tb.writeJavaFiles(src_m2, 548 "module m2x { }"); 549 Path src_m3 = src.resolve("m3x"); 550 tb.writeJavaFiles(src_m3, 551 "module m3x { }"); 552 Path src_m4 = src.resolve("m4x"); 553 tb.writeJavaFiles(src_m4, 554 "module m4x { }"); 555 Path src_test = src.resolve("test"); 556 tb.writeJavaFiles(src_test, 557 "module test { requires m1x; requires m2x; requires java.base; requires m3x; requires m4x; }"); 558 Path src_compile = src.resolve("compile"); 559 tb.writeJavaFiles(src_compile, 560 "module compile { exports p to test; }", 561 "package p; public class Test { }"); 562 Path classes = base.resolve("classes"); 563 tb.createDirectories(classes); 564 565 List<String> log = new JavacTask(tb) 566 .options("-processor", ListRequires.class.getName(), 567 "--module-source-path", src.toString(), 568 "--limit-modules", "compile", 569 "-XDaccessInternalAPI=true") 570 .outdir(classes) 571 .files(findJavaFiles(src_compile)) 572 .run(Expect.FAIL) 573 .writeAll() 574 .getOutputLines(Task.OutputKind.STDOUT); 575 576 List<String> expected = Arrays.asList( 577 "from directives:", 578 "java.base", 579 "from requires:", 580 "java.base" 581 ); 582 if (!Objects.equals(log, expected)) 583 throw new AssertionError("Unexpected output: " + log); 584 } 585 586 @SupportedAnnotationTypes("*") 587 @SupportedOptions("expectedEnclosedElements") 588 public static final class ListRequires extends AbstractProcessor { 589 590 private int round; 591 592 @Override 593 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 594 if (round++ == 0) { 595 ModuleElement compileE = processingEnv.getElementUtils().getModuleElement("compile"); 596 ModuleElement testE = ElementFilter.exportsIn(compileE.getDirectives()).get(0).getTargetModules().get(0); 597 598 System.out.println("from directives:"); 599 for (RequiresDirective rd : ElementFilter.requiresIn(testE.getDirectives())) { 600 System.out.println(rd.getDependency().getSimpleName()); 601 } 602 603 System.out.println("from requires:"); 604 for (RequiresDirective rd : ((ModuleSymbol) testE).requires) { 605 System.out.println(rd.getDependency().getSimpleName()); 606 } 607 } 608 609 return false; 610 } 611 612 @Override 613 public SourceVersion getSupportedSourceVersion() { 614 return SourceVersion.latest(); 615 } 616 617 } 618 619 @Test 620 public void testOnDemandCompletionModuleInfoJava(Path base) throws Exception { 621 Path src = base.resolve("src"); 622 Path src_m1 = src.resolve("m1x"); 623 tb.writeJavaFiles(src_m1, 624 "@Deprecated module m1x { }"); 625 Path src_m2 = src.resolve("m2x"); 626 tb.writeJavaFiles(src_m2, 627 "module m2x { requires m1x; }"); 628 Path src_m3 = src.resolve("m3x"); 629 tb.writeJavaFiles(src_m3, 630 "module m3x { requires m2x; requires m1x; }"); 631 Path classes = base.resolve("classes"); 632 tb.createDirectories(classes); 633 634 List<String> log; 635 List<String> expected; 636 637 log = new JavacTask(tb) 638 .options("--module-source-path", src.toString()) 639 .outdir(classes) 640 .files(findJavaFiles(src_m1)) 641 .run() 642 .writeAll() 643 .getOutputLines(Task.OutputKind.DIRECT); 644 645 expected = Arrays.asList(""); 646 647 if (!expected.equals(log)) { 648 throw new IllegalStateException(log.toString()); 649 } 650 651 log = new JavacTask(tb) 652 .options("--module-source-path", src.toString(), 653 "-XDrawDiagnostics", 654 "-Xlint:deprecation") 655 .outdir(classes) 656 .files(findJavaFiles(src_m3)) 657 .run() 658 .writeAll() 659 .getOutputLines(Task.OutputKind.DIRECT); 660 661 expected = Arrays.asList( 662 "module-info.java:1:23: compiler.warn.has.been.deprecated.module: m1x", 663 "module-info.java:1:37: compiler.warn.has.been.deprecated.module: m1x", 664 "2 warnings" 665 ); 666 667 if (!expected.equals(log)) { 668 throw new IllegalStateException(log.toString()); 669 } 670 } 671 672 @Test 673 public void testUnnamedPackage(Path base) throws Exception { 674 List<String> out; 675 List<String> expected; 676 677 //-source 8: 678 Path src8 = base.resolve("src8"); 679 Files.createDirectories(src8); 680 tb.writeJavaFiles(src8, 681 "package test; public class Test {}"); 682 Path classes = base.resolve("classes"); 683 tb.createDirectories(classes); 684 685 out = new JavacTask(tb) 686 .options("--source-path", src8.toString(), 687 "-processor", UnnamedPackageProcessor.class.getName(), 688 "-source", "8") 689 .outdir(classes) 690 .files(findJavaFiles(src8)) 691 .run() 692 .writeAll() 693 .getOutputLines(OutputKind.STDOUT); 694 695 expected = Arrays.asList("noModule"); 696 697 if (!expected.equals(out)) { 698 throw new AssertionError("Unexpected output: " + out); 699 } 700 701 //-source 9, unnamed: 702 Path srcUnnamed = base.resolve("srcUnnamed"); 703 Files.createDirectories(srcUnnamed); 704 tb.writeJavaFiles(srcUnnamed, 705 "public class Test {}"); 706 Path classesUnnamed = base.resolve("classesUnnamed"); 707 tb.createDirectories(classesUnnamed); 708 709 out = new JavacTask(tb) 710 .options("--source-path", srcUnnamed.toString(), 711 "-processor", UnnamedPackageProcessor.class.getName()) 712 .outdir(classesUnnamed) 713 .files(findJavaFiles(srcUnnamed)) 714 .run() 715 .writeAll() 716 .getOutputLines(OutputKind.STDOUT); 717 718 expected = Arrays.asList("unnamedModule"); 719 720 if (!expected.equals(out)) { 721 throw new AssertionError("Unexpected output: " + out); 722 } 723 724 //-source 9, named: 725 Path srcNamed = base.resolve("srcNamed"); 726 Files.createDirectories(srcNamed); 727 tb.writeJavaFiles(srcNamed, 728 "module m {}", 729 "public class Test {}"); 730 Path classesNamed = base.resolve("classesNamed"); 731 tb.createDirectories(classesNamed); 732 733 out = new JavacTask(tb) 734 .options("--source-path", srcNamed.toString(), 735 "-classpath", "", 736 "-processorpath", System.getProperty("test.class.path"), 737 "-processor", UnnamedPackageProcessor.class.getName()) 738 .outdir(classesNamed) 739 .files(findJavaFiles(srcNamed)) 740 .run() 741 .writeAll() 742 .getOutputLines(OutputKind.STDOUT); 743 744 expected = Arrays.asList("m"); 745 746 if (!expected.equals(out)) { 747 throw new AssertionError("Unexpected output: " + out); 748 } 749 750 //-source 9, conflict: 751 Path srcNamed2 = base.resolve("srcNamed2"); 752 Path srcNamed2m1 = srcNamed2.resolve("m1x"); 753 Files.createDirectories(srcNamed2m1); 754 tb.writeJavaFiles(srcNamed2m1, 755 "module m1x {}", 756 "public class Test {}"); 757 Path srcNamed2m2 = srcNamed2.resolve("m2x"); 758 Files.createDirectories(srcNamed2m2); 759 tb.writeJavaFiles(srcNamed2m2, 760 "module m2x {}", 761 "public class Test {}"); 762 Path classesNamed2 = base.resolve("classesNamed2"); 763 tb.createDirectories(classesNamed2); 764 765 out = new JavacTask(tb) 766 .options("--module-source-path", srcNamed2.toString(), 767 "-classpath", "", 768 "-processorpath", System.getProperty("test.class.path"), 769 "-processor", UnnamedPackageProcessor.class.getName(), 770 "-XDshould-stop.ifError=FLOW") 771 .outdir(classesNamed2) 772 .files(findJavaFiles(srcNamed2)) 773 .run(Expect.FAIL) 774 .writeAll() 775 .getOutputLines(OutputKind.STDOUT); 776 777 expected = Arrays.asList("null", 778 "m1x: true", 779 "m2x: true"); 780 781 if (!expected.equals(out)) { 782 throw new AssertionError("Unexpected output: " + out); 783 } 784 } 785 786 @SupportedAnnotationTypes("*") 787 public static final class UnnamedPackageProcessor extends AbstractProcessor { 788 789 int round = 0; 790 791 @Override 792 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 793 if (round++ != 0) 794 return false; 795 796 Elements elements = processingEnv.getElementUtils(); 797 PackageElement pe = elements.getPackageElement(""); 798 799 if (pe == null) { 800 System.out.println("null"); 801 } else { 802 ModuleElement mod = (ModuleElement) pe.getEnclosingElement(); 803 if (mod == null) { 804 System.out.println("noModule"); 805 } else if (mod.isUnnamed()) { 806 System.out.println("unnamedModule"); 807 } else { 808 System.out.println(mod); 809 } 810 } 811 812 ModuleElement m1x = elements.getModuleElement("m1x"); 813 ModuleElement m2x = elements.getModuleElement("m2x"); 814 815 if (m1x != null && m2x != null) { 816 System.out.println("m1x: " + (elements.getPackageElement(m1x, "") != null)); 817 System.out.println("m2x: " + (elements.getPackageElement(m2x, "") != null)); 818 } 819 820 return false; 821 } 822 823 } 824} 825