525 |
528 |
526 Path m1 = moduleSrc.resolve("m1x"); |
529 Path m1 = moduleSrc.resolve("m1x"); |
527 |
530 |
528 tb.writeJavaFiles(m1, |
531 tb.writeJavaFiles(m1, |
529 "module m1x { exports api1; }", |
532 "module m1x { exports api1; }", |
530 "package api1; public class Api { GenApi ga; impl.Impl i; }"); |
533 "package api1; public class Api { }", |
|
534 "package clash; public class C { }"); |
531 |
535 |
532 writeFile("1", m1, "api1", "api"); |
536 writeFile("1", m1, "api1", "api"); |
533 writeFile("1", m1, "impl", "impl"); |
537 writeFile("2", m1, "clash", "clash"); |
534 |
538 |
535 Path m2 = moduleSrc.resolve("m2x"); |
539 Path m2 = moduleSrc.resolve("m2x"); |
536 |
540 |
537 tb.writeJavaFiles(m2, |
541 tb.writeJavaFiles(m2, |
538 "module m2x { requires m1x; exports api2; }", |
542 "module m2x { requires m1x; exports api2; }", |
539 "package api2; public class Api { api1.GenApi ga1; GenApi qa2; impl.Impl i;}"); |
543 "package api2; public class Api { }", |
540 |
544 "package clash; public class C { }"); |
541 writeFile("2", m2, "api2", "api"); |
545 |
542 writeFile("2", m2, "impl", "impl"); |
546 writeFile("3", m2, "api2", "api"); |
543 |
547 writeFile("4", m2, "clash", "api"); |
544 for (FileType fileType : FileType.values()) { |
548 |
545 if (Files.isDirectory(classes)) { |
549 //passing testcases: |
546 tb.cleanDirectory(classes); |
550 for (String module : Arrays.asList("", "m1x/")) { |
547 } else { |
551 for (String originating : Arrays.asList("", ", jlObject")) { |
548 Files.createDirectories(classes); |
552 tb.writeJavaFiles(m1, |
549 } |
553 "package test; class Test { api1.Impl i; }"); |
550 |
554 |
551 new JavacTask(tb) |
555 //source: |
552 .options("-processor", MultiModeAPITestAP.class.getName(), |
556 runCompiler(base, |
553 "--module-source-path", moduleSrc.toString(), |
557 moduleSrc, |
554 "-Afiletype=" + fileType.name()) |
558 classes, |
555 .outdir(classes) |
559 "createSource(() -> filer.createSourceFile(\"" + module + "api1.Impl\"" + originating + "), \"api1.Impl\", \"package api1; public class Impl {}\")", |
556 .files(findJavaFiles(moduleSrc)) |
560 "--module-source-path", moduleSrc.toString()); |
557 .run() |
561 assertFileExists(classes, "m1x", "api1", "Impl.class"); |
558 .writeAll(); |
562 |
559 |
563 //class: |
560 assertFileExists(classes, "m1x", "api1", "GenApi.class"); |
564 runCompiler(base, |
561 assertFileExists(classes, "m1x", "impl", "Impl.class"); |
565 moduleSrc, |
562 assertFileExists(classes, "m1x", "api1", "gen1"); |
566 classes, |
563 assertFileExists(classes, "m2x", "api2", "GenApi.class"); |
567 "createClass(() -> filer.createClassFile(\"" + module + "api1.Impl\"" + originating + "), \"api1.Impl\", \"package api1; public class Impl {}\")", |
564 assertFileExists(classes, "m2x", "impl", "Impl.class"); |
568 "--module-source-path", moduleSrc.toString()); |
565 assertFileExists(classes, "m2x", "api2", "gen1"); |
569 assertFileExists(classes, "m1x", "api1", "Impl.class"); |
566 } |
570 |
567 } |
571 Files.delete(m1.resolve("test").resolve("Test.java")); |
568 |
572 |
569 enum FileType { |
573 //resource class output: |
570 SOURCE, |
574 runCompiler(base, |
571 CLASS; |
575 moduleSrc, |
|
576 classes, |
|
577 "createSource(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, \"" + module + "api1\", \"impl\"" + originating + "), \"impl\", \"impl\")", |
|
578 "--module-source-path", moduleSrc.toString()); |
|
579 assertFileExists(classes, "m1x", "api1", "impl"); |
|
580 } |
|
581 } |
|
582 |
|
583 //get resource module source path: |
|
584 runCompiler(base, |
|
585 m1, |
|
586 classes, |
|
587 "doReadResource(() -> filer.getResource(StandardLocation.MODULE_SOURCE_PATH, \"m1x/api1\", \"api\"), \"1\")", |
|
588 "--module-source-path", moduleSrc.toString()); |
|
589 |
|
590 //can generate resources to the single root module: |
|
591 runCompiler(base, |
|
592 m1, |
|
593 classes, |
|
594 "createSource(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, \"m1x/impl\", \"impl\"), \"impl\", \"impl\")", |
|
595 "--module-source-path", moduleSrc.toString()); |
|
596 assertFileExists(classes, "m1x", "impl", "impl"); |
|
597 |
|
598 //check --default-module-for-created-files option: |
|
599 for (String pack : Arrays.asList("clash", "doesnotexist")) { |
|
600 tb.writeJavaFiles(m1, |
|
601 "package test; class Test { " + pack + ".Pass i; }"); |
|
602 runCompiler(base, |
|
603 moduleSrc, |
|
604 classes, |
|
605 "createSource(() -> filer.createSourceFile(\"" + pack + ".Pass\")," + |
|
606 " \"" + pack + ".Pass\"," + |
|
607 " \"package " + pack + ";" + |
|
608 " public class Pass { }\")", |
|
609 "--module-source-path", moduleSrc.toString(), |
|
610 "--default-module-for-created-files=m1x"); |
|
611 assertFileExists(classes, "m1x", pack, "Pass.class"); |
|
612 assertFileNotExists(classes, "m2x", pack, "Pass.class"); |
|
613 |
|
614 runCompiler(base, |
|
615 moduleSrc, |
|
616 classes, |
|
617 "createClass(() -> filer.createClassFile(\"" + pack + ".Pass\")," + |
|
618 " \"" + pack + ".Pass\"," + |
|
619 " \"package " + pack + ";" + |
|
620 " public class Pass { }\")", |
|
621 "--module-source-path", moduleSrc.toString(), |
|
622 "--default-module-for-created-files=m1x"); |
|
623 assertFileExists(classes, "m1x", pack, "Pass.class"); |
|
624 assertFileNotExists(classes, "m2x", pack, "Pass.class"); |
|
625 |
|
626 Files.delete(m1.resolve("test").resolve("Test.java")); |
|
627 |
|
628 runCompiler(base, |
|
629 moduleSrc, |
|
630 classes, |
|
631 "createSource(() -> filer.createResource(StandardLocation.CLASS_OUTPUT," + |
|
632 " \"" + pack + "\", \"impl\"), \"impl\", \"impl\")", |
|
633 "--module-source-path", moduleSrc.toString(), |
|
634 "--default-module-for-created-files=m1x"); |
|
635 assertFileExists(classes, "m1x", pack, "impl"); |
|
636 assertFileNotExists(classes, "m2x", pack, "impl"); |
|
637 |
|
638 runCompiler(base, |
|
639 moduleSrc, |
|
640 classes, |
|
641 "doReadResource(() -> filer.getResource(StandardLocation.CLASS_OUTPUT," + |
|
642 " \"" + pack + "\", \"resource\"), \"1\")", |
|
643 p -> writeFile("1", p.resolve("m1x"), pack, "resource"), |
|
644 "--module-source-path", moduleSrc.toString(), |
|
645 "--default-module-for-created-files=m1x"); |
|
646 } |
|
647 |
|
648 //wrong default module: |
|
649 runCompiler(base, |
|
650 moduleSrc, |
|
651 classes, |
|
652 "expectFilerException(() -> filer.createResource(StandardLocation.CLASS_OUTPUT," + |
|
653 " \"clash\", \"impl\"))", |
|
654 "--module-source-path", moduleSrc.toString(), |
|
655 "--default-module-for-created-files=doesnotexist"); |
|
656 |
|
657 String[] failingCases = { |
|
658 //must not generate to unnamed package: |
|
659 "expectFilerException(() -> filer.createSourceFile(\"Fail\"))", |
|
660 "expectFilerException(() -> filer.createClassFile(\"Fail\"))", |
|
661 "expectFilerException(() -> filer.createSourceFile(\"m1x/Fail\"))", |
|
662 "expectFilerException(() -> filer.createClassFile(\"m1x/Fail\"))", |
|
663 |
|
664 //cannot infer module name, package clash: |
|
665 "expectFilerException(() -> filer.createSourceFile(\"clash.Fail\"))", |
|
666 "expectFilerException(() -> filer.createClassFile(\"clash.Fail\"))", |
|
667 "expectFilerException(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, \"clash\", \"impl\"))", |
|
668 "expectFilerException(() -> filer.getResource(StandardLocation.CLASS_OUTPUT, \"clash\", \"impl\"))", |
|
669 |
|
670 //cannot infer module name, package does not exist: |
|
671 "expectFilerException(() -> filer.createSourceFile(\"doesnotexist.Fail\"))", |
|
672 "expectFilerException(() -> filer.createClassFile(\"doesnotexist.Fail\"))", |
|
673 "expectFilerException(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, \"doesnotexist\", \"impl\"))", |
|
674 "expectFilerException(() -> filer.getResource(StandardLocation.CLASS_OUTPUT, \"doesnotexist\", \"impl\"))", |
|
675 |
|
676 //cannot generate sources/classes to modules that are not root modules: |
|
677 "expectFilerException(() -> filer.createSourceFile(\"java.base/fail.Fail\"))", |
|
678 "expectFilerException(() -> filer.createClassFile(\"java.base/fail.Fail\"))", |
|
679 |
|
680 //cannot read from module locations if module not given and not inferable: |
|
681 "expectFilerException(() -> filer.getResource(StandardLocation.SYSTEM_MODULES, \"fail\", \"Fail\"))", |
|
682 |
|
683 //wrong module given: |
|
684 "expectException(() -> filer.getResource(StandardLocation.SYSTEM_MODULES, \"java.compiler/java.lang\", \"Object.class\"))", |
|
685 }; |
|
686 |
|
687 for (String failingCode : failingCases) { |
|
688 System.err.println("failing code: " + failingCode); |
|
689 runCompiler(base, |
|
690 moduleSrc, |
|
691 classes, |
|
692 failingCode, |
|
693 "--module-source-path", moduleSrc.toString()); |
|
694 } |
572 } |
695 } |
573 |
696 |
574 public static abstract class GeneratingAP extends AbstractProcessor { |
697 public static abstract class GeneratingAP extends AbstractProcessor { |
575 |
698 |
576 void createSource(CreateFileObject file, String name, String content) { |
699 public void createSource(CreateFileObject file, String name, String content) { |
577 try (Writer out = file.create().openWriter()) { |
700 try (Writer out = file.create().openWriter()) { |
578 out.write(content); |
701 out.write(content); |
579 } catch (IOException ex) { |
702 } catch (IOException ex) { |
580 throw new IllegalStateException(ex); |
703 throw new IllegalStateException(ex); |
581 } |
704 } |
582 } |
705 } |
583 |
706 |
584 void createClass(CreateFileObject file, String name, String content) { |
707 public void createClass(CreateFileObject file, String name, String content) { |
585 String fileNameStub = name.replace(".", File.separator); |
708 String fileNameStub = name.replace(".", File.separator); |
586 |
709 |
587 try (OutputStream out = file.create().openOutputStream()) { |
710 try (OutputStream out = file.create().openOutputStream()) { |
588 Path scratch = Files.createDirectories(Paths.get("")); |
711 Path scratch = Files.createDirectories(Paths.get("")); |
589 Path scratchSrc = scratch.resolve(fileNameStub + ".java").toAbsolutePath(); |
712 Path scratchSrc = scratch.resolve(fileNameStub + ".java").toAbsolutePath(); |
634 } catch (IOException ex) { |
757 } catch (IOException ex) { |
635 throw new IllegalStateException(ex); |
758 throw new IllegalStateException(ex); |
636 } |
759 } |
637 } |
760 } |
638 |
761 |
|
762 public void checkResourceExists(CreateFileObject file) { |
|
763 try { |
|
764 file.create().openInputStream().close(); |
|
765 } catch (IOException ex) { |
|
766 throw new IllegalStateException(ex); |
|
767 } |
|
768 } |
|
769 |
639 public interface CreateFileObject { |
770 public interface CreateFileObject { |
640 public FileObject create() throws IOException; |
771 public FileObject create() throws IOException; |
641 } |
772 } |
642 |
773 |
643 void expectFilerException(Callable<Object> c) { |
774 public void expectFilerException(Callable<Object> c) { |
644 try { |
775 try { |
645 c.call(); |
776 c.call(); |
646 throw new AssertionError("Expected exception not thrown"); |
777 throw new AssertionError("Expected exception not thrown"); |
647 } catch (FilerException ex) { |
778 } catch (FilerException ex) { |
648 //expected |
779 //expected |
649 } catch (Exception ex) { |
780 } catch (Exception ex) { |
650 throw new IllegalStateException(ex); |
781 throw new IllegalStateException(ex); |
651 } |
782 } |
652 } |
783 } |
653 |
784 |
|
785 public void expectException(Callable<Object> c) { |
|
786 try { |
|
787 c.call(); |
|
788 throw new AssertionError("Expected exception not thrown"); |
|
789 } catch (IOException ex) { |
|
790 //expected |
|
791 } catch (Exception ex) { |
|
792 throw new IllegalStateException(ex); |
|
793 } |
|
794 } |
|
795 |
654 @Override |
796 @Override |
655 public SourceVersion getSupportedSourceVersion() { |
797 public SourceVersion getSupportedSourceVersion() { |
656 return SourceVersion.latest(); |
798 return SourceVersion.latest(); |
657 } |
799 } |
658 |
800 |
659 } |
801 } |
660 |
802 |
661 @SupportedAnnotationTypes("*") |
803 @Test |
662 @SupportedOptions({"filetype", "modulename"}) |
804 public void testGenerateSingleModule(Path base) throws Exception { |
663 public static final class MultiModeAPITestAP extends GeneratingAP { |
805 Path classes = base.resolve("classes"); |
664 |
806 |
665 int round; |
807 Files.createDirectories(classes); |
666 |
808 |
667 @Override |
809 Path src = base.resolve("module-src"); |
668 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
810 Path m1 = src.resolve("m1x"); |
669 if (round++ != 0) |
811 |
670 return false; |
812 tb.writeJavaFiles(m1, |
671 |
813 "module m1x { }", |
672 createClass("m1x", "api1.GenApi", "package api1; public class GenApi {}"); |
814 "package test; class Test { impl.Impl i; }"); |
673 createClass("m1x", "impl.Impl", "package impl; public class Impl {}"); |
815 Path m2 = src.resolve("m2x"); |
674 createClass("m2x", "api2.GenApi", "package api2; public class GenApi {}"); |
816 |
675 createClass("m2x", "impl.Impl", "package impl; public class Impl {}"); |
817 tb.writeJavaFiles(m2, |
676 |
818 "module m2x { }"); |
677 createResource("m1x", "api1", "gen1"); |
819 |
678 createResource("m2x", "api2", "gen1"); |
820 for (String[] options : new String[][] {new String[] {"-sourcepath", m1.toString()}, |
679 |
821 new String[] {"--module-source-path", src.toString()}}) { |
680 readResource("m1x", "api1", "api", "1"); |
822 String modulePath = options[0].equals("--module-source-path") ? "m1x" : ""; |
681 readResource("m1x", "impl", "impl", "1"); |
823 //passing testcases: |
682 readResource("m2x", "api2", "api", "2"); |
824 for (String module : Arrays.asList("", "m1x/")) { |
683 readResource("m2x", "impl", "impl", "2"); |
825 for (String originating : Arrays.asList("", ", jlObject")) { |
684 |
826 tb.writeJavaFiles(m1, |
685 Filer filer = processingEnv.getFiler(); |
827 "package test; class Test { impl.Impl i; }"); |
686 |
828 |
687 expectFilerException(() -> filer.createSourceFile("fail.Fail")); |
829 //source: |
688 expectFilerException(() -> filer.createClassFile("fail.Fail")); |
830 runCompiler(base, |
689 expectFilerException(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, "fail", "fail")); |
831 m1, |
690 expectFilerException(() -> filer.getResource(StandardLocation.MODULE_SOURCE_PATH, "fail", "fail")); |
832 classes, |
691 |
833 "createSource(() -> filer.createSourceFile(\"" + module + "impl.Impl\"" + originating + "), \"impl.Impl\", \"package impl; public class Impl {}\")", |
|
834 options); |
|
835 assertFileExists(classes, modulePath, "impl", "Impl.class"); |
|
836 |
|
837 //class: |
|
838 runCompiler(base, |
|
839 m1, |
|
840 classes, |
|
841 "createClass(() -> filer.createClassFile(\"" + module + "impl.Impl\"" + originating + "), \"impl.Impl\", \"package impl; public class Impl {}\")", |
|
842 options); |
|
843 assertFileExists(classes, modulePath, "impl", "Impl.class"); |
|
844 |
|
845 Files.delete(m1.resolve("test").resolve("Test.java")); |
|
846 |
|
847 //resource class output: |
|
848 runCompiler(base, |
|
849 m1, |
|
850 classes, |
|
851 "createSource(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, \"impl\", \"impl\"" + originating + "), \"impl\", \"impl\")", |
|
852 options); |
|
853 assertFileExists(classes, modulePath, "impl", "impl"); |
|
854 } |
|
855 } |
|
856 } |
|
857 |
|
858 //get resource source path: |
|
859 writeFile("1", m1, "impl", "resource"); |
|
860 runCompiler(base, |
|
861 m1, |
|
862 classes, |
|
863 "doReadResource(() -> filer.getResource(StandardLocation.SOURCE_PATH, \"impl\", \"resource\"), \"1\")", |
|
864 "-sourcepath", m1.toString()); |
|
865 //must not specify module when reading non-module oriented locations: |
|
866 runCompiler(base, |
|
867 m1, |
|
868 classes, |
|
869 "expectFilerException(() -> filer.getResource(StandardLocation.SOURCE_PATH, \"m1x/impl\", \"resource\"))", |
|
870 "-sourcepath", m1.toString()); |
|
871 |
|
872 Files.delete(m1.resolve("impl").resolve("resource")); |
|
873 |
|
874 //can read resources from the system module path if module name given: |
|
875 runCompiler(base, |
|
876 m1, |
|
877 classes, |
|
878 "checkResourceExists(() -> filer.getResource(StandardLocation.SYSTEM_MODULES, \"java.base/java.lang\", \"Object.class\"))", |
|
879 "-sourcepath", m1.toString()); |
|
880 |
|
881 //can read resources from the system module path if module inferable: |
|
882 runCompiler(base, |
|
883 m1, |
|
884 classes, |
|
885 "expectFilerException(() -> filer.getResource(StandardLocation.SYSTEM_MODULES, \"java.lang\", \"Object.class\"))", |
|
886 "-sourcepath", m1.toString()); |
|
887 |
|
888 //cannot generate resources to modules that are not root modules: |
|
889 runCompiler(base, |
|
890 m1, |
|
891 classes, |
|
892 "expectFilerException(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, \"java.base/fail\", \"Fail\"))", |
|
893 "--module-source-path", src.toString()); |
|
894 |
|
895 //can generate resources to the single root module: |
|
896 runCompiler(base, |
|
897 m1, |
|
898 classes, |
|
899 "createSource(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, \"impl\", \"impl\"), \"impl\", \"impl\")", |
|
900 "--module-source-path", src.toString()); |
|
901 assertFileExists(classes, "m1x", "impl", "impl"); |
|
902 |
|
903 String[] failingCases = { |
692 //must not generate to unnamed package: |
904 //must not generate to unnamed package: |
693 expectFilerException(() -> filer.createSourceFile("m1/Fail")); |
905 "expectFilerException(() -> filer.createSourceFile(\"Fail\"))", |
694 expectFilerException(() -> filer.createClassFile("m1/Fail")); |
906 "expectFilerException(() -> filer.createClassFile(\"Fail\"))", |
695 |
907 "expectFilerException(() -> filer.createSourceFile(\"m1x/Fail\"))", |
696 //cannot generate resources to modules that are not root modules: |
908 "expectFilerException(() -> filer.createClassFile(\"m1x/Fail\"))", |
697 expectFilerException(() -> filer.createSourceFile("java.base/fail.Fail")); |
909 |
698 expectFilerException(() -> filer.createClassFile("java.base/fail.Fail")); |
910 //cannot generate sources/classes to modules that are not root modules: |
699 expectFilerException(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, "java.base/fail", "Fail")); |
911 "expectFilerException(() -> filer.createSourceFile(\"java.base/fail.Fail\"))", |
700 |
912 "expectFilerException(() -> filer.createClassFile(\"java.base/fail.Fail\"))", |
701 return false; |
913 |
702 } |
914 //cannot specify module name for class output when not in the multi-module mode: |
703 |
915 "expectFilerException(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, \"m1x/fail\", \"Fail\"))", |
704 void createClass(String expectedModule, String name, String content) { |
916 |
705 Filer filer = processingEnv.getFiler(); |
917 //cannot read from module locations if module not given: |
706 FileType filetype = FileType.valueOf(processingEnv.getOptions().getOrDefault("filetype", "")); |
918 "expectFilerException(() -> filer.getResource(StandardLocation.SYSTEM_MODULES, \"fail\", \"Fail\"))", |
707 |
919 |
708 switch (filetype) { |
920 //wrong module given: |
709 case SOURCE: |
921 "expectException(() -> filer.getResource(StandardLocation.SYSTEM_MODULES, \"java.compiler/java.lang\", \"Object.class\"))", |
710 createSource(() -> filer.createSourceFile(expectedModule + "/" + name), name, content); |
922 }; |
711 break; |
923 |
712 case CLASS: |
924 for (String failingCode : failingCases) { |
713 createClass(() -> filer.createClassFile(expectedModule + "/" + name), name, content); |
925 System.err.println("failing code: " + failingCode); |
714 break; |
926 runCompiler(base, |
715 default: |
927 m1, |
716 throw new AssertionError("Unexpected filetype: " + filetype); |
928 classes, |
717 } |
929 failingCode, |
718 } |
930 "-sourcepath", m1.toString()); |
719 |
931 } |
720 void createResource(String expectedModule, String pkg, String relName) { |
932 |
721 try { |
933 Files.delete(m1.resolve("module-info.java")); |
722 Filer filer = processingEnv.getFiler(); |
|
723 |
|
724 filer.createResource(StandardLocation.CLASS_OUTPUT, expectedModule + "/" + pkg, relName) |
|
725 .openOutputStream() |
|
726 .close(); |
|
727 } catch (IOException ex) { |
|
728 throw new IllegalStateException(ex); |
|
729 } |
|
730 } |
|
731 |
|
732 void readResource(String expectedModule, String pkg, String relName, String expectedContent) { |
|
733 Filer filer = processingEnv.getFiler(); |
|
734 |
|
735 doReadResource(() -> filer.getResource(StandardLocation.MODULE_SOURCE_PATH, expectedModule + "/" + pkg, relName), |
|
736 expectedContent); |
|
737 } |
|
738 |
|
739 } |
|
740 |
|
741 @Test |
|
742 public void testGenerateInSingleNameModeAPI(Path base) throws Exception { |
|
743 Path classes = base.resolve("classes"); |
|
744 |
|
745 Files.createDirectories(classes); |
|
746 |
|
747 Path m1 = base.resolve("module-src"); |
|
748 |
|
749 tb.writeJavaFiles(m1, |
934 tb.writeJavaFiles(m1, |
750 "module m1x { }"); |
935 "package test; class Test { }"); |
751 |
936 |
752 writeFile("3", m1, "impl", "resource"); |
937 runCompiler(base, |
753 |
938 m1, |
|
939 classes, |
|
940 "expectFilerException(() -> filer.createSourceFile(\"m1x/impl.Impl\"))", |
|
941 "-sourcepath", m1.toString(), |
|
942 "-source", "8"); |
|
943 |
|
944 runCompiler(base, |
|
945 m1, |
|
946 classes, |
|
947 "expectFilerException(() -> filer.createClassFile(\"m1x/impl.Impl\"))", |
|
948 "-sourcepath", m1.toString(), |
|
949 "-source", "8"); |
|
950 } |
|
951 |
|
952 private void runCompiler(Path base, Path src, Path classes, |
|
953 String code, String... options) throws IOException { |
|
954 runCompiler(base, src, classes, code, p -> {}, options); |
|
955 } |
|
956 |
|
957 private void runCompiler(Path base, Path src, Path classes, |
|
958 String code, Consumer<Path> generateToClasses, |
|
959 String... options) throws IOException { |
|
960 Path apClasses = base.resolve("ap-classes"); |
|
961 if (Files.exists(apClasses)) { |
|
962 tb.cleanDirectory(apClasses); |
|
963 } else { |
|
964 Files.createDirectories(apClasses); |
|
965 } |
|
966 compileAP(apClasses, code); |
|
967 if (Files.exists(classes)) { |
|
968 tb.cleanDirectory(classes); |
|
969 } else { |
|
970 Files.createDirectories(classes); |
|
971 } |
|
972 generateToClasses.accept(classes); |
|
973 List<String> opts = new ArrayList<>(); |
|
974 opts.addAll(Arrays.asList(options)); |
|
975 opts.add("-processorpath"); |
|
976 opts.add(System.getProperty("test.class.path") + File.pathSeparator + apClasses.toString()); |
|
977 opts.add("-processor"); |
|
978 opts.add("AP"); |
754 new JavacTask(tb) |
979 new JavacTask(tb) |
755 .options("-processor", SingleNameModeAPITestAP.class.getName(), |
980 .options(opts) |
756 "-sourcepath", m1.toString()) |
|
757 .outdir(classes) |
981 .outdir(classes) |
758 .files(findJavaFiles(m1)) |
982 .files(findJavaFiles(src)) |
759 .run() |
983 .run() |
760 .writeAll(); |
984 .writeAll(); |
761 |
985 } |
762 assertFileExists(classes, "impl", "Impl1.class"); |
986 |
763 assertFileExists(classes, "impl", "Impl2.class"); |
987 private void compileAP(Path target, String code) { |
764 assertFileExists(classes, "impl", "Impl3"); |
988 String processorCode = |
765 assertFileExists(classes, "impl", "Impl4.class"); |
989 "import java.util.*;\n" + |
766 assertFileExists(classes, "impl", "Impl5.class"); |
990 "import javax.annotation.processing.*;\n" + |
767 assertFileExists(classes, "impl", "Impl6"); |
991 "import javax.lang.model.*;\n" + |
768 assertFileExists(classes, "impl", "Impl7.class"); |
992 "import javax.lang.model.element.*;\n" + |
769 assertFileExists(classes, "impl", "Impl8.class"); |
993 "import javax.lang.model.type.*;\n" + |
770 assertFileExists(classes, "impl", "Impl9"); |
994 "import javax.lang.model.util.*;\n" + |
771 } |
995 "import javax.tools.*;\n" + |
772 |
996 "@SupportedAnnotationTypes(\"*\")\n" + |
773 |
997 "public final class AP extends AnnotationProcessing.GeneratingAP {\n" + |
774 @SupportedAnnotationTypes("*") |
998 "\n" + |
775 public static final class SingleNameModeAPITestAP extends GeneratingAP { |
999 " int round;\n" + |
776 |
1000 "\n" + |
777 int round; |
1001 " @Override\n" + |
778 |
1002 " public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {\n" + |
779 @Override |
1003 " if (round++ != 0)\n" + |
780 public synchronized void init(ProcessingEnvironment processingEnv) { |
1004 " return false;\n" + |
781 super.init(processingEnv); |
1005 " Filer filer = processingEnv.getFiler();\n" + |
782 } |
1006 " TypeElement jlObject = processingEnv.getElementUtils().getTypeElement(\"java.lang.Object\");\n" + |
783 |
1007 code + ";\n" + |
784 @Override |
1008 " return false;\n" + |
785 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
1009 " }\n" + |
786 if (round++ != 0) |
1010 " }\n"; |
787 return false; |
1011 new JavacTask(tb) |
788 |
1012 .options("-classpath", System.getProperty("test.class.path")) |
789 Filer filer = processingEnv.getFiler(); |
1013 .sources(processorCode) |
790 |
1014 .outdir(target) |
791 createSource(() -> filer.createSourceFile("impl.Impl1"), "impl.Impl1", "package impl; class Impl1 {}"); |
1015 .run() |
792 createClass(() -> filer.createClassFile("impl.Impl2"), "impl.Impl2", "package impl; class Impl2 {}"); |
1016 .writeAll(); |
793 createSource(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, "impl", "Impl3"), "impl.Impl3", ""); |
|
794 doReadResource(() -> filer.getResource(StandardLocation.SOURCE_PATH, "impl", "resource"), "3"); |
|
795 |
|
796 createSource(() -> filer.createSourceFile("m1x/impl.Impl4"), "impl.Impl4", "package impl; class Impl4 {}"); |
|
797 createClass(() -> filer.createClassFile("m1x/impl.Impl5"), "impl.Impl5", "package impl; class Impl5 {}"); |
|
798 createSource(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, "m1x/impl", "Impl6"), "impl.Impl6", ""); |
|
799 doReadResource(() -> filer.getResource(StandardLocation.SOURCE_PATH, "m1x/impl", "resource"), "3"); |
|
800 |
|
801 TypeElement jlObject = processingEnv.getElementUtils().getTypeElement("java.lang.Object"); |
|
802 |
|
803 //"broken" originating element: |
|
804 createSource(() -> filer.createSourceFile("impl.Impl7", jlObject), "impl.Impl7", "package impl; class Impl7 {}"); |
|
805 createClass(() -> filer.createClassFile("impl.Impl8", jlObject), "impl.Impl8", "package impl; class Impl8 {}"); |
|
806 createSource(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, "impl", "Impl9", jlObject), "impl.Impl9", ""); |
|
807 |
|
808 //must not generate to unnamed package: |
|
809 expectFilerException(() -> filer.createSourceFile("Fail")); |
|
810 expectFilerException(() -> filer.createClassFile("Fail")); |
|
811 expectFilerException(() -> filer.createSourceFile("m1x/Fail")); |
|
812 expectFilerException(() -> filer.createClassFile("m1x/Fail")); |
|
813 |
|
814 //cannot generate resources to modules that are not root modules: |
|
815 expectFilerException(() -> filer.createSourceFile("java.base/fail.Fail")); |
|
816 expectFilerException(() -> filer.createClassFile("java.base/fail.Fail")); |
|
817 expectFilerException(() -> filer.createResource(StandardLocation.CLASS_OUTPUT, "java.base/fail", "Fail")); |
|
818 |
|
819 return false; |
|
820 } |
|
821 |
|
822 } |
1017 } |
823 |
1018 |
824 @Test |
1019 @Test |
825 public void testGenerateInUnnamedModeAPI(Path base) throws Exception { |
1020 public void testGenerateInUnnamedModeAPI(Path base) throws Exception { |
826 Path classes = base.resolve("classes"); |
1021 Path classes = base.resolve("classes"); |