1 19 20 package edu.umd.cs.findbugs.detect; 21 22 import java.util.HashSet ; 23 import java.util.Set ; 24 25 import org.apache.bcel.classfile.Attribute; 26 import org.apache.bcel.classfile.Code; 27 import org.apache.bcel.classfile.JavaClass; 28 import org.apache.bcel.classfile.Method; 29 30 import edu.umd.cs.findbugs.BugInstance; 31 import edu.umd.cs.findbugs.BugReporter; 32 import edu.umd.cs.findbugs.BytecodeScanningDetector; 33 import edu.umd.cs.findbugs.ba.AnalysisContext; 34 import edu.umd.cs.findbugs.ba.XFactory; 35 import edu.umd.cs.findbugs.ba.XMethod; 36 import edu.umd.cs.findbugs.util.ClassName; 37 38 public class UncallableMethodOfAnonymousClass extends BytecodeScanningDetector { 39 40 BugReporter bugReporter; 41 42 public UncallableMethodOfAnonymousClass(BugReporter bugReporter) { 43 this.bugReporter = bugReporter; 44 } 45 46 boolean isInnerClass = false; 47 48 @Override 49 public void visit(JavaClass obj) { 50 isInnerClass = ClassName.isAnonymous(getClassName()); 51 } 52 53 boolean definedInThisClassOrSuper(JavaClass clazz, String method) 54 throws ClassNotFoundException { 55 if (clazz == null) 56 return false; 57 for (Method m : clazz.getMethods()) 60 if (method.equals(m.getName() + ":" + m.getSignature())) 61 return true; 62 63 return definedInSuperClassOrInterface(clazz, method); 64 65 } 66 67 boolean definedInSuperClassOrInterface(JavaClass clazz, String method) 68 throws ClassNotFoundException { 69 if (clazz == null) 70 return false; 71 JavaClass superClass = clazz.getSuperClass(); 72 if (definedInThisClassOrSuper(superClass, method)) 73 return true; 74 for (JavaClass i : clazz.getInterfaces()) 75 if (definedInThisClassOrSuper(i, method)) 76 return true; 77 return false; 78 } 79 80 Set <String > definedInClass(JavaClass clazz) { 81 HashSet <String > result = new HashSet <String >(); 82 for(Method m : clazz.getMethods()) { 83 if (!skip(m)) 84 result.add(m.getName()+m.getSignature()); 85 } 86 return result; 87 } 88 89 static private boolean skip(Method obj) { 90 if (obj.getName().equals("<init>")) 91 return true; 92 if (obj.getName().startsWith("access$")) 93 return true; 94 if (obj.isSynthetic()) 95 return true; 96 if (obj.isPrivate()) 97 return true; 98 if (obj.isAbstract()) return true; 99 return false; 100 } 101 @Override 102 public void visit(Method obj) { 103 try { 104 if (!isInnerClass) 105 return; 106 if (skip(obj)) return; 107 108 JavaClass clazz = getThisClass(); 109 XMethod xmethod = XFactory.createXMethod(clazz, obj); 110 XFactory factory = AnalysisContext.currentXFactory(); 111 if (!factory.isCalled(xmethod) 112 && !definedInSuperClassOrInterface(clazz, obj.getName() 113 + ":" + obj.getSignature())) { 114 int priority = NORMAL_PRIORITY; 115 JavaClass superClass = clazz.getSuperClass(); 116 String superClassName = superClass.getClassName(); 117 if (superClass.isInterface() || superClassName.equals("java.lang.Object")) 118 priority = HIGH_PRIORITY; 119 else if (definedInClass(superClass).containsAll(definedInClass(clazz))) 120 priority = NORMAL_PRIORITY; 121 else 122 priority = HIGH_PRIORITY; 123 Code code = null; 124 for(Attribute a : obj.getAttributes()) 125 if (a instanceof Code) { 126 code = (Code) a; 127 break; 128 } 129 if (code != null && code.getLength() == 1) priority++; bugReporter.reportBug(new BugInstance("UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS", 131 priority).addClassAndMethod(this)); 132 133 } 134 135 } catch (ClassNotFoundException e) { 136 bugReporter.reportMissingClass(e); 137 } 138 139 } 140 141 } 142 | Popular Tags |