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

Hello, Annotation Processing!

Avatar for Tatsuya Maki Tatsuya Maki
December 10, 2016

Hello, Annotation Processing!

Introduction to Annotation Processing.

Avatar for Tatsuya Maki

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