01: package spoon.vsuite.findbugs.dm;
02:
03: import java.lang.annotation.Retention;
04: import java.lang.annotation.RetentionPolicy;
05:
06: import spoon.processing.AbstractProblemFixer;
07: import spoon.processing.AbstractProcessor;
08: import spoon.processing.Property;
09: import spoon.processing.Severity;
10: import spoon.reflect.Changes;
11: import spoon.reflect.code.CtInvocation;
12: import spoon.reflect.declaration.CtSimpleType;
13: import spoon.reflect.reference.CtExecutableReference;
14: import spoon.reflect.reference.CtTypeReference;
15:
16: /**
17: * Dm: Can't use reflection to check for presence of annotation with default
18: * retention (DMI_ANNOTATION_IS_NOT_VISIBLE_TO_REFLECTION) Unless an annotation
19: * has itself been annotated with a \@Retention other than the default of
20: * source-only retention, the annotation isn't retained in the classfile and
21: * can't be observed using reflection (e.g., by using the isAnnotationPresent
22: * method).
23: *
24: * @author Nicolas Petitprez
25: */
26: public class AnnotationIsNotVisible extends
27: AbstractProcessor<CtInvocation<?>> {
28: @Property
29: static Severity level = Severity.WARNING;
30:
31: public void process(CtInvocation<?> element) {
32: CtExecutableReference<?> ref = element.getExecutable();
33: if (ref.getSimpleName().equals("isAnnotationPresent")
34: && ref.getParameterTypes().size() == 1
35: && ref.getParameterTypes().get(0).equals(
36: getFactory().Type()
37: .createReference(Class.class))) {
38: // Checking annotation given in parameter
39: CtTypeReference<?> typeref = element.getArguments().get(0)
40: .getType();
41: Retention r = typeref.getAnnotation(Retention.class);
42: if (r == null || !r.value().equals(RetentionPolicy.RUNTIME)) {
43: if (typeref.getDeclaration() != null) {
44: getFactory()
45: .getEnvironment()
46: .report(
47: this ,
48: level,
49: element,
50: "Can't use reflection to check for presence of annotation with default retention",
51: new Fixer(typeref));
52: } else {
53: getFactory()
54: .getEnvironment()
55: .report(
56: this ,
57: level,
58: element,
59: "Can't use reflection to check for presence of annotation with default retention");
60: }
61: }
62: }
63:
64: }
65:
66: public class Fixer extends AbstractProblemFixer<CtInvocation<?>> {
67: CtTypeReference<?> typeref;
68:
69: public Fixer(CtTypeReference<?> typeref) {
70: super ();
71: this .typeref = typeref;
72: }
73:
74: public String getDescription() {
75: return getLabel();
76: }
77:
78: public String getLabel() {
79: return "Set runtime retention to annotation "
80: + typeref.toString();
81: }
82:
83: public Changes run(CtInvocation<?> element) {
84: Changes lst = new Changes();
85:
86: CtTypeReference<?> typeref = element.getArguments().get(0)
87: .getType();
88: CtSimpleType<?> t = typeref.getDeclaration();
89: try {
90: getFactory().Annotation().annotate(t, Retention.class,
91: "value", RetentionPolicy.RUNTIME);
92: } catch (SecurityException e) {
93: e.printStackTrace();
94: }
95: lst.getModified().add(t);
96: return lst;
97: }
98: }
99: }
|