Thread: [Fb-contrib-commit] fb-contrib/src/com/mebigfatguy/fbcontrib/detect ClassEnvy.java,1.2,1.3
Brought to you by:
dbrosius
From: Dave B. <dbr...@us...> - 2005-09-17 20:48:40
|
Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30146/src/com/mebigfatguy/fbcontrib/detect Modified Files: ClassEnvy.java Log Message: count field access for envy. up percentage to .90, fix finding the called method signature. Index: ClassEnvy.java =================================================================== RCS file: /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ClassEnvy.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- ClassEnvy.java 17 Sep 2005 04:44:50 -0000 1.2 +++ ClassEnvy.java 17 Sep 2005 20:48:31 -0000 1.3 @@ -22,6 +22,7 @@ import java.util.Iterator; import java.util.Map; +import org.apache.bcel.Repository; import org.apache.bcel.classfile.Code; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.generic.Type; @@ -41,9 +42,9 @@ private OpcodeStack stack; private String packageName; private String clsName; - private Map<String, Integer> clsMethodCount; - private int thisClsMethodCount; - private double envyPercent = 0.80; + private Map<String, Integer> clsAccessCount; + private int thisClsAccessCount; + private double envyPercent = 0.90; public ClassEnvy(BugReporter bugReporter) { this.bugReporter = bugReporter; @@ -71,21 +72,23 @@ public void visitCode(Code obj) { stack.resetForMethodEntry(this); - clsMethodCount = new HashMap<String, Integer>(); - thisClsMethodCount = 0; + clsAccessCount = new HashMap<String, Integer>(); + thisClsAccessCount = 0; super.visitCode(obj); String bestEnvy = null; - double bestPercent = -1.0; - Iterator<Map.Entry<String,Integer>> it = clsMethodCount.entrySet().iterator(); + double bestPercent = envyPercent; + Iterator<Map.Entry<String,Integer>> it = clsAccessCount.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String,Integer> entry = it.next(); + if (generalPurpose(entry.getKey())) + continue; Integer mc = entry.getValue(); if (mc.intValue() < 3) continue; - double percent = ((double)mc.intValue()) / ((double)(mc.intValue() + thisClsMethodCount)); + double percent = ((double)mc.intValue()) / ((double)(mc.intValue() + thisClsAccessCount)); if (percent > bestPercent) { bestPercent = percent; bestEnvy = entry.getKey(); @@ -112,40 +115,95 @@ return; if (seen == INVOKEINTERFACE) { - int parmCount = Type.getArgumentTypes(this.getMethodSig()).length; - try { - if (stack.getStackDepth() > parmCount) { - OpcodeStack.Item itm = stack.getStackItem(parmCount); - JavaClass jcls = itm.getJavaClass(); - if (jcls != null) - calledClass = itm.getJavaClass().getClassName(); - } - } catch (ClassNotFoundException cnfe) { - bugReporter.reportMissingClass(cnfe); - } - } - - String calledPackage = getPackageName(calledClass); - - if (calledClass.equals(clsName)) - thisClsMethodCount++; - else { - if (similarPackages(calledPackage, packageName, 2)) { - Integer cnt = clsMethodCount.get(calledClass); - if (cnt == null) { - cnt = new Integer(1); - clsMethodCount.put(calledClass, cnt); - } else { - clsMethodCount.put(calledClass, new Integer(cnt.intValue() + 1)); - } - } + int parmCount = Type.getArgumentTypes(this.getSigConstantOperand()).length; + if (!countClassAccess(parmCount)) + countClassAccess(calledClass); + } else { + countClassAccess(calledClass); } + } else if (seen == PUTFIELD) { + countClassAccess(1); + } else if (seen == GETFIELD) { + countClassAccess(0); } } finally { stack.sawOpcode(this, seen); } } + private boolean countClassAccess(int classAtStackIndex) { + String calledClass = null; + + try { + if (stack.getStackDepth() > classAtStackIndex) { + OpcodeStack.Item itm = stack.getStackItem(classAtStackIndex); + JavaClass cls = itm.getJavaClass(); + if (cls != null) + calledClass = cls.getClassName(); + else + return false; + } else + return false; + } catch (ClassNotFoundException cfne) { + bugReporter.reportMissingClass(cfne); + return false; + } + + countClassAccess(calledClass); + return true; + } + + private void countClassAccess(String calledClass) { + if (calledClass.equals(clsName)) + thisClsAccessCount++; + else { + String calledPackage = getPackageName(calledClass); + if (similarPackages(calledPackage, packageName, 2)) { + Integer cnt = clsAccessCount.get(calledClass); + if (cnt == null) { + cnt = new Integer(1); + clsAccessCount.put(calledClass, cnt); + } else { + clsAccessCount.put(calledClass, new Integer(cnt.intValue() + 1)); + } + } + } + } + + private boolean generalPurpose(String className) { + try { + JavaClass cls = Repository.lookupClass(className); + JavaClass[] infs = cls.getAllInterfaces(); + for (JavaClass inf : infs) { + String infName = inf.getClassName(); + if ("java.io.Serializable".equals(infName) + || "java.lang.Cloneable".equals(infName) + || "java.lang.Comparable".equals(infName) + || "java.lang.Runnable".equals(infName)) + continue; + if (infName.startsWith("java.lang.") + || infName.startsWith("javax.lang.")) + return true; + } + JavaClass[] sups = cls.getSuperClasses(); + for (JavaClass sup : sups) { + String supName = sup.getClassName(); + if ("java.lang.Object".equals(supName) + || "java.lang.Exception".equals(supName) + || "java.lang.RuntimeException".equals(supName) + || "java.lang.Throwable".equals(supName)) + continue; + if (supName.startsWith("java.lang.") + || supName.startsWith("javax.lang.")) + return true; + } + } catch (ClassNotFoundException cfne) { + bugReporter.reportMissingClass(cfne); + return true; + } + return false; + } + private String getPackageName(String className) { int dotPos = className.lastIndexOf("."); if (dotPos < 0) |