Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hello, Annotation Processing!

Tatsuya Maki
December 10, 2016

Hello, Annotation Processing!

Introduction to Annotation Processing.

Tatsuya Maki

December 10, 2016
Tweet

Other Decks in Technology

Transcript

  1. final class AutoValue_User extends User {
 private final String name;


    private final int age;
 
 AutoValue_User(String name, int age) {
 if (name == null) {
 throw new NullPointerException("Null name");
 }
 this.name = name;
 this.age = age;
 }
 
 @Override
 public String name() {
 return name;
 }
 
 @Override
 public int age() {
 return age;
 }
 
 @Override
 public String toString() {
 return "User{" + "name=" + name + ", " + "age=" + age + "}";
 }
 
 @Override
 public boolean equals(Object o) {
 if (o == this) {
 return true;
 }

  2. public class MainActivity extends AppCompatActivity {
 @BindView(R.id.fab)
 FloatingActionButton fab;
 


    @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 ButterKnife.bind(this);
 }
 
 @OnClick(R.id.fab)
 void showSnackBar(View view) {
 Snackbar.make(view, "FloatingActionButton is clicked!", Snackbar.LENGTH_LONG)
 .setAction("Action", null).show();
 }
 }
  3. public class MainActivity_ViewBinding<T extends MainActivity> implements Unbinder {
 protected T

    target;
 private View view2131492974;
 
 @UiThread
 public MainActivity_ViewBinding(final T target, View source) {
 this.target = target;
 View view;
 view = Utils.findRequiredView(source, R.id.fab, "field 'fab' and method 'showSnackBar'");
 target.fab = Utils.castView(view, R.id.fab, "field 'fab'", FloatingActionButton.class);
 view2131492974 = view;
 view.setOnClickListener(new DebouncingOnClickListener() {
 @Override
 public void doClick(View p0) {
 target.showSnackBar(p0);
 }
 });
 }
 
 @Override
 @CallSuper
 public void unbind() {
 T target = this.target;
 if (target == null) throw new IllegalStateException("Bindings already cleared.");
 target.fab = null;
 view2131492974.setOnClickListener(null);
 view2131492974 = null;
 this.target = null;
 }
 }
  4. public final class DaggerActivityComponent implements ActivityComponent {
 private DaggerActivityComponent(Builder builder)

    {
 assert builder != null;
 }
 
 public static Builder builder() {
 return new Builder();
 }
 
 public static ActivityComponent create() {
 return builder().build();
 }
 
 @Override
 public void inject(MainActivity activity) {
 MembersInjectors.<MainActivity>noOp().injectMembers(activity);
 }
 
 public static final class Builder {
 private Builder() {
 }
 
 public ActivityComponent build() {
 return new DaggerActivityComponent(this);
 }
 
 public Builder activityModule(ActivityModule activityModule) {
 Preconditions.checkNotNull(activityModule);
 return this;
 }
 }
 }
  5. *.java *.class Parse & Enter Annotation Processing Analyze & Generate

    構文木を分析し、classファイルに変換
  6. public interface Processor {
 Set<String> getSupportedOptions();
 
 Set<String> 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);
 }
  7. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public Set<String> getSupportedAnnotationTypes()

    {
 return Collections.singleton(MyAnnotation.class.getCanonicalName());
 } @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 } @Override
 public synchronized void init(ProcessingEnvironment environment) {
 super.init(environment);
 messager = environment.getMessager();
 elements = environment.getElementUtils();
 types = environment.getTypeUtils();
 filer = environment.getFiler();
 } @Override
 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { ... } }
  8. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public Set<String> getSupportedAnnotationTypes()

    {
 return Collections.singleton(MyAnnotation.class.getCanonicalName());
 } @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 } @Override
 public synchronized void init(ProcessingEnvironment environment) {
 super.init(environment);
 messager = environment.getMessager();
 elements = environment.getElementUtils();
 types = environment.getTypeUtils();
 filer = environment.getFiler();
 } @Override
 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { ... } }
  9. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public Set<String> getSupportedAnnotationTypes()

    {
 return Collections.singleton(MyAnnotation.class.getCanonicalName());
 } @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 } @Override
 public synchronized void init(ProcessingEnvironment environment) {
 super.init(environment);
 messager = environment.getMessager();
 elements = environment.getElementUtils();
 types = environment.getTypeUtils();
 filer = environment.getFiler();
 } @Override
 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { ... } }
  10. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public Set<String> getSupportedAnnotationTypes()

    {
 return Collections.singleton(MyAnnotation.class.getCanonicalName());
 } @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 } @Override
 public synchronized void init(ProcessingEnvironment environment) {
 super.init(environment);
 messager = environment.getMessager();
 elements = environment.getElementUtils();
 types = environment.getTypeUtils();
 filer = environment.getFiler();
 } @Override
 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { ... } }
  11. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public Set<String> getSupportedAnnotationTypes()

    {
 return Collections.singleton(MyAnnotation.class.getCanonicalName());
 } @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 } @Override
 public synchronized void init(ProcessingEnvironment environment) {
 super.init(environment);
 messager = environment.getMessager();
 elements = environment.getElementUtils();
 types = environment.getTypeUtils();
 filer = environment.getFiler();
 } @Override
 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { ... } }
  12. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public Set<String> getSupportedAnnotationTypes()

    {
 return Collections.singleton(MyAnnotation.class.getCanonicalName());
 } @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latestSupported();
 } @Override
 public synchronized void init(ProcessingEnvironment environment) {
 super.init(environment);
 messager = environment.getMessager();
 elements = environment.getElementUtils();
 types = environment.getTypeUtils();
 filer = environment.getFiler();
 } @Override
 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { ... } }
  13. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String message = annotation.message();
 writer.append(" return \"").append(message).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  14. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String value = annotation.value();
 writer.append(" return \"").append(value).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  15. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String value = annotation.value();
 writer.append(" return \"").append(value).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  16. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String value = annotation.value();
 writer.append(" return \"").append(value).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  17. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String value = annotation.value();
 writer.append(" return \"").append(value).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  18. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String value = annotation.value();
 writer.append(" return \"").append(value).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  19. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String message = annotation.message();
 writer.append(" return \"").append(message).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  20. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String message = annotation.message();
 writer.append(" return \"").append(message).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  21. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String message = annotation.message();
 writer.append(" return \"").append(message).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  22. public class MyAnnotationProcessor extends AbstractProcessor { @Override
 public boolean process(Set<?

    extends TypeElement> annotations, RoundEnvironment environment) {
 final Set<? extends Element> elements = environment.getElementsAnnotatedWith(MyAnnotation.class);
 elements.forEach(element -> {
 final Name className = element.getSimpleName();
 final Name packageName = this.elements.getPackageOf(element).getQualifiedName();
 try {
 final JavaFileObject file = filer.createSourceFile(packageName + ".MyAnnotation_" + className);
 try (final Writer writer = file.openWriter()) {
 writer.append("package ").append(packageName).append(";\n\n")
 .append("public class MyAnnotation_").append(className).append(" {\n\n")
 .append(" @Override\n")
 .append(" public String toString() {\n");
 
 final MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
 final String value = annotation.value();
 writer.append(" return \"").append(value).append("\";\n")
 .append(" }\n")
 .append("}\n");
 writer.flush();
 }
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, "Failed to generate a file:" + packageName);
 }
 });
 return false;
 }
 }
  23. . |--src | |-- main | | |-- java |

    | | `-- io.t28.example.MyAnnotationProcessor.java | | `-- resources | | `-- META-INF.services | | `-- javax.annotation.processing.Processor | `-- test | `-- java | `-- io.t28.example.MyAnnotationProcessorTest.java `-- build.gradle
  24. . |--src | |-- main | | |-- java |

    | | `-- io.t28.example.MyAnnotationProcessor.java | | `-- resources | | `-- META-INF.services | | `-- javax.annotation.processing.Processor | `-- test | `-- java | `-- io.t28.example.MyAnnotationProcessorTest.java `-- build.gradle