die AbstractProcessor unten verarbeitet greghmerrill des @ Unsafe Annotation und gibt Warnungen zu Methodenaufrufen an annotierte Annotated-Methoden aus.
Es ist eine geringfügige Änderung der greghmerrill eigenen Antwort, die war großartig, aber ich hatte einige Probleme bekommen meine IDEs inkrementellen Compiler (ich benutze Netbeans), um die Warnungen/Fehler etc aus dem Plugin - nur diejenigen, die ich gedruckt Vom Prozessor wurde gezeigt, obwohl das Verhalten wie erwartet war, als ich 'mvn clean kompilieren' lief (ich benutze Maven). Ob dies auf ein Problem von meiner Hand zurückzuführen ist, oder auf Unterschiede zwischen Plugins und AbstractProcessors/den Phasen des Kompilierungsprozesses, weiß ich nicht.
Wie dem auch sei:
package com.hervian.annotationutils.target;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.util.*;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeInfo;
import java.util.Set;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.tools.Diagnostic;
@SupportedAnnotationTypes({"com.hervian.annotationutils.target.Unsafe"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class UnsafeAnnotationProcessor extends AbstractProcessor implements TaskListener {
Trees trees;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
trees = Trees.instance(processingEnv);
JavacTask.instance(processingEnv).setTaskListener(this);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
//Process @Unsafe annotated methods if needed
return true;
}
@Override public void finished(TaskEvent taskEvt) {
if (taskEvt.getKind() == TaskEvent.Kind.ANALYZE) {
taskEvt.getCompilationUnit().accept(new TreeScanner<Void, Void>() {
@Override
public Void visitMethodInvocation(MethodInvocationTree methodInv, Void v) {
Element method = TreeInfo.symbol((JCTree) methodInv.getMethodSelect());
Unsafe unsafe = method.getAnnotation(Unsafe.class);
if (unsafe != null) {
JCTree jcTree = (JCTree) methodInv.getMethodSelect();
trees.printMessage(Diagnostic.Kind.WARNING, "Call to unsafe method.", jcTree, taskEvt.getCompilationUnit());
}
return super.visitMethodInvocation(methodInv, v);
}
}, null);
}
}
@Override public void started(TaskEvent taskEvt) { } }
Wenn die Annotation verwenden und Anrufe an die kommentierten Methode macht es wie folgt aussehen:
One den vollständig qualifizierten Klassennamen der Anmerkung hinzuzufügen, zu erinnern braucht Prozessor zu einer META-INF/Service-Datei namens javax.annotation.processing.Processor. Dadurch ist es für das ServiceLoader-Framework verfügbar.
Maven Benutzer, die Probleme mit den com.sun ** Importen haben, finden this answer von AnimeshSharma hilfreich.
Ich halte meine Annotation + Annotation Prozessor in einem separaten Projekt. Ich hatte Annotation Verarbeitung zu deaktivieren, indem Sie die folgenden auf die pom Zugabe:
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
die Anmerkung verwenden und mit dem Prozessor seine Arbeit tun war einfach: In meinem anderen Projekt (die, wo der Screenshot der Methode foo() ist von) Ich habe dem Projekt, das die Annotation und den Prozessor enthält, einfach eine Abhängigkeit hinzugefügt.
Schließlich sollte erwähnt werden, dass ich neu bei AbstractProcessors und TaskListeners bin. Ich habe, fx, keinen Überblick über die Leistung oder Robustheit des Codes. Das Ziel war einfach, "es zur Arbeit zu bringen" und einen Stummel für ähnliche Projekte zur Verfügung zu stellen.
Sind Sie sicher, dass das zur Kompilierzeit vollständig möglich ist? Es ist nicht immer möglich zu wissen, auf welche Methode Bezug genommen wird. Angenommen, Ihr 'Foo' würde eine Schnittstelle implementieren, mit der '@ Unsafe'-Anmerkung nur für die' Foo'-Implementierung. Dann würde ein Client, der die Schnittstelle verwendet, nicht angezeigt. – sisyphus
Sie möchten eine Warnung bezüglich der Codezeile ausgeben, die die Methode aufruft, so dass Sie die Bytecodeanalyse auf keinen Fall vermeiden können. – user3707125
@sisyphus, wenn ein Aufruf der Interface-Methode unsicher sein kann, sollte die Interface-Methode mit '@ Unsafe' gekennzeichnet werden. Somit ist die Kompilierzeitverarbeitung vollständig und solide. – mernst