From 7ebe0ed4443428b47f04f97c86c78c1ba775cedb Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 25 Sep 2008 06:05:31 +0000 Subject: [PATCH] Add link to report analyzer failures (parse errors, asserts, etc). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56606 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/scan-view/ScanView.py | 247 +++++++++++++++++++++++++++++------- utils/scan-build | 2 +- 2 files changed, 203 insertions(+), 46 deletions(-) diff --git a/tools/scan-view/ScanView.py b/tools/scan-view/ScanView.py index 2e06f2a8fb..98745eaa07 100644 --- a/tools/scan-view/ScanView.py +++ b/tools/scan-view/ScanView.py @@ -10,6 +10,7 @@ import shutil import threading import time import socket +import itertools import Reporter import ConfigParser @@ -21,6 +22,11 @@ kReportFileRE = re.compile('(.*/)?report-(.*)\\.html') kBugKeyValueRE = re.compile('') +# + +kReportCrashEntryRE = re.compile('') +kReportCrashEntryKeyValueRE = re.compile(' ?([^=]+)="(.*?)"') + kReportReplacements = [] # Add custom javascript. @@ -54,6 +60,12 @@ kReportReplacements.append((re.compile(''), kReportReplacements.append((re.compile(''), 'Report Bug')) +# Insert report crashes link. + +kReportReplacements.append((re.compile(''), + '
These files will automatically be attached to ' + + 'reports filed here: Report Crashes.')) + ### # Other simple parameters @@ -176,7 +188,11 @@ def parse_query(qs, fields=None): name, value = chunk.split('=', 1) name = urllib.unquote(name.replace('+', ' ')) value = urllib.unquote(value.replace('+', ' ')) - fields[name] = value + item = fields.get(name) + if item is None: + fields[name] = [value] + else: + item.append(value) return fields class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): @@ -229,6 +245,17 @@ class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): keys[k] = v return keys + def load_crashes(self): + path = posixpath.join(self.server.root, 'index.html') + data = open(path).read() + problems = [] + for item in kReportCrashEntryRE.finditer(data): + fieldData = item.group(1) + fields = dict([i.groups() for i in + kReportCrashEntryKeyValueRE.finditer(fieldData)]) + problems.append(fields) + return problems + def handle_exception(self, exc): import traceback s = StringIO.StringIO() @@ -238,18 +265,29 @@ class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): if f: self.copyfile(f, self.wfile) f.close() - - def submit_bug(self): - title = self.fields.get('title') - description = self.fields.get('description') - report = self.fields.get('report') - reporterIndex = self.fields.get('reporter') - - # Type check form parameters. - reportPath = posixpath.join(self.server.root, - 'report-%s.html' % report) - if not posixpath.exists(reportPath): - return (False, "Invalid report ID.") + + def get_scalar_field(self, name): + if name in self.fields: + return self.fields[name][0] + else: + return None + + def submit_bug(self, c): + title = self.get_scalar_field('title') + description = self.get_scalar_field('description') + report = self.get_scalar_field('report') + reporterIndex = self.get_scalar_field('reporter') + files = [] + for fileID in self.fields.get('files',[]): + try: + i = int(fileID) + except: + i = None + if i is None or i<0 or i>=len(c.files): + return (False, 'Invalid file ID') + files.append(c.files[i]) + print files + if not title: return (False, "Missing title.") if not description: @@ -268,15 +306,16 @@ class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): return (False, 'Missing field "%s" for %s report method.'%(name, reporter.getName())) - parameters[o] = self.fields[name] + parameters[o] = self.get_scalar_field(name) # Update config defaults. - self.server.config.set('ScanView', 'reporter', reporterIndex) - for o in reporter.getParameterNames(): - self.server.config.set(reporter.getName(), o, parameters[o]) + if report != 'None': + self.server.config.set('ScanView', 'reporter', reporterIndex) + for o in reporter.getParameterNames(): + self.server.config.set(reporter.getName(), o, parameters[o]) # Create the report. - bug = Reporter.BugReport(title, description, [reportPath]) + bug = Reporter.BugReport(title, description, files) # Kick off a reporting thread. t = ReporterThread(bug, reporter, parameters, self.server) @@ -290,11 +329,21 @@ class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): return (t.success, t.status) def send_report_submit(self): - report = self.fields.get('report') - title = self.fields.get('title') - description = self.fields.get('description') + print self.fields + report = self.get_scalar_field('report') + c = self.get_report_context(report) + if c.reportSource is None: + reportingFor = "Report Crashes > " + fileBug = """\ +File Bug > """%locals() + else: + reportingFor = 'Report %s > ' % (c.reportSource, + report) + fileBug = 'File Bug > ' % report + title = self.get_scalar_field('title') + description = self.get_scalar_field('description') - res,message = self.submit_bug() + res,message = self.submit_bug(c) if res: statusClass = 'SubmitOk' @@ -311,8 +360,8 @@ class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):

Summary > -Report %(report)s > -File Bug > +%(reportingFor)s +%(fileBug)s Submit

@@ -367,28 +416,106 @@ Submit return self.send_string(res, 'text/plain') - def send_report(self, report): - try: - keys = self.load_report(report) - except IOError: - return self.send_error(400, 'Invalid report.') + def get_report_context(self, report): + class Context: + pass + if report is None or report == 'None': + data = self.load_crashes() + # Don't allow empty reports. + if not data: + raise ValueError, 'No crashes detected!' + c = Context() + c.title = 'clang static analyzer failures' + + stderrSummary = "" + for item in data: + if 'stderr' in item: + path = posixpath.join(self.server.root, item['stderr']) + if os.path.exists(path): + lns = itertools.islice(open(path), 0, 10) + stderrSummary += '%s\n--\n%s' % (item.get('src', + ''), + ''.join(lns)) + + c.description = """\ +The clang static analyzer failed on these inputs: +%s - initialTitle = keys.get('DESC','') - initialDescription = """\ -Bug generated by the clang static analyzer. +STDERR Summary +-------------- +%s +""" % ('\n'.join([item.get('src','') for item in data]), + stderrSummary) + c.reportSource = None + c.navMarkup = "Report Crashes > " + c.files = [] + for item in data: + c.files.append(item.get('src','')) + c.files.append(posixpath.join(self.server.root, + item.get('file',''))) + c.files.append(posixpath.join(self.server.root, + item.get('clangfile',''))) + c.files.append(posixpath.join(self.server.root, + item.get('stderr',''))) + c.files.append(posixpath.join(self.server.root, + item.get('info',''))) + # Just in case something failed, ignore files which don't + # exist. + c.files = [f for f in c.files + if os.path.exists(f) and os.path.isfile(f)] + else: + # Check that this is a valid report. + path = posixpath.join(self.server.root, 'report-%s.html' % report) + if not posixpath.exists(path): + raise ValueError, 'Invalid report ID' + keys = self.load_report(report) + c = Context() + c.title = keys.get('DESC','clang error (unrecognized') + c.description = """\ +Bug reported by the clang static analyzer. Description: %s File: %s Line: %s -"""%(initialTitle, - keys.get('FILE',''), - keys.get('LINE','')) +"""%(c.title, keys.get('FILE',''), keys.get('LINE', '')) + c.reportSource = 'report-%s.html' % report + c.navMarkup = """Report %s > """ % (c.reportSource, + report) + + c.files = [path] + return c + + def send_report(self, report, configOverrides=None): + def getConfigOption(section, field): + if (configOverrides is not None and + section in configOverrides and + field in configOverrides[section]): + return configOverrides[section][field] + return self.server.config.get(section, field) + + # report is None is used for crashes + try: + c = self.get_report_context(report) + except ValueError, e: + return self.send_error(400, e.message) + + title = c.title + description= c.description + reportingFor = c.navMarkup + if c.reportSource is None: + extraIFrame = "" + else: + extraIFrame = """\ +""" % (c.reportSource, c.reportSource) reporterSelections = [] reporterOptions = [] - + try: - active = self.server.config.getint('ScanView','reporter') + active = int(getConfigOption('ScanView','reporter')) except: active = 0 for i,r in enumerate(self.server.reporters): @@ -402,7 +529,7 @@ Line: %s -"""%(o,r.getName(),o,self.server.config.get(r.getName(), o)) for o in r.getParameterNames()]) +"""%(o,r.getName(),o,getConfigOption(r.getName(),o)) for o in r.getParameterNames()]) display = ('none','')[selected] reporterOptions.append("""\ @@ -418,6 +545,23 @@ Line: %s reporterOptionsDivs = '\n'.join(reporterOptions) reportersArray = '[%s]'%(','.join([`r.getName()` for r in self.server.reporters])) + if c.files: + fieldSize = min(5, len(c.files)) + attachFileOptions = '\n'.join(["""\ +""" % (i,v) for i,v in enumerate(c.files)]) + attachFileRow = """\ + + + + +""" % (min(5, len(c.files)), attachFileOptions) + else: + attachFileRow = "" + result = """File Bug @@ -440,7 +584,7 @@ function updateReporterOptions() {

Summary > -Report %(report)s > +%(reportingFor)s File Bug

@@ -451,16 +595,20 @@ File Bug + + +%(attachFileRow)s +
%s:
Attach: + +
Title: - +
Description:

@@ -482,13 +630,11 @@ File Bug
- +%(extraIFrame)s """%locals() + return self.send_string(result) def send_head(self, fields=None): @@ -521,6 +667,17 @@ File Bug return self.send_string('Goodbye.', 'text/plain') elif name=='report_submit': return self.send_report_submit() + elif name=='report_crashes': + overrides = { 'ScanView' : {}, + 'Radar' : {}, + 'Email' : {} } + for i,r in enumerate(self.server.reporters): + if r.getName() == 'Radar': + overrides['ScanView']['reporter'] = i + break + overrides['Radar']['Component'] = 'llvm - checker' + overrides['Radar']['Component Version'] = 'X' + return self.send_report(None, overrides) elif name=='favicon.ico': return self.send_path(posixpath.join(kResources,'bugcatcher.ico')) diff --git a/utils/scan-build b/utils/scan-build index 03326fdf1a..1dc1770f58 100755 --- a/utils/scan-build +++ b/utils/scan-build @@ -687,7 +687,7 @@ ENDTEXT print OUT "$problem$srcfile$ppfile$ppfile.stderr.txt\n"; my $ppfile_clang = $ppfile; $ppfile_clang =~ s/[.](.+)$/.clang.$1/; - print OUT " \n"; + print OUT " \n"; } print OUT <