X-Git-Url: http://jaekl.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=prod%2Fnet%2Fjaekl%2Fcfb%2Fxml%2FBugInstance.java;h=0683a7d23c83dd1437b08ebe77bd545d01a830f4;hb=769f0f2e9b90516e68246b551a4c68f953018c72;hp=100251f9e9a37fce9235b30beb1492ebec24adc3;hpb=358d80a86ac7c79cd57b81a4f1708da80db2f0ec;p=cfb.git diff --git a/prod/net/jaekl/cfb/xml/BugInstance.java b/prod/net/jaekl/cfb/xml/BugInstance.java index 100251f..0683a7d 100644 --- a/prod/net/jaekl/cfb/xml/BugInstance.java +++ b/prod/net/jaekl/cfb/xml/BugInstance.java @@ -2,11 +2,13 @@ package net.jaekl.cfb.xml; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import org.xml.sax.Attributes; +import net.jaekl.cfb.store.Location; import net.jaekl.cfb.util.Util; import net.jaekl.qd.xml.MissingAttributeException; import net.jaekl.qd.xml.ParseResult; @@ -23,35 +25,63 @@ public class BugInstance extends ParseResult { static final String CATEGORY = "category"; static final String TYPE = "type"; + Long m_id; String m_category; String m_type; ArrayList m_classes; ArrayList m_methods; ArrayList m_locals; ArrayList m_lines; + ArrayList m_locations; public BugInstance() { super(TAG, INTERNAL, EXTERNAL); + m_id = null; m_category = m_type = null; m_classes = new ArrayList(); m_methods = new ArrayList(); m_locals = new ArrayList(); m_lines = new ArrayList(); + m_locations = new ArrayList(); + } + + public BugInstance(Long id, + String category, + String type, + Location[] locations, + LocalVariable[] variables) + { + super(TAG, INTERNAL, EXTERNAL); + + m_id = id; + m_category = category; + m_type = type; + + m_classes = new ArrayList(); + m_methods = new ArrayList(); + m_lines = new ArrayList(); + + m_locations = new ArrayList(Arrays.asList(locations)); + m_locals = new ArrayList(Arrays.asList(variables)); } public String getCategory() { return m_category; } public String getType() { return m_type; } - public List getClasses() { return Collections.unmodifiableList(m_classes); } - public List getMethods() { return Collections.unmodifiableList(m_methods); } - public List getLines() { return Collections.unmodifiableList(m_lines); } public List getVariables() { return Collections.unmodifiableList(m_locals); } + public List getLocations() { return Collections.unmodifiableList(m_locations); } @Override public void endContents(String uri, String localName, String qName, String chars) throws XmlParseException { - // no-op + // no operation + } + + @Override + public void complete() + { + computeLocations(); } @Override @@ -110,11 +140,18 @@ public class BugInstance extends ParseResult { bm.dump(pw, childIndent); } for (LocalVariable lv : m_locals) { - lv.dump(pw, childIndent); + if (null != lv) { + lv.dump(pw, childIndent); + } } 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. @@ -144,24 +181,17 @@ public class BugInstance extends ParseResult { return false; } - BugMethod thisMethod = this.getPrincipalMethod(); - BugMethod thatMethod = that.getPrincipalMethod(); - if (null == thisMethod) { - if (null == thatMethod) { + Location thisLoc = this.getPrincipalLocation(); + Location thatLoc = that.getPrincipalLocation(); + if (null == thisLoc) { + if (null == thatLoc) { return false; } } else { - if (! Util.objsAreEqual(thisMethod.getClassName(), thatMethod.getClassName())) { + if (! thisLoc.fuzzyEquals(thatLoc)) { return false; } - if (! Util.objsAreEqual(thisMethod.getMethodName(), thatMethod.getMethodName())) { - return false; - } - } - - if (! Util.objsAreEqual(this.getVariables(), that.getVariables())) { - return false; } return true; @@ -173,20 +203,77 @@ public class BugInstance extends ParseResult { public int hashCode() { int code = Util.objHashCode(m_type) - * Util.objHashCode(m_category) - * Util.objHashCode(getPrincipalMethod()) - * Util.objHashCode(getVariables()); + ^ Util.objHashCode(m_category) + ^ Util.objHashCode(getPrincipalLocation()); return code; } - // Get the "principal" method. + // Get the "principal" Location. // This should be the place where the bug is reported. - BugMethod getPrincipalMethod() + Location getPrincipalLocation() + { + if (null != m_locations && m_locations.size() > 0) { + return m_locations.get(0); + } + return null; + } + + private void computeLocations() { - List bugMethods = getMethods(); - if ((null == bugMethods) || (0 == bugMethods.size())) { - return null; + assert(null != m_classes); + assert(null != m_methods); + assert(null != m_lines); + + m_locations.clear(); + + /* + Somewhat unfortunate special case. + The primary "location" for a bug instance is split between tags. + Most bugs have a pattern like this: + + ... + + + + ... + + + + The primary location for a bug is given by the with no role attribute, + but the inside that method describes the whole range of lines + covered by that Method, not the spot where the bug is located--that is given + by the that is a direct child fo the . + */ + + BugMethod primaryMethod = null; + SourceLine primaryLine = null; + + for (BugMethod method : m_methods) { + if (null != method.getRole()) { + primaryMethod = method; + break; + } + } + if (m_lines.size() > 0) { + primaryLine = m_lines.get(0); + } + + if ((null != primaryMethod) && (null != primaryLine)) { + m_locations.add(new Location(primaryMethod, primaryLine)); + } + + for (BugMethod method : m_methods) { + if (primaryMethod != method) { + m_locations.add(new Location(method)); + } + } + for (SourceLine line : m_lines) { + if (primaryLine != line) { + m_locations.add(new Location(line)); + } + } + for (BugClass clazz : m_classes) { + m_locations.add(new Location(clazz)); } - return bugMethods.get(0); } }