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

Dagger

Slide 4

Slide 4 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 5

Slide 5 text

Butter Knife

Slide 6

Slide 6 text

Butter Knife class SimpleActivity extends Activity {
 @InjectView(R.id.title) TextView title;
 @InjectView(R.id.subtitle) TextView subtitle;
 @InjectView(R.id.hello) Button hello;
 @InjectView(R.id.list_of_things) ListView listOfThings;
 @InjectView(R.id.footer) TextView footer;
 
 // ...
 } jakewharton.github.io/butterknife/

Slide 7

Slide 7 text

Butter Knife class SimpleActivity extends Activity {
 @InjectView(R.id.title) TextView title;
 @InjectView(R.id.subtitle) TextView subtitle;
 @InjectView(R.id.hello) Button hello;
 @InjectView(R.id.list_of_things) ListView listOfThings;
 @InjectView(R.id.footer) TextView footer;
 
 // ...
 } jakewharton.github.io/butterknife/ ButterKnife.inject(this);

Slide 8

Slide 8 text

AutoValue

Slide 9

Slide 9 text

AutoValue @AutoValue
 abstract static 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 10

Slide 10 text

AutoParcel

Slide 11

Slide 11 text

AutoParcel @AutoParcel
 abstract class SomeModel implements Parcelable {
 abstract String name();
 abstract List subModels();
 abstract Map modelsMap();
 
 static SomeModel create(String name, List subModels, Map modelsMap) {
 return new AutoParcel_SomeModel(name, subModels, modelsMap);
 }
 } github.com/frankiesardo/auto-parcel/

Slide 12

Slide 12 text

Schematic

Slide 13

Slide 13 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";
 }

Slide 14

Slide 14 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";
 
 }

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

Doclet http://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/doclet/overview.html

Slide 17

Slide 17 text

Doclet import com.sun.javadoc.*; ! public class ExampleDoclet {
 public static boolean start(RootDoc root) {
 ! ! ! 
 }
 } http://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/doclet/overview.html

Slide 18

Slide 18 text

Doclet import com.sun.javadoc.*; ! public class ExampleDoclet {
 public static boolean start(RootDoc root) {
 ! ! ! 
 }
 } import com.sun.javadoc.*; ! public class ExampleDoclet {
 public static boolean start(RootDoc root) {
 ClassDoc[] classes = root.classes();
 for (int i = 0; i < classes.length; i++) {
 System.out.println(classes[i]);
 }
 return true; 
 }
 } http://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/doclet/overview.html

Slide 19

Slide 19 text

Doclet import com.sun.javadoc.*; ! public class ExampleDoclet {
 public static boolean start(RootDoc root) {
 ! ! ! 
 }
 } import com.sun.javadoc.*; ! public class ExampleDoclet {
 public static boolean start(RootDoc root) {
 ClassDoc[] classes = root.classes();
 for (int i = 0; i < classes.length; i++) {
 System.out.println(classes[i]);
 }
 return true; 
 }
 } javadoc -doclet ExampleDoclet -docletpath . RandomClass.java \
 FooBarClass.java HelloClass.java WorldClass.java import com.sun.javadoc.*; ! public class ExampleDoclet {
 public static boolean start(RootDoc root) {
 ClassDoc[] classes = root.classes();
 for (int i = 0; i < classes.length; i++) {
 System.out.println(classes[i]);
 }
 return true; 
 }
 } http://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/doclet/overview.html

Slide 20

Slide 20 text

Java 1.5

Slide 21

Slide 21 text

Java 1.5

Slide 22

Slide 22 text

Java 1.5 • JSR 14: Generics

Slide 23

Slide 23 text

Java 1.5 • JSR 14: Generics • JSR 175: Annotations

Slide 24

Slide 24 text

Java 1.5 • JSR 14: Generics • JSR 175: Annotations • Also a whole bunch of other really awesome things!

Slide 25

Slide 25 text

Java 1.5 • JSR 14: Generics • JSR 175: Annotations • Also a whole bunch of other really awesome things! • apt command-line tool

Slide 26

Slide 26 text

Annotation Processing Tool: apt apt

Slide 27

Slide 27 text

apt

Slide 28

Slide 28 text

@Target(ElementType.TYPE)
 public @interface Example {
 } apt

Slide 29

Slide 29 text

@Target(ElementType.TYPE)
 public @interface Example {
 } @Example
 public class RandomClass {
 // ...
 } @Example
 public class FooBarClass {
 // ...
 } @Example
 public class HelloClass {
 // ...
 } @Example
 public class WorldClass {
 // ...
 } @Target(ElementType.TYPE)
 public @interface Example {
 } apt

Slide 30

Slide 30 text

interface AnnotationProcessor {
 void process();
 } apt

Slide 31

Slide 31 text

interface AnnotationProcessorFactory { 
 AnnotationProcessor getProcessorFor( Set atds, AnnotationProcessorEnvironment env); 
 Collection supportedAnnotationTypes(); 
 Collection supportedOptions(); 
 } interface AnnotationProcessor {
 void process();
 } apt

Slide 32

Slide 32 text

apt public class ExampleAnnotationProcessorFactory implements AnnotationProcessorFactory { 
 
 
 
 
 
 
 
 
 
 
 
 
 }

Slide 33

Slide 33 text

apt public class ExampleAnnotationProcessorFactory implements AnnotationProcessorFactory { 
 
 
 
 
 
 
 
 
 
 @Override public Collection supportedOptions() {
 return Collections.emptyList();
 }
 }

Slide 34

Slide 34 text

apt public class ExampleAnnotationProcessorFactory implements AnnotationProcessorFactory { 
 
 
 
 
 
 @Override public Collection supportedAnnotationTypes() {
 return Collections.singletonList(Example.class.getName());
 }
 
 @Override public Collection supportedOptions() {
 return Collections.emptyList();
 }
 }

Slide 35

Slide 35 text

apt public class ExampleAnnotationProcessorFactory implements AnnotationProcessorFactory { 
 @Override public AnnotationProcessor getProcessorFor( Set atds,
 AnnotationProcessorEnvironment env) {
 return new ExampleAnnotationProcessor(atds, env);
 }
 
 @Override public Collection supportedAnnotationTypes() {
 return Collections.singletonList(Example.class.getName());
 }
 
 @Override public Collection supportedOptions() {
 return Collections.emptyList();
 }
 }

Slide 36

Slide 36 text

apt public class ExampleAnnotationProcessorFactory implements AnnotationProcessorFactory { 
 @Override public AnnotationProcessor getProcessorFor( Set atds,
 AnnotationProcessorEnvironment env) {
 return new ExampleAnnotationProcessor(atds, env);
 }
 
 @Override public Collection supportedAnnotationTypes() {
 return Collections.singletonList(Example.class.getName());
 }
 
 @Override public Collection supportedOptions() {
 return Collections.emptyList();
 }
 }

Slide 37

Slide 37 text

apt public class ExampleAnnotationProcessor implements AnnotationProcessor { 
 
 
 
 
 
 
 
 
 }

Slide 38

Slide 38 text

apt public class 
 
 
 
 
 
 
 
 
 } public class ExampleAnnotationProcessor implements AnnotationProcessor { 
 private final Set atds;
 private final AnnotationProcessorEnvironment env;
 
 public ExampleAnnotationProcessor( Set atds,
 AnnotationProcessorEnvironment env) {
 this.atds = atds;
 this.env = env;
 } 
 }

Slide 39

Slide 39 text

apt public class 
 
 
 
 
 
 
 
 
 } public class 
 
 Set atds 
 } public class ExampleAnnotationProcessor implements AnnotationProcessor { 
 
 
 
 
 
 
 
 
 } public class ExampleAnnotationProcessor implements AnnotationProcessor { 
 // ...
 
 
 
 
 
 
 
 } public class ExampleAnnotationProcessor implements AnnotationProcessor { 
 // ...
 
 @Override public void process() {
 ! ! 
 } ! 
 }

Slide 40

Slide 40 text

apt public class 
 
 
 
 
 
 
 
 
 } public class 
 
 Set atds 
 } public class ExampleAnnotationProcessor implements AnnotationProcessor { 
 
 
 
 
 
 
 
 
 } public class ExampleAnnotationProcessor implements AnnotationProcessor { 
 // ...
 
 
 
 
 
 
 
 } public class ExampleAnnotationProcessor implements AnnotationProcessor { 
 // ...
 
 @Override public void process() { for (AnnotationTypeDeclaration atd : atds) {
 MemberDeclaration member = atd.getDeclaringType();
 System.out.println(member);
 }
 } ! ! }

Slide 41

Slide 41 text

apt apt -classpath out/ src/RandomClass.java \
 src/FooBarClass.java src/HelloClass.java \
 src/WorldClass.java http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/apt.html

Slide 42

Slide 42 text

JSR 269

Slide 43

Slide 43 text

JSR 269 • 6 months after Java 5 released

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

JSR 269 • 6 months after Java 5 released • “Pluggable Annotation Processing API” • Google, Oracle, Sun, BEA Systems sponsored

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

interface AnnotationProcessor {
 void process();
 }

Slide 49

Slide 49 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 50

Slide 50 text

public class ExampleProcessor extends AbstractProcessor {
 
 
 
 
 
 
 
 
 
 
 
 
 
 }

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

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) {
 
 }
 }

Slide 56

Slide 56 text

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

Slide 57

Slide 57 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 58

Slide 58 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 59

Slide 59 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 60

Slide 60 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 61

Slide 61 text

Execution

Slide 62

Slide 62 text

Execution • Happens automatically when javac runs.

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

Service Loader

Slide 65

Slide 65 text

Service Loader • META-­‐INF/services/

Slide 66

Slide 66 text

Service Loader • META-­‐INF/services/ • File name of implemented fully-qualified class name.

Slide 67

Slide 67 text

Service Loader • META-­‐INF/services/ • File name of implemented fully-qualified class name. • javax.annotation.processing.Processor

Slide 68

Slide 68 text

Service Loader • META-­‐INF/services/ • File name of implemented fully-qualified class name. • javax.annotation.processing.Processor • Each line implementation fully-qualified class name.

Slide 69

Slide 69 text

Service Loader • META-­‐INF/services/ • File name of implemented fully-qualified class name. • javax.annotation.processing.Processor • Each line implementation fully-qualified class name. • com.example.ExampleProcessor

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 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 73

Slide 73 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 74

Slide 74 text

Environment

Slide 75

Slide 75 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 76

Slide 76 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 77

Slide 77 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 78

Slide 78 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 79

Slide 79 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 80

Slide 80 text

Processing Environment

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

Elements

Slide 87

Slide 87 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 88

Slide 88 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 89

Slide 89 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 90

Slide 90 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 91

Slide 91 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 92

Slide 92 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 93

Slide 93 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 94

Slide 94 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 95

Slide 95 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 96

Slide 96 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 97

Slide 97 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 98

Slide 98 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 99

Slide 99 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 100

Slide 100 text

Environment

Slide 101

Slide 101 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 102

Slide 102 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 103

Slide 103 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 104

Slide 104 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 105

Slide 105 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 106

Slide 106 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 107

Slide 107 text

Round Environment

Slide 108

Slide 108 text

Round Environment public interface RoundEnvironment {
 boolean processingOver();
 
 boolean errorRaised();
 
 Set extends Element> getRootElements();
 
 Set extends Element> getElementsAnnotatedWith(
 TypeElement a);
 
 Set extends Element> getElementsAnnotatedWith(
 Class extends Annotation> a);
 }

Slide 109

Slide 109 text

Round Environment public interface RoundEnvironment {
 boolean processingOver();
 
 boolean errorRaised();
 
 Set extends Element> getRootElements();
 
 Set extends Element> getElementsAnnotatedWith(
 TypeElement a);
 
 Set extends Element> getElementsAnnotatedWith(
 Class extends Annotation> a);
 }

Slide 110

Slide 110 text

Processing Rounds

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 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 125

Slide 125 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 126

Slide 126 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 127

Slide 127 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 128

Slide 128 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 129

Slide 129 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 130

Slide 130 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 131

Slide 131 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 132

Slide 132 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 133

Slide 133 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 134

Slide 134 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 135

Slide 135 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 136

Slide 136 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 137

Slide 137 text

No content

Slide 138

Slide 138 text

JavaCompiler

Slide 139

Slide 139 text

ExampleProcessor JavaCompiler OtherProcessor

Slide 140

Slide 140 text

ProcessingEnvironment ExampleProcessor JavaCompiler Filer OtherProcessor

Slide 141

Slide 141 text

ProcessingEnvironment ExampleProcessor JavaCompiler Filer OtherProcessor init() init()

Slide 142

Slide 142 text

ProcessingEnvironment ExampleProcessor JavaCompiler Filer OtherProcessor init() init()

Slide 143

Slide 143 text

ProcessingEnvironment ExampleProcessor JavaCompiler Filer OtherProcessor init() init()

Slide 144

Slide 144 text

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

Slide 145

Slide 145 text

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

Slide 146

Slide 146 text

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

Slide 147

Slide 147 text

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

Slide 148

Slide 148 text

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

Slide 149

Slide 149 text

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

Slide 150

Slide 150 text

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

Slide 151

Slide 151 text

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

Slide 152

Slide 152 text

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

Slide 153

Slide 153 text

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

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

Parsing and Generation

Slide 156

Slide 156 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 157

Slide 157 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 158

Slide 158 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 159

Slide 159 text

Parsing and Generation

Slide 160

Slide 160 text

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


Slide 161

Slide 161 text

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

Slide 162

Slide 162 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 163

Slide 163 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 164

Slide 164 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 165

Slide 165 text

Parsing and Generation

Slide 166

Slide 166 text

Parsing and Generation Element

Slide 167

Slide 167 text

Parsing and Generation Element

Slide 168

Slide 168 text

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

Slide 169

Slide 169 text

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

Slide 170

Slide 170 text

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

Slide 171

Slide 171 text

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

Slide 172

Slide 172 text

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

Slide 173

Slide 173 text

Bring Your Own Dependencies

Slide 174

Slide 174 text

Bring Your Own Dependencies • Guava, Guava, Guava!

Slide 175

Slide 175 text

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

Slide 176

Slide 176 text

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

Slide 177

Slide 177 text

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

Slide 178

Slide 178 text

JavaWriter

Slide 179

Slide 179 text

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

Slide 180

Slide 180 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 181

Slide 181 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 182

Slide 182 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(); JavaFileObject sourceFile = filer.createSourceFile(name, element);

Slide 183

Slide 183 text

AutoService

Slide 184

Slide 184 text

AutoService • Remember?
 META-­‐INF/services/javax.annotation.processing.Processor

Slide 185

Slide 185 text

AutoService • Remember?
 META-­‐INF/services/javax.annotation.processing.Processor • AutoService generates service files from annotations

Slide 186

Slide 186 text

AutoService • Remember?
 META-­‐INF/services/javax.annotation.processing.Processor • AutoService generates service files from annotations ! public class ExampleProcessor extends AbstractProcessor { // ... }

Slide 187

Slide 187 text

AutoService • Remember?
 META-­‐INF/services/javax.annotation.processing.Processor • AutoService generates service files from annotations ! public class ExampleProcessor extends AbstractProcessor { // ... } @AutoService(Processor.class)

Slide 188

Slide 188 text

Testing and Debugging

Slide 189

Slide 189 text

Testing and Debugging • Google to the rescue!

Slide 190

Slide 190 text

Testing and Debugging • Google to the rescue! • Guava

Slide 191

Slide 191 text

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

Slide 192

Slide 192 text

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

Slide 193

Slide 193 text

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

Slide 194

Slide 194 text

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

Slide 195

Slide 195 text

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

Slide 196

Slide 196 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 197

Slide 197 text

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

Slide 198

Slide 198 text

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

Slide 199

Slide 199 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 200

Slide 200 text

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

Slide 201

Slide 201 text

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

Slide 202

Slide 202 text

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

Slide 203

Slide 203 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 204

Slide 204 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 205

Slide 205 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 206

Slide 206 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 207

Slide 207 text

Debugging

Slide 208

Slide 208 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 209

Slide 209 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 210

Slide 210 text

Now What?

Slide 211

Slide 211 text

No content

Slide 212

Slide 212 text

Questions?