|
1 | 1 | /* |
2 | | - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | 4 | * |
5 | 5 | * This code is free software; you can redistribute it and/or modify it |
|
23 | 23 |
|
24 | 24 | /* |
25 | 25 | * @test |
26 | | - * @bug 8159602 8170549 8171255 8171322 8254023 |
| 26 | + * @bug 8159602 8170549 8171255 8171322 8254023 8341966 |
27 | 27 | * @summary Test annotations on module declaration. |
28 | 28 | * @library /tools/lib |
29 | 29 | * @enablePreview |
|
35 | 35 | */ |
36 | 36 |
|
37 | 37 | import java.io.File; |
| 38 | +import java.io.OutputStream; |
38 | 39 | import java.nio.file.Files; |
39 | 40 | import java.nio.file.Path; |
| 41 | +import java.util.ArrayList; |
40 | 42 | import java.util.Arrays; |
41 | 43 | import java.util.HashSet; |
42 | 44 | import java.util.List; |
|
55 | 57 | import java.lang.classfile.*; |
56 | 58 | import java.lang.classfile.ClassFile; |
57 | 59 | import java.lang.classfile.attribute.*; |
| 60 | +import java.lang.reflect.AccessFlag; |
58 | 61 | import toolbox.JavacTask; |
59 | 62 | import toolbox.Task; |
60 | 63 | import toolbox.Task.OutputKind; |
@@ -726,6 +729,93 @@ public TestCase(String extraDecl, String decl, String use, String expectedAnnota |
726 | 729 | } |
727 | 730 | } |
728 | 731 |
|
| 732 | + @Test |
| 733 | + public void testBrokenModuleInfoClassWithAnnotation(Path base) throws Exception { |
| 734 | + Path lib = base.resolve("lib"); |
| 735 | + tb.writeJavaFiles(lib, |
| 736 | + """ |
| 737 | + @Deprecated |
| 738 | + module m{} |
| 739 | + """); |
| 740 | + |
| 741 | + Path libClasses = base.resolve("lib-classes"); |
| 742 | + Files.createDirectories(libClasses); |
| 743 | + |
| 744 | + new JavacTask(tb) |
| 745 | + .options("--release", "21") |
| 746 | + .outdir(libClasses) |
| 747 | + .files(findJavaFiles(lib)) |
| 748 | + .run() |
| 749 | + .writeAll(); |
| 750 | + |
| 751 | + Path modifiedModuleInfo = libClasses.resolve("module-info.class"); |
| 752 | + ClassModel cm1 = ClassFile.of().parse(modifiedModuleInfo); |
| 753 | + byte[] newBytes = ClassFile.of().transformClass(cm1, (builder, element) -> { |
| 754 | + if (element instanceof ModuleAttribute attr) { |
| 755 | + List<ModuleRequireInfo> requires = new ArrayList<>(); |
| 756 | + |
| 757 | + for (ModuleRequireInfo mri : attr.requires()) { |
| 758 | + if (mri.requires().name().equalsString("java.base")) { |
| 759 | + requires.add(ModuleRequireInfo.of(mri.requires(), |
| 760 | + List.of(AccessFlag.TRANSITIVE), |
| 761 | + mri.requiresVersion() |
| 762 | + .orElse(null))); |
| 763 | + } else { |
| 764 | + requires.add(mri); |
| 765 | + } |
| 766 | + } |
| 767 | + |
| 768 | + builder.accept(ModuleAttribute.of(attr.moduleName(), |
| 769 | + attr.moduleFlagsMask(), |
| 770 | + attr.moduleVersion() |
| 771 | + .orElseGet(() -> null), |
| 772 | + requires, |
| 773 | + attr.exports(), |
| 774 | + attr.opens(), |
| 775 | + attr.uses(), |
| 776 | + attr.provides())); |
| 777 | + } else { |
| 778 | + builder.accept(element); |
| 779 | + } |
| 780 | + }); |
| 781 | + |
| 782 | + try (OutputStream out = Files.newOutputStream(modifiedModuleInfo)) { |
| 783 | + out.write(newBytes); |
| 784 | + } |
| 785 | + |
| 786 | + Path src = base.resolve("src"); |
| 787 | + Path classes = base.resolve("classes"); |
| 788 | + |
| 789 | + tb.writeJavaFiles(src, |
| 790 | + """ |
| 791 | + public class C {} |
| 792 | + """); |
| 793 | + |
| 794 | + Files.createDirectories(classes); |
| 795 | + |
| 796 | + List<String> actualErrors = |
| 797 | + new JavacTask(tb) |
| 798 | + .options("--module-path", libClasses.toString(), |
| 799 | + "--add-modules", "m", |
| 800 | + "-XDshould-stop.at=FLOW", |
| 801 | + "-XDdev", |
| 802 | + "-XDrawDiagnostics") |
| 803 | + .outdir(classes) |
| 804 | + .files(findJavaFiles(src)) |
| 805 | + .run(Task.Expect.FAIL) |
| 806 | + .writeAll() |
| 807 | + .getOutputLines(OutputKind.DIRECT); |
| 808 | + List<String> expectedErrors = List.of( |
| 809 | + "- compiler.err.cant.access: m.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.requires.flag: ACC_TRANSITIVE (0x0020))", |
| 810 | + "1 error" |
| 811 | + ); |
| 812 | + |
| 813 | + if (!expectedErrors.equals(actualErrors)) { |
| 814 | + throw new AssertionError("Unexpected errors, expected: " + expectedErrors + |
| 815 | + ", but got: " + actualErrors); |
| 816 | + } |
| 817 | + } |
| 818 | + |
729 | 819 | private static final String OPT_EXPECTED_ANNOTATIONS = "expectedAnnotations"; |
730 | 820 |
|
731 | 821 | @SupportedAnnotationTypes("*") |
|
0 commit comments