|
23 | 23 |
|
24 | 24 | /* |
25 | 25 | * @test |
26 | | - * @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336 |
| 26 | + * @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336 8373094 |
27 | 27 | * @summary Verify error recovery w.r.t. Attr |
28 | 28 | * @library /tools/lib |
29 | 29 | * @modules jdk.compiler/com.sun.tools.javac.api |
|
32 | 32 | * @run main AttrRecovery |
33 | 33 | */ |
34 | 34 |
|
| 35 | +import com.sun.source.tree.IdentifierTree; |
35 | 36 | import com.sun.source.tree.MemberReferenceTree; |
| 37 | +import com.sun.source.tree.MemberSelectTree; |
36 | 38 | import com.sun.source.tree.MethodInvocationTree; |
| 39 | +import com.sun.source.tree.MethodTree; |
37 | 40 | import com.sun.source.tree.VariableTree; |
38 | 41 | import com.sun.source.util.TaskEvent; |
39 | 42 | import com.sun.source.util.TaskListener; |
40 | 43 | import com.sun.source.util.TreePathScanner; |
41 | 44 | import com.sun.source.util.Trees; |
42 | 45 | import java.nio.file.Files; |
43 | 46 | import java.nio.file.Path; |
| 47 | +import java.util.ArrayList; |
44 | 48 | import java.util.IdentityHashMap; |
45 | 49 | import java.util.List; |
46 | 50 | import java.util.Map; |
47 | 51 | import java.util.Objects; |
48 | 52 | import java.util.stream.Collectors; |
| 53 | +import java.util.stream.Stream; |
49 | 54 | import javax.lang.model.element.Element; |
50 | 55 | import javax.lang.model.element.VariableElement; |
51 | 56 | import javax.lang.model.type.DeclaredType; |
@@ -495,4 +500,155 @@ private void verifyElement() { |
495 | 500 | } |
496 | 501 | } |
497 | 502 | } |
| 503 | + |
| 504 | + @Test //JDK-8373094 |
| 505 | + public void testSensibleAttribution() throws Exception { |
| 506 | + Path curPath = Path.of("."); |
| 507 | + Path lib = curPath.resolve("lib"); |
| 508 | + Path classes = lib.resolve("classes"); |
| 509 | + Files.createDirectories(classes); |
| 510 | + new JavacTask(tb) |
| 511 | + .outdir(classes) |
| 512 | + .sources(""" |
| 513 | + package test; |
| 514 | + public class Intermediate<T> extends Base<T> {} |
| 515 | + """, |
| 516 | + """ |
| 517 | + package test; |
| 518 | + public class Base<T> { |
| 519 | + public void t(Missing<T> m) {} |
| 520 | + } |
| 521 | + """, |
| 522 | + """ |
| 523 | + package test; |
| 524 | + public class Missing<T> { |
| 525 | + } |
| 526 | + """) |
| 527 | + .run() |
| 528 | + .writeAll(); |
| 529 | + |
| 530 | + Files.delete(classes.resolve("test").resolve("Missing.class")); |
| 531 | + |
| 532 | + record TestCase(String code, List<String> options, String... expectedErrors) {} |
| 533 | + TestCase[] testCases = new TestCase[] { |
| 534 | + new TestCase(""" |
| 535 | + package test; |
| 536 | + public class Test extends Intermediate<String> { |
| 537 | + private void test() { |
| 538 | + int i = 0; |
| 539 | + System.err.println(i); |
| 540 | + while (true) { |
| 541 | + break; |
| 542 | + } |
| 543 | + } |
| 544 | + } |
| 545 | + """, |
| 546 | + List.of(), |
| 547 | + "Test.java:2:8: compiler.err.cant.access: test.Missing, (compiler.misc.class.file.not.found: test.Missing)", |
| 548 | + "1 error"), |
| 549 | + new TestCase(""" |
| 550 | + package test; |
| 551 | + public class Test extends Intermediate<String> { |
| 552 | + private void test() { |
| 553 | + int i = 0; |
| 554 | + System.err.println(i); |
| 555 | + while (true) { |
| 556 | + break; |
| 557 | + } |
| 558 | + } |
| 559 | + } |
| 560 | + """, |
| 561 | + List.of("-XDshould-stop.at=FLOW"), |
| 562 | + "Test.java:2:8: compiler.err.cant.access: test.Missing, (compiler.misc.class.file.not.found: test.Missing)", |
| 563 | + "1 error"), |
| 564 | + }; |
| 565 | + |
| 566 | + for (TestCase tc : testCases) { |
| 567 | + List<String> attributes = new ArrayList<>(); |
| 568 | + List<String> actual = new JavacTask(tb) |
| 569 | + .options(Stream.concat(List.of("-XDrawDiagnostics", "-XDdev").stream(), |
| 570 | + tc.options.stream()).toList()) |
| 571 | + .classpath(classes) |
| 572 | + .sources(tc.code()) |
| 573 | + .outdir(curPath) |
| 574 | + .callback(task -> { |
| 575 | + task.addTaskListener(new TaskListener() { |
| 576 | + @Override |
| 577 | + public void finished(TaskEvent e) { |
| 578 | + if (e.getKind() != TaskEvent.Kind.ANALYZE) { |
| 579 | + return ; |
| 580 | + } |
| 581 | + Trees trees = Trees.instance(task); |
| 582 | + new TreePathScanner<Void, Void>() { |
| 583 | + boolean check; |
| 584 | + |
| 585 | + @Override |
| 586 | + public Void visitMethod(MethodTree node, Void p) { |
| 587 | + if (node.getName().contentEquals("test")) { |
| 588 | + check = true; |
| 589 | + try { |
| 590 | + return super.visitMethod(node, p); |
| 591 | + } finally { |
| 592 | + check = false; |
| 593 | + } |
| 594 | + } |
| 595 | + |
| 596 | + return super.visitMethod(node, p); |
| 597 | + } |
| 598 | + |
| 599 | + @Override |
| 600 | + public Void visitMethodInvocation(MethodInvocationTree node, Void p) { |
| 601 | + if (!node.toString().contains("super")) { |
| 602 | + verifyElement(); |
| 603 | + } |
| 604 | + return super.visitMethodInvocation(node, p); |
| 605 | + } |
| 606 | + |
| 607 | + @Override |
| 608 | + public Void visitIdentifier(IdentifierTree node, Void p) { |
| 609 | + verifyElement(); |
| 610 | + return super.visitIdentifier(node, p); |
| 611 | + } |
| 612 | + |
| 613 | + @Override |
| 614 | + public Void visitMemberSelect(MemberSelectTree node, Void p) { |
| 615 | + verifyElement(); |
| 616 | + return super.visitMemberSelect(node, p); |
| 617 | + } |
| 618 | + |
| 619 | + private void verifyElement() { |
| 620 | + if (!check) { |
| 621 | + return ; |
| 622 | + } |
| 623 | + |
| 624 | + Element el = trees.getElement(getCurrentPath()); |
| 625 | + if (el == null) { |
| 626 | + error("Unattributed tree: " + getCurrentPath().getLeaf()); |
| 627 | + } else { |
| 628 | + attributes.add(el.toString()); |
| 629 | + } |
| 630 | + } |
| 631 | + }.scan(e.getCompilationUnit(), null); |
| 632 | + } |
| 633 | + }); |
| 634 | + }) |
| 635 | + .run(Expect.FAIL) |
| 636 | + .writeAll() |
| 637 | + .getOutputLines(OutputKind.DIRECT); |
| 638 | + |
| 639 | + List<String> expectedErrors = List.of(tc.expectedErrors); |
| 640 | + |
| 641 | + if (!Objects.equals(actual, expectedErrors)) { |
| 642 | + error("Expected: " + expectedErrors + ", but got: " + actual); |
| 643 | + } |
| 644 | + |
| 645 | + List<String> expectedAttributes = |
| 646 | + List.of("println(int)", "println(int)", "err", "java.lang.System", "i"); |
| 647 | + |
| 648 | + if (!Objects.equals(attributes, expectedAttributes)) { |
| 649 | + error("Expected: " + expectedAttributes + ", but got: " + attributes); |
| 650 | + } |
| 651 | + } |
| 652 | + } |
| 653 | + |
498 | 654 | } |
0 commit comments