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