1 19 20 package edu.umd.cs.findbugs.detect; 21 22 import org.apache.bcel.Repository; 23 import org.apache.bcel.classfile.Code; 24 import org.apache.bcel.classfile.ConstantNameAndType; 25 import org.apache.bcel.classfile.JavaClass; 26 import org.apache.bcel.classfile.Method; 27 28 import edu.umd.cs.findbugs.BugInstance; 29 import edu.umd.cs.findbugs.BugReporter; 30 import edu.umd.cs.findbugs.Detector; 31 import edu.umd.cs.findbugs.MethodAnnotation; 32 import edu.umd.cs.findbugs.StatelessDetector; 33 import edu.umd.cs.findbugs.ba.ClassContext; 34 import edu.umd.cs.findbugs.ba.PruneInfeasibleExceptionEdges; 35 import edu.umd.cs.findbugs.ba.PruneUnconditionalExceptionThrowerEdges; 36 import edu.umd.cs.findbugs.ba.XFactory; 37 import edu.umd.cs.findbugs.visitclass.DismantleBytecode; 38 39 public class CloneIdiom extends DismantleBytecode implements Detector, StatelessDetector { 40 41 boolean hasCloneMethod; 42 MethodAnnotation cloneMethodAnnotation; 43 boolean referencesCloneMethod; 44 boolean invokesSuperClone; 45 boolean isFinal; 46 boolean cloneOnlyThrowsException; 47 48 boolean check; 49 boolean implementsCloneableDirectly; 51 private BugReporter bugReporter; 52 53 public CloneIdiom(BugReporter bugReporter) { 54 this.bugReporter = bugReporter; 55 } 56 57 58 59 public void visitClassContext(ClassContext classContext) { 60 classContext.getJavaClass().accept(this); 61 } 62 63 64 public void report() { 65 } 66 67 @Override 68 public void visit(Code obj) { 69 if (getMethodName().equals("clone") && 70 getMethodSig().startsWith("()")) 71 super.visit(obj); 72 } 73 74 @Override 75 public void sawOpcode(int seen) { 76 if (seen == INVOKESPECIAL 77 && getNameConstantOperand().equals("clone") 78 && getSigConstantOperand().startsWith("()")) { 79 84 invokesSuperClone = true; 85 } 86 } 87 88 @Override 89 public void visit(JavaClass obj) { 90 implementsCloneableDirectly = false; 91 invokesSuperClone = false; 92 cloneOnlyThrowsException = false; 93 check = false; 95 isFinal = obj.isFinal(); 96 if (obj.isInterface()) return; 97 if (obj.isAbstract()) return; 98 String [] interface_names = obj.getInterfaceNames(); 100 for (String interface_name : interface_names) { 101 if (interface_name.equals("java.lang.Cloneable")) { 102 implementsCloneableDirectly = true; 103 break; 105 } 106 } 107 108 try { 109 JavaClass superClass = obj.getSuperClass(); 111 if (superClass != null && Repository.implementationOf(superClass, "java.lang.Cloneable")) 112 implementsCloneableDirectly = false; 113 } catch (ClassNotFoundException e) { 114 } 116 hasCloneMethod = false; 117 referencesCloneMethod = false; 118 check = true; 119 super.visit(obj); 120 } 121 122 @Override 123 public void visitAfter(JavaClass obj) { 124 if (!check) return; 125 if (cloneOnlyThrowsException) return; 126 if (implementsCloneableDirectly && !hasCloneMethod) { 127 if (!referencesCloneMethod) 128 bugReporter.reportBug(new BugInstance(this, "CN_IDIOM", NORMAL_PRIORITY) 129 .addClass(this)); 130 } 131 132 if (hasCloneMethod && !invokesSuperClone && !isFinal && obj.isPublic()) { 133 bugReporter.reportBug(new BugInstance(this, "CN_IDIOM_NO_SUPER_CALL", (obj.isPublic() || obj.isProtected()) ? 134 NORMAL_PRIORITY : LOW_PRIORITY) 135 .addClass(this) 136 .addMethod(cloneMethodAnnotation)); 137 } 138 139 146 } 147 148 @Override 149 public void visit(ConstantNameAndType obj) { 150 String methodName = obj.getName(getConstantPool()); 151 String methodSig = obj.getSignature(getConstantPool()); 152 if (!methodName.equals("clone")) return; 153 if (!methodSig.startsWith("()")) return; 154 referencesCloneMethod = true; 155 } 156 157 @Override 158 public void visit(Method obj) { 159 if (obj.isAbstract()) return; 160 if (!obj.isPublic()) return; 161 if (!getMethodName().equals("clone")) return; 162 if (!getMethodSig().startsWith("()")) return; 163 hasCloneMethod = true; 164 cloneMethodAnnotation = MethodAnnotation.fromVisitedMethod(this); 165 cloneOnlyThrowsException = 166 PruneUnconditionalExceptionThrowerEdges.doesMethodUnconditionallyThrowException(XFactory.createXMethod(this), getThisClass(), obj); 167 } 170 } 171 | Popular Tags |