/*
* 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.ba;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.log.Profiler;
/**
* @author pugh
*/
public class NullnessAnnotationDatabase extends AnnotationDatabase<NullnessAnnotation> implements INullnessAnnotationDatabase {
public NullnessAnnotationDatabase() {
setAddClassOnly(true);
loadAuxiliaryAnnotations();
setAddClassOnly(false);
}
@Override
public void loadAuxiliaryAnnotations() {
DefaultNullnessAnnotations.addDefaultNullnessAnnotations(this);
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#parameterMustBeNonNull
* (edu.umd.cs.findbugs.ba.XMethod, int)
*/
public boolean parameterMustBeNonNull(XMethod m, int param) {
if (param == 0) {
if (m.getName().equals("equals") && m.getSignature().equals("(Ljava/lang/Object;)Z") && !m.isStatic())
return false;
else if (m.getName().equals("main") && m.getSignature().equals("([Ljava/lang/String;)V") && m.isStatic()
&& m.isPublic())
return true;
else if (assertsFirstParameterIsNonnull(m))
return true;
else if (m.getName().equals("compareTo") && m.getSignature().endsWith(";)Z") && !m.isStatic())
return true;
}
if (!anyAnnotations(NullnessAnnotation.NONNULL))
return false;
XMethodParameter xmp = new XMethodParameter(m, param);
NullnessAnnotation resolvedAnnotation = getResolvedAnnotation(xmp, true);
if (false) {
System.out.println("QQQ parameter " + param + " of " + m + " is " + resolvedAnnotation);
System.out.println(m.getSignature());
}
return resolvedAnnotation == NullnessAnnotation.NONNULL;
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#getResolvedAnnotation
* (java.lang.Object, boolean)
*/
@CheckForNull
@Override
public NullnessAnnotation getResolvedAnnotation(final Object o, boolean getMinimal) {
Profiler profiler = Global.getAnalysisCache().getProfiler();
profiler.start(this.getClass());
try {
if (o instanceof XMethodParameter) {
XMethodParameter mp = (XMethodParameter) o;
XMethod m = mp.getMethod();
// TODO: Handle argument to equals specially: generate special
// bug code for it
int parameterNumber = mp.getParameterNumber();
if (parameterNumber == 0) {
if (m.getName().equals("equals") && m.getSignature().equals("(Ljava/lang/Object;)Z") && !m.isStatic())
return NullnessAnnotation.CHECK_FOR_NULL;
else if (m.getName().equals("main") && m.getSignature().equals("([Ljava/lang/String;)V") && m.isStatic()
&& m.isPublic())
return NullnessAnnotation.NONNULL;
else if (assertsFirstParameterIsNonnull(m))
return NullnessAnnotation.NONNULL;
else if (m.getName().equals("compareTo") && m.getSignature().endsWith(";)Z") && !m.isStatic())
return NullnessAnnotation.NONNULL;
}
} else if (o instanceof XMethod) {
XMethod m = (XMethod) o;
String name = m.getName();
String signature = m.getSignature();
if (!m.isStatic()
&& (name.equals("clone") && signature.equals("()Ljava/lang/Object;") || name.equals("toString")
&& signature.equals("()Ljava/lang/String;") || m.isPrivate() && name.equals("readResolve")
&& signature.equals("()Ljava/lang/Object;"))) {
NullnessAnnotation result = super.getDirectAnnotation(m);
if (result != null)
return result;
return NullnessAnnotation.NONNULL;
}
} else if (o instanceof XField) {
XField f = (XField) o;
if (f.getName().startsWith("this$"))
return NullnessAnnotation.NONNULL;
}
NullnessAnnotation result = super.getResolvedAnnotation(o, getMinimal);
return result;
} finally {
profiler.end(this.getClass());
}
}
/**
* @param m
* @return
*/
public static boolean assertsFirstParameterIsNonnull(XMethod m) {
return (m.getName().equalsIgnoreCase("checkNonNull") || m.getName().equalsIgnoreCase("checkNotNull") || m.getName()
.equalsIgnoreCase("assertNotNull")) && m.getSignature().startsWith("(Ljava/lang/Object;");
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.ba.AnnotationDatabase#addDefaultMethodAnnotation(
* java.lang.String, edu.umd.cs.findbugs.ba.AnnotationEnumeration)
*/
@Override
public void addDefaultMethodAnnotation(String name, NullnessAnnotation annotation) {
super.addDefaultMethodAnnotation(name, annotation);
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.ba.AnnotationDatabase#addDefaultAnnotation(java.lang
* .String, java.lang.String, edu.umd.cs.findbugs.ba.AnnotationEnumeration)
*/
@Override
public void addDefaultAnnotation(AnnotationDatabase.Target target, String c, NullnessAnnotation n) {
super.addDefaultAnnotation(target, c, n);
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.ba.AnnotationDatabase#addFieldAnnotation(java.lang
* .String, java.lang.String, java.lang.String, boolean,
* edu.umd.cs.findbugs.ba.AnnotationEnumeration)
*/
@Override
public void addFieldAnnotation(String name, String name2, String sig, boolean isStatic, NullnessAnnotation annotation) {
super.addFieldAnnotation(name, name2, sig, isStatic, annotation);
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.ba.AnnotationDatabase#addMethodAnnotation(java.lang
* .String, java.lang.String, java.lang.String, boolean,
* edu.umd.cs.findbugs.ba.AnnotationEnumeration)
*/
@Override
public void addMethodAnnotation(String name, String name2, String sig, boolean isStatic, NullnessAnnotation annotation) {
super.addMethodAnnotation(name, name2, sig, isStatic, annotation);
}
/*
* (non-Javadoc)
*
* @see
* edu.umd.cs.findbugs.ba.AnnotationDatabase#addMethodParameterAnnotation
* (java.lang.String, java.lang.String, java.lang.String, boolean, int,
* edu.umd.cs.findbugs.ba.AnnotationEnumeration)
*/
@Override
public void addMethodParameterAnnotation(String name, String name2, String sig, boolean isStatic, int param,
NullnessAnnotation annotation) {
super.addMethodParameterAnnotation(name, name2, sig, isStatic, param, annotation);
}
}