/* * 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); } }