हम एनोटेशन के साथ ऐसा कर सकते हैं!
त्रुटि बढ़ाने के लिए, Messager
संदेश भेजने के लिए उपयोग करें Diagnostic.Kind.ERROR
। संक्षिप्त उदाहरण:
processingEnv.getMessager().printMessage(
Diagnostic.Kind.ERROR, "Something happened!", element);
यहाँ एक काफी सरल एनोटेशन है जो मैंने इसे लिखने के लिए लिखा था।
यह @Marker
एनोटेशन बताता है कि लक्ष्य एक मार्कर इंटरफ़ेस है:
package marker;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Marker {
}
और एनोटेशन प्रोसेसर एक त्रुटि का कारण बनता है यदि यह नहीं है:
package marker;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
import javax.tools.Diagnostic;
import java.util.Set;
@SupportedAnnotationTypes("marker.Marker")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public final class MarkerProcessor extends AbstractProcessor {
private void causeError(String message, Element e) {
processingEnv.getMessager()
.printMessage(Diagnostic.Kind.ERROR, message, e);
}
private void causeError(
Element subtype, Element supertype, Element method) {
String message;
if (subtype == supertype) {
message = String.format(
"@Marker target %s declares a method %s",
subtype, method);
} else {
message = String.format(
"@Marker target %s has a superinterface " +
"%s which declares a method %s",
subtype, supertype, method);
}
causeError(message, subtype);
}
@Override
public boolean process(
Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
Elements elementUtils = processingEnv.getElementUtils();
boolean processMarker = annotations.contains(
elementUtils.getTypeElement(Marker.class.getName()));
if (!processMarker)
return false;
for (Element e : roundEnv.getElementsAnnotatedWith(Marker.class)) {
ElementKind kind = e.getKind();
if (kind != ElementKind.INTERFACE) {
causeError(String.format(
"target of @Marker %s is not an interface", e), e);
continue;
}
if (kind == ElementKind.ANNOTATION_TYPE) {
causeError(String.format(
"target of @Marker %s is an annotation", e), e);
continue;
}
ensureNoMethodsDeclared(e, e);
}
return true;
}
private void ensureNoMethodsDeclared(
Element subtype, Element supertype) {
TypeElement type = (TypeElement) supertype;
for (Element member : type.getEnclosedElements()) {
if (member.getKind() != ElementKind.METHOD)
continue;
if (member.getModifiers().contains(Modifier.STATIC))
continue;
causeError(subtype, supertype, member);
}
Types typeUtils = processingEnv.getTypeUtils();
for (TypeMirror face : type.getInterfaces()) {
ensureNoMethodsDeclared(subtype, typeUtils.asElement(face));
}
}
}
उदाहरण के लिए, ये सही उपयोग हैं @Marker
:
लेकिन इन उपयोगों के @Marker
कारण संकलक त्रुटि होगी:
यहाँ एक ब्लॉग पोस्ट है जो मुझे इस विषय पर शुरू करने में बहुत सहायक लगी:
छोटे नोट: नीचे टिप्पणी करने वाला व्यक्ति जो इंगित कर रहा है , वह यह है कि MarkerProcessor
संदर्भों के कारण Marker.class
, उस पर एक संकलन-समय निर्भरता है। मैंने उपरोक्त उदाहरण इस धारणा के साथ लिखा है कि दोनों वर्ग एक ही JAR फ़ाइल (कहते हैं marker.jar
) में जाएंगे , लेकिन यह हमेशा संभव नहीं है।
उदाहरण के लिए, मान लें कि निम्न वर्गों के साथ एक आवेदन JAR है:
com.acme.app.Main
com.acme.app.@Ann
com.acme.app.AnnotatedTypeA (uses @Ann)
com.acme.app.AnnotatedTypeB (uses @Ann)
तब प्रोसेसर के लिए @Ann
एक अलग जार में मौजूद होता है, जिसका उपयोग एप्लिकेशन जार को संकलित करते समय किया जाता है:
com.acme.proc.AnnProcessor (processes @Ann)
उस मामले में, सीधे AnnProcessor
प्रकार को संदर्भित करने में सक्षम नहीं होगा @Ann
, क्योंकि यह एक परिपत्र JAR निर्भरता पैदा करेगा। यह केवल नाम या / के @Ann
द्वारा संदर्भित करने में सक्षम होगा ।String
TypeElement
TypeMirror