Hello,
i wrote a rule to check if a method is annotated with a configured annotation. I can sucessfully test it using a test in my local project but once i try to use it in the server the symbol.metadata().isAnnotatedWith fails.
I’ve added some warn logs; the line ‘Detected method name’ i can see it in my local test but not during the scanning process
Can anyone give my some ideas why? Here is my rule code
import java.util.Arrays;
import java.util.List;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.plugins.java.api.JavaFileScanner;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.Symbol.MethodSymbol;
import org.sonar.plugins.java.api.semantic.SymbolMetadata.AnnotationValue;
import org.sonar.plugins.java.api.tree.BaseTreeVisitor;
import org.sonar.plugins.java.api.tree.MethodTree;
@Rule(key = "AnnotationPresentRule")
public class AnnotationPresentRule extends BaseTreeVisitor implements JavaFileScanner {
private static final Logger LOG = Loggers.get(AnnotationPresentRule.class);
public static final String DEFAULT_NAME_VALUE = "javax.ws.rs.Consumes";
public static final String DEFAULT_CONTAINS_VALUE = "application/json;charset=UTF-8";
private JavaFileScannerContext context;
public AnnotationPresentRule() {
super();
LOG.warn("AnnotationPresentRule new instance!");
}
@RuleProperty(defaultValue = DEFAULT_NAME_VALUE, description = "Name of the annotation to check, without the prefix @, for instance 'javax.ws.rs.Consumes'")
private String name;
@RuleProperty(defaultValue = DEFAULT_CONTAINS_VALUE, description = "The value annotation contains, without the prefix @, for instance 'application/json;charset=UTF-8;charset=UTF-8'")
private String contains;
@Override
public void scanFile(JavaFileScannerContext context) {
this.context = context;
scan(context.getTree());
}
@Override
public void visitMethod(MethodTree tree) {
MethodSymbol symbol = tree.symbol();
LOG.warn("Checking method name {} annotated with {} which has to contains {}", symbol.name(), getName(), getContains());
if (symbol.metadata().isAnnotatedWith(getName())) {
LOG.warn("Detected method name {} annotated with {} ", symbol.name(), getName());
if (isAnnotatedWithContains(symbol)) {
context.reportIssue(this, tree, String.format("Detected using of annotation @%s with value %s", getName(), getContains()));
}
}
// The call to the super implementation allows to continue the visit
// of
// the AST.
// Be careful to always call this method to visit every node of the
// tree.
super.visitMethod(tree);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContains() {
return contains;
}
public void setContains(String contains) {
this.contains = contains;
}
private boolean isAnnotatedWithContains(Symbol checkSymbol) {
List<AnnotationValue> valuesForAnnotation = checkSymbol.metadata().valuesForAnnotation(getName());
if (valuesForAnnotation == null) {
return false;
}
boolean b = valuesForAnnotation.stream().filter(annotationValue -> "value".equals(annotationValue.name())).anyMatch(
annotationValue -> {
if(annotationValue.value() instanceof Object[]) {
return Arrays.stream((Object[]) annotationValue.value()).anyMatch(aValue -> getContains().equals(aValue));
} else {
return getContains().equals(annotationValue.value());
}
}
);
return b;
}
}