src.java.compiler.share.classes.javax.annotation.processing.Processor Maven / Gradle / Ivy
Show all versions of nb-javac Show documentation
/*
* Copyright (c) 2005, 2022, 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:
*
*
*
* - 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.
*
*
- Next, the tool calls the {@link #init init} method with
* an appropriate {@link ProcessingEnvironment}.
*
*
- 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.
*
*
- 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 interfaces of the annotations {@linkplain
* AnnotatedConstruct present} on the {@linkplain
* RoundEnvironment#getRootElements root elements}, what {@linkplain
* #getSupportedAnnotationTypes annotation interfaces a processor
* supports}, and whether or not a processor {@linkplain #process
* claims the annotation interfaces it processes}. A processor will
* be asked to process a subset of the annotation interfaces it
* supports, possibly an empty set.
*
* For a given round, the tool computes the set of annotation
* interfaces that are present on the elements enclosed within the
* root elements. If there is at least one annotation interface
* present, then as processors claim annotation interfaces, they are
* removed from the set of unmatched annotation interfaces. When the
* set is empty or no more processors are available, the round has run
* to completion. If there are no annotation interfaces present,
* annotation processing still occurs but only universal
* processors which support processing all annotation interfaces,
* {@code "*"}, can claim the (empty) set of annotation interfaces.
*
*
An annotation interface is considered present if there is at least
* one annotation of that interface 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 classes and interfaces 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 interface 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 interfaces},
* processors are advised to include both the repeatable annotation
* interface and its containing annotation interface in the set of {@linkplain
* #getSupportedAnnotationTypes() supported annotation interfaces} 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:
*
*
*
* - The result of processing a given input is not a function of the presence or absence
* of other inputs (orthogonality).
*
*
- Processing the same input produces the same output (consistency).
*
*
- Processing input A followed by processing input B
* is equivalent to processing B then A
* (commutativity)
*
*
- 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.
*
* @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 set if none
* @see javax.annotation.processing.SupportedOptions
*/
Set getSupportedOptions();
/**
* Returns the names of the annotation interfaces supported by this
* processor. An element of the result may be the canonical
* (fully qualified) name of a supported annotation interface.
* Alternately it may be of the form "name.*
"
* representing the set of all annotation interfaces with canonical
* names beginning with "name.
".
*
* In either of those cases, the name of the annotation interface 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 interfaces 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 interfaces with
* a module name do not match.
*
* Finally, {@code "*"} by itself represents the set of all
* annotation interfaces, 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:
*
- ModuleName
/
*
* - DotStar:
*
.
*
*
*
*
* where TypeName and ModuleName are as defined in
* The Java Language Specification
* ({@jls 6.5 Determining the Meaning of a Name}).
*
* @apiNote When running in an environment which supports modules,
* processors are encouraged to include the module prefix when
* describing their supported annotation interfaces. 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 interfaces supported by this processor
* or an empty set if none
* @see javax.annotation.processing.SupportedAnnotationTypes
* @jls 3.8 Identifiers
*/
Set getSupportedAnnotationTypes();
/**
* {@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 interfaces on {@linkplain
* RoundEnvironment#getRootElements() root elements} originating
* from the prior round and returns whether or not these
* annotation interfaces are claimed by this processor. If {@code
* true} is returned, the annotation interfaces are claimed and
* subsequent processors will not be asked to process them; if
* {@code false} is returned, the annotation interfaces 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 interfaces requested to be processed
* @param roundEnv environment for information about the current and prior round
* @return whether or not the set of annotation interfaces are claimed by this processor
*/
boolean process(Set extends TypeElement> 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 interface, 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 List.of({@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 List.of({@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 extends Completion> getCompletions(Element element,
AnnotationMirror annotation,
ExecutableElement member,
String userText);
}