All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.annotation.processing.Processor Maven / Gradle / Ivy

There is a newer version: 9-dev-r4023-3
Show newest version
/*
 * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * 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.
 */

package javax.annotation.processing;

import java.util.Set;
import javax.lang.model.util.Elements;
import javax.lang.model.AnnotatedConstruct;
import javax.lang.model.element.*;
import javax.lang.model.SourceVersion;

/**
 * The interface for an annotation processor.
 *
 * 

Annotation processing happens in a sequence of {@linkplain * javax.annotation.processing.RoundEnvironment rounds}. On each * round, a processor may be asked to {@linkplain #process process} a * subset of the annotations found on the source and class files * produced by a prior round. The inputs to the first round of * processing are the initial inputs to a run of the tool; these * initial inputs can be regarded as the output of a virtual zeroth * round of processing. If a processor was asked to process on a * given round, it will be asked to process on subsequent rounds, * including the last round, even if there are no annotations for it * to process. The tool infrastructure may also ask a processor to * process files generated implicitly by the tool's operation. * *

Each implementation of a {@code Processor} must provide a * public no-argument constructor to be used by tools to instantiate * the processor. The tool infrastructure will interact with classes * implementing this interface as follows: * *

    * *
  1. If an existing {@code Processor} object is not being used, to * create an instance of a processor the tool calls the no-arg * constructor of the processor class. * *
  2. Next, the tool calls the {@link #init init} method with * an appropriate {@code ProcessingEnvironment}. * *
  3. Afterwards, the tool calls {@link #getSupportedAnnotationTypes * getSupportedAnnotationTypes}, {@link #getSupportedOptions * getSupportedOptions}, and {@link #getSupportedSourceVersion * getSupportedSourceVersion}. These methods are only called once per * run, not on each round. * *
  4. As appropriate, the tool calls the {@link #process process} * method on the {@code Processor} object; a new {@code Processor} * object is not created for each round. * *
* * If a processor object is created and used without the above * protocol being followed, then the processor's behavior is not * defined by this interface specification. * *

The tool uses a discovery process to find annotation * processors and decide whether or not they should be run. By * configuring the tool, the set of potential processors can be * controlled. For example, for a {@link javax.tools.JavaCompiler * JavaCompiler} the list of candidate processors to run can be * {@linkplain javax.tools.JavaCompiler.CompilationTask#setProcessors * set directly} or controlled by a {@linkplain * javax.tools.StandardLocation#ANNOTATION_PROCESSOR_PATH search path} * used for a {@linkplain java.util.ServiceLoader service-style} * lookup. Other tool implementations may have different * configuration mechanisms, such as command line options; for * details, refer to the particular tool's documentation. Which * processors the tool asks to {@linkplain #process run} is a function * of the types of the annotations {@linkplain AnnotatedConstruct present} * on the {@linkplain * RoundEnvironment#getRootElements root elements}, what {@linkplain * #getSupportedAnnotationTypes annotation types a processor * supports}, and whether or not a processor {@linkplain #process * claims the annotation types it processes}. A processor will be asked to * process a subset of the annotation types it supports, possibly an * empty set. * * For a given round, the tool computes the set of annotation types * that are present on the elements enclosed within the root elements. * If there is at least one annotation type present, then as * processors claim annotation types, they are removed from the set of * unmatched annotation types. When the set is empty or no more * processors are available, the round has run to completion. If * there are no annotation types present, annotation processing still * occurs but only universal processors which support * processing all annotation types, {@code "*"}, can claim the (empty) * set of annotation types. * *

An annotation type is considered present if there is at least * one annotation of that type present on an element enclosed within * the root elements of a round. For this purpose, a type parameter is * considered to be enclosed by its {@linkplain * TypeParameterElement#getGenericElement generic * element}. * For this purpose, a package element is not considered to * enclose the top-level types within that package. (A root element * representing a package is created when a {@code package-info} file * is processed.) Likewise, for this purpose, a module element is * not considered to enclose the packages within that * module. (A root element representing a module is created when a * {@code module-info} file is processed.) * * Annotations on {@linkplain * java.lang.annotation.ElementType#TYPE_USE type uses}, as opposed to * annotations on elements, are ignored when computing whether or not * an annotation type is present. * *

An annotation is present if it meets the definition of being * present given in {@link AnnotatedConstruct}. In brief, an * annotation is considered present for the purposes of discovery if * it is directly present or present via inheritance. An annotation is * not considered present by virtue of being wrapped by a * container annotation. Operationally, this is equivalent to an * annotation being present on an element if and only if it would be * included in the results of {@link * Elements#getAllAnnotationMirrors(Element)} called on that element. Since * annotations inside container annotations are not considered * present, to properly process {@linkplain * java.lang.annotation.Repeatable repeatable annotation types}, * processors are advised to include both the repeatable annotation * type and its containing annotation type in the set of {@linkplain * #getSupportedAnnotationTypes() supported annotation types} of a * processor. * *

Note that if a processor supports {@code "*"} and returns {@code * true}, all annotations are claimed. Therefore, a universal * processor being used to, for example, implement additional validity * checks should return {@code false} so as to not prevent other such * checkers from being able to run. * *

If a processor throws an uncaught exception, the tool may cease * other active annotation processors. If a processor raises an * error, the current round will run to completion and the subsequent * round will indicate an {@linkplain RoundEnvironment#errorRaised * error was raised}. Since annotation processors are run in a * cooperative environment, a processor should throw an uncaught * exception only in situations where no error recovery or reporting * is feasible. * *

The tool environment is not required to support annotation * processors that access environmental resources, either {@linkplain * RoundEnvironment per round} or {@linkplain ProcessingEnvironment * cross-round}, in a multi-threaded fashion. * *

If the methods that return configuration information about the * annotation processor return {@code null}, return other invalid * input, or throw an exception, the tool infrastructure must treat * this as an error condition. * *

To be robust when running in different tool implementations, an * annotation processor should have the following properties: * *

    * *
  1. The result of processing a given input is not a function of the presence or absence * of other inputs (orthogonality). * *
  2. Processing the same input produces the same output (consistency). * *
  3. Processing input A followed by processing input B * is equivalent to processing B then A * (commutativity) * *
  4. Processing an input does not rely on the presence of the output * of other annotation processors (independence) * *
* *

The {@link Filer} interface discusses restrictions on how * processors can operate on files. * * @apiNote Implementors of this interface may find it convenient * to extend {@link AbstractProcessor} rather than implementing this * interface directly. * * @author Joseph D. Darcy * @author Scott Seligman * @author Peter von der Ahé * @since 1.6 */ public interface Processor { /** * Returns the options recognized by this processor. An * implementation of the processing tool must provide a way to * pass processor-specific options distinctly from options passed * to the tool itself, see {@link ProcessingEnvironment#getOptions * getOptions}. * *

Each string returned in the set must be a period separated * sequence of {@linkplain * javax.lang.model.SourceVersion#isIdentifier identifiers}: * *

*
*
SupportedOptionString: *
Identifiers * *
Identifiers: *
Identifier *
Identifier {@code .} Identifiers * *
Identifier: *
Syntactic identifier, including keywords and literals *
*
* *

A tool might use this information to determine if any * options provided by a user are unrecognized by any processor, * in which case it may wish to report a warning. * * @return the options recognized by this processor or an * empty collection if none * @see javax.annotation.processing.SupportedOptions */ Set getSupportedOptions(); /** * Returns the names of the annotation types supported by this * processor. An element of the result may be the canonical * (fully qualified) name of a supported annotation type. * Alternately it may be of the form "name.*" * representing the set of all annotation types with canonical * names beginning with "name.". * * In either of those cases, the name of the annotation type can * be optionally preceded by a module name followed by a {@code * "/"} character. For example, if a processor supports {@code * "a.B"}, this can include multiple annotation types named {@code * a.B} which reside in different modules. To only support {@code * a.B} in the {@code Foo} module, instead use {@code "Foo/a.B"}. * * If a module name is included, only an annotation in that module * is matched. In particular, if a module name is given in an * environment where modules are not supported, such as an * annotation processing environment configured for a {@linkplain * javax.annotation.processing.ProcessingEnvironment#getSourceVersion * source version} without modules, then the annotation types with * a module name do not match. * * Finally, {@code "*"} by itself represents the set of all * annotation types, including the empty set. Note that a * processor should not claim {@code "*"} unless it is actually * processing all files; claiming unnecessary annotations may * cause a performance slowdown in some environments. * *

Each string returned in the set must be accepted by the * following grammar: * *

*
*
SupportedAnnotationTypeString: *
ModulePrefixopt TypeName DotStaropt *
* * *
ModulePrefix: *
TypeName / * *
DotStar: *
. * *
*
* * where TypeName is as defined in * The Java™ Language Specification. * * @apiNote When running in an environment which supports modules, * processors are encouraged to include the module prefix when * describing their supported annotation types. The method {@link * AbstractProcessor#getSupportedAnnotationTypes * AbstractProcessor.getSupportedAnnotationTypes} provides support * for stripping off the module prefix when running in an * environment without modules. * * @return the names of the annotation types supported by this processor * @see javax.annotation.processing.SupportedAnnotationTypes * @jls 3.8 Identifiers * @jls 6.5.5 Meaning of Type Names */ Set getSupportedAnnotationTypes(); /** * Returns the latest source version supported by this annotation * processor. * * @return the latest source version supported by this annotation * processor. * @see javax.annotation.processing.SupportedSourceVersion * @see ProcessingEnvironment#getSourceVersion */ SourceVersion getSupportedSourceVersion(); /** * Initializes the processor with the processing environment. * * @param processingEnv environment for facilities the tool framework * provides to the processor */ void init(ProcessingEnvironment processingEnv); /** * Processes a set of annotation types on type elements * originating from the prior round and returns whether or not * these annotation types are claimed by this processor. If {@code * true} is returned, the annotation types are claimed and subsequent * processors will not be asked to process them; if {@code false} * is returned, the annotation types are unclaimed and subsequent * processors may be asked to process them. A processor may * always return the same boolean value or may vary the result * based on its own chosen criteria. * *

The input set will be empty if the processor supports {@code * "*"} and the root elements have no annotations. A {@code * Processor} must gracefully handle an empty set of annotations. * * @param annotations the annotation types requested to be processed * @param roundEnv environment for information about the current and prior round * @return whether or not the set of annotation types are claimed by this processor */ boolean process(Set annotations, RoundEnvironment roundEnv); /** * Returns to the tool infrastructure an iterable of suggested * completions to an annotation. Since completions are being asked * for, the information provided about the annotation may be * incomplete, as if for a source code fragment. A processor may * return an empty iterable. Annotation processors should focus * their efforts on providing completions for annotation members * with additional validity constraints known to the processor, for * example an {@code int} member whose value should lie between 1 * and 10 or a string member that should be recognized by a known * grammar, such as a regular expression or a URL. * *

Since incomplete programs are being modeled, some of the * parameters may only have partial information or may be {@code * null}. At least one of {@code element} and {@code userText} * must be non-{@code null}. If {@code element} is non-{@code null}, * {@code annotation} and {@code member} may be {@code * null}. Processors may not throw a {@code NullPointerException} * if some parameters are {@code null}; if a processor has no * completions to offer based on the provided information, an * empty iterable can be returned. The processor may also return * a single completion with an empty value string and a message * describing why there are no completions. * *

Completions are informative and may reflect additional * validity checks performed by annotation processors. For * example, consider the simple annotation: * *

*
    * @MersennePrime {
    *    int value();
    * }
    * 
*
* * (A Mersenne prime is prime number of the form * 2n - 1.) Given an {@code AnnotationMirror} * for this annotation type, a list of all such primes in the * {@code int} range could be returned without examining any other * arguments to {@code getCompletions}: * *
*
    * import static javax.annotation.processing.Completions.*;
    * ...
    * return Arrays.asList({@link Completions#of(String) of}("3"),
    *                      of("7"),
    *                      of("31"),
    *                      of("127"),
    *                      of("8191"),
    *                      of("131071"),
    *                      of("524287"),
    *                      of("2147483647"));
    * 
*
* * A more informative set of completions would include the number * of each prime: * *
*
    * return Arrays.asList({@link Completions#of(String, String) of}("3",          "M2"),
    *                      of("7",          "M3"),
    *                      of("31",         "M5"),
    *                      of("127",        "M7"),
    *                      of("8191",       "M13"),
    *                      of("131071",     "M17"),
    *                      of("524287",     "M19"),
    *                      of("2147483647", "M31"));
    * 
*
* * However, if the {@code userText} is available, it can be checked * to see if only a subset of the Mersenne primes are valid. For * example, if the user has typed * *
* * @MersennePrime(1 * *
* * the value of {@code userText} will be {@code "1"}; and only * two of the primes are possible completions: * *
*
    * return Arrays.asList(of("127",        "M7"),
    *                      of("131071",     "M17"));
    * 
*
* * Sometimes no valid completion is possible. For example, there * is no in-range Mersenne prime starting with 9: * *
* * @MersennePrime(9 * *
* * An appropriate response in this case is to either return an * empty list of completions, * *
*
    * return Collections.emptyList();
    * 
*
* * or a single empty completion with a helpful message * *
*
    * return Arrays.asList(of("", "No in-range Mersenne primes start with 9"));
    * 
*
* * @param element the element being annotated * @param annotation the (perhaps partial) annotation being * applied to the element * @param member the annotation member to return possible completions for * @param userText source code text to be completed * * @return suggested completions to the annotation */ Iterable getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy