From 4354a33874648a3524534e4d1e0093f37ded8bf7 Mon Sep 17 00:00:00 2001 From: Chih-Hung Hsieh Date: Fri, 22 Jul 2016 14:09:31 -0700 Subject: [PATCH] Add option to dump HTML warnings per project. * Use --byproject flag to dump warnings in HTML file by projects. * Add external/google and vendor/google projects, vs other external/non-google and vendor/non-google projects. * Refactor code in dumpcategory to dump warnings by projects when --byproject is specified. * Recognize new compiler -Wvarargs warning pattern. * No change to default HTML output format. Change-Id: I2406ad392ab18683357ff0ee0cf6c41f87cf399c Test: run through current build.log files. --- tools/warn.py | 138 +++++++++++++++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 51 deletions(-) diff --git a/tools/warn.py b/tools/warn.py index 51349af80..6effd61ac 100755 --- a/tools/warn.py +++ b/tools/warn.py @@ -10,6 +10,10 @@ parser.add_argument('--gencsv', help='Generate a CSV file with number of various warnings', action="store_true", default=False) +parser.add_argument('--byproject', + help='Separate warnings in HTML output by project names', + action="store_true", + default=False) parser.add_argument('--url', help='Root URL of an Android source code tree prefixed ' 'before files in warnings') @@ -1660,6 +1664,7 @@ warnpatterns = [ { 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'', 'description':'Undefined result', 'patterns':[r".*: warning: The result of .+ is undefined", + r".*: warning: passing an object that .+ has undefined behavior \[-Wvarargs\]", r".*: warning: 'this' pointer cannot be null in well-defined C\+\+ code;", r".*: warning: shifting a negative signed value is undefined"] }, { 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'', @@ -1796,43 +1801,52 @@ warnpatterns = [ # A list of [project_name, file_path_pattern]. # project_name should not contain comma, to be used in CSV output. projectlist = [ - ['art', r"(^|.*/)art/.*: warning:"], - ['bionic', r"(^|.*/)bionic/.*: warning:"], - ['bootable', r"(^|.*/)bootable/.*: warning:"], - ['build', r"(^|.*/)build/.*: warning:"], - ['cts', r"(^|.*/)cts/.*: warning:"], - ['dalvik', r"(^|.*/)dalvik/.*: warning:"], - ['developers', r"(^|.*/)developers/.*: warning:"], - ['development', r"(^|.*/)development/.*: warning:"], - ['device', r"(^|.*/)device/.*: warning:"], - ['doc', r"(^|.*/)doc/.*: warning:"], - ['external', r"(^|.*/)external/.*: warning:"], - ['frameworks', r"(^|.*/)frameworks/.*: warning:"], - ['hardware', r"(^|.*/)hardware/.*: warning:"], - ['kernel', r"(^|.*/)kernel/.*: warning:"], - ['libcore', r"(^|.*/)libcore/.*: warning:"], - ['libnativehelper', r"(^|.*/)libnativehelper/.*: warning:"], - ['ndk', r"(^|.*/)ndk/.*: warning:"], - ['packages', r"(^|.*/)packages/.*: warning:"], - ['pdk', r"(^|.*/)pdk/.*: warning:"], - ['prebuilts', r"(^|.*/)prebuilts/.*: warning:"], - ['system', r"(^|.*/)system/.*: warning:"], - ['toolchain', r"(^|.*/)toolchain/.*: warning:"], - ['test', r"(^|.*/)test/.*: warning:"], - ['tools', r"(^|.*/)tools/.*: warning:"], - ['vendor', r"(^|.*/)vendor/.*: warning:"], - ['out/obj', r".*/(gen|obj[^/]*)/(include|EXECUTABLES|SHARED_LIBRARIES|STATIC_LIBRARIES)/.*: warning:"], - ['other', r".*: warning:"], + ['art', r"(^|.*/)art/.*: warning:"], + ['bionic', r"(^|.*/)bionic/.*: warning:"], + ['bootable', r"(^|.*/)bootable/.*: warning:"], + ['build', r"(^|.*/)build/.*: warning:"], + ['cts', r"(^|.*/)cts/.*: warning:"], + ['dalvik', r"(^|.*/)dalvik/.*: warning:"], + ['developers', r"(^|.*/)developers/.*: warning:"], + ['development', r"(^|.*/)development/.*: warning:"], + ['device', r"(^|.*/)device/.*: warning:"], + ['doc', r"(^|.*/)doc/.*: warning:"], + # match external/google* before external/ + ['external/google', r"(^|.*/)external/google.*: warning:"], + ['external/non-google', r"(^|.*/)external/.*: warning:"], + ['frameworks', r"(^|.*/)frameworks/.*: warning:"], + ['hardware', r"(^|.*/)hardware/.*: warning:"], + ['kernel', r"(^|.*/)kernel/.*: warning:"], + ['libcore', r"(^|.*/)libcore/.*: warning:"], + ['libnativehelper', r"(^|.*/)libnativehelper/.*: warning:"], + ['ndk', r"(^|.*/)ndk/.*: warning:"], + ['packages', r"(^|.*/)packages/.*: warning:"], + ['pdk', r"(^|.*/)pdk/.*: warning:"], + ['prebuilts', r"(^|.*/)prebuilts/.*: warning:"], + ['system', r"(^|.*/)system/.*: warning:"], + ['toolchain', r"(^|.*/)toolchain/.*: warning:"], + ['test', r"(^|.*/)test/.*: warning:"], + ['tools', r"(^|.*/)tools/.*: warning:"], + # match vendor/google* before vendor/ + ['vendor/google', r"(^|.*/)vendor/google.*: warning:"], + ['vendor/non-google', r"(^|.*/)vendor/.*: warning:"], + # keep out/obj and other patterns at the end. + ['out/obj', r".*/(gen|obj[^/]*)/(include|EXECUTABLES|SHARED_LIBRARIES|STATIC_LIBRARIES)/.*: warning:"], + ['other', r".*: warning:"], ] projectpatterns = [] for p in projectlist: projectpatterns.append({'description':p[0], 'members':[], 'pattern':re.compile(p[1])}) -# Each warning pattern has a dictionary that maps -# a project name to number of warnings in that project. +# 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. +# (3) 'projectwarning' maps a project name to a list of warning of that project. for w in warnpatterns: w['projects'] = {} + w['projectanchor'] = {} + w['projectwarning'] = {} platformversion = 'unknown' targetproduct = 'unknown' @@ -1937,17 +1951,12 @@ def dumpseverity(sev): output('
\n') for i in warnpatterns: if i['severity'] == sev and len(i['members']) > 0: - output('\n\n') anchor += 1 i['anchor'] = str(anchor) - mark = str(anchor) + '_mark' - output('' + - '\n') - output('
' + descriptionfor(i) + - ' (' + str(len(i['members'])) + ')
\n') - dumpcategory(i) + if args.byproject: + dumpcategorybyproject(sev, i) + else: + dumpcategory(sev, i) output('
\n') def allpatterns(cat): @@ -2002,19 +2011,35 @@ def warningwithurl(line): else: return '' + filepath + ':' + linenumber + ':' + warning -# dump a category, provided it is not marked as 'SKIP' and has more than 0 occurrences -def dumpcategory(cat): - if cat['severity'] != severity.SKIP and len(cat['members']) != 0: - header = [descriptionfor(cat),str(len(cat['members'])) + ' occurences:'] - if cat['option'] != '': - header[1:1] = [' (related option: ' + cat['option'] +')'] +def dumpgroup(sev, anchor, description, warnings): + mark = anchor + '_mark' + output('\n\n') + output('' + + '\n') + output('
' + description + '
\n') + output('\n') - output('\n') +# dump warnings in a category +def dumpcategory(sev, cat): + description = descriptionfor(cat) + ' (' + str(len(cat['members'])) + ')' + dumpgroup(sev, cat['anchor'], description, cat['members']) +# similar to dumpcategory but output one table per project. +def dumpcategorybyproject(sev, cat): + warning = descriptionfor(cat) + projects = cat['projectwarning'].keys() + projects.sort() + for p in projects: + anchor = cat['projectanchor'][p] + projectwarnings = cat['projectwarning'][p] + description = '{}, in {} ({})'.format(warning, p, len(projectwarnings)) + dumpgroup(sev, anchor, description, projectwarnings) def findproject(line): for p in projectpatterns: @@ -2023,15 +2048,26 @@ def findproject(line): return '???' def classifywarning(line): + global anchor for i in warnpatterns: for cpat in i['compiledpatterns']: if cpat.match(line): i['members'].append(line) pname = findproject(line) + # Count warnings by project. if pname in i['projects']: - i['projects'][pname] += 1 + i['projects'][pname] += 1 else: - i['projects'][pname] = 1 + i['projects'][pname] = 1 + # Collect warnings by project. + if args.byproject: + if pname in i['projectwarning']: + i['projectwarning'][pname].append(line) + else: + i['projectwarning'][pname] = [line] + if pname not in i['projectanchor']: + anchor += 1 + i['projectanchor'][pname] = str(anchor) return else: # If we end up here, there was a problem parsing the log