summaryrefslogtreecommitdiffstats
path: root/utils/analyzer/CmpRuns.py
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-08-15 20:02:54 +0000
committerdim <dim@FreeBSD.org>2012-08-15 20:02:54 +0000
commit554bcb69c2d785a011a30e7db87a36a87fe7db10 (patch)
tree9abb1a658a297776086f4e0dfa6ca533de02104e /utils/analyzer/CmpRuns.py
parentbb67ca86b31f67faee50bd10c3b036d65751745a (diff)
downloadFreeBSD-src-554bcb69c2d785a011a30e7db87a36a87fe7db10.zip
FreeBSD-src-554bcb69c2d785a011a30e7db87a36a87fe7db10.tar.gz
Vendor import of clang trunk r161861:
http://llvm.org/svn/llvm-project/cfe/trunk@161861
Diffstat (limited to 'utils/analyzer/CmpRuns.py')
-rwxr-xr-xutils/analyzer/CmpRuns.py135
1 files changed, 85 insertions, 50 deletions
diff --git a/utils/analyzer/CmpRuns.py b/utils/analyzer/CmpRuns.py
index e68c45df..f2961cf 100755
--- a/utils/analyzer/CmpRuns.py
+++ b/utils/analyzer/CmpRuns.py
@@ -11,12 +11,67 @@ two perspectives:
2. For use by end users who want to integrate regular static analyzer testing
into a buildbot like environment.
+
+Usage:
+
+ # Load the results of both runs, to obtain lists of the corresponding
+ # AnalysisDiagnostic objects.
+ #
+ # root - the name of the root directory, which will be disregarded when
+ # determining the source file name
+ #
+ resultsA = loadResults(dirA, opts, root, deleteEmpty)
+ resultsB = loadResults(dirB, opts, root, deleteEmpty)
+
+ # Generate a relation from diagnostics in run A to diagnostics in run B
+ # to obtain a list of triples (a, b, confidence).
+ diff = compareResults(resultsA, resultsB)
+
"""
import os
import plistlib
#
+class AnalysisDiagnostic:
+ def __init__(self, data, report, htmlReport):
+ self._data = data
+ self._loc = self._data['location']
+ self._report = report
+ self._htmlReport = htmlReport
+
+ def getFileName(self):
+ return self._report.run.getSourceName(self._report.files[self._loc['file']])
+
+ def getLine(self):
+ return self._loc['line']
+
+ def getColumn(self):
+ return self._loc['col']
+
+ def getCategory(self):
+ return self._data['category']
+
+ def getDescription(self):
+ return self._data['description']
+
+ def getIssueIdentifier(self) :
+ id = ''
+ if 'issue_context' in self._data :
+ id += self._data['issue_context'] + ":"
+ if 'issue_hash' in self._data :
+ id += str(self._data['issue_hash']) + ":"
+ return id + ":" + self.getFileName()
+
+ def getReport(self):
+ if self._htmlReport is None:
+ return " "
+ return os.path.join(self._report.run.path, self._htmlReport)
+
+ def getReadableName(self):
+ return '%s:%d:%d, %s: %s' % (self.getFileName(), self.getLine(),
+ self.getColumn(), self.getCategory(),
+ self.getDescription())
class multidict:
def __init__(self, elts=()):
@@ -45,8 +100,9 @@ class multidict:
#
class CmpOptions:
- def __init__(self, verboseLog=None, root=""):
- self.root = root
+ def __init__(self, verboseLog=None, rootA="", rootB=""):
+ self.rootA = rootA
+ self.rootB = rootB
self.verboseLog = verboseLog
class AnalysisReport:
@@ -54,49 +110,22 @@ class AnalysisReport:
self.run = run
self.files = files
-class AnalysisDiagnostic:
- def __init__(self, data, report, htmlReport):
- self.data = data
- self.report = report
- self.htmlReport = htmlReport
-
- def getReadableName(self):
- loc = self.data['location']
- filename = self.report.run.getSourceName(self.report.files[loc['file']])
- line = loc['line']
- column = loc['col']
- category = self.data['category']
- description = self.data['description']
-
- # FIXME: Get a report number based on this key, to 'distinguish'
- # reports, or something.
-
- return '%s:%d:%d, %s: %s' % (filename, line, column, category,
- description)
-
- def getReportData(self):
- if self.htmlReport is None:
- return " "
- return os.path.join(self.report.run.path, self.htmlReport)
- # We could also dump the report with:
- # return open(os.path.join(self.report.run.path,
- # self.htmlReport), "rb").read()
-
class AnalysisRun:
- def __init__(self, path, opts):
+ def __init__(self, path, root, opts):
self.path = path
+ self.root = root
self.reports = []
self.diagnostics = []
self.opts = opts
def getSourceName(self, path):
- if path.startswith(self.opts.root):
- return path[len(self.opts.root):]
+ if path.startswith(self.root):
+ return path[len(self.root):]
return path
-def loadResults(path, opts, deleteEmpty=True):
- run = AnalysisRun(path, opts)
-
+def loadResults(path, opts, root = "", deleteEmpty=True):
+ run = AnalysisRun(path, root, opts)
+
for f in os.listdir(path):
if (not f.startswith('report') or
not f.endswith('plist')):
@@ -134,6 +163,9 @@ def loadResults(path, opts, deleteEmpty=True):
return run
+def cmpAnalysisDiagnostic(d) :
+ return d.getIssueIdentifier()
+
def compareResults(A, B):
"""
compareResults - Generate a relation from diagnostics in run A to
@@ -152,14 +184,14 @@ def compareResults(A, B):
neqB = []
eltsA = list(A.diagnostics)
eltsB = list(B.diagnostics)
- eltsA.sort(key = lambda d: d.data)
- eltsB.sort(key = lambda d: d.data)
+ eltsA.sort(key = cmpAnalysisDiagnostic)
+ eltsB.sort(key = cmpAnalysisDiagnostic)
while eltsA and eltsB:
a = eltsA.pop()
b = eltsB.pop()
- if a.data['location'] == b.data['location']:
+ if (a.getIssueIdentifier() == b.getIssueIdentifier()) :
res.append((a, b, 0))
- elif a.data > b.data:
+ elif a._data > b._data:
neqA.append(a)
eltsB.append(b)
else:
@@ -181,10 +213,10 @@ def compareResults(A, B):
return res
-def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True):
+def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True):
# Load the run results.
- resultsA = loadResults(dirA, opts, deleteEmpty)
- resultsB = loadResults(dirB, opts, deleteEmpty)
+ resultsA = loadResults(dirA, opts, opts.rootA, deleteEmpty)
+ resultsB = loadResults(dirB, opts, opts.rootB, deleteEmpty)
# Open the verbose log, if given.
if opts.verboseLog:
@@ -201,13 +233,13 @@ def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True):
foundDiffs += 1
if auxLog:
print >>auxLog, ("('ADDED', %r, %r)" % (b.getReadableName(),
- b.getReportData()))
+ b.getReport()))
elif b is None:
print "REMOVED: %r" % a.getReadableName()
foundDiffs += 1
if auxLog:
print >>auxLog, ("('REMOVED', %r, %r)" % (a.getReadableName(),
- a.getReportData()))
+ a.getReport()))
elif confidence:
print "CHANGED: %r to %r" % (a.getReadableName(),
b.getReadableName())
@@ -216,8 +248,8 @@ def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True):
print >>auxLog, ("('CHANGED', %r, %r, %r, %r)"
% (a.getReadableName(),
b.getReadableName(),
- a.getReportData(),
- b.getReportData()))
+ a.getReport(),
+ b.getReport()))
else:
pass
@@ -233,8 +265,11 @@ def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True):
def main():
from optparse import OptionParser
parser = OptionParser("usage: %prog [options] [dir A] [dir B]")
- parser.add_option("", "--root", dest="root",
- help="Prefix to ignore on source files",
+ parser.add_option("", "--rootA", dest="rootA",
+ help="Prefix to ignore on source files for directory A",
+ action="store", type=str, default="")
+ parser.add_option("", "--rootB", dest="rootB",
+ help="Prefix to ignore on source files for directory B",
action="store", type=str, default="")
parser.add_option("", "--verbose-log", dest="verboseLog",
help="Write additional information to LOG [default=None]",
@@ -247,7 +282,7 @@ def main():
dirA,dirB = args
- cmpScanBuildResults(dirA, dirB, opts)
+ dumpScanBuildResultsDiff(dirA, dirB, opts)
if __name__ == '__main__':
main()
OpenPOWER on IntegriCloud