HTML report: display 'verbose' message using clickable expandable divs
This commit is contained in:
parent
45a2986f34
commit
ab6178f739
|
@ -14,6 +14,7 @@ from pygments.formatters import HtmlFormatter
|
|||
from xml.sax import parse as xml_parse
|
||||
from xml.sax import SAXParseException as XmlParseException
|
||||
from xml.sax.handler import ContentHandler as XmlContentHandler
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
"""
|
||||
Turns a cppcheck xml file into a browsable html report along
|
||||
|
@ -56,6 +57,25 @@ h1 {
|
|||
display: inline-block;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
div.verbose {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
div.verbose div.content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
margin: 4px;
|
||||
max-width: 40%;
|
||||
white-space: pre-wrap;
|
||||
border: 1px solid black;
|
||||
background-color: #FFFFCC;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.highlight .hll {
|
||||
padding: 1px;
|
||||
}
|
||||
|
@ -156,8 +176,42 @@ HTML_HEAD = """
|
|||
<style>
|
||||
%s
|
||||
</style>
|
||||
<script language="javascript">
|
||||
function getStyle(el,styleProp) {
|
||||
if (el.currentStyle)
|
||||
var y = el.currentStyle[styleProp];
|
||||
else if (window.getComputedStyle)
|
||||
var y = document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
|
||||
return y;
|
||||
}
|
||||
function toggle() {
|
||||
var el = this.expandable_content;
|
||||
var mark = this.expandable_marker;
|
||||
if (el.style.display == "block") {
|
||||
el.style.display = "none";
|
||||
mark.innerHTML = "[+]";
|
||||
} else {
|
||||
el.style.display = "block";
|
||||
mark.innerHTML = "[-]";
|
||||
}
|
||||
}
|
||||
function init_expandables() {
|
||||
var elts = document.getElementsByClassName("expandable");
|
||||
for (var i = 0; i < elts.length; i++) {
|
||||
var el = elts[i];
|
||||
var clickable = el.getElementsByTagName("span")[0];
|
||||
var marker = clickable.getElementsByClassName("marker")[0];
|
||||
var content = el.getElementsByClassName("content")[0];
|
||||
var width = clickable.clientWidth - parseInt(getStyle(content, "padding-left")) - parseInt(getStyle(content, "padding-right"));
|
||||
content.style.width = width + "px";
|
||||
clickable.expandable_content = content;
|
||||
clickable.expandable_marker = marker;
|
||||
clickable.onclick = toggle;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<body onload="init_expandables()">
|
||||
<div id="header">
|
||||
<h1>Cppcheck report - %s: %s </h1>
|
||||
</div>
|
||||
|
@ -189,6 +243,18 @@ HTML_FOOTER = """
|
|||
HTML_ERROR = "<span class='error2'><--- %s</span>\n"
|
||||
HTML_INCONCLUSIVE = "<span class='inconclusive2'><--- %s</span>\n"
|
||||
|
||||
HTML_EXPANDABLE_ERROR = "<div class='verbose expandable'><span class='error2'><--- %s <span class='marker'>[+]</span></span><div class='content'>%s</div></div>\n"""
|
||||
HTML_EXPANDABLE_INCONCLUSIVE = "<div class='verbose expandable'><span class='inconclusive2'><--- %s <span class='marker'>[+]</span></span><div class='content'>%s</div></div>\n"""
|
||||
|
||||
# escape() and unescape() takes care of &, < and >.
|
||||
html_escape_table = {
|
||||
'"': """,
|
||||
"'": "'"
|
||||
}
|
||||
html_unescape_table = {v:k for k, v in html_escape_table.items()}
|
||||
|
||||
def html_escape(text):
|
||||
return escape(text, html_escape_table)
|
||||
|
||||
class AnnotateCodeFormatter(HtmlFormatter):
|
||||
errors = []
|
||||
|
@ -203,8 +269,16 @@ class AnnotateCodeFormatter(HtmlFormatter):
|
|||
if error['line'] == line_no:
|
||||
try:
|
||||
if error['inconclusive'] == 'true':
|
||||
if error.get('verbose'):
|
||||
index = t.rfind('\n')
|
||||
t = t[:index] + HTML_EXPANDABLE_INCONCLUSIVE % (error['msg'], html_escape(error['verbose'].replace("\\012", '\n'))) + t[index+1:]
|
||||
else:
|
||||
t = t.replace('\n', HTML_INCONCLUSIVE % error['msg'])
|
||||
except KeyError:
|
||||
if error.get('verbose'):
|
||||
index = t.rfind('\n')
|
||||
t = t[:index] + HTML_EXPANDABLE_ERROR % (error['msg'], html_escape(error['verbose'].replace("\\012", '\n'))) + t[index+1:]
|
||||
else:
|
||||
t = t.replace('\n', HTML_ERROR % error['msg'])
|
||||
|
||||
line_no = line_no + 1
|
||||
|
@ -253,6 +327,7 @@ class CppCheckHandler(XmlContentHandler):
|
|||
'id': attributes['id'],
|
||||
'severity': attributes['severity'],
|
||||
'msg': attributes['msg'],
|
||||
'verbose': attributes.get('verbose'),
|
||||
'inconclusive': attributes['inconclusive']
|
||||
})
|
||||
except KeyError:
|
||||
|
@ -261,14 +336,14 @@ class CppCheckHandler(XmlContentHandler):
|
|||
'line': 0,
|
||||
'id': attributes['id'],
|
||||
'severity': attributes['severity'],
|
||||
'msg': attributes['msg']
|
||||
'msg': attributes['msg'],
|
||||
'verbose': attributes.get('verbose')
|
||||
})
|
||||
elif name == 'location':
|
||||
assert self.errors
|
||||
self.errors[-1]['file'] = attributes['file']
|
||||
self.errors[-1]['line'] = int(attributes['line'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configure all the options this little utility is using.
|
||||
parser = optparse.OptionParser()
|
||||
|
@ -374,6 +449,7 @@ if __name__ == '__main__':
|
|||
lineanchors='line',
|
||||
encoding=options.source_encoding)
|
||||
htmlFormatter.errors = errors
|
||||
|
||||
with io.open(os.path.join(options.report_dir, htmlfile),
|
||||
'w') as output_file:
|
||||
output_file.write(HTML_HEAD %
|
||||
|
|
Loading…
Reference in New Issue