/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Objects of this class hold and manage the state needed to support
* annotation processing.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
private final boolean printProcessorInfo;
private final boolean printRounds;
private final boolean verbose;
private final boolean lint;
private final boolean procOnly;
private final boolean fatalErrors;
private final boolean werror;
private final boolean showResolveErrors;
private boolean foundTypeProcessors;
/**
* Holds relevant state history of which processors have been
* used.
*/
/**
* Map of processor-specific options.
*/
/**
*/
/**
* Annotations implicitly processed and claimed by javac.
*/
/**
* Set of packages given on command line.
*/
/** The log to be used for error reporting.
*/
/** Diagnostic factory.
*/
/**
* Source level of the compile.
*/
/**
* JavacMessages object used for localization
*/
foundTypeProcessors = false;
// Initialize services before any processors are initialized
// in case processors use them.
}
}
try {
} catch (Throwable t) {
new AssertionError("Problem instantiating PrintingProcessor.");
assertError.initCause(t);
throw assertError;
}
} else if (processors != null) {
} else {
try {
// If processorpath is not explicitly set, use the classpath.
/*
* If the "-processor" option is used, search the appropriate
* path for the named class. Otherwise, use a service
* provider mechanism to create the processor iterator.
*/
if (processorNames != null) {
} else {
}
} catch (SecurityException e) {
/*
* A security exception will occur if we can't create a classloader.
* Ignore the exception if, with hindsight, we didn't need it anyway
* (i.e. no processor was specified either explicitly, or implicitly,
* in service configuration file.) Otherwise, we cannot continue.
*/
}
}
}
/**
* Returns an empty processor iterator if no processors are on the
* relevant path, otherwise if processors are present, logs an
* error. Called when a service loader is unavailable for some
* reason, either because a service loader class cannot be found
* or because a security policy prevents class loaders from being
* created.
*
* @param key The resource key to use to log an error message
* @param e If non-null, pass this exception to Abort
*/
if (fileManager instanceof JavacFileManager) {
handleException(key, e);
} else {
handleException(key, e);
}
}
/**
* Handle a security exception thrown during initializing the
* Processor iterator.
*/
if (e != null) {
throw new Abort(e);
} else {
throw new Abort();
}
}
/**
* Use a service loader appropriate for the platform to provide an
* iterator over annotations processors. If
* java.util.ServiceLoader is present use it, otherwise, use
* sun.misc.Service, otherwise fail if a loader is needed.
*/
// The to-be-wrapped iterator.
private boolean jusl;
try {
try {
loadMethodName = "load";
jusl = true;
} catch (ClassNotFoundException cnfe) {
try {
loadMethodName = "providers";
jusl = false;
} catch (ClassNotFoundException cnfe2) {
// Fail softly if a loader is not actually needed.
null);
return;
}
}
// java.util.ServiceLoader.load or sun.misc.Service.providers
Class.class,
ClassLoader.class);
Processor.class,
// For java.util.ServiceLoader, we have to call another
// method to get the iterator.
if (jusl) {
}
// The result should now be an iterator.
} catch (Throwable t) {
throw new Abort(t);
}
}
public boolean hasNext() {
try {
} catch (Throwable t) {
if ("ServiceConfigurationError".
}
throw new Abort(t);
}
}
try {
} catch (Throwable t) {
if ("ServiceConfigurationError".
} else {
}
throw new Abort(t);
}
}
public void remove() {
throw new UnsupportedOperationException();
}
public void close() {
if (jusl) {
try {
// Call java.util.ServiceLoader.reload
} catch(Exception e) {
; // Ignore problems during a call to reload.
}
}
}
}
this.processorCL = processorCL;
}
public boolean hasNext() {
return true;
else {
return false;
else {
try {
try {
} catch (ClassNotFoundException cnfe) {
return false;
} catch (ClassCastException cce) {
return false;
} catch (Exception e ) {
return false;
}
} catch(ClientCodeException e) {
throw e;
} catch(Throwable t) {
throw new AnnotationProcessingError(t);
}
return true;
}
}
}
if (hasNext()) {
return p;
} else
throw new NoSuchElementException();
}
public void remove () {
throw new UnsupportedOperationException();
}
}
public boolean atLeastOneProcessor() {
}
if (sepIndex == -1)
else if (sepIndex >= 3) {
}
}
}
}
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 boolean contributed;
processor = p;
contributed = false;
try {
log));
}
}
} catch (ClientCodeException e) {
throw e;
} 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.
*/
}
}
if (!valid)
return valid;
}
for(Pattern p: supportedAnnotationPatterns) {
return true;
}
return false;
}
/**
* Remove options that are matched by this processor.
*/
}
}
// 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 provider
* mechanism if additional queries are made.
*/
boolean onProcInterator;
this.onProcInterator = false;
}
if (!onProcInterator) {
else
onProcInterator = true;
}
return ps;
} else
throw new NoSuchElementException();
}
public boolean hasNext() {
if (onProcInterator)
else
}
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.
*/
if (!onProcInterator) {
if (ps.contributed)
}
}
}
}
return new ProcessorStateIterator(this);
}
this.processorIterator = processorIterator;
}
/**
* Free jar files, etc. if using a service loader.
*/
public void close() {
if (processorIterator != null &&
processorIterator instanceof ServiceIterator) {
}
}
}
for(TypeElement a : annotationsPresent) {
a);
}
// Give "*" processors a chance to match
// 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.
false,
JavacProcessingEnvironment.this);
}
}
ps.contributed = true;
if (printProcessorInfo || verbose) {
}
if (processingResult) {
}
}
}
// Remove annotations processed by javac
}
}
// Run contributing processors that haven't run yet
// Debugging
}
/**
* Computes the set of annotations on the symbol in question.
* Leave class public for external testing purposes.
*/
public static class ComputeAnnotationSet extends
super();
}
// Don't scan enclosed elements of a package
return p;
}
for (AnnotationMirror annotationMirror :
elements.getAllAnnotationMirrors(e) ) {
}
return super.scan(e, p);
}
}
try {
} catch (BadClassFile ex) {
return false;
} catch (CompletionFailure ex) {
return false;
} catch (ClientCodeException e) {
throw e;
} catch (Throwable t) {
throw new AnnotationProcessingError(t);
}
}
/**
* Helper object for a single round of annotation processing.
*/
class Round {
/** The round number. */
final int number;
/** The context for the round. */
/** The compiler for the round. */
/** The log for the round. */
/** The ASTs to be compiled. */
/** The classes to be compiler that have were generated. */
/** The set of annotations to be processed this round. */
/** The set of top level classes to be processed this round. */
/** The set of package-info files to be processed this round. */
/** The number of Messager errors generated in this round. */
int nMessagerErrors;
/** Create a round (common code). */
log.deferDiagnostics = true;
// the following is for the benefit of JavacProcessingEnvironment.getContext()
// the following will be populated as needed
}
/** Create the first round. */
// The reverse() in the following line is to maintain behavioural
// compatibility with the previous revision of the code. Strictly speaking,
// it should not be necessary, but a javah golden file test fails without it.
}
/** Create a new round. */
this(prev.nextContext(),
// Check for errors after parsing
if (unrecoverableError())
return;
if (unrecoverableError())
return;
}
/** Create the next round to be used. */
try {
} finally {
}
}
/** Create the compiler to be used for the final compilation. */
try {
if (errorStatus) {
}
return c;
} finally {
}
}
/** Return the number of errors found so far in this round.
* This may include uncoverable errors, such as parse errors,
* and transient errors, such as missing symbols. */
int errorCount() {
return compiler.errorCount();
}
/** Return the number of warnings found so far in this round. */
int warningCount() {
return compiler.warningCount();
}
/** Return whether or not an unrecoverable error has occurred. */
boolean unrecoverableError() {
if (messager.errorRaised())
return true;
switch (d.getKind()) {
case WARNING:
if (werror)
return true;
break;
case ERROR:
return true;
break;
}
}
return false;
}
/** Find the set of annotations present in the set of top level
* classes and package info files to be processed this round. */
void findAnnotationsPresent() {
// Use annotation processing to compute the set of annotations present
}
/** Enter a set of generated class files. */
throw new AssertionError(file);
if (p.package_info == null)
cs = p.package_info;
} else
}
}
/** Enter a set of syntax trees. */
}
/** Run a processing round. */
if (taskListener != null)
try {
if (lastRound) {
filer.setLastRound(true);
JavacProcessingEnvironment.this);
} else {
}
} finally {
if (taskListener != null)
}
}
if (!showAll) {
// suppress errors, which are all presumed to be transient resolve errors
}
}
/** Print info about this round. */
if (printRounds || verbose) {
ap,
}
}
/** Get the context for the next round of processing.
* Important values are propogated from round to round;
* other values are implicitly reset.
*/
final boolean shareNames = true;
if (shareNames) {
}
if (jfm instanceof JavacFileManager) {
}
}
}
return next;
}
}
// TODO: internal catch clauses?; catch and rethrow an annotation
// processing error
boolean errorStatus;
boolean moreToDo;
do {
// Run processors for round n
// Processors for round n have run to completion.
// Check for errors and whether there is more work to do.
// Set up next round.
// Copy mutable collections returned from filer.
// Check for errors during setup.
if (round.unrecoverableError())
errorStatus = true;
} while (moreToDo && !errorStatus);
// run last round
round.showDiagnostics(true);
/*
* If an annotation processor raises an error in a round,
* that round runs to completion and one last round occurs.
* The last round may also occur because no more source or
* class files have been generated. Therefore, if an error
* was raised on either of the last *two* rounds, the compile
* should exit with a nonzero exit code. The current value of
* errorStatus holds whether or not an error was raised on the
* second to last round; errorRaised() gives the error status
* of the last round.
*/
if (messager.errorRaised()
errorStatus = true;
// Free resources
this.close();
if (taskListener != null)
if (errorStatus) {
return compiler;
}
if (procOnly && !foundTypeProcessors) {
} else {
if (procOnly && foundTypeProcessors)
}
return compiler;
}
private void warnIfUnmatchedOptions() {
if (!unmatchedProcessorOptions.isEmpty()) {
}
}
/**
* Free resources related to annotation processing.
*/
public void close() {
try {
} catch (IOException e) {
throw new FatalError(msg, e);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
// avoid unchecked warning from use of varargs
}
}
}
/*
* Called retroactively to determine if a class loader was required,
* after we have failed to create one.
*/
return true;
try {
return true;
} catch (MalformedURLException ex) {
throw new AssertionError(ex);
}
catch (ServiceProxy.ServiceConfigurationError e) {
return true;
}
}
return false;
}
return nodes;
}
}
super.visitTopLevel(node);
}
super.visitClassDef(node);
}
super.visitMethodDef(node);
}
super.visitVarDef(node);
}
super.visitNewClass(node);
}
super.visitAssignop(node);
}
super.visitUnary(node);
}
super.visitBinary(node);
}
super.visitSelect(node);
}
super.visitIdent(node);
}
};
private boolean moreToDo() {
}
/**
* {@inheritdoc}
*
* Command line options suitable for presenting to annotation
* processors. "-Afoo=bar" should be "-Afoo" => "bar".
*/
return processorOptions;
}
return messager;
}
return filer;
}
return elementUtils;
}
return typeUtils;
}
}
return messages.getCurrentLocale();
}
return specifiedPackages;
}
/**
* Convert import-style string for supported annotations into a
* regex matching that string. If the string is a valid
* import-style string, return a regex that won't match anything.
*/
if (isValidImportString(s)) {
return validImportStringToPattern(s);
} else {
return noMatches; // won't match any valid identifier
}
}
/**
* Return true if the argument string is a valid import-style
* string specifying claimed annotations; return false otherwise.
*/
if (s.equals("*"))
return true;
boolean valid = true;
String t = s;
if (index != -1) {
// '*' must be last character...
// ... any and preceding character must be '.'
// Strip off ".*$" for identifier checks
}
} else
return false;
}
// Verify string is off the form (javaId \.)+ or javaId
if (valid) {
}
return valid;
}
if (s.equals("*")) {
return allMatches;
} else {
}
}
}
/**
* For internal use only. This method will be
* removed without warning.
*/
return context;
}
return "javac ProcessingEnvironment";
}
if (!SourceVersion.isIdentifier(s))
return false;
}
return true;
}
}