forked from openkylin/platform_build
Merge "Fix pylint warnings and now prefer python3" am: 7b3a8fb7ec
am: ebb825c42d
Change-Id: I31a58138b7a1e19ca4819c824bea89592ca50acc
This commit is contained in:
commit
be06ed28b5
153
tools/warn.py
153
tools/warn.py
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/python
|
#!/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.
|
"""Grep warnings messages and output HTML tables or warning counts in CSV.
|
||||||
|
|
||||||
|
@ -74,9 +74,11 @@ Use option --gencsv to output warning counts in CSV format.
|
||||||
# escape_string, strip_escape_string, emit_warning_arrays
|
# escape_string, strip_escape_string, emit_warning_arrays
|
||||||
# emit_js_data():
|
# emit_js_data():
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import argparse
|
import argparse
|
||||||
import cgi
|
import cgi
|
||||||
import csv
|
import csv
|
||||||
|
import io
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -540,7 +542,7 @@ warn_patterns = [
|
||||||
{'category': 'java',
|
{'category': 'java',
|
||||||
'severity': Severity.LOW,
|
'severity': Severity.LOW,
|
||||||
'description':
|
'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\] .+"]},
|
'patterns': [r".*: warning: \[LambdaFunctionalInterface\] .+"]},
|
||||||
{'category': 'java',
|
{'category': 'java',
|
||||||
'severity': Severity.LOW,
|
'severity': Severity.LOW,
|
||||||
|
@ -1270,7 +1272,7 @@ warn_patterns = [
|
||||||
{'category': 'java',
|
{'category': 'java',
|
||||||
'severity': Severity.MEDIUM,
|
'severity': Severity.MEDIUM,
|
||||||
'description':
|
'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\] .+"]},
|
'patterns': [r".*: warning: \[ShortCircuitBoolean\] .+"]},
|
||||||
{'category': 'java',
|
{'category': 'java',
|
||||||
'severity': Severity.MEDIUM,
|
'severity': Severity.MEDIUM,
|
||||||
|
@ -1535,7 +1537,7 @@ warn_patterns = [
|
||||||
{'category': 'java',
|
{'category': 'java',
|
||||||
'severity': Severity.HIGH,
|
'severity': Severity.HIGH,
|
||||||
'description':
|
'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\] .+"]},
|
'patterns': [r".*: warning: \[ComparableType\] .+"]},
|
||||||
{'category': 'java',
|
{'category': 'java',
|
||||||
'severity': Severity.HIGH,
|
'severity': Severity.HIGH,
|
||||||
|
@ -1790,7 +1792,7 @@ warn_patterns = [
|
||||||
{'category': 'java',
|
{'category': 'java',
|
||||||
'severity': Severity.HIGH,
|
'severity': Severity.HIGH,
|
||||||
'description':
|
'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\] .+"]},
|
'patterns': [r".*: warning: \[IterablePathParameter\] .+"]},
|
||||||
{'category': 'java',
|
{'category': 'java',
|
||||||
'severity': Severity.HIGH,
|
'severity': Severity.HIGH,
|
||||||
|
@ -2922,17 +2924,17 @@ def html_big(param):
|
||||||
|
|
||||||
|
|
||||||
def dump_html_prologue(title):
|
def dump_html_prologue(title):
|
||||||
print '<html>\n<head>'
|
print('<html>\n<head>')
|
||||||
print '<title>' + title + '</title>'
|
print('<title>' + title + '</title>')
|
||||||
print html_head_scripts
|
print(html_head_scripts)
|
||||||
emit_stats_by_project()
|
emit_stats_by_project()
|
||||||
print '</head>\n<body>'
|
print('</head>\n<body>')
|
||||||
print html_big(title)
|
print(html_big(title))
|
||||||
print '<p>'
|
print('<p>')
|
||||||
|
|
||||||
|
|
||||||
def dump_html_epilogue():
|
def dump_html_epilogue():
|
||||||
print '</body>\n</head>\n</html>'
|
print('</body>\n</head>\n</html>')
|
||||||
|
|
||||||
|
|
||||||
def sort_warnings():
|
def sort_warnings():
|
||||||
|
@ -2943,6 +2945,7 @@ def sort_warnings():
|
||||||
def emit_stats_by_project():
|
def emit_stats_by_project():
|
||||||
"""Dump a google chart table of warnings per project and severity."""
|
"""Dump a google chart table of warnings per project and severity."""
|
||||||
# warnings[p][s] is number of warnings in project p of severity s.
|
# 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}
|
warnings = {p: {s: 0 for s in Severity.range} for p in project_names}
|
||||||
for i in warn_patterns:
|
for i in warn_patterns:
|
||||||
s = i['severity']
|
s = i['severity']
|
||||||
|
@ -2988,11 +2991,11 @@ def emit_stats_by_project():
|
||||||
total_all_severities += total_by_severity[s]
|
total_all_severities += total_by_severity[s]
|
||||||
one_row.append(total_all_projects)
|
one_row.append(total_all_projects)
|
||||||
stats_rows.append(one_row)
|
stats_rows.append(one_row)
|
||||||
print '<script>'
|
print('<script>')
|
||||||
emit_const_string_array('StatsHeader', stats_header)
|
emit_const_string_array('StatsHeader', stats_header)
|
||||||
emit_const_object_array('StatsRows', stats_rows)
|
emit_const_object_array('StatsRows', stats_rows)
|
||||||
print draw_table_javascript
|
print(draw_table_javascript)
|
||||||
print '</script>'
|
print('</script>')
|
||||||
|
|
||||||
|
|
||||||
def dump_stats():
|
def dump_stats():
|
||||||
|
@ -3008,14 +3011,14 @@ def dump_stats():
|
||||||
skipped += len(i['members'])
|
skipped += len(i['members'])
|
||||||
else:
|
else:
|
||||||
known += len(i['members'])
|
known += len(i['members'])
|
||||||
print 'Number of classified warnings: <b>' + str(known) + '</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 skipped warnings: <b>' + str(skipped) + '</b><br>')
|
||||||
print 'Number of unclassified warnings: <b>' + str(unknown) + '</b><br>'
|
print('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>')
|
||||||
total = unknown + known + skipped
|
total = unknown + known + skipped
|
||||||
extra_msg = ''
|
extra_msg = ''
|
||||||
if total < 1000:
|
if total < 1000:
|
||||||
extra_msg = ' (low count may indicate incremental build)'
|
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]
|
# New base table of warnings, [severity, warn_id, project, warning_message]
|
||||||
|
@ -3029,14 +3032,14 @@ def dump_stats():
|
||||||
# id for each warning pattern
|
# id for each warning pattern
|
||||||
# sort by project, severity, warn_id, warning_message
|
# sort by project, severity, warn_id, warning_message
|
||||||
def emit_buttons():
|
def emit_buttons():
|
||||||
print ('<button class="button" onclick="expandCollapse(1);">'
|
print('<button class="button" onclick="expandCollapse(1);">'
|
||||||
'Expand all warnings</button>\n'
|
'Expand all warnings</button>\n'
|
||||||
'<button class="button" onclick="expandCollapse(0);">'
|
'<button class="button" onclick="expandCollapse(0);">'
|
||||||
'Collapse all warnings</button>\n'
|
'Collapse all warnings</button>\n'
|
||||||
'<button class="button" onclick="groupBySeverity();">'
|
'<button class="button" onclick="groupBySeverity();">'
|
||||||
'Group warnings by severity</button>\n'
|
'Group warnings by severity</button>\n'
|
||||||
'<button class="button" onclick="groupByProject();">'
|
'<button class="button" onclick="groupByProject();">'
|
||||||
'Group warnings by project</button><br>')
|
'Group warnings by project</button><br>')
|
||||||
|
|
||||||
|
|
||||||
def all_patterns(category):
|
def all_patterns(category):
|
||||||
|
@ -3051,14 +3054,14 @@ def dump_fixed():
|
||||||
"""Show which warnings no longer occur."""
|
"""Show which warnings no longer occur."""
|
||||||
anchor = 'fixed_warnings'
|
anchor = 'fixed_warnings'
|
||||||
mark = anchor + '_mark'
|
mark = anchor + '_mark'
|
||||||
print ('\n<br><p style="background-color:lightblue"><b>'
|
print('\n<br><p style="background-color:lightblue"><b>'
|
||||||
'<button id="' + mark + '" '
|
'<button id="' + mark + '" '
|
||||||
'class="bt" onclick="expand(\'' + anchor + '\');">'
|
'class="bt" onclick="expand(\'' + anchor + '\');">'
|
||||||
'⊕</button> Fixed warnings. '
|
'⊕</button> Fixed warnings. '
|
||||||
'No more occurrences. Please consider turning these into '
|
'No more occurrences. Please consider turning these into '
|
||||||
'errors if possible, before they are reintroduced in to the build'
|
'errors if possible, before they are reintroduced in to the build'
|
||||||
':</b></p>')
|
':</b></p>')
|
||||||
print '<blockquote>'
|
print('<blockquote>')
|
||||||
fixed_patterns = []
|
fixed_patterns = []
|
||||||
for i in warn_patterns:
|
for i in warn_patterns:
|
||||||
if not i['members']:
|
if not i['members']:
|
||||||
|
@ -3066,16 +3069,16 @@ def dump_fixed():
|
||||||
all_patterns(i) + ')')
|
all_patterns(i) + ')')
|
||||||
if i['option']:
|
if i['option']:
|
||||||
fixed_patterns.append(' ' + i['option'])
|
fixed_patterns.append(' ' + i['option'])
|
||||||
fixed_patterns.sort()
|
fixed_patterns = sorted(fixed_patterns)
|
||||||
print '<div id="' + anchor + '" style="display:none;"><table>'
|
print('<div id="' + anchor + '" style="display:none;"><table>')
|
||||||
cur_row_class = 0
|
cur_row_class = 0
|
||||||
for text in fixed_patterns:
|
for text in fixed_patterns:
|
||||||
cur_row_class = 1 - cur_row_class
|
cur_row_class = 1 - cur_row_class
|
||||||
# remove last '\n'
|
# remove last '\n'
|
||||||
t = text[:-1] if text[-1] == '\n' else text
|
t = text[:-1] if text[-1] == '\n' else text
|
||||||
print '<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>'
|
print('<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>')
|
||||||
print '</table></div>'
|
print('</table></div>')
|
||||||
print '</blockquote>'
|
print('</blockquote>')
|
||||||
|
|
||||||
|
|
||||||
def find_project_index(line):
|
def find_project_index(line):
|
||||||
|
@ -3187,8 +3190,9 @@ def normalize_path(path):
|
||||||
def normalize_warning_line(line):
|
def normalize_warning_line(line):
|
||||||
"""Normalize file path relative to android_root in a warning line."""
|
"""Normalize file path relative to android_root in a warning line."""
|
||||||
# replace fancy quotes with plain ol' quotes
|
# replace fancy quotes with plain ol' quotes
|
||||||
line = line.replace('‘', "'")
|
line = re.sub(u'[\u2018\u2019]', '\'', line)
|
||||||
line = line.replace('’', "'")
|
# replace non-ASCII chars to spaces
|
||||||
|
line = re.sub(u'[^\x00-\x7f]', ' ', line)
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
first_column = line.find(':')
|
first_column = line.find(':')
|
||||||
if first_column > 0:
|
if first_column > 0:
|
||||||
|
@ -3246,21 +3250,22 @@ def strip_escape_string(s):
|
||||||
|
|
||||||
|
|
||||||
def emit_warning_array(name):
|
def emit_warning_array(name):
|
||||||
print 'var warning_{} = ['.format(name)
|
print('var warning_{} = ['.format(name))
|
||||||
for i in range(len(warn_patterns)):
|
for i in range(len(warn_patterns)):
|
||||||
print '{},'.format(warn_patterns[i][name])
|
print('{},'.format(warn_patterns[i][name]))
|
||||||
print '];'
|
print('];')
|
||||||
|
|
||||||
|
|
||||||
def emit_warning_arrays():
|
def emit_warning_arrays():
|
||||||
emit_warning_array('severity')
|
emit_warning_array('severity')
|
||||||
print 'var warning_description = ['
|
print('var warning_description = [')
|
||||||
for i in range(len(warn_patterns)):
|
for i in range(len(warn_patterns)):
|
||||||
if warn_patterns[i]['members']:
|
if warn_patterns[i]['members']:
|
||||||
print '"{}",'.format(escape_string(warn_patterns[i]['description']))
|
print('"{}",'.format(escape_string(warn_patterns[i]['description'])))
|
||||||
else:
|
else:
|
||||||
print '"",' # no such warning
|
print('"",') # no such warning
|
||||||
print '];'
|
print('];')
|
||||||
|
|
||||||
|
|
||||||
scripts_for_warning_groups = """
|
scripts_for_warning_groups = """
|
||||||
function compareMessages(x1, x2) { // of the same warning type
|
function compareMessages(x1, x2) { // of the same warning type
|
||||||
|
@ -3393,39 +3398,42 @@ scripts_for_warning_groups = """
|
||||||
|
|
||||||
# Emit a JavaScript const string
|
# Emit a JavaScript const string
|
||||||
def emit_const_string(name, value):
|
def emit_const_string(name, value):
|
||||||
print 'const ' + name + ' = "' + escape_string(value) + '";'
|
print('const ' + name + ' = "' + escape_string(value) + '";')
|
||||||
|
|
||||||
|
|
||||||
# Emit a JavaScript const integer array.
|
# Emit a JavaScript const integer array.
|
||||||
def emit_const_int_array(name, array):
|
def emit_const_int_array(name, array):
|
||||||
print 'const ' + name + ' = ['
|
print('const ' + name + ' = [')
|
||||||
for n in array:
|
for n in array:
|
||||||
print str(n) + ','
|
print(str(n) + ',')
|
||||||
print '];'
|
print('];')
|
||||||
|
|
||||||
|
|
||||||
# Emit a JavaScript const string array.
|
# Emit a JavaScript const string array.
|
||||||
def emit_const_string_array(name, array):
|
def emit_const_string_array(name, array):
|
||||||
print 'const ' + name + ' = ['
|
print('const ' + name + ' = [')
|
||||||
for s in array:
|
for s in array:
|
||||||
print '"' + strip_escape_string(s) + '",'
|
print('"' + strip_escape_string(s) + '",')
|
||||||
print '];'
|
print('];')
|
||||||
|
|
||||||
|
|
||||||
# Emit a JavaScript const string array for HTML.
|
# Emit a JavaScript const string array for HTML.
|
||||||
def emit_const_html_string_array(name, array):
|
def emit_const_html_string_array(name, array):
|
||||||
print 'const ' + name + ' = ['
|
print('const ' + name + ' = [')
|
||||||
for s in array:
|
for s in array:
|
||||||
print '"' + cgi.escape(strip_escape_string(s)) + '",'
|
# Not using html.escape yet, to work for both python 2 and 3,
|
||||||
print '];'
|
# 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.
|
# Emit a JavaScript const object array.
|
||||||
def emit_const_object_array(name, array):
|
def emit_const_object_array(name, array):
|
||||||
print 'const ' + name + ' = ['
|
print('const ' + name + ' = [')
|
||||||
for x in array:
|
for x in array:
|
||||||
print str(x) + ','
|
print(str(x) + ',')
|
||||||
print '];'
|
print('];')
|
||||||
|
|
||||||
|
|
||||||
def emit_js_data():
|
def emit_js_data():
|
||||||
|
@ -3471,18 +3479,18 @@ def dump_html():
|
||||||
dump_html_prologue('Warnings for ' + platform_version + ' - ' +
|
dump_html_prologue('Warnings for ' + platform_version + ' - ' +
|
||||||
target_product + ' - ' + target_variant)
|
target_product + ' - ' + target_variant)
|
||||||
dump_stats()
|
dump_stats()
|
||||||
print '<br><div id="stats_table"></div><br>'
|
print('<br><div id="stats_table"></div><br>')
|
||||||
print '\n<script>'
|
print('\n<script>')
|
||||||
emit_js_data()
|
emit_js_data()
|
||||||
print scripts_for_warning_groups
|
print(scripts_for_warning_groups)
|
||||||
print '</script>'
|
print('</script>')
|
||||||
emit_buttons()
|
emit_buttons()
|
||||||
# Warning messages are grouped by severities or project names.
|
# 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:
|
if args.byproject:
|
||||||
print '<script>groupByProject();</script>'
|
print('<script>groupByProject();</script>')
|
||||||
else:
|
else:
|
||||||
print '<script>groupBySeverity();</script>'
|
print('<script>groupBySeverity();</script>')
|
||||||
dump_fixed()
|
dump_fixed()
|
||||||
dump_html_epilogue()
|
dump_html_epilogue()
|
||||||
|
|
||||||
|
@ -3506,8 +3514,7 @@ def count_severity(writer, sev, kind):
|
||||||
warning = kind + ': ' + description_for_csv(i)
|
warning = kind + ': ' + description_for_csv(i)
|
||||||
writer.writerow([n, '', warning])
|
writer.writerow([n, '', warning])
|
||||||
# print number of warnings for each project, ordered by project name.
|
# print number of warnings for each project, ordered by project name.
|
||||||
projects = i['projects'].keys()
|
projects = sorted(i['projects'].keys())
|
||||||
projects.sort()
|
|
||||||
for p in projects:
|
for p in projects:
|
||||||
writer.writerow([i['projects'][p], p, warning])
|
writer.writerow([i['projects'][p], p, warning])
|
||||||
writer.writerow([total, '', kind + ' warnings'])
|
writer.writerow([total, '', kind + ' warnings'])
|
||||||
|
@ -3526,7 +3533,9 @@ def dump_csv(writer):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
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)
|
parallel_classify_warnings(warning_lines)
|
||||||
# If a user pases a csv path, save the fileoutput to the path
|
# If a user pases a csv path, save the fileoutput to the path
|
||||||
# If the user also passed gencsv write the output to stdout
|
# If the user also passed gencsv write the output to stdout
|
||||||
|
|
Loading…
Reference in New Issue