[JAVA] Unklarer Fehler bei der Verarbeitung von Anmerkungen * Nicht behoben

Ich bin auf einen Fehler gestoßen, den ich nicht verstanden habe, als ich meinen eigenen Anmerkungsprozess erstellt habe. Beachten Sie, welche Art von Fehler Sie kennen.

Umgebung

Java

openjdk 10.0.2

Gradle

Gradle 4.10

Eclipse

4.8.0 (Photon)Pleiades

Implementierung

Ordnerstruktur


|-settings.gradle
|-build.gradle
|-foo/
| `-src/main/java/
|   `-foo/
|     |-Foo.java
|     |-ConcreteClass.java
|     |-MyAnnotation.java
|     `-MyInterface.java
|
`-bar/
  `src/main/
   |-java/
   | `-bar/
   |   `-MyProcessor.java
   `-resources/
     `-META-INF/services/
       `-javax.annotation.processing.Processor

--Multi-Projekt von foo, bar --bar implementiert die Annotationsverarbeitung und foo verwendet sie

MyProcessor.java


package bar;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;

public class MyProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (!annotations.isEmpty()) {
            try {
                JavaFileObject javaFileObject = this.processingEnv.getFiler().createSourceFile("foo.AutoGeneratedClass");
                try (BufferedWriter writer = new BufferedWriter(javaFileObject.openWriter())) {
                    writer.write(
                        "package foo;\n" +
                        "import foo.MyInterface;\n" +
                        "public class AutoGeneratedClass implements MyInterface {}"
                    );
                }
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
        
        return true;
    }
    
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
    }
    
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return Set.of("foo.MyAnnotation");
    }
}

MyInterface.java


package foo;

public interface MyInterface {}

MyAnnotation.java


package foo;

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    Class<? extends MyInterface> clazz();
}

ConcreteClass.java


package foo;

public class ConcreteClass extends AutoGeneratedClass {}

--Erstellen Sie "ConcreteClass", indem Sie "AutoGeneratedClass" erben, die automatisch durch die Annotationsverarbeitung generiert wird

Foo.java


package foo;

@MyAnnotation(clazz=ConcreteClass.class)
public class Foo {}

--Klasse, die tatsächlich "MyAnnotation" verwendet

Nach Klassendiagramm organisieren

apt.jpg

Ereignisse, die auftreten

Das Kompilieren sieht folgendermaßen aus:

> gradle :foo:compileJava
> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Error:Symbol kann nicht gefunden werden
public class ConcreteClass extends AutoGeneratedClass {
                                   ^
Symbol:Klasse AutoGeneratedClass
...\foo\src\main\java\foo\Foo.java:3:Error:Inkompatibler Typ: Class<ConcreteClass>Klasse<? extends MyInterface>Kann nicht konvertiert werden:
@MyAnnotation(clazz=ConcreteClass.class)
                                 ^
2 Fehler

Probieren Sie verschiedene Dinge aus

Kommt in Eclipse nicht vor

Es tritt nicht auf, wenn Sie die Angabe der Obergrenze des Typarguments beenden

MyAnnotation.java


package foo;

...

public @interface MyAnnotation {
-   Class<? extends MyInterface> clazz();
+   Class<?> clazz();
}

--Entfernen Sie die Obergrenze von "MyInterface", die im "clazz" -Element von "MyAnnotation" angegeben ist

Ergebnis kompilieren


> gradle :foo:compileJava
...
BUILD SUCCESSFUL in 3s

--Dann wird die Zusammenstellung bestanden. --Geheimnis

Kein Fehler, wenn die Obergrenze auf eine automatisch generierte Klasse festgelegt ist

MyAnnotation.java


package foo;

...
public @interface MyAnnotation {
-   Class<? extends MyInterface> clazz();
+   Class<? extends AutoGeneratedClass> clazz();
}

Ergebnis kompilieren


> gradle :foo:compileJava
...
BUILD SUCCESSFUL in 3s

Es tritt kein Fehler auf, selbst wenn die automatisch generierte Klasse von clazz angegeben wird

Foo.java


package foo;

- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation(clazz=AutoGeneratedClass.class)
public class Foo {}

--MyAnnotation hat die Obergrenze vonClass <? Extends MyInterface>

Ergebnis kompilieren


...
BUILD SUCCESSFUL in 4s

--Dies kompiliert auch --Interface-> Automatisch generierte Klasse-> Es scheint, dass ein Fehler auftritt, wenn es sich um eine Beziehung einer selbst erstellten Klasse handelt

Sich auf ConcreteClass zu verlassen ist in Ordnung

Foo.java


package foo;

- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
public class Foo {
+   private Class<?> clazz = ConcreteClass.class;
}

Ergebnis kompilieren


> gradle :foo:compileJava
BUILD SUCCESSFUL in 3s

Es ist sinnlos, mit einer Anmerkung darauf zu verweisen, die nicht das Verarbeitungsziel ist

OtherAnnotation.java


package foo;

...

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface OtherAnnotation {
    Class<? extends MyInterface> clazz();
}

--Erstelle OtherAnnotation.java mit der gleichen Definition wie MyAnnotation

Foo.java


package foo;

- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
+ @OtherAnnotation(clazz=ConcreteClass.class)
public class Foo {}

Ergebnis kompilieren


> gradle :foo:compileJava
> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Error:Symbol kann nicht gefunden werden
public class ConcreteClass extends AutoGeneratedClass {
                                   ^
Symbol:Klasse AutoGeneratedClass
...\foo\src\main\java\foo\Foo.java:4:Error:Inkompatibler Typ: Class<ConcreteClass>Klasse<? extends MyInterface>Kann nicht konvertiert werden:
@OtherAnnotation(clazz=ConcreteClass.class)
                                    ^
2 Fehler

Sie können es nicht an einem Ort schreiben, der nichts mit der Verarbeitung von Anmerkungen zu tun hat

OtherClass.java


package foo;

@OtherAnnotation(clazz=ConcreteClass.class)
public class OtherClass {}

Foo.java


package foo;

- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
public class Foo {}

--OtherAnnotation ist das gleiche wie das vorherige

Ergebnis kompilieren


> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Error:Symbol kann nicht gefunden werden
public class ConcreteClass extends AutoGeneratedClass {
                                   ^
Symbol:Klasse AutoGeneratedClass
...\foo\src\main\java\foo\OtherClass.java:3:Error:Inkompatibler Typ: Class<ConcreteClass>Klasse<? extends MyInterface>Kann nicht konvertiert werden:
@OtherAnnotation(clazz=ConcreteClass.class)
                                    ^
2 Fehler

Symptome organisieren

Nach der Organisation der Ergebnisse verschiedener Versuche scheint ein Fehler aufzutreten, wenn die folgenden Bedingungen erfüllt sind:

Fazit

Ich bin mir nicht sicher.

Recommended Posts

Unklarer Fehler bei der Verarbeitung von Anmerkungen * Nicht behoben
Fehler bei der Implementierung der Tagging-Funktion
Verwenden Sie MouseListener für die Verarbeitung
Fehlerbehandlung mit Graphql-Ruby