Slide 1

Slide 1 text

Annotation Processing Jake Wharton Boilerplate Destruction!

Slide 2

Slide 2 text

Annotation Processing Jake Wharton Boilerplate Destruction!

Slide 3

Slide 3 text

JSR 269

Slide 4

Slide 4 text

JSR 269 • 6 months after Java 5 released

Slide 5

Slide 5 text

JSR 269 • 6 months after Java 5 released • “Pluggable Annotation Processing API”

Slide 6

Slide 6 text

JSR 269 • 6 months after Java 5 released • “Pluggable Annotation Processing API” • Preceded by doclet and apt standalone tools

Slide 7

Slide 7 text

JSR 269 • 6 months after Java 5 released • “Pluggable Annotation Processing API” • Preceded by doclet and apt standalone tools • Google, Oracle, Sun, BEA Systems sponsored

Slide 8

Slide 8 text

JSR 269 • 6 months after Java 5 released • “Pluggable Annotation Processing API” • Preceded by doclet and apt standalone tools • Google, Oracle, Sun, BEA Systems sponsored • Simplify and standardize processing annotations

Slide 9

Slide 9 text

JSR 269 • 6 months after Java 5 released • “Pluggable Annotation Processing API” • Preceded by doclet and apt standalone tools • Google, Oracle, Sun, BEA Systems sponsored • Simplify and standardize processing annotations • No standalone tool, part of javac

Slide 10

Slide 10 text

AutoValue @AutoValue
 abstract class Animal {
 static Animal create(String name, int numberOfLegs) {
 return new AutoValue_Animal(name, numberOfLegs);
 } 
 abstract String name();
 abstract int numberOfLegs();
 } github.com/google/auto/

Slide 11

Slide 11 text

AutoValue github.com/google/auto/ final class AutoValue_Animal extends Animal {
 private final String name;
 private final int numberOfLegs;
 
 AutoValue_Animal(
 String name,
 int numberOfLegs) {
 if (name == null) {
 throw new NullPointerException("Null name");
 }
 this.name = name;
 this.numberOfLegs = numberOfLegs;
 }
 
 @Override
 String name() {
 return name;
 }
 
 @Override
 int numberOfLegs() {
 return numberOfLegs;
 }
 
 @Override
 public String toString() {
 return "Animal{"
 + "name=" + name
 + ", numberOfLegs=" + numberOfLegs
 + "}";
 }
 
 @Override
 public boolean equals(Object o) {
 if (o == this) {
 return true;
 }
 if (o instanceof Animal) {
 Animal that = (Animal) o;
 return (this.name.equals(that.name()))
 && (this.numberOfLegs == that.numberOfLegs());
 }
 return false;
 }
 
 @Override
 public int hashCode() {
 int h = 1;
 h *= 1000003;
 h ^= name.hashCode();
 h *= 1000003;
 h ^= numberOfLegs;
 return h;
 }
 }

Slide 12

Slide 12 text

AutoValue github.com/google/auto/ final class AutoValue_Animal extends Animal {
 private final String name;
 private final int numberOfLegs;
 
 AutoValue_Animal(
 String name,
 int numberOfLegs) {
 if (name == null) {
 throw new NullPointerException("Null name");
 }
 this.name = name;
 this.numberOfLegs = numberOfLegs;
 }
 
 @Override
 String name() {
 return name;
 }
 
 @Override
 int numberOfLegs() {
 return numberOfLegs;
 }
 
 @Override
 public String toString() {
 return "Animal{"
 + "name=" + name
 + ", numberOfLegs=" + numberOfLegs
 + "}";
 }
 
 @Override
 public boolean equals(Object o) {
 if (o == this) {
 return true;
 }
 if (o instanceof Animal) {
 Animal that = (Animal) o;
 return (this.name.equals(that.name()))
 && (this.numberOfLegs == that.numberOfLegs());
 }
 return false;
 }
 
 @Override
 public int hashCode() {
 int h = 1;
 h *= 1000003;
 h ^= name.hashCode();
 h *= 1000003;
 h ^= numberOfLegs;
 return h;
 }
 } Final fields Constructor Getters .toString() .equals() .hashCode()

Slide 13

Slide 13 text

AutoParcel github.com/frankiesardo/auto-parcel/ @AutoParcel
 abstract class Animal implements Parcelable {
 static Animal create(String name, int numberOfLegs) {
 return new AutoParcel_Animal(name, numberOfLegs);
 } 
 abstract String name();
 abstract int numberOfLegs();
 }

Slide 14

Slide 14 text

AutoParcel github.com/frankiesardo/auto-parcel/ @AutoParcel
 abstract class Animal implements Parcelable {
 static Animal create(String name, int numberOfLegs) {
 return new AutoParcel_Animal(name, numberOfLegs);
 } 
 abstract String name();
 abstract int numberOfLegs();
 }

Slide 15

Slide 15 text

AutoParcel final class AutoParcel_Animal extends Animal {
 private final String name;
 private final int numberOfLegs;
 
 AutoParcel_Animal(
 String name,
 int numberOfLegs) {
 if (name == null) {
 throw new NullPointerException("Null name");
 }
 this.name = name;
 this.numberOfLegs = numberOfLegs;
 }
 
 @Override
 String name() {
 return name;
 }
 
 @Override
 int numberOfLegs() {
 return numberOfLegs;
 }
 
 @Override
 public String toString() {
 return "Animal{"
 + "name=" + name
 + ", numberOfLegs=" + numberOfLegs
 + "}";
 }
 
 @Override
 public boolean equals(Object o) {
 if (o == this) {
 return true;
 }
 if (o instanceof Animal) {
 Animal that = (Animal) o;
 return (this.name.equals(that.name()))
 && (this.numberOfLegs == that.numberOfLegs());
 }
 return false;
 }
 
 @Override
 public int hashCode() {
 int h = 1;
 h *= 1000003;
 h ^= name.hashCode();
 h *= 1000003;
 h ^= numberOfLegs;
 return h;
 }
 
 public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
 @Override public Animal createFromParcel(Parcel in) {
 return new AutoParcel_Animal(in);
 }
 @Override public Animal[] newArray(int size) {
 return new Animal[size];
 }
 };
 
 private final static ClassLoader CL = AutoParcel_Animal.class.getClassLoader();
 
 private AutoParcel_Animal(Parcel in) {
 this(
 (String) in.readValue(CL),
 (Integer) in.readValue(CL));
 }
 
 @Override public void writeToParcel(Parcel dest, int flags) {
 dest.writeValue(name);
 dest.writeValue(numberOfLegs);
 }
 
 @Override public int describeContents() {
 return 0;
 }
 } github.com/frankiesardo/auto-parcel/

Slide 16

Slide 16 text

AutoParcel final class AutoParcel_Animal extends Animal {
 private final String name;
 private final int numberOfLegs;
 
 AutoParcel_Animal(
 String name,
 int numberOfLegs) {
 if (name == null) {
 throw new NullPointerException("Null name");
 }
 this.name = name;
 this.numberOfLegs = numberOfLegs;
 }
 
 @Override
 String name() {
 return name;
 }
 
 @Override
 int numberOfLegs() {
 return numberOfLegs;
 }
 
 @Override
 public String toString() {
 return "Animal{"
 + "name=" + name
 + ", numberOfLegs=" + numberOfLegs
 + "}";
 }
 
 @Override
 public boolean equals(Object o) {
 if (o == this) {
 return true;
 }
 if (o instanceof Animal) {
 Animal that = (Animal) o;
 return (this.name.equals(that.name()))
 && (this.numberOfLegs == that.numberOfLegs());
 }
 return false;
 }
 
 @Override
 public int hashCode() {
 int h = 1;
 h *= 1000003;
 h ^= name.hashCode();
 h *= 1000003;
 h ^= numberOfLegs;
 return h;
 }
 
 public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
 @Override public Animal createFromParcel(Parcel in) {
 return new AutoParcel_Animal(in);
 }
 @Override public Animal[] newArray(int size) {
 return new Animal[size];
 }
 };
 
 private final static ClassLoader CL = AutoParcel_Animal.class.getClassLoader();
 
 private AutoParcel_Animal(Parcel in) {
 this(
 (String) in.readValue(CL),
 (Integer) in.readValue(CL));
 }
 
 @Override public void writeToParcel(Parcel dest, int flags) {
 dest.writeValue(name);
 dest.writeValue(numberOfLegs);
 }
 
 @Override public int describeContents() {
 return 0;
 }
 } Final fields Constructor Getters .toString() .equals() .hashCode() github.com/frankiesardo/auto-parcel/ CREATOR Parcel constructor Parcel writer

Slide 17

Slide 17 text

Butter Knife class SimpleActivity extends Activity {
 @InjectView(R.id.title) TextView title;
 @InjectView(R.id.hello) Button hello;
 @InjectView(R.id.list_of_things) ListView listOfThings;
 @OnClick(R.id.hello) void sayHello() {
 Toast.makeText(this, "Hello, views!", LENGTH_SHORT).show();
 } ! 
 // ...
 } jakewharton.github.io/butterknife/

Slide 18

Slide 18 text

Butter Knife jakewharton.github.io/butterknife/ static void inject(Finder finder, final SimpleActivity target, Object source) {
 View view;
 view = finder.findRequired(source, 2130968576, "field 'title'");
 target.title = (android.widget.TextView) view;
 view = finder.findRequired(source, 2130968578, "field 'hello' and method 'sayHello'");
 target.hello = (android.widget.Button) view;
 view.setOnClickListener(new View.OnClickListener() {
 @Override public void onClick(View p0) {
 target.sayHello();
 }
 });
 view = finder.findRequired(source, 2130968579, "field 'listOfThings'"); target.listOfThings = (android.widget.ListView) view;
 }

Slide 19

Slide 19 text

Butter Knife jakewharton.github.io/butterknife/ static void inject(Finder finder, final SimpleActivity target, Object source) {
 View view;
 view = finder.findRequired(source, 2130968576, "field 'title'");
 target.title = (android.widget.TextView) view;
 view = finder.findRequired(source, 2130968578, "field 'hello' and method 'sayHello'");
 target.hello = (android.widget.Button) view;
 view.setOnClickListener(new View.OnClickListener() {
 @Override public void onClick(View p0) {
 target.sayHello();
 }
 });
 view = finder.findRequired(source, 2130968579, "field 'listOfThings'"); target.listOfThings = (android.widget.ListView) view;
 }

Slide 20

Slide 20 text

Butter Knife jakewharton.github.io/butterknife/ static void inject(Finder finder, final SimpleActivity target, Object source) {
 View view;
 view = finder.findRequired(source, 2130968576, "field 'title'");
 target.title = (android.widget.TextView) view;
 view = finder.findRequired(source, 2130968578, "field 'hello' and method 'sayHello'");
 target.hello = (android.widget.Button) view;
 view.setOnClickListener(new View.OnClickListener() {
 @Override public void onClick(View p0) {
 target.sayHello();
 }
 });
 view = finder.findRequired(source, 2130968579, "field 'listOfThings'"); target.listOfThings = (android.widget.ListView) view;
 }

Slide 21

Slide 21 text

Butter Knife jakewharton.github.io/butterknife/ static void inject(Finder finder, final SimpleActivity target, Object source) {
 View view;
 view = finder.findRequired(source, 2130968576, "field 'title'");
 target.title = (android.widget.TextView) view;
 view = finder.findRequired(source, 2130968578, "field 'hello' and method 'sayHello'");
 target.hello = (android.widget.Button) view;
 view.setOnClickListener(new View.OnClickListener() {
 @Override public void onClick(View p0) {
 target.sayHello();
 }
 });
 view = finder.findRequired(source, 2130968579, "field 'listOfThings'"); target.listOfThings = (android.widget.ListView) view;
 }

Slide 22

Slide 22 text

Dagger square.github.io/dagger/ @Module(injects = CoffeeApp.class)
 class DripCoffeeModule {
 @Provides @Singleton Heater provideHeater() {
 return new ElectricHeater();
 }
 
 @Provides Pump providePump(Thermosiphon pump) {
 return pump;
 }
 }


Slide 23

Slide 23 text

Dagger class CoffeeMaker {
 @Inject Lazy heater;
 @Inject Pump pump;
 
 public void brew() {
 heater.get().on();
 pump.pump();
 System.out.println(" [_]P coffee! [_]P ");
 heater.get().off();
 }
 }
 square.github.io/dagger/

Slide 24

Slide 24 text

Dagger square.github.io/dagger/ class DripCoffeeModule$$ModuleAdapter extends ModuleAdapter { 
 @Override
 public void getBindings(BindingsGroup bindings, DripCoffeeModule module) {
 bindings.contributeProvidesBinding("coffee.Heater", new ProvideHeaterAdapter(module)); bindings.contributeProvidesBinding("coffee.Pump",
 new ProvidePumpAdapter(module));
 } }

Slide 25

Slide 25 text

Dagger square.github.io/dagger/ class DripCoffeeModule$$ModuleAdapter extends ModuleAdapter { 
 @Override
 public void getBindings(BindingsGroup bindings, DripCoffeeModule module) {
 bindings.contributeProvidesBinding("coffee.Heater", new ProvideHeaterAdapter(module)); bindings.contributeProvidesBinding("coffee.Pump",
 new ProvidePumpAdapter(module));
 } }

Slide 26

Slide 26 text

Dagger square.github.io/dagger/ class ProvideHeaterProvidesAdapter extends ProvidesBinding { 
 private final DripCoffeeModule module;
 
 public ProvideHeaterProvidesAdapter(DripCoffeeModule module) {
 this.module = module;
 }
 
 @Override
 public Heater get() {
 return module.provideHeater();
 }
 }

Slide 27

Slide 27 text

Dagger square.github.io/dagger/ class CoffeeMaker$$InjectAdapter
 extends Binding {
 
 private Binding> heater;
 private Binding pump;
 
 CoffeeMaker$$InjectAdapter() {
 super("coffee.CoffeeMaker", CoffeeMaker.class);
 }
 
 @Override public void attach(Linker linker) {
 heater = linker.requestBinding("dagger.Lazy");
 pump = linker.requestBinding("coffee.Pump");
 } ! // ...
 }

Slide 28

Slide 28 text

Dagger square.github.io/dagger/ class CoffeeMaker$$InjectAdapter
 extends Binding {
 
 private Binding> heater;
 private Binding pump;
 
 CoffeeMaker$$InjectAdapter() {
 super("coffee.CoffeeMaker", CoffeeMaker.class);
 }
 
 @Override public void attach(Linker linker) {
 heater = linker.requestBinding("dagger.Lazy");
 pump = linker.requestBinding("coffee.Pump");
 } ! // ...
 }

Slide 29

Slide 29 text

Dagger square.github.io/dagger/ class CoffeeMaker$$InjectAdapter
 extends Binding {
 
 // ...
 
 @Override public CoffeeMaker get() {
 CoffeeMaker result = new CoffeeMaker();
 injectMembers(result);
 return result;
 }
 
 @Override public void injectMembers(CoffeeMaker object) {
 object.heater = heater.get();
 object.pump = pump.get();
 }
 }

Slide 30

Slide 30 text

Dagger square.github.io/dagger/ class CoffeeMaker$$InjectAdapter
 extends Binding {
 
 // ...
 
 @Override public CoffeeMaker get() {
 CoffeeMaker result = new CoffeeMaker();
 injectMembers(result);
 return result;
 }
 
 @Override public void injectMembers(CoffeeMaker object) {
 object.heater = heater.get();
 object.pump = pump.get();
 }
 }

Slide 31

Slide 31 text

Dagger square.github.io/dagger/ @Module(injects = CoffeeApp.class)
 class DripCoffeeModule {
 @Provides @Singleton Heater provideHeater() {
 return new ElectricHeater();
 }
 
 @Provides Pump providePump(Thermosiphon pump) {
 return pump;
 }
 } class CoffeeMaker {
 @Inject Lazy heater;
 @Inject Pump pump;
 // ...
 }

Slide 32

Slide 32 text

Dagger square.github.io/dagger/ @Module(injects = CoffeeApp.class)
 class DripCoffeeModule {
 @Provides @Singleton Heater provideHeater() {
 return new ElectricHeater();
 }
 
 @Provides Pump providePump(Thermosiphon pump) {
 return pump;
 }
 } class CoffeeMaker {
 @Inject Lazy heater;
 @Inject Pump pump;
 // ...
 } class ProvideHeaterProvidesAdapter extends ProvidesBinding { 
 private final DripCoffeeModule module;
 
 public ProvideHeaterProvidesAdapter(DripCoffeeModule module) {
 this.module = module;
 }
 
 @Override
 public Heater get() {
 return module.provideHeater();
 }
 }

Slide 33

Slide 33 text

Dagger square.github.io/dagger/ @Module(injects = CoffeeApp.class)
 class DripCoffeeModule {
 @Provides @Singleton Heater provideHeater() {
 return new ElectricHeater();
 }
 
 @Provides Pump providePump(Thermosiphon pump) {
 return pump;
 }
 } class CoffeeMaker {
 @Inject Lazy heater;
 @Inject Pump pump;
 // ...
 } class DripCoffeeModule$$ModuleAdapter extends ModuleAdapter { 
 @Override
 public void getBindings(BindingsGroup bindings, DripCoffeeModule module) {
 bindings.contributeProvidesBinding("coffee.Heater", new ProvideHeaterAdapter(module)); bindings.contributeProvidesBinding("coffee.Pump",
 new ProvidePumpAdapter(module));
 } } class ProvideHeaterProvidesAdapter extends ProvidesBinding { 
 private final DripCoffeeModule module;
 
 public ProvideHeaterProvidesAdapter(DripCoffeeModule module) {
 this.module = module;
 }
 
 @Override
 public Heater get() {
 return module.provideHeater();
 }
 }

Slide 34

Slide 34 text

Dagger square.github.io/dagger/ @Module(injects = CoffeeApp.class)
 class DripCoffeeModule {
 @Provides @Singleton Heater provideHeater() {
 return new ElectricHeater();
 }
 
 @Provides Pump providePump(Thermosiphon pump) {
 return pump;
 }
 } class CoffeeMaker {
 @Inject Lazy heater;
 @Inject Pump pump;
 // ...
 } class DripCoffeeModule$$ModuleAdapter extends ModuleAdapter { 
 @Override
 public void getBindings(BindingsGroup bindings, DripCoffeeModule module) {
 bindings.contributeProvidesBinding("coffee.Heater", new ProvideHeaterAdapter(module)); bindings.contributeProvidesBinding("coffee.Pump",
 new ProvidePumpAdapter(module));
 } } class ProvideHeaterProvidesAdapter extends ProvidesBinding { 
 private final DripCoffeeModule module;
 
 public ProvideHeaterProvidesAdapter(DripCoffeeModule module) {
 this.module = module;
 }
 
 @Override
 public Heater get() {
 return module.provideHeater();
 }
 } class ObjectGraph {
 // ...
 }

Slide 35

Slide 35 text

Dagger square.github.io/dagger/ @Module(injects = CoffeeApp.class)
 class DripCoffeeModule {
 @Provides @Singleton Heater provideHeater() {
 return new ElectricHeater();
 }
 
 @Provides Pump providePump(Thermosiphon pump) {
 return pump;
 }
 } class CoffeeMaker {
 @Inject Lazy heater;
 @Inject Pump pump;
 // ...
 } class DripCoffeeModule$$ModuleAdapter extends ModuleAdapter { 
 @Override
 public void getBindings(BindingsGroup bindings, DripCoffeeModule module) {
 bindings.contributeProvidesBinding("coffee.Heater", new ProvideHeaterAdapter(module)); bindings.contributeProvidesBinding("coffee.Pump",
 new ProvidePumpAdapter(module));
 } } class ProvideHeaterProvidesAdapter extends ProvidesBinding { 
 private final DripCoffeeModule module;
 
 public ProvideHeaterProvidesAdapter(DripCoffeeModule module) {
 this.module = module;
 }
 
 @Override
 public Heater get() {
 return module.provideHeater();
 }
 } class CoffeeMaker$$InjectAdapter
 extends Binding {
 
 @Override public void attach(Linker linker) {
 heater = linker.requestBinding("dagger.Lazy");
 pump = linker.requestBinding("coffee.Pump");
 } 
 @Override public void injectMembers(CoffeeMaker object) {
 object.heater = heater.get();
 object.pump = pump.get();
 } ! // ...
 } class ObjectGraph {
 // ...
 }

Slide 36

Slide 36 text

Dagger square.github.io/dagger/ @Module(injects = CoffeeApp.class)
 class DripCoffeeModule {
 @Provides @Singleton Heater provideHeater() {
 return new ElectricHeater();
 }
 
 @Provides Pump providePump(Thermosiphon pump) {
 return pump;
 }
 } class CoffeeMaker {
 @Inject Lazy heater;
 @Inject Pump pump;
 // ...
 } class DripCoffeeModule$$ModuleAdapter extends ModuleAdapter { 
 @Override
 public void getBindings(BindingsGroup bindings, DripCoffeeModule module) {
 bindings.contributeProvidesBinding("coffee.Heater", new ProvideHeaterAdapter(module)); bindings.contributeProvidesBinding("coffee.Pump",
 new ProvidePumpAdapter(module));
 } } class ProvideHeaterProvidesAdapter extends ProvidesBinding { 
 private final DripCoffeeModule module;
 
 public ProvideHeaterProvidesAdapter(DripCoffeeModule module) {
 this.module = module;
 }
 
 @Override
 public Heater get() {
 return module.provideHeater();
 }
 } class CoffeeMaker$$InjectAdapter
 extends Binding {
 
 @Override public void attach(Linker linker) {
 heater = linker.requestBinding("dagger.Lazy");
 pump = linker.requestBinding("coffee.Pump");
 } 
 @Override public void injectMembers(CoffeeMaker object) {
 object.heater = heater.get();
 object.pump = pump.get();
 } ! // ...
 } class ObjectGraph {
 // ...
 }

Slide 37

Slide 37 text

Dagger square.github.io/dagger/ @Module(injects = CoffeeApp.class)
 class DripCoffeeModule {
 @Provides @Singleton Heater provideHeater() {
 return new ElectricHeater();
 }
 
 @Provides Pump providePump(Thermosiphon pump) {
 return pump;
 }
 } class CoffeeMaker {
 @Inject Lazy heater;
 @Inject Pump pump;
 // ...
 } class DripCoffeeModule$$ModuleAdapter extends ModuleAdapter { 
 @Override
 public void getBindings(BindingsGroup bindings, DripCoffeeModule module) {
 bindings.contributeProvidesBinding("coffee.Heater", new ProvideHeaterAdapter(module)); bindings.contributeProvidesBinding("coffee.Pump",
 new ProvidePumpAdapter(module));
 } } class ProvideHeaterProvidesAdapter extends ProvidesBinding { 
 private final DripCoffeeModule module;
 
 public ProvideHeaterProvidesAdapter(DripCoffeeModule module) {
 this.module = module;
 }
 
 @Override
 public Heater get() {
 return module.provideHeater();
 }
 } class CoffeeMaker$$InjectAdapter
 extends Binding {
 
 @Override public void attach(Linker linker) {
 heater = linker.requestBinding("dagger.Lazy");
 pump = linker.requestBinding("coffee.Pump");
 } 
 @Override public void injectMembers(CoffeeMaker object) {
 object.heater = heater.get();
 object.pump = pump.get();
 } ! // ...
 }

Slide 38

Slide 38 text

Schematic interface NoteColumns {
 
 @DataType(INTEGER) @PrimaryKey @AutoIncrement
 String _ID = "_id";
 
 @DataType(INTEGER) @References(table = NotesDatabase.LISTS,
 column = ListColumns._ID)
 String LIST_ID = "listId";
 
 @DataType(TEXT) String NOTE = "note";
 } github.com/SimonVT/schematic/

Slide 39

Slide 39 text

Schematic @Database(version = NotesDatabase.VERSION)
 public final class NotesDatabase {
 
 public static final int VERSION = 1;
 
 @Table(ListColumns.class)
 public static final String LISTS = "lists";
 
 @Table(NoteColumns.class)
 public static final String NOTES = "notes";
 
 } github.com/SimonVT/schematic/

Slide 40

Slide 40 text

Schematic @ContentProvider(authority = NotesProvider.AUTHORITY,
 database = NotesDatabase.class)
 public final class NotesProvider {
 // ...
 } github.com/SimonVT/schematic/

Slide 41

Slide 41 text

Execution

Slide 42

Slide 42 text

Execution • Happens automatically when javac runs.

Slide 43

Slide 43 text

Execution • Happens automatically when javac runs. • ServiceLoader finds and creates Processor instances.

Slide 44

Slide 44 text

interface Processor {
 Set getSupportedOptions();
 
 Set getSupportedAnnotationTypes();
 
 SourceVersion getSupportedSourceVersion();
 
 void init(ProcessingEnvironment processingEnv);
 
 boolean process(Set extends TypeElement> annotations,
 RoundEnvironment roundEnv);
 
 Iterable extends Completion> getCompletions(Element element,
 AnnotationMirror annotation,
 ExecutableElement member,
 String userText);
 }

Slide 45

Slide 45 text

public class ExampleProcessor extends AbstractProcessor {
 
 
 
 
 
 
 
 
 
 
 
 
 
 }

Slide 46

Slide 46 text

public class ExampleProcessor extends AbstractProcessor {
 @Override public SourceVersion getSupportedSourceVersion() {
 
 }
 
 
 
 
 
 
 
 
 
 
 }

Slide 47

Slide 47 text

public class ExampleProcessor extends AbstractProcessor {
 @Override public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 }
 
 
 
 
 
 
 
 
 
 
 }

Slide 48

Slide 48 text

public class ExampleProcessor extends AbstractProcessor {
 @Override public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 }
 
 @Override public Set getSupportedAnnotationTypes() {
 
 }
 
 
 
 
 
 
 }

Slide 49

Slide 49 text

public class ExampleProcessor extends AbstractProcessor {
 @Override public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 }
 
 @Override public Set getSupportedAnnotationTypes() {
 return Collections.singleton(Example.class.getName());
 }
 
 
 
 
 
 
 }

Slide 50

Slide 50 text

public class ExampleProcessor extends AbstractProcessor {
 @Override public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 }
 
 @Override public Set getSupportedAnnotationTypes() {
 return Collections.singleton(Example.class.getName());
 }
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 
 }
 }

Slide 51

Slide 51 text

public class ExampleProcessor extends AbstractProcessor {
 // ...
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 ! ! ! ! ! 
 }
 }

Slide 52

Slide 52 text

public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 
 
 
 
 
 }
 }

Slide 53

Slide 53 text

public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element);
 }
 
 
 }
 }

Slide 54

Slide 54 text

public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element);
 }
 
 return false;
 }
 }

Slide 55

Slide 55 text

public class ExampleProcessor extends AbstractProcessor {
 @Override public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 }
 
 @Override public Set getSupportedAnnotationTypes() {
 return Collections.singleton(Example.class.getName());
 }
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element);
 }
 return false;
 }
 }

Slide 56

Slide 56 text

Execution • Happens automatically when javac runs. • ServiceLoader finds and creates Processor instances.

Slide 57

Slide 57 text

Execution • Happens automatically when javac runs. • ServiceLoader finds and creates Processor instances. • Inside a full JVM.

Slide 58

Slide 58 text

Execution • Happens automatically when javac runs. • ServiceLoader finds and creates Processor instances. • Inside a full JVM. • Compiled sources and its dependencies not available.

Slide 59

Slide 59 text

Execution • Happens automatically when javac runs. • ServiceLoader finds and creates Processor instances. • Inside a full JVM. • Compiled sources and its dependencies not available. • Bring your own dependencies.

Slide 60

Slide 60 text

Environment interface Processor {
 Set getSupportedOptions();
 
 Set getSupportedAnnotationTypes();
 
 SourceVersion getSupportedSourceVersion();
 
 void init(ProcessingEnvironment processingEnv);
 
 boolean process(Set extends TypeElement> annotations,
 RoundEnvironment roundEnv);
 
 Iterable extends Completion> getCompletions(Element element,
 AnnotationMirror annotation,
 ExecutableElement member,
 String userText);
 }

Slide 61

Slide 61 text

Environment interface Processor {
 Set getSupportedOptions();
 
 Set getSupportedAnnotationTypes();
 
 SourceVersion getSupportedSourceVersion();
 
 void init(ProcessingEnvironment processingEnv);
 
 boolean process(Set extends TypeElement> annotations,
 RoundEnvironment roundEnv);
 
 Iterable extends Completion> getCompletions(Element element,
 AnnotationMirror annotation,
 ExecutableElement member,
 String userText);
 }

Slide 62

Slide 62 text

Environment interface Processor {
 Set getSupportedOptions();
 
 Set getSupportedAnnotationTypes();
 
 SourceVersion getSupportedSourceVersion();
 
 void init(ProcessingEnvironment processingEnv);
 
 boolean process(Set extends TypeElement> annotations,
 RoundEnvironment roundEnv);
 
 Iterable extends Completion> getCompletions(Element element,
 AnnotationMirror annotation,
 ExecutableElement member,
 String userText);
 }

Slide 63

Slide 63 text

Processing Environment interface ProcessingEnvironment {
 Map getOptions(); 
 SourceVersion getSourceVersion();
 
 Locale getLocale();
 
 Messager getMessager();
 
 Filer getFiler();
 
 Elements getElementUtils();
 
 Types getTypeUtils();
 }

Slide 64

Slide 64 text

Processing Environment interface ProcessingEnvironment {
 Map getOptions(); 
 SourceVersion getSourceVersion();
 
 Locale getLocale();
 
 Messager getMessager();
 
 Filer getFiler();
 
 Elements getElementUtils();
 
 Types getTypeUtils();
 }

Slide 65

Slide 65 text

Processing Environment interface ProcessingEnvironment {
 Map getOptions(); 
 SourceVersion getSourceVersion();
 
 Locale getLocale();
 
 Messager getMessager();
 
 Filer getFiler();
 
 Elements getElementUtils();
 
 Types getTypeUtils();
 }

Slide 66

Slide 66 text

Processing Environment interface ProcessingEnvironment {
 Map getOptions(); 
 SourceVersion getSourceVersion();
 
 Locale getLocale();
 
 Messager getMessager();
 
 Filer getFiler();
 
 Elements getElementUtils();
 
 Types getTypeUtils();
 }

Slide 67

Slide 67 text

Elements @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 }

Slide 68

Slide 68 text

Elements @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 } TypeElement

Slide 69

Slide 69 text

Elements @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 } TypeElement VariableElement

Slide 70

Slide 70 text

Elements @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 } TypeElement VariableElement ExecutableElement

Slide 71

Slide 71 text

Elements @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 } TypeElement VariableElement ExecutableElement ExecutableElement

Slide 72

Slide 72 text

Elements @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 } TypeElement VariableElement ExecutableElement ExecutableElement

Slide 73

Slide 73 text

Elements @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 } TypeElement VariableElement ExecutableElement ExecutableElement

Slide 74

Slide 74 text

Types @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 }

Slide 75

Slide 75 text

Types @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 }

Slide 76

Slide 76 text

Types @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 }

Slide 77

Slide 77 text

Types @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 }

Slide 78

Slide 78 text

Types @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 }

Slide 79

Slide 79 text

Types @Example
 public class ExampleClass implements Runnable { 
 private final String name;
 
 public ExampleClass(String name) {
 this.name = name;
 }
 
 @Override public void run() {
 System.out.println("Hello, " + name);
 }
 }

Slide 80

Slide 80 text

Environment public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element
 }
 return false;
 }
 } 
 
 
 
 
 
 
 
 
 );
 
 
 


Slide 81

Slide 81 text

Environment public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element
 }
 return false;
 }
 } 
 
 
 
 
 
 
 
 
 );
 
 
 


Slide 82

Slide 82 text

Environment public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println( );
 }
 return false;
 }
 } 
 
 
 
 
 
 
 
 
 element.asType()
 
 
 


Slide 83

Slide 83 text

Environment public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element.asType());
 }
 return false;
 }
 }

Slide 84

Slide 84 text

Environment public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element.asType());
 }
 return false;
 }
 }

Slide 85

Slide 85 text

Environment public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element.asType());
 }
 return false;
 }
 }

Slide 86

Slide 86 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 }

Slide 87

Slide 87 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } javac

Slide 88

Slide 88 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac

Slide 89

Slide 89 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac javac

Slide 90

Slide 90 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Example
 public class RandomClass {
 // ...
 } javac

Slide 91

Slide 91 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Example
 public class RandomClass {
 // ...
 } javac ExampleProcessor

Slide 92

Slide 92 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } @Example
 public class RandomClass {
 // ...
 } javac ExampleProcessor

Slide 93

Slide 93 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } @Example
 public class RandomClass {
 // ...
 } javac OtherProcessor

Slide 94

Slide 94 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } @Example
 public class RandomClass {
 // ...
 } javac

Slide 95

Slide 95 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } @Example
 public class RandomClass {
 // ...
 } javac

Slide 96

Slide 96 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } @Example
 public class RandomClass {
 // ...
 }

Slide 97

Slide 97 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } @Example
 public class RandomClass {
 // ...
 } javac

Slide 98

Slide 98 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } @Example
 public class RandomClass {
 // ...
 } javac

Slide 99

Slide 99 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac

Slide 100

Slide 100 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac ExampleProcessor

Slide 101

Slide 101 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac OtherProcessor

Slide 102

Slide 102 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac OtherProcessor public class OtherGenClass {
 // ...
 }

Slide 103

Slide 103 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac public class OtherGenClass {
 // ...
 }

Slide 104

Slide 104 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac public class OtherGenClass {
 // ...
 }

Slide 105

Slide 105 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac public class OtherGenClass {
 // ...
 }

Slide 106

Slide 106 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac public class OtherGenClass {
 // ...
 } OtherGenClass.class public class OtherGenClass {
 // ...
 }

Slide 107

Slide 107 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac public class OtherGenClass {
 // ...
 } ExampleProcessor OtherGenClass.class public class OtherGenClass {
 // ...
 }

Slide 108

Slide 108 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac public class OtherGenClass {
 // ...
 } OtherProcessor OtherGenClass.class public class OtherGenClass {
 // ...
 }

Slide 109

Slide 109 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac public class OtherGenClass {
 // ...
 } OtherGenClass.class public class OtherGenClass {
 // ...
 }

Slide 110

Slide 110 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } javac public class OtherGenClass {
 // ...
 } OtherGenClass.class public class OtherGenClass {
 // ...
 }

Slide 111

Slide 111 text

Processing Rounds @Example
 public class RandomClass {
 // ...
 } ExampleProcessor OtherProcessor javac RandomClass.class out/ @Other
 public class GeneratedClass {
 // ...
 } GeneratedClass.class @Example
 public class RandomClass {
 // ...
 } @Other
 public class GeneratedClass {
 // ...
 } public class OtherGenClass {
 // ...
 } OtherGenClass.class public class OtherGenClass {
 // ...
 }

Slide 112

Slide 112 text

No content

Slide 113

Slide 113 text

JavaCompiler

Slide 114

Slide 114 text

ExampleProcessor JavaCompiler OtherProcessor

Slide 115

Slide 115 text

ProcessingEnvironment ExampleProcessor JavaCompiler Filer OtherProcessor

Slide 116

Slide 116 text

ProcessingEnvironment ExampleProcessor JavaCompiler Filer OtherProcessor init() init()

Slide 117

Slide 117 text

ProcessingEnvironment ExampleProcessor JavaCompiler Filer OtherProcessor init() init()

Slide 118

Slide 118 text

ProcessingEnvironment ExampleProcessor JavaCompiler Filer OtherProcessor init() init()

Slide 119

Slide 119 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() init()

Slide 120

Slide 120 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init()

Slide 121

Slide 121 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init()

Slide 122

Slide 122 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init()

Slide 123

Slide 123 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init()

Slide 124

Slide 124 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init()

Slide 125

Slide 125 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init()

Slide 126

Slide 126 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init() process()

Slide 127

Slide 127 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init() process()

Slide 128

Slide 128 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init() process()

Slide 129

Slide 129 text

ProcessingEnvironment ExampleProcessor JavaCompiler RoundEnvironment Filer OtherProcessor init() process() init() process()

Slide 130

Slide 130 text

Parsing and Generation public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 
 for (Element element : elements) {
 
 
 }
 return false;
 }
 }

Slide 131

Slide 131 text

Parsing and Generation public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 
 for (Element element : elements) {
 
 
 }
 return false;
 }
 } 
 
 
 
 
 
 
 
 
 // Look at attributes of 'element'.
 
 
 
 


Slide 132

Slide 132 text

Parsing and Generation public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 
 for (Element element : elements) {
 
 
 }
 return false;
 }
 } 
 
 
 
 
 
 
 
 
 // Look at attributes of 'element'.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 // Generate some code based on attributes.
 
 
 


Slide 133

Slide 133 text

Parsing and Generation @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 
 
 
 
 return false;
 }


Slide 134

Slide 134 text

Parsing and Generation @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 
 
 
 
 return false;
 }
 
 
 
 List models = parseExampleAnnotations(env);

Slide 135

Slide 135 text

Parsing and Generation @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 
 
 
 
 return false;
 }
 
 
 
 List models = parseExampleAnnotations(env); 
 
 
 
 
 
 
 
 
 
 List parseExampleAnnotations(RoundEnvironment env) {
 // ...
 }

Slide 136

Slide 136 text

Parsing and Generation @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 
 
 
 
 return false;
 }
 
 
 
 List models = parseExampleAnnotations(env); 
 
 
 
 for (ExampleModel model : models) {
 emitExampleCode(model);
 } 
 
 
 
 
 
 
 
 
 
 List parseExampleAnnotations(RoundEnvironment env) {
 // ...
 }

Slide 137

Slide 137 text

Parsing and Generation @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 
 
 
 
 return false;
 }
 
 
 
 List models = parseExampleAnnotations(env); 
 
 
 
 for (ExampleModel model : models) {
 emitExampleCode(model);
 } 
 
 
 
 
 
 
 
 
 
 List parseExampleAnnotations(RoundEnvironment env) {
 // ...
 } 
 
 
 
 
 
 
 
 
 ! ! 
 
 void emitExampleCode(ExampleModel model) {
 // ...
 }

Slide 138

Slide 138 text

Parsing and Generation Element

Slide 139

Slide 139 text

Parsing and Generation Element

Slide 140

Slide 140 text

Parsing and Generation Element ExampleModel ! name: “Foo” package: “com.example” public: true

Slide 141

Slide 141 text

Parsing and Generation Element ExampleModel ! name: “Foo” package: “com.example” public: true

Slide 142

Slide 142 text

Parsing and Generation Element ExampleModel ! name: “Foo” package: “com.example” public: true ExampleModel ! name: “Foo” package: “com.example” public: true element:

Slide 143

Slide 143 text

Parsing and Generation Element ExampleModel ! name: “Foo” package: “com.example” public: true ExampleModel ! name: “Foo” package: “com.example” public: true element: GeneratedClass

Slide 144

Slide 144 text

Parsing and Generation Element ExampleModel ! name: “Foo” package: “com.example” public: true ExampleModel ! name: “Foo” package: “com.example” public: true element: GeneratedClass

Slide 145

Slide 145 text

Bring Your Own Dependencies

Slide 146

Slide 146 text

Bring Your Own Dependencies • Guava, Guava, Guava!

Slide 147

Slide 147 text

Bring Your Own Dependencies • Guava, Guava, Guava! • JavaWriter

Slide 148

Slide 148 text

Bring Your Own Dependencies • Guava, Guava, Guava! • JavaWriter • google/auto ‘common’

Slide 149

Slide 149 text

Bring Your Own Dependencies • Guava, Guava, Guava! • JavaWriter • google/auto ‘common’ • AutoService (google/auto)

Slide 150

Slide 150 text

JavaWriter

Slide 151

Slide 151 text

JavaWriter JavaFileObject sourceFile = filer.createSourceFile(name, element);

Slide 152

Slide 152 text

JavaWriter JavaFileObject sourceFile = filer.createSourceFile(name, element); ! ! ! JavaWriter writer = new JavaWriter(sourceFile.openWriter());
 writer.emitPackage("com.example")
 .emitAnnotation(Other.class)
 .beginType("GeneratedClass", "class")
 .emitSingleLineComment("...")
 .endType();

Slide 153

Slide 153 text

JavaWriter JavaFileObject sourceFile = filer.createSourceFile(name, element); ! ! @com.example.Other
 public class GeneratedClass {
 // ...
 } ! ! ! JavaWriter writer = new JavaWriter(sourceFile.openWriter());
 writer.emitPackage("com.example")
 .emitAnnotation(Other.class)
 .beginType("GeneratedClass", "class")
 .emitSingleLineComment("...")
 .endType();

Slide 154

Slide 154 text

JavaWriter JavaFileObject sourceFile = filer.createSourceFile(name, element); import com.example.Other; ! @Other
 public class GeneratedClass {
 // ...
 } ! ! ! JavaWriter writer = new JavaWriter(sourceFile.openWriter());
 writer.emitPackage("com.example")
 .emitImports(Other.class)
 .emitAnnotation(Other.class)
 .beginType("GeneratedClass", "class")
 .emitSingleLineComment("...")
 .endType();

Slide 155

Slide 155 text

AutoService

Slide 156

Slide 156 text

AutoService • Remember “ServiceLoader finds and creates”

Slide 157

Slide 157 text

AutoService • Remember “ServiceLoader finds and creates” • AutoService generates service files from annotations

Slide 158

Slide 158 text

AutoService • Remember “ServiceLoader finds and creates” • AutoService generates service files from annotations ! public class ExampleProcessor extends AbstractProcessor { // ... }

Slide 159

Slide 159 text

AutoService • Remember “ServiceLoader finds and creates” • AutoService generates service files from annotations ! public class ExampleProcessor extends AbstractProcessor { // ... } @AutoService(Processor.class)

Slide 160

Slide 160 text

Testing and Debugging

Slide 161

Slide 161 text

Testing and Debugging • Google to the rescue!

Slide 162

Slide 162 text

Testing and Debugging • Google to the rescue! • Guava, Guava, Guava!

Slide 163

Slide 163 text

Testing and Debugging • Google to the rescue! • Guava, Guava, Guava! • compile-testing

Slide 164

Slide 164 text

Testing and Debugging • Google to the rescue! • Guava, Guava, Guava! • compile-testing • Truth

Slide 165

Slide 165 text

final class TestProcessors {
 static Iterable extends Processor> exampleProcessors() {
 return Collections.singletonList(
 new ExampleProcessor()
 );
 }
 }

Slide 166

Slide 166 text

String input = Joiner.on('\n').join(
 "package test;",
 "import com.example.Example;",
 "@Example",
 "public class ExampleClass {",
 "}"
 );

Slide 167

Slide 167 text

String input = Joiner.on('\n').join(
 "package test;",
 "import com.example.Example;",
 "@Example",
 "public class ExampleClass {",
 "}"
 ); JavaFileObject inputFile =
 JavaFileObjects.forSourceString("test.Test", input);

Slide 168

Slide 168 text

JavaFileObject inputFile =
 JavaFileObjects.forSourceString("test.Test", input); String input = """\
 package test; 
 import com.example.Example; 
 @Example
 public class ExampleClass {
 } """ .stripIndent()

Slide 169

Slide 169 text

String expected = Joiner.on('\n').join(
 "package test;",
 "import com.example.Other;",
 "@Other",
 "public class GeneratedClass {",
 "}"
 );

Slide 170

Slide 170 text

String expected = Joiner.on('\n').join(
 "package test;",
 "import com.example.Other;",
 "@Other",
 "public class GeneratedClass {",
 "}"
 ); JavaFileObject expectedFile =
 JavaFileObjects.forSourceString("test.GeneratedClass", expected);

Slide 171

Slide 171 text

ASSERT.about(javaSource())
 .that(inputFile)
 .processedWith(exampleProcessors())
 .compilesWithoutError()
 .and()
 .generatesSources(expectedFile);

Slide 172

Slide 172 text

ASSERT.about(javaSource())
 .that(inputFile)
 .processedWith(exampleProcessors())
 .compilesWithoutError()
 .and()
 .generatesSources(expectedFile);

Slide 173

Slide 173 text

ASSERT.about(javaSource())
 .that(inputFile)
 .processedWith(exampleProcessors())
 .compilesWithoutError()
 .and()
 .generatesSources(expectedFile);

Slide 174

Slide 174 text

ASSERT.about(javaSource())
 .that(inputFile)
 .processedWith(exampleProcessors())
 .compilesWithoutError()
 .and()
 .generatesSources(expectedFile); String input = Joiner.on('\n').join(
 "package test;",
 "import com.example.Example;",
 "@Example",
 "public class ExampleClass {",
 "}"
 );

Slide 175

Slide 175 text

ASSERT.about(javaSource())
 .that(inputFile)
 .processedWith(exampleProcessors())
 .compilesWithoutError()
 .and()
 .generatesSources(expectedFile); String input = Joiner.on('\n').join(
 "package test;",
 "import com.example.Example;",
 "@Example",
 "public class ExampleClass {",
 "}"
 ); final class TestProcessors {
 static Iterable extends Processor> exampleProcessors() {
 return Collections.singletonList(
 new ExampleProcessor()
 );
 }
 }

Slide 176

Slide 176 text

ASSERT.about(javaSource())
 .that(inputFile)
 .processedWith(exampleProcessors())
 .compilesWithoutError()
 .and()
 .generatesSources(expectedFile); String input = Joiner.on('\n').join(
 "package test;",
 "import com.example.Example;",
 "@Example",
 "public class ExampleClass {",
 "}"
 ); final class TestProcessors {
 static Iterable extends Processor> exampleProcessors() {
 return Collections.singletonList(
 new ExampleProcessor()
 );
 }
 } String expected = Joiner.on('\n').join(
 "package test;",
 "import com.example.Other;",
 "@Other",
 "public class GeneratedClass {",
 "}"
 );

Slide 177

Slide 177 text

ASSERT.about(javaSource())
 .that(inputFile)
 .processedWith(exampleProcessors())
 .compilesWithoutError()
 .and()
 .generatesSources(expectedFile); String input = Joiner.on('\n').join(
 "package test;",
 "import com.example.Example;",
 "@Example",
 "public class ExampleClass {",
 "}"
 ); final class TestProcessors {
 static Iterable extends Processor> exampleProcessors() {
 return Collections.singletonList(
 new ExampleProcessor()
 );
 }
 } String expected = Joiner.on('\n').join(
 "package test;",
 "import com.example.Other;",
 "@Other",
 "public class GeneratedClass {",
 "}"
 );

Slide 178

Slide 178 text

public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element
 }
 return false;
 }
 } Debugging

Slide 179

Slide 179 text

public class ExampleProcessor extends AbstractProcessor {
 // ...
 
 @Override public boolean process(
 Set extends TypeElement> annotations,
 RoundEnvironment env) {
 Set extends Element> elements
 = env.getElementsAnnotatedWith(Example.class);
 for (Element element : elements) {
 System.out.println(element
 }
 return false;
 }
 } Debugging

Slide 180

Slide 180 text

Now What?

Slide 181

Slide 181 text

No content

Slide 182

Slide 182 text

Questions?