Loading tools/warn.py +81 −72 Original line number Diff line number Diff line #!/usr/bin/python # This file uses the following encoding: utf-8 # Prefer python3 but work also with python2. """Grep warnings messages and output HTML tables or warning counts in CSV. Loading Loading @@ -74,9 +74,11 @@ Use option --gencsv to output warning counts in CSV format. # escape_string, strip_escape_string, emit_warning_arrays # emit_js_data(): from __future__ import print_function import argparse import cgi import csv import io import multiprocessing import os import re Loading Loading @@ -540,7 +542,7 @@ warn_patterns = [ {'category': 'java', 'severity': Severity.LOW, 'description': 'Java: Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.', u'Java: Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.', 'patterns': [r".*: warning: \[LambdaFunctionalInterface\] .+"]}, {'category': 'java', 'severity': Severity.LOW, Loading Loading @@ -1270,7 +1272,7 @@ warn_patterns = [ {'category': 'java', 'severity': Severity.MEDIUM, 'description': 'Java: Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.', u'Java: Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.', 'patterns': [r".*: warning: \[ShortCircuitBoolean\] .+"]}, {'category': 'java', 'severity': Severity.MEDIUM, Loading Loading @@ -1535,7 +1537,7 @@ warn_patterns = [ {'category': 'java', 'severity': Severity.HIGH, 'description': 'Java: Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.', u'Java: Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.', 'patterns': [r".*: warning: \[ComparableType\] .+"]}, {'category': 'java', 'severity': Severity.HIGH, Loading Loading @@ -1790,7 +1792,7 @@ warn_patterns = [ {'category': 'java', 'severity': Severity.HIGH, 'description': 'Java: Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity', u'Java: Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity', 'patterns': [r".*: warning: \[IterablePathParameter\] .+"]}, {'category': 'java', 'severity': Severity.HIGH, Loading Loading @@ -2922,17 +2924,17 @@ def html_big(param): def dump_html_prologue(title): print '<html>\n<head>' print '<title>' + title + '</title>' print html_head_scripts print('<html>\n<head>') print('<title>' + title + '</title>') print(html_head_scripts) emit_stats_by_project() print '</head>\n<body>' print html_big(title) print '<p>' print('</head>\n<body>') print(html_big(title)) print('<p>') def dump_html_epilogue(): print '</body>\n</head>\n</html>' print('</body>\n</head>\n</html>') def sort_warnings(): Loading @@ -2943,6 +2945,7 @@ def sort_warnings(): def emit_stats_by_project(): """Dump a google chart table of warnings per project and severity.""" # warnings[p][s] is number of warnings in project p of severity s. # pylint:disable=g-complex-comprehension warnings = {p: {s: 0 for s in Severity.range} for p in project_names} for i in warn_patterns: s = i['severity'] Loading Loading @@ -2988,11 +2991,11 @@ def emit_stats_by_project(): total_all_severities += total_by_severity[s] one_row.append(total_all_projects) stats_rows.append(one_row) print '<script>' print('<script>') emit_const_string_array('StatsHeader', stats_header) emit_const_object_array('StatsRows', stats_rows) print draw_table_javascript print '</script>' print(draw_table_javascript) print('</script>') def dump_stats(): Loading @@ -3008,14 +3011,14 @@ def dump_stats(): skipped += len(i['members']) else: known += len(i['members']) print 'Number of classified warnings: <b>' + str(known) + '</b><br>' print 'Number of skipped warnings: <b>' + str(skipped) + '</b><br>' print 'Number of unclassified warnings: <b>' + str(unknown) + '</b><br>' print('Number of classified warnings: <b>' + str(known) + '</b><br>') print('Number of skipped warnings: <b>' + str(skipped) + '</b><br>') print('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>') total = unknown + known + skipped extra_msg = '' if total < 1000: extra_msg = ' (low count may indicate incremental build)' print 'Total number of warnings: <b>' + str(total) + '</b>' + extra_msg print('Total number of warnings: <b>' + str(total) + '</b>' + extra_msg) # New base table of warnings, [severity, warn_id, project, warning_message] Loading Loading @@ -3058,7 +3061,7 @@ def dump_fixed(): 'No more occurrences. Please consider turning these into ' 'errors if possible, before they are reintroduced in to the build' ':</b></p>') print '<blockquote>' print('<blockquote>') fixed_patterns = [] for i in warn_patterns: if not i['members']: Loading @@ -3066,16 +3069,16 @@ def dump_fixed(): all_patterns(i) + ')') if i['option']: fixed_patterns.append(' ' + i['option']) fixed_patterns.sort() print '<div id="' + anchor + '" style="display:none;"><table>' fixed_patterns = sorted(fixed_patterns) print('<div id="' + anchor + '" style="display:none;"><table>') cur_row_class = 0 for text in fixed_patterns: cur_row_class = 1 - cur_row_class # remove last '\n' t = text[:-1] if text[-1] == '\n' else text print '<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>' print '</table></div>' print '</blockquote>' print('<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>') print('</table></div>') print('</blockquote>') def find_project_index(line): Loading Loading @@ -3187,8 +3190,9 @@ def normalize_path(path): def normalize_warning_line(line): """Normalize file path relative to android_root in a warning line.""" # replace fancy quotes with plain ol' quotes line = line.replace('‘', "'") line = line.replace('’', "'") line = re.sub(u'[\u2018\u2019]', '\'', line) # replace non-ASCII chars to spaces line = re.sub(u'[^\x00-\x7f]', ' ', line) line = line.strip() first_column = line.find(':') if first_column > 0: Loading Loading @@ -3246,21 +3250,22 @@ def strip_escape_string(s): def emit_warning_array(name): print 'var warning_{} = ['.format(name) print('var warning_{} = ['.format(name)) for i in range(len(warn_patterns)): print '{},'.format(warn_patterns[i][name]) print '];' print('{},'.format(warn_patterns[i][name])) print('];') def emit_warning_arrays(): emit_warning_array('severity') print 'var warning_description = [' print('var warning_description = [') for i in range(len(warn_patterns)): if warn_patterns[i]['members']: print '"{}",'.format(escape_string(warn_patterns[i]['description'])) print('"{}",'.format(escape_string(warn_patterns[i]['description']))) else: print '"",' # no such warning print '];' print('"",') # no such warning print('];') scripts_for_warning_groups = """ function compareMessages(x1, x2) { // of the same warning type Loading Loading @@ -3393,39 +3398,42 @@ scripts_for_warning_groups = """ # Emit a JavaScript const string def emit_const_string(name, value): print 'const ' + name + ' = "' + escape_string(value) + '";' print('const ' + name + ' = "' + escape_string(value) + '";') # Emit a JavaScript const integer array. def emit_const_int_array(name, array): print 'const ' + name + ' = [' print('const ' + name + ' = [') for n in array: print str(n) + ',' print '];' print(str(n) + ',') print('];') # Emit a JavaScript const string array. def emit_const_string_array(name, array): print 'const ' + name + ' = [' print('const ' + name + ' = [') for s in array: print '"' + strip_escape_string(s) + '",' print '];' print('"' + strip_escape_string(s) + '",') print('];') # Emit a JavaScript const string array for HTML. def emit_const_html_string_array(name, array): print 'const ' + name + ' = [' print('const ' + name + ' = [') for s in array: print '"' + cgi.escape(strip_escape_string(s)) + '",' print '];' # Not using html.escape yet, to work for both python 2 and 3, # until all users switch to python 3. # pylint:disable=deprecated-method print('"' + cgi.escape(strip_escape_string(s)) + '",') print('];') # Emit a JavaScript const object array. def emit_const_object_array(name, array): print 'const ' + name + ' = [' print('const ' + name + ' = [') for x in array: print str(x) + ',' print '];' print(str(x) + ',') print('];') def emit_js_data(): Loading Loading @@ -3471,18 +3479,18 @@ def dump_html(): dump_html_prologue('Warnings for ' + platform_version + ' - ' + target_product + ' - ' + target_variant) dump_stats() print '<br><div id="stats_table"></div><br>' print '\n<script>' print('<br><div id="stats_table"></div><br>') print('\n<script>') emit_js_data() print scripts_for_warning_groups print '</script>' print(scripts_for_warning_groups) print('</script>') emit_buttons() # Warning messages are grouped by severities or project names. print '<br><div id="warning_groups"></div>' print('<br><div id="warning_groups"></div>') if args.byproject: print '<script>groupByProject();</script>' print('<script>groupByProject();</script>') else: print '<script>groupBySeverity();</script>' print('<script>groupBySeverity();</script>') dump_fixed() dump_html_epilogue() Loading @@ -3506,8 +3514,7 @@ def count_severity(writer, sev, kind): warning = kind + ': ' + description_for_csv(i) writer.writerow([n, '', warning]) # print number of warnings for each project, ordered by project name. projects = i['projects'].keys() projects.sort() projects = sorted(i['projects'].keys()) for p in projects: writer.writerow([i['projects'][p], p, warning]) writer.writerow([total, '', kind + ' warnings']) Loading @@ -3526,7 +3533,9 @@ def dump_csv(writer): def main(): warning_lines = parse_input_file(open(args.buildlog, 'r')) # We must use 'utf-8' codec to parse some non-ASCII code in warnings. warning_lines = parse_input_file( io.open(args.buildlog, mode='r', encoding='utf-8')) parallel_classify_warnings(warning_lines) # If a user pases a csv path, save the fileoutput to the path # If the user also passed gencsv write the output to stdout Loading Loading
tools/warn.py +81 −72 Original line number Diff line number Diff line #!/usr/bin/python # This file uses the following encoding: utf-8 # Prefer python3 but work also with python2. """Grep warnings messages and output HTML tables or warning counts in CSV. Loading Loading @@ -74,9 +74,11 @@ Use option --gencsv to output warning counts in CSV format. # escape_string, strip_escape_string, emit_warning_arrays # emit_js_data(): from __future__ import print_function import argparse import cgi import csv import io import multiprocessing import os import re Loading Loading @@ -540,7 +542,7 @@ warn_patterns = [ {'category': 'java', 'severity': Severity.LOW, 'description': 'Java: Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.', u'Java: Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.', 'patterns': [r".*: warning: \[LambdaFunctionalInterface\] .+"]}, {'category': 'java', 'severity': Severity.LOW, Loading Loading @@ -1270,7 +1272,7 @@ warn_patterns = [ {'category': 'java', 'severity': Severity.MEDIUM, 'description': 'Java: Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.', u'Java: Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.', 'patterns': [r".*: warning: \[ShortCircuitBoolean\] .+"]}, {'category': 'java', 'severity': Severity.MEDIUM, Loading Loading @@ -1535,7 +1537,7 @@ warn_patterns = [ {'category': 'java', 'severity': Severity.HIGH, 'description': 'Java: Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.', u'Java: Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.', 'patterns': [r".*: warning: \[ComparableType\] .+"]}, {'category': 'java', 'severity': Severity.HIGH, Loading Loading @@ -1790,7 +1792,7 @@ warn_patterns = [ {'category': 'java', 'severity': Severity.HIGH, 'description': 'Java: Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity', u'Java: Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity', 'patterns': [r".*: warning: \[IterablePathParameter\] .+"]}, {'category': 'java', 'severity': Severity.HIGH, Loading Loading @@ -2922,17 +2924,17 @@ def html_big(param): def dump_html_prologue(title): print '<html>\n<head>' print '<title>' + title + '</title>' print html_head_scripts print('<html>\n<head>') print('<title>' + title + '</title>') print(html_head_scripts) emit_stats_by_project() print '</head>\n<body>' print html_big(title) print '<p>' print('</head>\n<body>') print(html_big(title)) print('<p>') def dump_html_epilogue(): print '</body>\n</head>\n</html>' print('</body>\n</head>\n</html>') def sort_warnings(): Loading @@ -2943,6 +2945,7 @@ def sort_warnings(): def emit_stats_by_project(): """Dump a google chart table of warnings per project and severity.""" # warnings[p][s] is number of warnings in project p of severity s. # pylint:disable=g-complex-comprehension warnings = {p: {s: 0 for s in Severity.range} for p in project_names} for i in warn_patterns: s = i['severity'] Loading Loading @@ -2988,11 +2991,11 @@ def emit_stats_by_project(): total_all_severities += total_by_severity[s] one_row.append(total_all_projects) stats_rows.append(one_row) print '<script>' print('<script>') emit_const_string_array('StatsHeader', stats_header) emit_const_object_array('StatsRows', stats_rows) print draw_table_javascript print '</script>' print(draw_table_javascript) print('</script>') def dump_stats(): Loading @@ -3008,14 +3011,14 @@ def dump_stats(): skipped += len(i['members']) else: known += len(i['members']) print 'Number of classified warnings: <b>' + str(known) + '</b><br>' print 'Number of skipped warnings: <b>' + str(skipped) + '</b><br>' print 'Number of unclassified warnings: <b>' + str(unknown) + '</b><br>' print('Number of classified warnings: <b>' + str(known) + '</b><br>') print('Number of skipped warnings: <b>' + str(skipped) + '</b><br>') print('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>') total = unknown + known + skipped extra_msg = '' if total < 1000: extra_msg = ' (low count may indicate incremental build)' print 'Total number of warnings: <b>' + str(total) + '</b>' + extra_msg print('Total number of warnings: <b>' + str(total) + '</b>' + extra_msg) # New base table of warnings, [severity, warn_id, project, warning_message] Loading Loading @@ -3058,7 +3061,7 @@ def dump_fixed(): 'No more occurrences. Please consider turning these into ' 'errors if possible, before they are reintroduced in to the build' ':</b></p>') print '<blockquote>' print('<blockquote>') fixed_patterns = [] for i in warn_patterns: if not i['members']: Loading @@ -3066,16 +3069,16 @@ def dump_fixed(): all_patterns(i) + ')') if i['option']: fixed_patterns.append(' ' + i['option']) fixed_patterns.sort() print '<div id="' + anchor + '" style="display:none;"><table>' fixed_patterns = sorted(fixed_patterns) print('<div id="' + anchor + '" style="display:none;"><table>') cur_row_class = 0 for text in fixed_patterns: cur_row_class = 1 - cur_row_class # remove last '\n' t = text[:-1] if text[-1] == '\n' else text print '<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>' print '</table></div>' print '</blockquote>' print('<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>') print('</table></div>') print('</blockquote>') def find_project_index(line): Loading Loading @@ -3187,8 +3190,9 @@ def normalize_path(path): def normalize_warning_line(line): """Normalize file path relative to android_root in a warning line.""" # replace fancy quotes with plain ol' quotes line = line.replace('‘', "'") line = line.replace('’', "'") line = re.sub(u'[\u2018\u2019]', '\'', line) # replace non-ASCII chars to spaces line = re.sub(u'[^\x00-\x7f]', ' ', line) line = line.strip() first_column = line.find(':') if first_column > 0: Loading Loading @@ -3246,21 +3250,22 @@ def strip_escape_string(s): def emit_warning_array(name): print 'var warning_{} = ['.format(name) print('var warning_{} = ['.format(name)) for i in range(len(warn_patterns)): print '{},'.format(warn_patterns[i][name]) print '];' print('{},'.format(warn_patterns[i][name])) print('];') def emit_warning_arrays(): emit_warning_array('severity') print 'var warning_description = [' print('var warning_description = [') for i in range(len(warn_patterns)): if warn_patterns[i]['members']: print '"{}",'.format(escape_string(warn_patterns[i]['description'])) print('"{}",'.format(escape_string(warn_patterns[i]['description']))) else: print '"",' # no such warning print '];' print('"",') # no such warning print('];') scripts_for_warning_groups = """ function compareMessages(x1, x2) { // of the same warning type Loading Loading @@ -3393,39 +3398,42 @@ scripts_for_warning_groups = """ # Emit a JavaScript const string def emit_const_string(name, value): print 'const ' + name + ' = "' + escape_string(value) + '";' print('const ' + name + ' = "' + escape_string(value) + '";') # Emit a JavaScript const integer array. def emit_const_int_array(name, array): print 'const ' + name + ' = [' print('const ' + name + ' = [') for n in array: print str(n) + ',' print '];' print(str(n) + ',') print('];') # Emit a JavaScript const string array. def emit_const_string_array(name, array): print 'const ' + name + ' = [' print('const ' + name + ' = [') for s in array: print '"' + strip_escape_string(s) + '",' print '];' print('"' + strip_escape_string(s) + '",') print('];') # Emit a JavaScript const string array for HTML. def emit_const_html_string_array(name, array): print 'const ' + name + ' = [' print('const ' + name + ' = [') for s in array: print '"' + cgi.escape(strip_escape_string(s)) + '",' print '];' # Not using html.escape yet, to work for both python 2 and 3, # until all users switch to python 3. # pylint:disable=deprecated-method print('"' + cgi.escape(strip_escape_string(s)) + '",') print('];') # Emit a JavaScript const object array. def emit_const_object_array(name, array): print 'const ' + name + ' = [' print('const ' + name + ' = [') for x in array: print str(x) + ',' print '];' print(str(x) + ',') print('];') def emit_js_data(): Loading Loading @@ -3471,18 +3479,18 @@ def dump_html(): dump_html_prologue('Warnings for ' + platform_version + ' - ' + target_product + ' - ' + target_variant) dump_stats() print '<br><div id="stats_table"></div><br>' print '\n<script>' print('<br><div id="stats_table"></div><br>') print('\n<script>') emit_js_data() print scripts_for_warning_groups print '</script>' print(scripts_for_warning_groups) print('</script>') emit_buttons() # Warning messages are grouped by severities or project names. print '<br><div id="warning_groups"></div>' print('<br><div id="warning_groups"></div>') if args.byproject: print '<script>groupByProject();</script>' print('<script>groupByProject();</script>') else: print '<script>groupBySeverity();</script>' print('<script>groupBySeverity();</script>') dump_fixed() dump_html_epilogue() Loading @@ -3506,8 +3514,7 @@ def count_severity(writer, sev, kind): warning = kind + ': ' + description_for_csv(i) writer.writerow([n, '', warning]) # print number of warnings for each project, ordered by project name. projects = i['projects'].keys() projects.sort() projects = sorted(i['projects'].keys()) for p in projects: writer.writerow([i['projects'][p], p, warning]) writer.writerow([total, '', kind + ' warnings']) Loading @@ -3526,7 +3533,9 @@ def dump_csv(writer): def main(): warning_lines = parse_input_file(open(args.buildlog, 'r')) # We must use 'utf-8' codec to parse some non-ASCII code in warnings. warning_lines = parse_input_file( io.open(args.buildlog, mode='r', encoding='utf-8')) parallel_classify_warnings(warning_lines) # If a user pases a csv path, save the fileoutput to the path # If the user also passed gencsv write the output to stdout Loading