# Eclipse: Eigene Compiler Fehler generieren und anzeigen mit Annotation Processors



## Thomas Darimont (8. Oktober 2010)

Hallo,

Inspiriert von diesem Beitrag:
http://www.tutorials.de/java/367200-annotation-target-annotationprocessor-debug-new-post.html 
hier mal ein kleines einfaches Beispiel wie man eigene AnnotationProcessors in der Eclipse IDE verwenden kann.
Übrigens eine ähnliche Möglichkeit bietet beispielsweise AspectJ mit declare error / warning 

Als Beispiel wollen wir einen AnnotationProcessor schrieben der die Verwendung von einer Annotation pürfen soll.
Die Annotation (CustomAnnotation) soll dabei nur für Felder verwendet werden dürfen die vom Typ 
javax.swing.table.TableModel sind, ansonsten soll ein Compiler-Fehler generiert und im Java Editor angezeigt werden.

Dazu erstellen wir uns eine CustomAnnotation:

```
package de.tutorials.training;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CustomAnnotation {
}
```

Nun erstellen wir einen AnnoationProcessor der unsere Prüfung durchführt:

```
package de.tutorials.training.ap;

import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.swing.table.TableModel;
import javax.tools.Diagnostic.Kind;

import de.tutorials.training.CustomAnnotation;

@SupportedAnnotationTypes(value = { "de.tutorials.training.CustomAnnotation" })
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class CustomAnnotationProcessor extends AbstractProcessor {

  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

    Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(CustomAnnotation.class);
    for (Element annotatedElement : annotatedElements) {
      TypeMirror typeMirror = annotatedElement.asType();

      if (!TableModel.class.getName().equals(typeMirror.toString())) {
        processingEnv.getMessager().printMessage(Kind.ERROR, "CustomAnnotation is only allowed for fields of Type " + TableModel.class.getName(), annotatedElement);
      }
    }

    return true;
  }
}
```

Anschließend definieren wir eine Datei in einem neuen Verzeichnis (im Projekt-root)
META-INF/services/javax.annotation.processing.Processor
mit dem Inhalt:

```
de.tutorials.training.ap.CustomAnnotationProcessor
```
Hierbei kommt der bewährte java ServiceLoader Erweiterungsmechanismus zum Zuge 
Siehe:
http://www.tutorials.de/java/310207-eine-art-plugin-system-2.html
http://www.tutorials.de/java/357126-wieder-mal-java-und-plug-ins.html#post1850187
http://www.tutorials.de/enterprise-...-den-code-des-hauptprogramms.html#post1873521
http://www.tutorials.de/java/358931-services-dynamisch-laden.html

Anschließend erstellen wir (der einfachheit halber) im Projekt selbst wieder ein Verzeichnis ap.
Anschließend exportieren wir die CustomAnnotation unseren CustomAnnotationProcessor und das komplette META-INF Verzeichnis
als .jar Datei in unseren zuvor erstelltes Verzeichnis ap. (customAnnotationProcessor.jar)


Nun gehen wir in die Projekt Einstellungen (Project Properties) 
-> Zu Java Compiler -> Enable project specific settings -> Annoation Processing -> Enable Project specific Settings 
(Enable Annoation processing, Enable Annotation Processing in Editor) -> Factory Path -> Enable Project specific Settings ->
Add jars -> ap/customAnnotationProcessor.jar. Selektieren wir nun dieses jar wieder sollten wir unter -> advanced unseren
CustomAnnoationProcessor sehen.

Erstellen wir nun folgende neue Java Klasse :

```
package de.tutorials.training;

import javax.swing.table.TableModel;

public class CustomAnnotationTest {
  @CustomAnnotation
  static TableModel bubu1;

  @CustomAnnotation
  static Object bubu2; //1
}
```
so bekommen wir im Java Editor vom Java Compiler an Stelle //1 den Fehler: CustomAnnotation is only allowed for fields of Type javax.swing.table.TableModel

Siehe Screenshot.

Mit dieser Technik lassen sich nun zahlreiche Source Code Checks auch direkt im Java Editor anzeigen 

Gruß Tom


----------

