Annotations Processor Tools (APT)

29
Annotation Processing Tools 101

Transcript of Annotations Processor Tools (APT)

Annotation Processing Tools

101

Txus Ballesteros @txusballesteros

Rubén Serrano @akelael

Agenda

1. Annotation Processing Tool

2. Discusión

3. Caso práctico

¿Qué es eso de APT?

public @interface DummyAnnotiation {}

Anotación

Retención• Constructor

• Atributo

• Variable

• Método

• Parámetro

• Etc.

• Source

• Class

• Runtime

Objetivo

Anotación@Retention(CLASS) @Target(FIELD) public @interface InjectView { int value();}

RuntimeClass tiene la magia:

• getAnnotation(Class<T> annotationType)

• getAnnotations()

• getDeclaredAnnotations()

• isAnnotationPresent(Class<T> annotationType)

Mirror APIhttp://docs.oracle.com/javase/1.5.0/docs/guide/apt/mirror/overview-summary.html

Discusión

Caso Práctico

Android Transformerhttps://github.com/txusballesteros/android-transformer

Creando Anotaciones

@Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface Mappable { Class<?> with();}

Creando Anotaciones

@Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface Mappable { Class<?> with();}

Configurando las Anotaciones

@Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface Mappable { Class<?> with();}

Configurando las Anotaciones

@Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface Mappable { Class<?> with();}

@SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes({ "com.mobandme.android.transformer.compiler.Mapping", "com.mobandme.android.transformer.compiler.Mappable", "com.mobandme.android.transformer.compiler.Parse"}) public class AnnotationsProcessor extends AbstractProcessor { RoundEnvironment roundEnvironment; Map<String, MapperInfo> mappersList; @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { return true; }

Creando el Procesador

@SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes({ "com.mobandme.android.transformer.compiler.Mapping", "com.mobandme.android.transformer.compiler.Mappable", "com.mobandme.android.transformer.compiler.Parse"}) public class AnnotationsProcessor extends AbstractProcessor { RoundEnvironment roundEnvironment; Map<String, MapperInfo> mappersList; @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { return true; }

Creando el Procesador

@SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes({ "com.mobandme.android.transformer.compiler.Mapping", "com.mobandme.android.transformer.compiler.Mappable", "com.mobandme.android.transformer.compiler.Parse"}) public class AnnotationsProcessor extends AbstractProcessor { RoundEnvironment roundEnvironment; Map<String, MapperInfo> mappersList; @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { return true; }

Configurando el Procesador

Implementando el Procesador@SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes({ "com.mobandme.android.transformer.compiler.Mapping", "com.mobandme.android.transformer.compiler.Mappable", "com.mobandme.android.transformer.compiler.Parse"}) public class AnnotationsProcessor extends AbstractProcessor { RoundEnvironment roundEnvironment; Map<String, MapperInfo> mappersList; @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { return true; }

Implementando el Procesadorprivate void processMappedAnnotationElements() {

Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Mapped.class); for (Element mappedElement : elements) { if (mappedElement.getKind() == ElementKind.FIELD) { Mapped mappedAnnotation = mappedElement.getAnnotation(Mapped.class); String toFieldName = mappedAnnotation.toField(); } }}

Implementando el Procesadorprivate void processMappedAnnotationElements() {

Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Mapped.class); for (Element mappedElement : elements) { if (mappedElement.getKind() == ElementKind.FIELD) { Mapped mappedAnnotation = mappedElement.getAnnotation(Mapped.class); String toFieldName = mappedAnnotation.toField(); } }}

Implementando el Procesadorprivate void processMappedAnnotationElements() {

Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Mapped.class); for (Element mappedElement : elements) { if (mappedElement.getKind() == ElementKind.FIELD) { Mapped mappedAnnotation = mappedElement.getAnnotation(Mapped.class); String toFieldName = mappedAnnotation.toField(); } }}

Implementando el Procesadorprivate void processMappedAnnotationElements() {

Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Mapped.class); for (Element mappedElement : elements) { if (mappedElement.getKind() == ElementKind.FIELD) { Mapped mappedAnnotation = mappedElement.getAnnotation(Mapped.class); String toFieldName = mappedAnnotation.toField(); } }}

Generando el CódigoJavaFileObject file = processingEnv.getFiler().createSourceFile(name);

BufferedWriter buffer = new BufferedWriter(file.openWriter());

//…

buffer.close();

Configurando el Entorno

com.mobandme.android.transformer.compiler.internal.AnnotationsProcessor

Configuración de Gradle para el Compiladorbuildscript { repositories { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } jcenter() } dependencies { classpath 'com.jimdo.gradle:gradle-apt-plugin:0.5-SNAPSHOT' } } apply plugin: 'java'apply plugin: 'apt'

El resultado final

¿Preguntas?