There are two main purposes of the annotation processing environment - analysis and code generation.
The analysis permits you to extend the capabilities of the java compiler, analyzing program elements as they are being compiled, possibly adding additional constraints, validations, and reporting errors and warnings for violations of those constraints.
Code generation permits you to generate additional supplementary code from signals in your existing hand-written code, primarily (though not exclusively) keyed off of Annotations.
Some examples include Dagger, which is a system for compile-time-analyzed dependency injection, reporting errors and warnings normally found at runtime instead during the compilation of the code. Dagger also generates all the code that would normally be done with reflection, or by hand-writing glue-code, providing substantial performance benefits (in some cases) as well as infrastructure code which is available for step-through debugging, etc.
Another example is the Checker Framework which evaluates a variety of checks against your code, including null safety, etc.
A third example is Auto-Value intended to make small value types nearly trivial to write.
One thing the annotation processing environment is decidedly not suited for is mutation of existing code in place, or modification of code currently under compilation. While some projects do this, they are not actually using the annotation processor APIs but casting to internal compiler types to do so. While this is clearly possible, it's potentially brittle, and may not work reliably from version to version, or compiler to compiler, requiring custom handling for each version and compiler vendor.