/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2005, University of Maryland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.umd.cs.findbugs.detect;
import java.util.HashMap;
import java.util.Map;
import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.ba.AnnotationDatabase;
import edu.umd.cs.findbugs.ba.NullnessAnnotation;
import edu.umd.cs.findbugs.ba.NullnessAnnotationDatabase;
import edu.umd.cs.findbugs.ba.XFactory;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.ba.XMethodParameter;
import edu.umd.cs.findbugs.visitclass.AnnotationVisitor;
/**
* Scan application classes for
* NonNull annotations.
*
* @author David Hovemeyer
* @author William Pugh
*/
public class BuildNonNullAnnotationDatabase extends AnnotationVisitor {
private static final boolean DEBUG = SystemProperties.getBoolean("fnd.debug.annotation");
private static final String DEFAULT_ANNOTATION_ANNOTATION_CLASS = "DefaultAnnotation";
private static final Map<String, AnnotationDatabase.Target> defaultKind = new HashMap<String, AnnotationDatabase.Target>();
static {
defaultKind.put("", AnnotationDatabase.Target.ANY);
defaultKind.put("ForParameters", AnnotationDatabase.Target.PARAMETER);
defaultKind.put("ForMethods", AnnotationDatabase.Target.METHOD);
defaultKind.put("ForFields", AnnotationDatabase.Target.FIELD);
}
private NullnessAnnotationDatabase database;
public BuildNonNullAnnotationDatabase(@CheckForNull NullnessAnnotationDatabase database) {
this.database = database;
}
static String lastPortion(String className) {
int i = className.lastIndexOf(".");
if (i < 0)
return className;
return className.substring(i + 1);
}
@Override
public void visitAnnotation(String annotationClass,
Map<String, Object> map, boolean runtimeVisible) {
if (database == null) {
return;
}
NullnessAnnotation n = NullnessAnnotation.Parser.parse(annotationClass);
annotationClass = lastPortion(annotationClass);
if (n == null) {
if (annotationClass.startsWith("DefaultAnnotation")) {
Object v = map.get("value");
if (v == null || !(v instanceof Object[]))
return;
annotationClass = annotationClass.substring("DefaultAnnotation"
.length());
AnnotationDatabase.Target annotationTarget = defaultKind.get(annotationClass);
if (annotationTarget != null)
for (Object aClass : (Object[]) v) {
n = NullnessAnnotation.Parser.parse((String) aClass);
if (n != null)
database
.addDefaultAnnotation(annotationTarget,
getDottedClassName(), n);
}
}
}
else if (visitingMethod())
database.addDirectAnnotation(
XFactory.createXMethod(this), n);
else if (visitingField())
database.addDirectAnnotation(
XFactory.createXField(this), n);
}
@Override
public void visitSyntheticParameterAnnotation(int p, boolean runtimeVisible) {
if (database == null) {
return;
}
XMethod xmethod = XFactory.createXMethod(this);
XMethodParameter xparameter = new XMethodParameter(xmethod, p);
database.addDirectAnnotation(
xparameter, NullnessAnnotation.UNKNOWN_NULLNESS);
}
@Override
public void visitParameterAnnotation(int p, String annotationClass,
Map<String, Object> map, boolean runtimeVisible) {
if (database == null) {
return;
}
NullnessAnnotation n = NullnessAnnotation.Parser.parse(annotationClass);
annotationClass = lastPortion(annotationClass);
if (n == null)
return;
XMethod xmethod = XFactory.createXMethod(this);
if (DEBUG) {
System.out.println("Parameter "
+ p
+ " @"
+ annotationClass.substring(annotationClass
.lastIndexOf('/') + 1) + " in "
+ xmethod.toString());
}
XMethodParameter xparameter = new XMethodParameter(xmethod, p);
database.addDirectAnnotation(
xparameter, n);
}
}