adds support for fields as well as local variables.
[cfb.git] / prod / net / jaekl / cfb / xml / BugInstance.java
index 96a815e5aaa41089beafd6599878a83d0e922e3a..9e0395fd0334b1863c02abf5560dc6bddba7d011 100644 (file)
@@ -18,10 +18,11 @@ public class BugInstance extends ParseResult {
 
        static final String TAG = "BugInstance";
        static final String[] INTERNAL = {  };
-       static final Object[][] EXTERNAL = { { BugClass.TAG, BugClass.class},
-                                                { BugMethod.TAG, BugMethod.class},
-                                                { LocalVariable.TAG, LocalVariable.class},
-                                                { SourceLine.TAG, SourceLine.class} };
+       static final Object[][] EXTERNAL = { { BugClass.TAG, BugClass.class },
+                                                { BugMethod.TAG, BugMethod.class },
+                                                { Field.TAG, Field.class },
+                                                { LocalVariable.TAG, LocalVariable.class },
+                                                { SourceLine.TAG, SourceLine.class } };
        static final String CATEGORY = "category";
        static final String TYPE = "type";
 
@@ -30,7 +31,7 @@ public class BugInstance extends ParseResult {
        String m_type;
        ArrayList<BugClass> m_classes;
        ArrayList<BugMethod> m_methods;
-       ArrayList<LocalVariable> m_locals;
+       ArrayList<Variable> m_vars;
        ArrayList<SourceLine> m_lines;
        ArrayList<Location> m_locations;
        
@@ -41,7 +42,7 @@ public class BugInstance extends ParseResult {
                m_category = m_type = null;
                m_classes = new ArrayList<BugClass>();
                m_methods = new ArrayList<BugMethod>();
-               m_locals = new ArrayList<LocalVariable>();
+               m_vars = new ArrayList<Variable>();
                m_lines = new ArrayList<SourceLine>();
                m_locations = new ArrayList<Location>();
        }
@@ -50,23 +51,25 @@ public class BugInstance extends ParseResult {
                                   String category, 
                                   String type,
                                   Location[] locations,
-                                  LocalVariable[] variables)
+                                  Variable[] variables)
        {
                super(TAG, INTERNAL, EXTERNAL);
                
                m_id = id;
                m_category = category;
                m_type = type;
-               m_classes = null;
-               m_methods = null;
-               m_lines = null;
+               
+               m_classes = new ArrayList<BugClass>();
+               m_methods = new ArrayList<BugMethod>();
+               m_lines = new ArrayList<SourceLine>();
+
                m_locations = new ArrayList<Location>(Arrays.asList(locations));
-               m_locals = new ArrayList<LocalVariable>(Arrays.asList(variables));
+               m_vars = new ArrayList<Variable>(Arrays.asList(variables));
        }
        
        public String getCategory() { return m_category; }
        public String getType() { return m_type; }
-       public List<LocalVariable> getVariables() { return Collections.unmodifiableList(m_locals); }
+       public List<Variable> getVariables() { return Collections.unmodifiableList(m_vars); }
        public List<Location> getLocations() { return Collections.unmodifiableList(m_locations); }
        
        @Override
@@ -100,11 +103,18 @@ public class BugInstance extends ParseResult {
                                m_methods.add((BugMethod)pr);
                        }                       
                }
+               else if (Field.TAG.equals(localName)) {
+                       ParseResult[] collected = collectParsedChildren(Field.class);
+                       for (ParseResult pr : collected) {
+                               assert(pr instanceof Field);
+                               m_vars.add((Field)pr);
+                       }                                               
+               }
                else if (LocalVariable.TAG.equals(localName)) {
                        ParseResult[] collected = collectParsedChildren(LocalVariable.class);
                        for (ParseResult pr : collected) {
                                assert(pr instanceof LocalVariable);
-                               m_locals.add((LocalVariable)pr);
+                               m_vars.add((LocalVariable)pr);
                        }                       
                }
                else if (SourceLine.TAG.equals(localName)) {
@@ -137,12 +147,17 @@ public class BugInstance extends ParseResult {
                for (BugMethod bm : m_methods) {
                        bm.dump(pw, childIndent);
                }
-               for (LocalVariable lv : m_locals) {
-                       lv.dump(pw, childIndent);
+               for (Variable var : m_vars) {
+                       pw.println(margin + "  " + var.getDescription());
                }
                for (SourceLine sl : m_lines) {
                        sl.dump(pw, childIndent);
                }
+               for (Location loc : m_locations) {
+                       if (null != loc) {
+                               loc.dump(pw, childIndent);
+                       }
+               }
        }
        
        // Note that this is a heuristic, "fuzzy", equals.
@@ -180,16 +195,9 @@ public class BugInstance extends ParseResult {
                                }
                        }
                        else {
-                               if (! Util.objsAreEqual(thisLoc.getClassName(), thatLoc.getClassName())) {
+                               if (! thisLoc.fuzzyEquals(thatLoc)) {
                                        return false;
                                }
-                               if (! Util.objsAreEqual(thisLoc.getMethodName(), thatLoc.getMethodName())) {
-                                       return false;
-                               }
-                       }
-                       
-                       if (! Util.objsAreEqual(this.getVariables(), that.getVariables())) {
-                               return false;
                        }
                        
                        return true;
@@ -201,9 +209,8 @@ public class BugInstance extends ParseResult {
        public int hashCode() 
        {
                int code = Util.objHashCode(m_type)
-                                * Util.objHashCode(m_category)
-                                * Util.objHashCode(getPrincipalLocation())
-                                * Util.objHashCode(getVariables());
+                                ^ Util.objHashCode(m_category)
+                                ^ Util.objHashCode(getPrincipalLocation());
                return code;
        }
        
@@ -211,9 +218,21 @@ public class BugInstance extends ParseResult {
        // This should be the place where the bug is reported.
        Location getPrincipalLocation()
        {
-               if (null != m_locations && m_locations.size() > 0) {
-                       return m_locations.get(0);
+               if (null == m_locations) {
+                       return null;
                }
+               
+               for (int idx = 0; idx < m_locations.size(); ++idx) {
+                       Location loc = m_locations.get(idx);
+                       if (Location.METHOD_CALLED.equals(loc.getMethodRole())) {
+                               // METHOD_CALLED locations describe the method that is being called,
+                               // but the bug is located in the caller, not in the callee.
+                               // Thus, ignore this information about the callee.
+                               continue;
+                       }
+                       return loc;
+               }
+               
                return null;
        }