From 9635991f7480e1b82f897948cf8adf56537c1818 Mon Sep 17 00:00:00 2001 From: Chris Jaekl Date: Sun, 27 Sep 2015 22:06:25 +0900 Subject: [PATCH] Add local variable information to DB store. --- prod/net/jaekl/cfb/analyze/Analyzer.java | 2 + prod/net/jaekl/cfb/db/CfbSchema.java | 52 ++++++---- prod/net/jaekl/cfb/db/Condition.java | 10 ++ prod/net/jaekl/cfb/store/DbStore.java | 121 +++++++++++++++++++++- prod/net/jaekl/cfb/store/Location.java | 12 +++ prod/net/jaekl/cfb/xml/BugInstance.java | 1 + prod/net/jaekl/cfb/xml/BugMethod.java | 1 + prod/net/jaekl/cfb/xml/LocalVariable.java | 3 + 8 files changed, 177 insertions(+), 25 deletions(-) diff --git a/prod/net/jaekl/cfb/analyze/Analyzer.java b/prod/net/jaekl/cfb/analyze/Analyzer.java index 22d65ed..1ac5677 100644 --- a/prod/net/jaekl/cfb/analyze/Analyzer.java +++ b/prod/net/jaekl/cfb/analyze/Analyzer.java @@ -34,6 +34,8 @@ public class Analyzer { pw.println(cmdLine); pw.flush(); Command.Result fbResult = new Command().exec(cmdLine); + pw.println("==> " + fbResult.getRetCode()); + pw.flush(); if (0 != fbResult.getRetCode()) { // Our attempt to execute FindBugs failed. // Report the error and return null. diff --git a/prod/net/jaekl/cfb/db/CfbSchema.java b/prod/net/jaekl/cfb/db/CfbSchema.java index 49adde6..9a6cc3b 100644 --- a/prod/net/jaekl/cfb/db/CfbSchema.java +++ b/prod/net/jaekl/cfb/db/CfbSchema.java @@ -23,43 +23,52 @@ public class CfbSchema extends Schema { public static final Sequence FOUND_SEQ = new Sequence("FOUND_SEQ"); public static final Sequence LOC_SEQ = new Sequence("LOC_SEQ"); public static final Sequence RUN_SEQ = new Sequence("RUN_SEQ"); + public static final Sequence VARIABLE_SEQ = new Sequence("VARIABLE_SEQ"); - public static final Column BUGID = new Column("BUGID", INTEGER, -1, NOT_NULL); - public static final Column CATEGORY = new Column("CATEGORY", VARCHAR, 80, NOT_NULL); - public static final Column CATEGORYID = new Column("CATEGORYID", INTEGER, -1, NOT_NULL); - public static final Column CLASSNAME = new Column("CLASSNAME", VARCHAR, 256, NOT_NULL); - public static final Column ENDLINE = new Column("ENDLINE", INTEGER, -1, NULL); - public static final Column ENDTIME = new Column("ENDTIME", TIMESTAMPTZ, -1, NOT_NULL); - public static final Column FIRSTLOCID = new Column("FIRSTLOCID", INTEGER, -1, NOT_NULL); - public static final Column FOUNDID = new Column("FOUNDID", INTEGER, -1, NOT_NULL); - public static final Column LOCID = new Column("LOCID", INTEGER, -1, NOT_NULL); - public static final Column METHODNAME = new Column("METHODNAME", VARCHAR, 256, NULL); - public static final Column RUNID = new Column("RUNID", INTEGER, -1, NOT_NULL); - public static final Column SECONDLOCID = new Column("SECONDLOCID", INTEGER, -1, NULL); - public static final Column STARTLINE = new Column("STARTLINE", INTEGER, -1, NULL); - public static final Column STARTTIME = new Column("STARTTIME", TIMESTAMPTZ, -1, NOT_NULL); - public static final Column THIRDLOCID = new Column("THIRDLOCID", INTEGER, -1, NULL); - public static final Column TYPE = new Column("TYPE", VARCHAR, 80, NOT_NULL ); - public static final Column VERSION = new Column("VERSION", VARCHAR, 32, NULL); + public static final Column BUGID = new Column("BUGID", INTEGER, -1, NOT_NULL); + public static final Column CATEGORY = new Column("CATEGORY", VARCHAR, 80, NOT_NULL); + public static final Column CATEGORYID = new Column("CATEGORYID", INTEGER, -1, NOT_NULL); + public static final Column CLASSNAME = new Column("CLASSNAME", VARCHAR, 256, NOT_NULL); + public static final Column ENDLINE = new Column("ENDLINE", INTEGER, -1, NULL); + public static final Column ENDTIME = new Column("ENDTIME", TIMESTAMPTZ, -1, NOT_NULL); + public static final Column FIRSTLOCID = new Column("FIRSTLOCID", INTEGER, -1, NOT_NULL); + public static final Column FOUNDID = new Column("FOUNDID", INTEGER, -1, NOT_NULL); + public static final Column LOCID = new Column("LOCID", INTEGER, -1, NOT_NULL); + public static final Column METHODNAME = new Column("METHODNAME", VARCHAR, 256, NULL); + public static final Column METHODROLE = new Column("METHODROLE", VARCHAR, 80, NULL); + public static final Column NAME = new Column("NAME", VARCHAR, 256, NOT_NULL); + public static final Column RUNID = new Column("RUNID", INTEGER, -1, NOT_NULL); + public static final Column SECONDLOCID = new Column("SECONDLOCID", INTEGER, -1, NULL); + public static final Column STARTLINE = new Column("STARTLINE", INTEGER, -1, NULL); + public static final Column STARTTIME = new Column("STARTTIME", TIMESTAMPTZ, -1, NOT_NULL); + public static final Column THIRDLOCID = new Column("THIRDLOCID", INTEGER, -1, NULL); + public static final Column TYPE = new Column("TYPE", VARCHAR, 80, NOT_NULL); + public static final Column VARID_FK = new Column("VARID", INTEGER, -1, NULL); // foreign key + public static final Column VARID_PK = new Column("VARID", INTEGER, -1, NOT_NULL); // primary key + public static final Column VARROLE = new Column("VARROLE", VARCHAR, 80, NOT_NULL); + public static final Column VERSION = new Column("VERSION", VARCHAR, 32, NULL); private static final Column[] BUGS_COLS = { BUGID, TYPE }; private static final Column[] CATEGORIES_COLS = { CATEGORYID, CATEGORY }; - private static final Column[] FOUND_COLS = { FOUNDID, BUGID, CATEGORYID, FIRSTLOCID, SECONDLOCID, THIRDLOCID }; - private static final Column[] LOCATIONS_COLS = { LOCID, CLASSNAME, METHODNAME, STARTLINE, ENDLINE }; + private static final Column[] FOUND_COLS = { FOUNDID, BUGID, CATEGORYID, FIRSTLOCID, SECONDLOCID, THIRDLOCID, VARID_FK }; + private static final Column[] LOCATIONS_COLS = { LOCID, CLASSNAME, METHODNAME, METHODROLE, STARTLINE, ENDLINE }; private static final Column[] RUNS_COLS = { RUNID, VERSION, STARTTIME, ENDTIME }; + private static final Column[] VARIABLES_COLS = { VARID_PK, NAME, VARROLE }; public static final Table BUGS = new Table("BUGS", BUGS_COLS); public static final Table CATEGORIES = new Table("CATEGORIES", CATEGORIES_COLS); public static final Table FOUND = new Table("FOUND", FOUND_COLS); public static final Table LOCATIONS = new Table("LOCATIONS", LOCATIONS_COLS); public static final Table RUNS = new Table("RUNS", RUNS_COLS); + public static final Table VARIABLES = new Table("VARIABLES", VARIABLES_COLS); private static final Sequence[] SEQUENCES = { BUG_SEQ, CATEGORY_SEQ, FOUND_SEQ, LOC_SEQ, - RUN_SEQ + RUN_SEQ, + VARIABLE_SEQ }; private static final Table[] TABLES = { @@ -67,7 +76,8 @@ public class CfbSchema extends Schema { CATEGORIES, FOUND, LOCATIONS, - RUNS + RUNS, + VARIABLES }; public CfbSchema(DbDriver driver) { diff --git a/prod/net/jaekl/cfb/db/Condition.java b/prod/net/jaekl/cfb/db/Condition.java index b221551..98bd5f2 100644 --- a/prod/net/jaekl/cfb/db/Condition.java +++ b/prod/net/jaekl/cfb/db/Condition.java @@ -11,12 +11,22 @@ public class Condition { m_column = column; m_value = value; m_operation = operation; + + if ((null == m_value) && (Operation.EQUAL == m_operation)) { + m_operation = Operation.NULL; + } } public Condition(Column column, Object value) { this(column, value, Operation.EQUAL); } + public Condition(Column column, Operation operation) { + this(column, null, operation); + + assert(Operation.NULL == operation || Operation.NOT_NULL == operation); + } + public Column getColumn() { return m_column; } public Object getValue() { return m_value; } public Operation getOperation() { return m_operation; } diff --git a/prod/net/jaekl/cfb/store/DbStore.java b/prod/net/jaekl/cfb/store/DbStore.java index 6e17cff..315ade5 100644 --- a/prod/net/jaekl/cfb/store/DbStore.java +++ b/prod/net/jaekl/cfb/store/DbStore.java @@ -17,6 +17,7 @@ import net.jaekl.cfb.db.driver.DbDriver; import net.jaekl.cfb.xml.BugClass; import net.jaekl.cfb.xml.BugInstance; import net.jaekl.cfb.xml.BugMethod; +import net.jaekl.cfb.xml.LocalVariable; import net.jaekl.cfb.xml.SourceLine; import net.jaekl.cfb.xml.messages.MessageCollection; @@ -76,6 +77,7 @@ public class DbStore { values[row][3] = getLocId(firstLoc); values[row][4] = getLocId(secondLoc); values[row][5] = getLocId(thirdLoc); + values[row][6] = getVarId(bug); row++; } @@ -87,11 +89,51 @@ public class DbStore { { ArrayList locs = new ArrayList(); - for (SourceLine line : bug.getLines()) { - locs.add(new Location(line)); + /* + 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 : bug.getMethods()) { + if (null != method.getRole()) { + primaryMethod = method; + break; + } + } + if (bug.getLines().size() > 0) { + primaryLine = bug.getLines().get(0); + } + + if ((null != primaryMethod) && (null != primaryLine)) { + locs.add(new Location(primaryMethod, primaryLine)); } + for (BugMethod method : bug.getMethods()) { - locs.add(new Location(method)); + if (primaryMethod != method) { + locs.add(new Location(method)); + } + } + for (SourceLine line : bug.getLines()) { + if (primaryLine != line) { + locs.add(new Location(line)); + } } for (BugClass clazz : bug.getClasses()) { locs.add(new Location(clazz)); @@ -117,9 +159,11 @@ public class DbStore { { Column[] columns = { CfbSchema.LOCID }; Table[] tables = { CfbSchema.LOCATIONS }; + Condition[] conditions = { new Condition( CfbSchema.CLASSNAME, loc.getClassName(), Operation.EQUAL ), new Condition( CfbSchema.METHODNAME, loc.getMethodName(), Operation.EQUAL ), + new Condition( CfbSchema.METHODROLE, loc.getMethodRole(), Operation.EQUAL ), new Condition( CfbSchema.STARTLINE, loc.getStart(), Operation.EQUAL ), new Condition( CfbSchema.ENDLINE, loc.getEnd(), Operation.EQUAL ) }; @@ -141,11 +185,80 @@ public class DbStore { Long.valueOf(locId), loc.getClassName(), loc.getMethodName(), + loc.getMethodRole(), Long.valueOf(loc.getStart()), Long.valueOf(loc.getEnd()) } }; - m_driver.insert(m_con, CfbSchema.LOCATIONS, values); + int count = m_driver.insert(m_con, CfbSchema.LOCATIONS, values); + if (1 != count) { + return null; + } return Long.valueOf(locId); } + + Long getVarId(BugInstance bug) throws SQLException, TypeMismatchException + { + if (null == bug) { + return null; + } + + List vars = bug.getVariables(); + if ((null == vars) || (0 == vars.size())) { + return null; + } + + return getVarId(vars.get(0)); + } + + Long getVarId(LocalVariable var) throws SQLException, TypeMismatchException + { + if (null == var) { + return null; + } + + Long result = findVarId(var); + + if (null != result) { + return result; + } + + return storeVar(var); + } + + Long findVarId(LocalVariable var) throws SQLException, TypeMismatchException + { + Column[] columns = { CfbSchema.VARID_PK }; + Table[] tables = { CfbSchema.VARIABLES }; + + Condition[] conditions = { + new Condition( CfbSchema.NAME, var.getName(), Operation.EQUAL ), + new Condition( CfbSchema.VARROLE, var.getRole(), Operation.EQUAL ) + }; + List rows = m_driver.select(m_con, columns, tables, conditions); + if (rows.size() > 0) { + assert(1 == rows.size()); // should only have one match + + return rows.get(0).getLong(0); + } + + return null; // not found + } + + Long storeVar(LocalVariable var) throws SQLException + { + long varId = m_driver.nextVal(m_con, CfbSchema.VARIABLE_SEQ); + + Object[][] values = { { + Long.valueOf(varId), + var.getName(), + var.getRole() + } }; + int count = m_driver.insert(m_con, CfbSchema.VARIABLES, values); + if (1 != count) { + return null; + } + + return Long.valueOf(varId); + } } diff --git a/prod/net/jaekl/cfb/store/Location.java b/prod/net/jaekl/cfb/store/Location.java index 2cd91c8..1ffc732 100644 --- a/prod/net/jaekl/cfb/store/Location.java +++ b/prod/net/jaekl/cfb/store/Location.java @@ -7,6 +7,7 @@ import net.jaekl.cfb.xml.SourceLine; public class Location { String m_className; String m_methodName; + String m_methodRole; int m_startLine; int m_endLine; @@ -20,6 +21,15 @@ public class Location { init(method.getSourceLines()); m_className = method.getClassName(); m_methodName = method.getMethodName(); + m_methodRole = method.getRole(); + } + + public Location(BugMethod method, SourceLine sourceLine) + { + init(sourceLine); + m_className = method.getClassName(); + m_methodName = method.getMethodName(); + m_methodRole = method.getRole(); } public Location(BugClass bugClass) @@ -30,6 +40,7 @@ public class Location { public String getClassName() { return m_className; } public String getMethodName() { return m_methodName; } + public String getMethodRole() { return m_methodRole; } public int getStart() { return m_startLine; } public int getEnd() { return m_endLine; } @@ -45,6 +56,7 @@ public class Location { { m_className = sourceLine.getClassName(); m_methodName = null; + m_methodRole = null; m_startLine = sourceLine.getStart(); m_endLine = sourceLine.getEnd(); } diff --git a/prod/net/jaekl/cfb/xml/BugInstance.java b/prod/net/jaekl/cfb/xml/BugInstance.java index 4c78f8d..3386e3f 100644 --- a/prod/net/jaekl/cfb/xml/BugInstance.java +++ b/prod/net/jaekl/cfb/xml/BugInstance.java @@ -44,6 +44,7 @@ public class BugInstance extends ParseResult { 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); } @Override public void endContents(String uri, String localName, String qName, String chars) diff --git a/prod/net/jaekl/cfb/xml/BugMethod.java b/prod/net/jaekl/cfb/xml/BugMethod.java index 33c615a..4e5fc47 100644 --- a/prod/net/jaekl/cfb/xml/BugMethod.java +++ b/prod/net/jaekl/cfb/xml/BugMethod.java @@ -39,6 +39,7 @@ public class BugMethod extends ParseResult { public String getClassName() { return m_className; } public String getMethodName() { return m_methodName; } + public String getRole() { return m_role; } public SourceLine[] getSourceLines() { return m_sourceLines.toArray(new SourceLine[m_sourceLines.size()]); } @Override diff --git a/prod/net/jaekl/cfb/xml/LocalVariable.java b/prod/net/jaekl/cfb/xml/LocalVariable.java index fb19868..a4d26d8 100644 --- a/prod/net/jaekl/cfb/xml/LocalVariable.java +++ b/prod/net/jaekl/cfb/xml/LocalVariable.java @@ -26,6 +26,9 @@ public class LocalVariable extends ParseResult { m_name = m_role = null; } + public String getName() { return m_name; } + public String getRole() { return m_role; } + @Override public void handleMainAttributes(Attributes attr) throws MissingAttributeException -- 2.39.2