diff --git a/tools/warn.py b/tools/warn.py index c223d9ee73..7d9ba6530b 100755 --- a/tools/warn.py +++ b/tools/warn.py @@ -8,6 +8,77 @@ Use option --byproject to output tables grouped by source file projects. Use option --gencsv to output warning counts in CSV format. """ +# List of important data structures and functions in this script. +# +# To parse and keep warning message in the input file: +# severity: classification of message severity +# severity.range [0, 1, ... last_severity_level] +# severity.colors for header background +# severity.column_headers for the warning count table +# severity.headers for warning message tables +# warn_patterns: +# warn_patterns[w]['category'] tool that issued the warning, not used now +# warn_patterns[w]['description'] table heading +# warn_patterns[w]['members'] matched warnings from input +# warn_patterns[w]['option'] compiler flag to control the warning +# warn_patterns[w]['patterns'] regular expressions to match warnings +# warn_patterns[w]['projects'][p] number of warnings of pattern w in p +# warn_patterns[w]['severity'] severity level +# project_list[p][0] project name +# project_list[p][1] regular expression to match a project path +# project_patterns[p] re.compile(project_list[p][1]) +# project_names[p] project_list[p][0] +# warning_messages array of each warning message, without source url +# warning_records array of [idx to warn_patterns, +# idx to project_names, +# idx to warning_messages] +# platform_version +# target_product +# target_variant +# compile_patterns, parse_input_file +# +# To emit html page of warning messages: +# flags: --byproject, --url, --separator +# Old stuff for static html components: +# html_script_style: static html scripts and styles +# htmlbig: +# dump_stats, dump_html_prologue, dump_html_epilogue: +# emit_buttons: +# dump_fixed +# sort_warnings: +# emit_stats_by_project: +# all_patterns, +# findproject, classify_warning +# dump_html +# +# New dynamic HTML page's static JavaScript data: +# Some data are copied from Python to JavaScript, to generate HTML elements. +# FlagURL args.url +# FlagSeparator args.separator +# SeverityColors: severity.colors +# SeverityHeaders: severity.headers +# SeverityColumnHeaders: severity.column_headers +# ProjectNames: project_names, or project_list[*][0] +# WarnPatternsSeverity: warn_patterns[*]['severity'] +# WarnPatternsDescription: warn_patterns[*]['description'] +# WarnPatternsOption: warn_patterns[*]['option'] +# WarningMessages: warning_messages +# Warnings: warning_records +# StatsHeader: warning count table header row +# StatsRows: array of warning count table rows +# +# New dynamic HTML page's dynamic JavaScript data: +# +# New dynamic HTML related function to emit data: +# escape_string, strip_escape_string, emit_warning_arrays +# emit_js_data(): +# +# To emit csv files of warning message counts: +# flag --gencsv +# description_for_csv, string_for_csv: +# count_severity(sev, kind): +# dump_csv(): + import argparse import re @@ -31,33 +102,32 @@ parser.add_argument(dest='buildlog', metavar='build.log', args = parser.parse_args() -# if you add another level, don't forget to give it a color below class severity: # pylint:disable=invalid-name,old-style-class """Severity levels and attributes.""" - UNKNOWN = 0 - FIXMENOW = 1 - HIGH = 2 - MEDIUM = 3 - LOW = 4 - TIDY = 5 - HARMLESS = 6 + # numbered by dump order + FIXMENOW = 0 + HIGH = 1 + MEDIUM = 2 + LOW = 3 + TIDY = 4 + HARMLESS = 5 + UNKNOWN = 6 SKIP = 7 + range = range(8) attributes = [ # pylint:disable=bad-whitespace - ['lightblue', 'Unknown', 'Unknown warnings'], ['fuchsia', 'FixNow', 'Critical warnings, fix me now'], ['red', 'High', 'High severity warnings'], ['orange', 'Medium', 'Medium severity warnings'], ['yellow', 'Low', 'Low severity warnings'], ['peachpuff', 'Tidy', 'Clang-Tidy warnings'], ['limegreen', 'Harmless', 'Harmless warnings'], + ['lightblue', 'Unknown', 'Unknown warnings'], ['grey', 'Unhandled', 'Unhandled warnings'] ] - color = [a[0] for a in attributes] + colors = [a[0] for a in attributes] column_headers = [a[1] for a in attributes] - header = [a[2] for a in attributes] - # order to dump by severity - kinds = [FIXMENOW, HIGH, MEDIUM, LOW, TIDY, HARMLESS, UNKNOWN, SKIP] + headers = [a[2] for a in attributes] warn_patterns = [ # TODO(chh): fix pylint space and indentation warnings @@ -84,7 +154,7 @@ warn_patterns = [ 'patterns':[r".*: warning: implicit declaration of function .+", r".*: warning: implicitly declaring library function" ] }, { 'category':'C/C++', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, conflicting types for ...', 'patterns':[r".*: warning: conflicting types for '.+'"] }, { 'category':'C/C++', 'severity':severity.HIGH, 'option':'-Wtype-limits', 'description':'Expression always evaluates to true or false', @@ -159,7 +229,7 @@ warn_patterns = [ 'description':'Need virtual destructor', 'patterns':[r".*: warning: delete called .* has virtual functions but non-virtual destructor"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, near initialization for ...', 'patterns':[r".*: warning: \(near initialization for '.+'\)"] }, { 'category':'C/C++', 'severity':severity.MEDIUM, 'option':'-Wdate-time', 'description':'Expansion of data or time macro', @@ -299,7 +369,7 @@ warn_patterns = [ r".*: warning: Access to .+ results in a dereference of a null pointer", r".*: warning: Null pointer argument in"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, parameter name (without types) in function declaration', 'patterns':[r".*: warning: parameter names \(without types\) in function declaration"] }, { 'category':'C/C++', 'severity':severity.MEDIUM, 'option':'-Wstrict-aliasing', 'description':'Dereferencing <foo> breaks strict aliasing rules', @@ -315,7 +385,7 @@ warn_patterns = [ 'description':'Symbol redefined', 'patterns':[r".*: warning: "".+"" redefined"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, ... location of the previous definition', 'patterns':[r".*: warning: this is the location of the previous definition"] }, { 'category':'ld', 'severity':severity.MEDIUM, 'description':'ld: type and size of dynamic symbol are not defined', @@ -351,7 +421,7 @@ warn_patterns = [ 'description':'Redundant declaration', 'patterns':[r".*: warning: redundant redeclaration of '.+'"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, previous declaration ... was here', 'patterns':[r".*: warning: previous declaration of '.+' was here"] }, { 'category':'C/C++', 'severity':severity.MEDIUM, 'option':'-Wswitch-enum', 'description':'Enum value not handled in switch', @@ -1154,13 +1224,13 @@ warn_patterns = [ 'patterns':[r".*: warning: '.+' will be initialized after", r".*: warning: field .+ will be initialized after .+Wreorder"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, ....', 'patterns':[r".*: warning: '.+'"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, base ...', 'patterns':[r".*: warning: base '.+'"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, when initialized here', 'patterns':[r".*: warning: when initialized here"] }, { 'category':'C/C++', 'severity':severity.MEDIUM, 'option':'-Wmissing-parameter-type', 'description':'Parameter type not specified', @@ -1206,7 +1276,7 @@ warn_patterns = [ 'description':'<foo> declared inside parameter list, scope limited to this definition', 'patterns':[r".*: warning: '.+' declared inside parameter list"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, its scope is only this ...', 'patterns':[r".*: warning: its scope is only this definition or declaration, which is probably not what you want"] }, { 'category':'C/C++', 'severity':severity.LOW, 'option':'-Wcomment', 'description':'Line continuation inside comment', @@ -1277,7 +1347,7 @@ warn_patterns = [ 'description':'Overload resolution chose to promote from unsigned or enum to signed type' , 'patterns':[r".*: warning: passing '.+' chooses '.+' over '.+'.*Wsign-promo"] }, { 'category':'cont.', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, in call to ...', 'patterns':[r".*: warning: in call to '.+'"] }, { 'category':'C/C++', 'severity':severity.HIGH, 'option':'-Wextra', 'description':'Base should be explicitly initialized in copy constructor', @@ -1469,13 +1539,13 @@ warn_patterns = [ # these next ones are to deal with formatting problems resulting from the log being mixed up by 'make -j' { 'category':'C/C++', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, ,', 'patterns':[r".*: warning: ,$"] }, { 'category':'C/C++', 'severity':severity.SKIP, - 'description':'', + 'description':'skip,', 'patterns':[r".*: warning: $"] }, { 'category':'C/C++', 'severity':severity.SKIP, - 'description':'', + 'description':'skip, In file included from ...', 'patterns':[r".*: warning: In file included from .+,"] }, # warnings from clang-tidy @@ -1610,16 +1680,56 @@ project_list = [ # 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:"], + ['frameworks/av/camera',r"(^|.*/)frameworks/av/camera/.*: warning:"], + ['frameworks/av/cmds', r"(^|.*/)frameworks/av/cmds/.*: warning:"], + ['frameworks/av/drm', r"(^|.*/)frameworks/av/drm/.*: warning:"], + ['frameworks/av/include',r"(^|.*/)frameworks/av/include/.*: warning:"], + ['frameworks/av/media', r"(^|.*/)frameworks/av/media/.*: warning:"], + ['frameworks/av/radio', r"(^|.*/)frameworks/av/radio/.*: warning:"], + ['frameworks/av/services', r"(^|.*/)frameworks/av/services/.*: warning:"], + ['frameworks/av/Other', r"(^|.*/)frameworks/av/.*: warning:"], + ['frameworks/base', r"(^|.*/)frameworks/base/.*: warning:"], + ['frameworks/compile', r"(^|.*/)frameworks/compile/.*: warning:"], + ['frameworks/minikin', r"(^|.*/)frameworks/minikin/.*: warning:"], + ['frameworks/native', r"(^|.*/)frameworks/native/.*: warning:"], + ['frameworks/opt', r"(^|.*/)frameworks/opt/.*: warning:"], + ['frameworks/rs', r"(^|.*/)frameworks/rs/.*: warning:"], + ['frameworks/webview', r"(^|.*/)frameworks/webview/.*: warning:"], + ['frameworks/wilhelm', r"(^|.*/)frameworks/wilhelm/.*: warning:"], + ['frameworks/Other', r"(^|.*/)frameworks/.*: warning:"], + ['hardware/akm', r"(^|.*/)hardware/akm/.*: warning:"], + ['hardware/broadcom', r"(^|.*/)hardware/broadcom/.*: warning:"], + ['hardware/google', r"(^|.*/)hardware/google/.*: warning:"], + ['hardware/intel', r"(^|.*/)hardware/intel/.*: warning:"], + ['hardware/interfaces', r"(^|.*/)hardware/interfaces/.*: warning:"], + ['hardware/libhardware',r"(^|.*/)hardware/libhardware/.*: warning:"], + ['hardware/libhardware_legacy',r"(^|.*/)hardware/libhardware_legacy/.*: warning:"], + ['hardware/qcom', r"(^|.*/)hardware/qcom/.*: warning:"], + ['hardware/ril', r"(^|.*/)hardware/ril/.*: warning:"], + ['hardware/Other', r"(^|.*/)hardware/.*: warning:"], ['kernel', r"(^|.*/)kernel/.*: warning:"], ['libcore', r"(^|.*/)libcore/.*: warning:"], - ['libnativehelper', r"(^|.*/)libnativehelper/.*: warning:"], + ['libnativehelper', r"(^|.*/)libnativehelper/.*: warning:"], ['ndk', r"(^|.*/)ndk/.*: warning:"], + # match vendor/unbungled_google/packages before other packages + ['unbundled_google', r"(^|.*/)unbundled_google/.*: warning:"], ['packages', r"(^|.*/)packages/.*: warning:"], ['pdk', r"(^|.*/)pdk/.*: warning:"], ['prebuilts', r"(^|.*/)prebuilts/.*: warning:"], - ['system', r"(^|.*/)system/.*: warning:"], + ['system/bt', r"(^|.*/)system/bt/.*: warning:"], + ['system/connectivity', r"(^|.*/)system/connectivity/.*: warning:"], + ['system/core', r"(^|.*/)system/core/.*: warning:"], + ['system/extras', r"(^|.*/)system/extras/.*: warning:"], + ['system/gatekeeper', r"(^|.*/)system/gatekeeper/.*: warning:"], + ['system/keymaster', r"(^|.*/)system/keymaster/.*: warning:"], + ['system/libhwbinder', r"(^|.*/)system/libhwbinder/.*: warning:"], + ['system/media', r"(^|.*/)system/media/.*: warning:"], + ['system/netd', r"(^|.*/)system/netd/.*: warning:"], + ['system/security', r"(^|.*/)system/security/.*: warning:"], + ['system/sepolicy', r"(^|.*/)system/sepolicy/.*: warning:"], + ['system/tools', r"(^|.*/)system/tools/.*: warning:"], + ['system/vold', r"(^|.*/)system/vold/.*: warning:"], + ['system/Other', r"(^|.*/)system/.*: warning:"], ['toolchain', r"(^|.*/)toolchain/.*: warning:"], ['test', r"(^|.*/)test/.*: warning:"], ['tools', r"(^|.*/)tools/.*: warning:"], @@ -1627,33 +1737,28 @@ project_list = [ ['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:"], + ['out/obj', r".*/(gen|obj[^/]*)/(include|EXECUTABLES|SHARED_LIBRARIES|STATIC_LIBRARIES|NATIVE_TESTS)/.*: warning:"], ['other', r".*: warning:"], ] project_patterns = [] project_names = [] +warning_messages = [] +warning_records = [] def initialize_arrays(): """Complete global arrays before they are used.""" - global project_names + global project_names, project_patterns project_names = [p[0] for p in project_list] - for p in project_list: - project_patterns.append({'description': p[0], - 'members': [], - 'pattern': re.compile(p[1])}) - # Each warning pattern has 3 dictionaries: - # (1) 'projects' maps a project name to number of warnings in that project. - # (2) 'project_anchor' maps a project name to its anchor number for HTML. - # (3) 'project_warnings' maps a project name to a list of warning messages. + project_patterns = [re.compile(p[1]) for p in project_list] for w in warn_patterns: w['members'] = [] if 'option' not in w: w['option'] = '' + # Each warning pattern has a 'projects' dictionary, that + # maps a project name to number of warnings in that project. w['projects'] = {} - w['project_anchor'] = {} - w['project_warnings'] = {} initialize_arrays() @@ -1666,46 +1771,41 @@ target_variant = 'unknown' ##### Data and functions to dump html file. ################################## -anchor = 0 -cur_row_class = 0 - -html_script_style = """\ - - \n""" - - -def output(text): - print text, + if (!e || !f) break; + e.style.display = (show ? 'block' : 'none'); + f.innerHTML = (show ? '⊖' : '⊕'); + } + }; + + + +""" def html_big(param): @@ -1713,24 +1813,17 @@ def html_big(param): def dump_html_prologue(title): - output('\n
\n') - output('\n') + print '\n
' + print '' def dump_html_epilogue(): - output('\n\n\n') - - -def table_row(text): - global cur_row_class - cur_row_class = 1 - cur_row_class - # remove last '\n' - t = text[:-1] if text[-1] == '\n' else text - output('