📄 javacprocessingenvironment.java
字号:
throw new UnsupportedOperationException(); } } private static class NameProcessIterator implements Iterator<Processor> { Processor nextProc = null; Iterator<String> names; ClassLoader processorCL; Log log; NameProcessIterator(String names, ClassLoader processorCL, Log log) { this.names = Arrays.asList(names.split(",")).iterator(); this.processorCL = processorCL; this.log = log; } public boolean hasNext() { if (nextProc != null) return true; else { if (!names.hasNext()) return false; else { String processorName = names.next(); Processor processor; try { try { processor = (Processor) (processorCL.loadClass(processorName).newInstance()); } catch (ClassNotFoundException cnfe) { log.error("proc.processor.not.found", processorName); return false; } catch (ClassCastException cce) { log.error("proc.processor.wrong.type", processorName); return false; } catch (Exception e ) { log.error("proc.processor.cant.instantiate", processorName); return false; } } catch(Throwable t) { throw new AnnotationProcessingError(t); } nextProc = processor; return true; } } } public Processor next() { if (hasNext()) { Processor p = nextProc; nextProc = null; return p; } else throw new NoSuchElementException(); } public void remove () { throw new UnsupportedOperationException(); } } public boolean atLeastOneProcessor() { return discoveredProcs.iterator().hasNext(); } private Map<String, String> initProcessorOptions(Context context) { Options options = Options.instance(context); Set<String> keySet = options.keySet(); Map<String, String> tempOptions = new LinkedHashMap<String, String>(); for(String key : keySet) { if (key.startsWith("-A") && key.length() > 2) { int sepIndex = key.indexOf('='); String candidateKey = null; String candidateValue = null; if (sepIndex == -1) candidateKey = key.substring(2); else if (sepIndex >= 3) { candidateKey = key.substring(2, sepIndex); candidateValue = (sepIndex < key.length()-1)? key.substring(sepIndex+1) : null; } tempOptions.put(candidateKey, candidateValue); } } return Collections.unmodifiableMap(tempOptions); } private Set<String> initUnmatchedProcessorOptions() { Set<String> unmatchedProcessorOptions = new HashSet<String>(); unmatchedProcessorOptions.addAll(processorOptions.keySet()); return unmatchedProcessorOptions; } /** * State about how a processor has been used by the tool. If a * processor has been used on a prior round, its process method is * called on all subsequent rounds, perhaps with an empty set of * annotations to process. The {@code annotatedSupported} method * caches the supported annotation information from the first (and * only) getSupportedAnnotationTypes call to the processor. */ static class ProcessorState { public Processor processor; public boolean contributed; private ArrayList<Pattern> supportedAnnotationPatterns; private ArrayList<String> supportedOptionNames; ProcessorState(Processor p, Log log, Source source, ProcessingEnvironment env) { processor = p; contributed = false; try { processor.init(env); checkSourceVersionCompatibility(source, log); supportedAnnotationPatterns = new ArrayList<Pattern>(); for (String importString : processor.getSupportedAnnotationTypes()) { supportedAnnotationPatterns.add(importStringToPattern(importString, processor, log)); } supportedOptionNames = new ArrayList<String>(); for (String optionName : processor.getSupportedOptions() ) { if (checkOptionName(optionName, log)) supportedOptionNames.add(optionName); } } catch (Throwable t) { throw new AnnotationProcessingError(t); } } /** * Checks whether or not a processor's source version is * compatible with the compilation source version. The * processor's source version needs to be greater than or * equal to the source version of the compile. */ private void checkSourceVersionCompatibility(Source source, Log log) { SourceVersion procSourceVersion = processor.getSupportedSourceVersion(); if (procSourceVersion.compareTo(Source.toSourceVersion(source)) < 0 ) { log.warning("proc.processor.incompatible.source.version", procSourceVersion, processor.getClass().getName(), source.name); } } private boolean checkOptionName(String optionName, Log log) { boolean valid = isValidOptionName(optionName); if (!valid) log.error("proc.processor.bad.option.name", optionName, processor.getClass().getName()); return valid; } public boolean annotationSupported(String annotationName) { for(Pattern p: supportedAnnotationPatterns) { if (p.matcher(annotationName).matches()) return true; } return false; } /** * Remove options that are matched by this processor. */ public void removeSupportedOptions(Set<String> unmatchedProcessorOptions) { unmatchedProcessorOptions.removeAll(supportedOptionNames); } } // TODO: These two classes can probably be rewritten better... /** * This class holds information about the processors that have * been discoverd so far as well as the means to discover more, if * necessary. A single iterator should be used per round of * annotation processing. The iterator first visits already * discovered processors then fails over to the service provided * mechanism if additional queries are made. */ class DiscoveredProcessors implements Iterable<ProcessorState> { class ProcessorStateIterator implements Iterator<ProcessorState> { DiscoveredProcessors psi; Iterator<ProcessorState> innerIter; boolean onProcInterator; ProcessorStateIterator(DiscoveredProcessors psi) { this.psi = psi; this.innerIter = psi.procStateList.iterator(); this.onProcInterator = false; } public ProcessorState next() { if (!onProcInterator) { if (innerIter.hasNext()) return innerIter.next(); else onProcInterator = true; } if (psi.processorIterator.hasNext()) { ProcessorState ps = new ProcessorState(psi.processorIterator.next(), log, source, JavacProcessingEnvironment.this); psi.procStateList.add(ps); return ps; } else throw new NoSuchElementException(); } public boolean hasNext() { if (onProcInterator) return psi.processorIterator.hasNext(); else return innerIter.hasNext() || psi.processorIterator.hasNext(); } public void remove () { throw new UnsupportedOperationException(); } /** * Run all remaining processors on the procStateList that * have not already run this round with an empty set of * annotations. */ public void runContributingProcs(RoundEnvironment re) { if (!onProcInterator) { Set<TypeElement> emptyTypeElements = Collections.emptySet(); while(innerIter.hasNext()) { ProcessorState ps = innerIter.next(); if (ps.contributed) callProcessor(ps.processor, emptyTypeElements, re); } } } } Iterator<? extends Processor> processorIterator; ArrayList<ProcessorState> procStateList; public ProcessorStateIterator iterator() { return new ProcessorStateIterator(this); } DiscoveredProcessors(Iterator<? extends Processor> processorIterator) { this.processorIterator = processorIterator; this.procStateList = new ArrayList<ProcessorState>(); } } private void discoverAndRunProcs(Context context, Set<TypeElement> annotationsPresent, List<ClassSymbol> topLevelClasses, List<PackageSymbol> packageInfoFiles) { // Writer for -XprintRounds and -XprintProcessorInfo data PrintWriter xout = context.get(Log.outKey); Map<String, TypeElement> unmatchedAnnotations = new HashMap<String, TypeElement>(annotationsPresent.size()); for(TypeElement a : annotationsPresent) { unmatchedAnnotations.put(a.getQualifiedName().toString(), a); } // Give "*" processors a chance to match if (unmatchedAnnotations.size() == 0) unmatchedAnnotations.put("", null); DiscoveredProcessors.ProcessorStateIterator psi = discoveredProcs.iterator(); // TODO: Create proper argument values; need past round // information to fill in this constructor. Note that the 1 // st round of processing could be the last round if there // were parse errors on the initial source files; however, we // are not doing processing in that case. Set<Element> rootElements = new LinkedHashSet<Element>(); rootElements.addAll(topLevelClasses); rootElements.addAll(packageInfoFiles); rootElements = Collections.unmodifiableSet(rootElements); RoundEnvironment renv = new JavacRoundEnvironment(false, false, rootElements, JavacProcessingEnvironment.this); while(unmatchedAnnotations.size() > 0 && psi.hasNext() ) { ProcessorState ps = psi.next(); Set<String> matchedNames = new HashSet<String>(); Set<TypeElement> typeElements = new LinkedHashSet<TypeElement>(); for (String unmatchedAnnotationName : unmatchedAnnotations.keySet()) { if (ps.annotationSupported(unmatchedAnnotationName) ) { matchedNames.add(unmatchedAnnotationName); TypeElement te = unmatchedAnnotations.get(unmatchedAnnotationName); if (te != null) typeElements.add(te); } } if (matchedNames.size() > 0 || ps.contributed) { boolean processingResult = callProcessor(ps.processor, typeElements, renv); ps.contributed = true; ps.removeSupportedOptions(unmatchedProcessorOptions); if (printProcessorInfo || verbose) { xout.println(Log.getLocalizedString("x.print.processor.info", ps.processor.getClass().getName(), matchedNames.toString(), processingResult)); } if (processingResult) { unmatchedAnnotations.keySet().removeAll(matchedNames); } } } unmatchedAnnotations.remove(""); if (lint && unmatchedAnnotations.size() > 0) { // Remove annotations processed by javac unmatchedAnnotations.keySet().removeAll(platformAnnotations); if (unmatchedAnnotations.size() > 0) { log = Log.instance(context); log.warning("proc.annotations.without.processors", unmatchedAnnotations.keySet()); } } // Run contributing processors that haven't run yet psi.runContributingProcs(renv); // Debugging if (options.get("displayFilerState") != null) filer.displayState();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -