35 import java.nio.file.Path;
36 import java.util.*;
37 import java.util.Map.Entry;
38 import java.util.regex.*;
39 import java.util.stream.Collectors;
40
41 import javax.annotation.processing.*;
42 import javax.lang.model.SourceVersion;
43 import javax.lang.model.element.*;
44 import javax.lang.model.util.*;
45 import javax.tools.JavaFileManager;
46 import javax.tools.JavaFileObject;
47 import javax.tools.JavaFileObject.Kind;
48 import javax.tools.StandardJavaFileManager;
49
50 import static javax.tools.StandardLocation.*;
51
52 import com.sun.source.util.TaskEvent;
53 import com.sun.tools.javac.api.MultiTaskListener;
54 import com.sun.tools.javac.code.*;
55 import com.sun.tools.javac.code.Scope.WriteableScope;
56 import com.sun.tools.javac.code.Source.Feature;
57 import com.sun.tools.javac.code.Symbol.*;
58 import com.sun.tools.javac.code.Type.ClassType;
59 import com.sun.tools.javac.code.Types;
60 import com.sun.tools.javac.comp.AttrContext;
61 import com.sun.tools.javac.comp.Check;
62 import com.sun.tools.javac.comp.Enter;
63 import com.sun.tools.javac.comp.Env;
64 import com.sun.tools.javac.comp.Modules;
65 import com.sun.tools.javac.file.JavacFileManager;
66 import com.sun.tools.javac.main.JavaCompiler;
67 import com.sun.tools.javac.main.Option;
68 import com.sun.tools.javac.model.JavacElements;
69 import com.sun.tools.javac.model.JavacTypes;
70 import com.sun.tools.javac.platform.PlatformDescription;
71 import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
72 import com.sun.tools.javac.resources.CompilerProperties.Errors;
73 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
74 import com.sun.tools.javac.tree.*;
160 JCDiagnostic.Factory diags;
161
162 /**
163 * Source level of the compile.
164 */
165 Source source;
166
167 private ClassLoader processorClassLoader;
168 private ServiceLoader<Processor> serviceLoader;
169 private SecurityException processorLoaderException;
170
171 private final JavaFileManager fileManager;
172
173 /**
174 * JavacMessages object used for localization
175 */
176 private JavacMessages messages;
177
178 private MultiTaskListener taskListener;
179 private final Symtab symtab;
180 private final Names names;
181 private final Enter enter;
182 private final Completer initialCompleter;
183 private final Check chk;
184
185 private final Context context;
186
187 /** Get the JavacProcessingEnvironment instance for this context. */
188 public static JavacProcessingEnvironment instance(Context context) {
189 JavacProcessingEnvironment instance = context.get(JavacProcessingEnvironment.class);
190 if (instance == null)
191 instance = new JavacProcessingEnvironment(context);
192 return instance;
193 }
194
195 protected JavacProcessingEnvironment(Context context) {
196 this.context = context;
197 context.put(JavacProcessingEnvironment.class, this);
198 log = Log.instance(context);
199 source = Source.instance(context);
210 fatalErrors = options.isSet("fatalEnterError");
211 showResolveErrors = options.isSet("showResolveErrors");
212 werror = options.isSet(Option.WERROR);
213 fileManager = context.get(JavaFileManager.class);
214 platformAnnotations = initPlatformAnnotations();
215
216 // Initialize services before any processors are initialized
217 // in case processors use them.
218 filer = new JavacFiler(context);
219 messager = new JavacMessager(context, this);
220 elementUtils = JavacElements.instance(context);
221 typeUtils = JavacTypes.instance(context);
222 modules = Modules.instance(context);
223 types = Types.instance(context);
224 annotate = Annotate.instance(context);
225 processorOptions = initProcessorOptions();
226 unmatchedProcessorOptions = initUnmatchedProcessorOptions();
227 messages = JavacMessages.instance(context);
228 taskListener = MultiTaskListener.instance(context);
229 symtab = Symtab.instance(context);
230 names = Names.instance(context);
231 enter = Enter.instance(context);
232 initialCompleter = ClassFinder.instance(context).getCompleter();
233 chk = Check.instance(context);
234 initProcessorLoader();
235 }
236
237 public void setProcessors(Iterable<? extends Processor> processors) {
238 Assert.checkNull(discoveredProcs);
239 initProcessorIterator(processors);
240 }
241
242 private Set<String> initPlatformAnnotations() {
243 Set<String> platformAnnotations = new HashSet<>();
244 platformAnnotations.add("java.lang.Deprecated");
245 platformAnnotations.add("java.lang.Override");
246 platformAnnotations.add("java.lang.SuppressWarnings");
247 platformAnnotations.add("java.lang.annotation.Documented");
248 platformAnnotations.add("java.lang.annotation.Inherited");
249 platformAnnotations.add("java.lang.annotation.Retention");
648 private Set<String> initUnmatchedProcessorOptions() {
649 Set<String> unmatchedProcessorOptions = new HashSet<>();
650 unmatchedProcessorOptions.addAll(processorOptions.keySet());
651 return unmatchedProcessorOptions;
652 }
653
654 /**
655 * State about how a processor has been used by the tool. If a
656 * processor has been used on a prior round, its process method is
657 * called on all subsequent rounds, perhaps with an empty set of
658 * annotations to process. The {@code annotationSupported} method
659 * caches the supported annotation information from the first (and
660 * only) getSupportedAnnotationTypes call to the processor.
661 */
662 static class ProcessorState {
663 public Processor processor;
664 public boolean contributed;
665 private ArrayList<Pattern> supportedAnnotationPatterns;
666 private ArrayList<String> supportedOptionNames;
667
668 ProcessorState(Processor p, Log log, Source source, boolean allowModules, ProcessingEnvironment env) {
669 processor = p;
670 contributed = false;
671
672 try {
673 processor.init(env);
674
675 checkSourceVersionCompatibility(source, log);
676
677 supportedAnnotationPatterns = new ArrayList<>();
678 for (String importString : processor.getSupportedAnnotationTypes()) {
679 supportedAnnotationPatterns.add(importStringToPattern(allowModules,
680 importString,
681 processor,
682 log));
683 }
684
685 supportedOptionNames = new ArrayList<>();
686 for (String optionName : processor.getSupportedOptions() ) {
687 if (checkOptionName(optionName, log))
688 supportedOptionNames.add(optionName);
689 }
690
691 } catch (ClientCodeException e) {
692 throw e;
693 } catch (Throwable t) {
694 throw new AnnotationProcessingError(t);
695 }
696 }
697
698 /**
699 * Checks whether or not a processor's source version is
700 * compatible with the compilation source version. The
701 * processor's source version needs to be greater than or
702 * equal to the source version of the compile.
703 */
704 private void checkSourceVersionCompatibility(Source source, Log log) {
705 SourceVersion procSourceVersion = processor.getSupportedSourceVersion();
706
707 if (procSourceVersion.compareTo(Source.toSourceVersion(source)) < 0 ) {
708 log.warning(Warnings.ProcProcessorIncompatibleSourceVersion(procSourceVersion,
709 processor.getClass().getName(),
710 source.name));
711 }
712 }
713
714 private boolean checkOptionName(String optionName, Log log) {
750 DiscoveredProcessors psi;
751 Iterator<ProcessorState> innerIter;
752 boolean onProcInterator;
753
754 ProcessorStateIterator(DiscoveredProcessors psi) {
755 this.psi = psi;
756 this.innerIter = psi.procStateList.iterator();
757 this.onProcInterator = false;
758 }
759
760 public ProcessorState next() {
761 if (!onProcInterator) {
762 if (innerIter.hasNext())
763 return innerIter.next();
764 else
765 onProcInterator = true;
766 }
767
768 if (psi.processorIterator.hasNext()) {
769 ProcessorState ps = new ProcessorState(psi.processorIterator.next(),
770 log, source, Feature.MODULES.allowedInSource(source),
771 JavacProcessingEnvironment.this);
772 psi.procStateList.add(ps);
773 return ps;
774 } else
775 throw new NoSuchElementException();
776 }
777
778 public boolean hasNext() {
779 if (onProcInterator)
780 return psi.processorIterator.hasNext();
781 else
782 return innerIter.hasNext() || psi.processorIterator.hasNext();
783 }
784
785 public void remove () {
786 throw new UnsupportedOperationException();
787 }
788
789 /**
790 * Run all remaining processors on the procStateList that
942 }
943
944 void addAnnotations(Element e, Set<TypeElement> p) {
945 for (AnnotationMirror annotationMirror :
946 elements.getAllAnnotationMirrors(e) ) {
947 Element e2 = annotationMirror.getAnnotationType().asElement();
948 p.add((TypeElement) e2);
949 }
950 }
951
952 @Override @DefinedBy(Api.LANGUAGE_MODEL)
953 public Set<TypeElement> scan(Element e, Set<TypeElement> p) {
954 addAnnotations(e, p);
955 return super.scan(e, p);
956 }
957 }
958
959 private boolean callProcessor(Processor proc,
960 Set<? extends TypeElement> tes,
961 RoundEnvironment renv) {
962 try {
963 return proc.process(tes, renv);
964 } catch (ClassFinder.BadClassFile ex) {
965 log.error(Errors.ProcCantAccess1(ex.sym, ex.getDetailValue()));
966 return false;
967 } catch (CompletionFailure ex) {
968 StringWriter out = new StringWriter();
969 ex.printStackTrace(new PrintWriter(out));
970 log.error(Errors.ProcCantAccess(ex.sym, ex.getDetailValue(), out.toString()));
971 return false;
972 } catch (ClientCodeException e) {
973 throw e;
974 } catch (Throwable t) {
975 throw new AnnotationProcessingError(t);
976 }
977 }
978
979 /**
980 * Helper object for a single round of annotation processing.
981 */
982 class Round {
983 /** The round number. */
984 final int number;
985 /** The diagnostic handler for the round. */
986 final Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
987
988 /** The ASTs to be compiled. */
989 List<JCCompilationUnit> roots;
990 /** The trees that need to be cleaned - includes roots and implicitly parsed trees. */
991 Set<JCCompilationUnit> treesToClean;
992 /** The classes to be compiler that have were generated. */
993 Map<ModuleSymbol, Map<String, JavaFileObject>> genClassFiles;
994
995 /** The set of annotations to be processed this round. */
|
35 import java.nio.file.Path;
36 import java.util.*;
37 import java.util.Map.Entry;
38 import java.util.regex.*;
39 import java.util.stream.Collectors;
40
41 import javax.annotation.processing.*;
42 import javax.lang.model.SourceVersion;
43 import javax.lang.model.element.*;
44 import javax.lang.model.util.*;
45 import javax.tools.JavaFileManager;
46 import javax.tools.JavaFileObject;
47 import javax.tools.JavaFileObject.Kind;
48 import javax.tools.StandardJavaFileManager;
49
50 import static javax.tools.StandardLocation.*;
51
52 import com.sun.source.util.TaskEvent;
53 import com.sun.tools.javac.api.MultiTaskListener;
54 import com.sun.tools.javac.code.*;
55 import com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler;
56 import com.sun.tools.javac.code.Scope.WriteableScope;
57 import com.sun.tools.javac.code.Source.Feature;
58 import com.sun.tools.javac.code.Symbol.*;
59 import com.sun.tools.javac.code.Type.ClassType;
60 import com.sun.tools.javac.code.Types;
61 import com.sun.tools.javac.comp.AttrContext;
62 import com.sun.tools.javac.comp.Check;
63 import com.sun.tools.javac.comp.Enter;
64 import com.sun.tools.javac.comp.Env;
65 import com.sun.tools.javac.comp.Modules;
66 import com.sun.tools.javac.file.JavacFileManager;
67 import com.sun.tools.javac.main.JavaCompiler;
68 import com.sun.tools.javac.main.Option;
69 import com.sun.tools.javac.model.JavacElements;
70 import com.sun.tools.javac.model.JavacTypes;
71 import com.sun.tools.javac.platform.PlatformDescription;
72 import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
73 import com.sun.tools.javac.resources.CompilerProperties.Errors;
74 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
75 import com.sun.tools.javac.tree.*;
161 JCDiagnostic.Factory diags;
162
163 /**
164 * Source level of the compile.
165 */
166 Source source;
167
168 private ClassLoader processorClassLoader;
169 private ServiceLoader<Processor> serviceLoader;
170 private SecurityException processorLoaderException;
171
172 private final JavaFileManager fileManager;
173
174 /**
175 * JavacMessages object used for localization
176 */
177 private JavacMessages messages;
178
179 private MultiTaskListener taskListener;
180 private final Symtab symtab;
181 private final DeferredCompletionFailureHandler dcfh;
182 private final Names names;
183 private final Enter enter;
184 private final Completer initialCompleter;
185 private final Check chk;
186
187 private final Context context;
188
189 /** Get the JavacProcessingEnvironment instance for this context. */
190 public static JavacProcessingEnvironment instance(Context context) {
191 JavacProcessingEnvironment instance = context.get(JavacProcessingEnvironment.class);
192 if (instance == null)
193 instance = new JavacProcessingEnvironment(context);
194 return instance;
195 }
196
197 protected JavacProcessingEnvironment(Context context) {
198 this.context = context;
199 context.put(JavacProcessingEnvironment.class, this);
200 log = Log.instance(context);
201 source = Source.instance(context);
212 fatalErrors = options.isSet("fatalEnterError");
213 showResolveErrors = options.isSet("showResolveErrors");
214 werror = options.isSet(Option.WERROR);
215 fileManager = context.get(JavaFileManager.class);
216 platformAnnotations = initPlatformAnnotations();
217
218 // Initialize services before any processors are initialized
219 // in case processors use them.
220 filer = new JavacFiler(context);
221 messager = new JavacMessager(context, this);
222 elementUtils = JavacElements.instance(context);
223 typeUtils = JavacTypes.instance(context);
224 modules = Modules.instance(context);
225 types = Types.instance(context);
226 annotate = Annotate.instance(context);
227 processorOptions = initProcessorOptions();
228 unmatchedProcessorOptions = initUnmatchedProcessorOptions();
229 messages = JavacMessages.instance(context);
230 taskListener = MultiTaskListener.instance(context);
231 symtab = Symtab.instance(context);
232 dcfh = DeferredCompletionFailureHandler.instance(context);
233 names = Names.instance(context);
234 enter = Enter.instance(context);
235 initialCompleter = ClassFinder.instance(context).getCompleter();
236 chk = Check.instance(context);
237 initProcessorLoader();
238 }
239
240 public void setProcessors(Iterable<? extends Processor> processors) {
241 Assert.checkNull(discoveredProcs);
242 initProcessorIterator(processors);
243 }
244
245 private Set<String> initPlatformAnnotations() {
246 Set<String> platformAnnotations = new HashSet<>();
247 platformAnnotations.add("java.lang.Deprecated");
248 platformAnnotations.add("java.lang.Override");
249 platformAnnotations.add("java.lang.SuppressWarnings");
250 platformAnnotations.add("java.lang.annotation.Documented");
251 platformAnnotations.add("java.lang.annotation.Inherited");
252 platformAnnotations.add("java.lang.annotation.Retention");
651 private Set<String> initUnmatchedProcessorOptions() {
652 Set<String> unmatchedProcessorOptions = new HashSet<>();
653 unmatchedProcessorOptions.addAll(processorOptions.keySet());
654 return unmatchedProcessorOptions;
655 }
656
657 /**
658 * State about how a processor has been used by the tool. If a
659 * processor has been used on a prior round, its process method is
660 * called on all subsequent rounds, perhaps with an empty set of
661 * annotations to process. The {@code annotationSupported} method
662 * caches the supported annotation information from the first (and
663 * only) getSupportedAnnotationTypes call to the processor.
664 */
665 static class ProcessorState {
666 public Processor processor;
667 public boolean contributed;
668 private ArrayList<Pattern> supportedAnnotationPatterns;
669 private ArrayList<String> supportedOptionNames;
670
671 ProcessorState(Processor p, Log log, Source source, DeferredCompletionFailureHandler dcfh,
672 boolean allowModules, ProcessingEnvironment env) {
673 processor = p;
674 contributed = false;
675
676 Handler prevDeferredHandler = dcfh.setHandler(dcfh.userCodeHandler);
677 try {
678 processor.init(env);
679
680 checkSourceVersionCompatibility(source, log);
681
682 supportedAnnotationPatterns = new ArrayList<>();
683 for (String importString : processor.getSupportedAnnotationTypes()) {
684 supportedAnnotationPatterns.add(importStringToPattern(allowModules,
685 importString,
686 processor,
687 log));
688 }
689
690 supportedOptionNames = new ArrayList<>();
691 for (String optionName : processor.getSupportedOptions() ) {
692 if (checkOptionName(optionName, log))
693 supportedOptionNames.add(optionName);
694 }
695
696 } catch (ClientCodeException e) {
697 throw e;
698 } catch (Throwable t) {
699 throw new AnnotationProcessingError(t);
700 } finally {
701 dcfh.setHandler(prevDeferredHandler);
702 }
703 }
704
705 /**
706 * Checks whether or not a processor's source version is
707 * compatible with the compilation source version. The
708 * processor's source version needs to be greater than or
709 * equal to the source version of the compile.
710 */
711 private void checkSourceVersionCompatibility(Source source, Log log) {
712 SourceVersion procSourceVersion = processor.getSupportedSourceVersion();
713
714 if (procSourceVersion.compareTo(Source.toSourceVersion(source)) < 0 ) {
715 log.warning(Warnings.ProcProcessorIncompatibleSourceVersion(procSourceVersion,
716 processor.getClass().getName(),
717 source.name));
718 }
719 }
720
721 private boolean checkOptionName(String optionName, Log log) {
757 DiscoveredProcessors psi;
758 Iterator<ProcessorState> innerIter;
759 boolean onProcInterator;
760
761 ProcessorStateIterator(DiscoveredProcessors psi) {
762 this.psi = psi;
763 this.innerIter = psi.procStateList.iterator();
764 this.onProcInterator = false;
765 }
766
767 public ProcessorState next() {
768 if (!onProcInterator) {
769 if (innerIter.hasNext())
770 return innerIter.next();
771 else
772 onProcInterator = true;
773 }
774
775 if (psi.processorIterator.hasNext()) {
776 ProcessorState ps = new ProcessorState(psi.processorIterator.next(),
777 log, source, dcfh,
778 Feature.MODULES.allowedInSource(source),
779 JavacProcessingEnvironment.this);
780 psi.procStateList.add(ps);
781 return ps;
782 } else
783 throw new NoSuchElementException();
784 }
785
786 public boolean hasNext() {
787 if (onProcInterator)
788 return psi.processorIterator.hasNext();
789 else
790 return innerIter.hasNext() || psi.processorIterator.hasNext();
791 }
792
793 public void remove () {
794 throw new UnsupportedOperationException();
795 }
796
797 /**
798 * Run all remaining processors on the procStateList that
950 }
951
952 void addAnnotations(Element e, Set<TypeElement> p) {
953 for (AnnotationMirror annotationMirror :
954 elements.getAllAnnotationMirrors(e) ) {
955 Element e2 = annotationMirror.getAnnotationType().asElement();
956 p.add((TypeElement) e2);
957 }
958 }
959
960 @Override @DefinedBy(Api.LANGUAGE_MODEL)
961 public Set<TypeElement> scan(Element e, Set<TypeElement> p) {
962 addAnnotations(e, p);
963 return super.scan(e, p);
964 }
965 }
966
967 private boolean callProcessor(Processor proc,
968 Set<? extends TypeElement> tes,
969 RoundEnvironment renv) {
970 Handler prevDeferredHandler = dcfh.setHandler(dcfh.userCodeHandler);
971 try {
972 return proc.process(tes, renv);
973 } catch (ClassFinder.BadClassFile ex) {
974 log.error(Errors.ProcCantAccess1(ex.sym, ex.getDetailValue()));
975 return false;
976 } catch (CompletionFailure ex) {
977 StringWriter out = new StringWriter();
978 ex.printStackTrace(new PrintWriter(out));
979 log.error(Errors.ProcCantAccess(ex.sym, ex.getDetailValue(), out.toString()));
980 return false;
981 } catch (ClientCodeException e) {
982 throw e;
983 } catch (Throwable t) {
984 throw new AnnotationProcessingError(t);
985 } finally {
986 dcfh.setHandler(prevDeferredHandler);
987 }
988 }
989
990 /**
991 * Helper object for a single round of annotation processing.
992 */
993 class Round {
994 /** The round number. */
995 final int number;
996 /** The diagnostic handler for the round. */
997 final Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
998
999 /** The ASTs to be compiled. */
1000 List<JCCompilationUnit> roots;
1001 /** The trees that need to be cleaned - includes roots and implicitly parsed trees. */
1002 Set<JCCompilationUnit> treesToClean;
1003 /** The classes to be compiler that have were generated. */
1004 Map<ModuleSymbol, Map<String, JavaFileObject>> genClassFiles;
1005
1006 /** The set of annotations to be processed this round. */
|