diff --git a/tools/warn.py b/tools/warn.py
index ce78d5d668..572ac68dec 100755
--- a/tools/warn.py
+++ b/tools/warn.py
@@ -2,7 +2,6 @@
# This file uses the following encoding: utf-8
import argparse
-import sys
import re
parser = argparse.ArgumentParser(description='Convert a build log into HTML')
@@ -26,14 +25,15 @@ args = parser.parse_args()
# if you add another level, don't forget to give it a color below
class severity:
- UNKNOWN=0
- SKIP=100
- FIXMENOW=1
- HIGH=2
- MEDIUM=3
- LOW=4
- TIDY=5
- HARMLESS=6
+ UNKNOWN = 0
+ FIXMENOW = 1
+ HIGH = 2
+ MEDIUM = 3
+ LOW = 4
+ TIDY = 5
+ HARMLESS = 6
+ SKIP = 100
+ kinds = [FIXMENOW, HIGH, MEDIUM, LOW, TIDY, HARMLESS, UNKNOWN, SKIP]
def colorforseverity(sev):
if sev == severity.FIXMENOW:
@@ -69,6 +69,23 @@ def headerforseverity(sev):
return 'Unknown warnings'
return 'Unhandled warnings'
+def columnheaderforseverity(sev):
+ if sev == severity.FIXMENOW:
+ return 'FixNow'
+ if sev == severity.HIGH:
+ return 'High'
+ if sev == severity.MEDIUM:
+ return 'Medium'
+ if sev == severity.LOW:
+ return 'Low'
+ if sev == severity.HARMLESS:
+ return 'Harmless'
+ if sev == severity.TIDY:
+ return 'Tidy'
+ if sev == severity.UNKNOWN:
+ return 'Unknown'
+ return 'Unhandled'
+
warnpatterns = [
{ 'category':'make', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'make: overriding commands/ignoring old commands',
@@ -240,7 +257,8 @@ warnpatterns = [
'patterns':[r".*: warning: control reaches end of non-void function"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wimplicit-int',
'description':'Implicit int type',
- 'patterns':[r".*: warning: type specifier missing, defaults to 'int'"] },
+ 'patterns':[r".*: warning: type specifier missing, defaults to 'int'",
+ r".*: warning: type defaults to 'int' in declaration of '.+'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wmain-return-type',
'description':'Main function should return int',
'patterns':[r".*: warning: return type of 'main' is not 'int'"] },
@@ -295,9 +313,6 @@ warnpatterns = [
r".*: warning: .+ results in a null pointer dereference",
r".*: warning: Access to .+ results in a dereference of a null pointer",
r".*: warning: Null pointer argument in"] },
- { 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
- 'description':'',
- 'patterns':[r".*: warning: type defaults to 'int' in declaration of '.+'"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: parameter names \(without types\) in function declaration"] },
@@ -1909,6 +1924,8 @@ projectpatterns = []
for p in projectlist:
projectpatterns.append({'description':p[0], 'members':[], 'pattern':re.compile(p[1])})
+projectnames = [p[0] for p in projectlist]
+
# Each warning pattern has 3 dictionaries:
# (1) 'projects' maps a project name to number of warnings in that project.
# (2) 'projectanchor' maps a project name to its anchor number for HTML.
@@ -1953,12 +1970,13 @@ html_script_style = """\
};
\n"""
@@ -1990,45 +2008,114 @@ def sortwarnings():
for i in warnpatterns:
i['members'] = sorted(set(i['members']))
+# dump a table of warnings per project and severity
+def dumpstatsbyproject():
+ projects = set(projectnames)
+ severities = set(severity.kinds)
+
+ # warnings[p][s] is number of warnings in project p of severity s.
+ warnings = {p:{s:0 for s in severity.kinds} for p in projectnames}
+ for i in warnpatterns:
+ s = i['severity']
+ for p in i['projects']:
+ warnings[p][s] += i['projects'][p]
+
+ # totalbyseverity[s] is number of warnings of severity s.
+ totalbyseverity = {s:0 for s in severity.kinds}
+
+ # emit table header
+ output('
\n'.format(totalallprojects))
+
+ # at the end of table, verify total counts
+ output('
\n')
+ if totalallprojects != totalallseverities:
+ output('
ERROR: Sum of warnings by project ' +
+ '!= Sum of warnings by severity.
\n')
+
# dump some stats about total number of warnings and such
def dumpstats():
known = 0
+ skipped = 0
unknown = 0
sortwarnings()
for i in warnpatterns:
if i['severity'] == severity.UNKNOWN:
unknown += len(i['members'])
- elif i['severity'] != severity.SKIP:
+ elif i['severity'] == severity.SKIP:
+ skipped += len(i['members'])
+ else:
known += len(i['members'])
output('\nNumber of classified warnings: ' + str(known) + ' ' )
+ output('\nNumber of skipped warnings: ' + str(skipped) + ' ')
output('\nNumber of unclassified warnings: ' + str(unknown) + ' ')
- total = unknown + known
+ total = unknown + known + skipped
output('\nTotal number of warnings: ' + str(total) + '')
if total < 1000:
output('(low count may indicate incremental build)')
output('
\n')
+
+def emitbuttons():
output(' ' +
+ 'Expand all warnings\n' +
'')
- output(' \n')
+ 'Collapse all warnings \n')
# dump everything for a given severity
def dumpseverity(sev):
global anchor
+ total = 0
+ for i in warnpatterns:
+ if i['severity'] == sev:
+ total = total + len(i['members'])
output('\n ' +
- headerforseverity(sev) + ':\n')
+ headerforseverity(sev) + ': ' + str(total) + '\n')
output('
\n')
for i in warnpatterns:
- if i['severity'] == sev and len(i['members']) > 0:
- anchor += 1
- i['anchor'] = str(anchor)
- if args.byproject:
- dumpcategorybyproject(sev, i)
- else:
- dumpcategory(sev, i)
+ if i['severity'] == sev and len(i['members']) > 0:
+ anchor += 1
+ i['anchor'] = str(anchor)
+ if args.byproject:
+ dumpcategorybyproject(sev, i)
+ else:
+ dumpcategory(sev, i)
output('
\n')
+# emit all skipped project anchors for expand_collapse.
+def dumpskippedanchors():
+ output('
\n') # hide these fake elements
+ for i in warnpatterns:
+ if i['severity'] == severity.SKIP and len(i['members']) > 0:
+ projects = i['projectwarning'].keys()
+ for p in projects:
+ output('' +
+ '\n')
+ output('
\n')
+
def allpatterns(cat):
pats = ''
for i in cat['patterns']:
@@ -2057,7 +2144,7 @@ def dumpfixed():
output('
\n')
fixed_patterns = []
for i in warnpatterns:
- if len(i['members']) == 0 and i['severity'] != severity.SKIP:
+ if len(i['members']) == 0:
fixed_patterns.append(i['description'] + ' (' +
allpatterns(i) + ') ' + i['option'])
fixed_patterns.sort()
@@ -2083,14 +2170,14 @@ def warningwithurl(line):
def dumpgroup(sev, anchor, description, warnings):
mark = anchor + '_mark'
- output('\n
\n')
+ output('\n
\n')
output('
' +
'
' + description + '
\n')
output('
\n')
output('
')
- output('
\n')
+ output('
\n')
for i in warnings:
tablerow(warningwithurl(i))
output('
\n')
@@ -2191,16 +2278,15 @@ def parseinputfile():
def dumphtml():
dumphtmlprologue('Warnings for ' + platformversion + ' - ' + targetproduct + ' - ' + targetvariant)
dumpstats()
+ dumpstatsbyproject()
+ emitbuttons()
# sort table based on number of members once dumpstats has deduplicated the
# members.
warnpatterns.sort(reverse=True, key=lambda i: len(i['members']))
- dumpseverity(severity.FIXMENOW)
- dumpseverity(severity.HIGH)
- dumpseverity(severity.MEDIUM)
- dumpseverity(severity.LOW)
- dumpseverity(severity.TIDY)
- dumpseverity(severity.HARMLESS)
- dumpseverity(severity.UNKNOWN)
+ # Dump warnings by severity. If severity.SKIP warnings are not dumpped,
+ # the project anchors should be dumped through dumpskippedanchors.
+ for s in severity.kinds:
+ dumpseverity(s)
dumpfixed()
dumphtmlepilogue()
@@ -2237,13 +2323,8 @@ def countseverity(sev, kind):
def dumpcsv():
sortwarnings()
total = 0
- total += countseverity(severity.FIXMENOW, 'FixNow')
- total += countseverity(severity.HIGH, 'High')
- total += countseverity(severity.MEDIUM, 'Medium')
- total += countseverity(severity.LOW, 'Low')
- total += countseverity(severity.TIDY, 'Tidy')
- total += countseverity(severity.HARMLESS, 'Harmless')
- total += countseverity(severity.UNKNOWN, 'Unknown')
+ for s in severity.kinds:
+ total += countseverity(s, columnheaderforseverity(s))
print '{},,{}'.format(total, 'All warnings')