Call a writer to dump html; new warning patterns.
* HTML emit functions now take a writer parameter. This makes warn_common.py one step closer to the ChromeOS version. * Add new found warning patterns from java and yacc. Test: warn.py --url=http://cs/android --separator='?l=' build.log > warnings.html Test: warn.py --gencsv build.log > warnings.csv Change-Id: I5c446ca767746598f07603591fdf98f7d82cae17
This commit is contained in:
@@ -93,6 +93,8 @@ warn_patterns = [
|
|||||||
[r".*: warning: \[MultipleTopLevelClasses\] .+"]),
|
[r".*: warning: \[MultipleTopLevelClasses\] .+"]),
|
||||||
java_low('Avoid having multiple unary operators acting on the same variable in a method call',
|
java_low('Avoid having multiple unary operators acting on the same variable in a method call',
|
||||||
[r".*: warning: \[MultipleUnaryOperatorsInMethodCall\] .+"]),
|
[r".*: warning: \[MultipleUnaryOperatorsInMethodCall\] .+"]),
|
||||||
|
java_low('OnNameExpected naming style',
|
||||||
|
[r".*\.java:.*: warning: .+ \[OnNameExpected\]$"]),
|
||||||
java_low('Package names should match the directory they are declared in',
|
java_low('Package names should match the directory they are declared in',
|
||||||
[r".*: warning: \[PackageLocation\] .+"]),
|
[r".*: warning: \[PackageLocation\] .+"]),
|
||||||
java_low('Non-standard parameter comment; prefer `/* paramName= */ arg`',
|
java_low('Non-standard parameter comment; prefer `/* paramName= */ arg`',
|
||||||
|
@@ -46,6 +46,10 @@ def kotlin(description, pattern_list):
|
|||||||
return warn('Kotlin', Severity.MEDIUM, description, pattern_list)
|
return warn('Kotlin', Severity.MEDIUM, description, pattern_list)
|
||||||
|
|
||||||
|
|
||||||
|
def yacc(description, pattern_list):
|
||||||
|
return warn('yacc', Severity.MEDIUM, description, pattern_list)
|
||||||
|
|
||||||
|
|
||||||
warn_patterns = [
|
warn_patterns = [
|
||||||
# pylint:disable=line-too-long,g-inconsistent-quotes
|
# pylint:disable=line-too-long,g-inconsistent-quotes
|
||||||
# aapt warnings
|
# aapt warnings
|
||||||
@@ -115,6 +119,14 @@ warn_patterns = [
|
|||||||
kotlin('library has Kotlin runtime',
|
kotlin('library has Kotlin runtime',
|
||||||
[r".*: warning: library has Kotlin runtime bundled into it",
|
[r".*: warning: library has Kotlin runtime bundled into it",
|
||||||
r".*: warning: some JAR files .* have the Kotlin Runtime library"]),
|
r".*: warning: some JAR files .* have the Kotlin Runtime library"]),
|
||||||
|
# Yacc warnings
|
||||||
|
yacc('deprecate directive',
|
||||||
|
[r".*\.yy?:.*: warning: deprecated directive: "]),
|
||||||
|
yacc('shift/reduce conflicts',
|
||||||
|
[r".*\.yy?: warning: .+ shift/reduce conflicts "]),
|
||||||
|
{'category': 'yacc', 'severity': Severity.SKIP,
|
||||||
|
'description': 'yacc: fix-its can be applied',
|
||||||
|
'patterns': [r".*\.yy?: warning: fix-its can be applied."]},
|
||||||
# Rust warnings
|
# Rust warnings
|
||||||
{'category': 'Rust', 'severity': Severity.HIGH,
|
{'category': 'Rust', 'severity': Severity.HIGH,
|
||||||
'description': 'Rust: Does not derive Copy',
|
'description': 'Rust: Does not derive Copy',
|
||||||
|
@@ -199,22 +199,30 @@ html_head_scripts = """\
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def make_writer(output_stream):
|
||||||
|
|
||||||
|
def writer(text):
|
||||||
|
return output_stream.write(text + '\n')
|
||||||
|
|
||||||
|
return writer
|
||||||
|
|
||||||
|
|
||||||
def html_big(param):
|
def html_big(param):
|
||||||
return '<font size="+2">' + param + '</font>'
|
return '<font size="+2">' + param + '</font>'
|
||||||
|
|
||||||
|
|
||||||
def dump_html_prologue(title):
|
def dump_html_prologue(title, writer):
|
||||||
print('<html>\n<head>')
|
writer('<html>\n<head>')
|
||||||
print('<title>' + title + '</title>')
|
writer('<title>' + title + '</title>')
|
||||||
print(html_head_scripts)
|
writer(html_head_scripts)
|
||||||
emit_stats_by_project()
|
emit_stats_by_project(writer)
|
||||||
print('</head>\n<body>')
|
writer('</head>\n<body>')
|
||||||
print(html_big(title))
|
writer(html_big(title))
|
||||||
print('<p>')
|
writer('<p>')
|
||||||
|
|
||||||
|
|
||||||
def dump_html_epilogue():
|
def dump_html_epilogue(writer):
|
||||||
print('</body>\n</head>\n</html>')
|
writer('</body>\n</head>\n</html>')
|
||||||
|
|
||||||
|
|
||||||
def sort_warnings():
|
def sort_warnings():
|
||||||
@@ -222,7 +230,7 @@ def sort_warnings():
|
|||||||
i['members'] = sorted(set(i['members']))
|
i['members'] = sorted(set(i['members']))
|
||||||
|
|
||||||
|
|
||||||
def emit_stats_by_project():
|
def emit_stats_by_project(writer):
|
||||||
"""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
|
# pylint:disable=g-complex-comprehension
|
||||||
@@ -277,14 +285,14 @@ def emit_stats_by_project():
|
|||||||
total_all_severities += total_by_severity[s.value]
|
total_all_severities += total_by_severity[s.value]
|
||||||
one_row.append(total_all_projects)
|
one_row.append(total_all_projects)
|
||||||
stats_rows.append(one_row)
|
stats_rows.append(one_row)
|
||||||
print('<script>')
|
writer('<script>')
|
||||||
emit_const_string_array('StatsHeader', stats_header)
|
emit_const_string_array('StatsHeader', stats_header, writer)
|
||||||
emit_const_object_array('StatsRows', stats_rows)
|
emit_const_object_array('StatsRows', stats_rows, writer)
|
||||||
print(draw_table_javascript)
|
writer(draw_table_javascript)
|
||||||
print('</script>')
|
writer('</script>')
|
||||||
|
|
||||||
|
|
||||||
def dump_stats():
|
def dump_stats(writer):
|
||||||
"""Dump some stats about total number of warnings and such."""
|
"""Dump some stats about total number of warnings and such."""
|
||||||
known = 0
|
known = 0
|
||||||
skipped = 0
|
skipped = 0
|
||||||
@@ -297,14 +305,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>')
|
writer('Number of classified warnings: <b>' + str(known) + '</b><br>')
|
||||||
print('Number of skipped warnings: <b>' + str(skipped) + '</b><br>')
|
writer('Number of skipped warnings: <b>' + str(skipped) + '</b><br>')
|
||||||
print('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>')
|
writer('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)
|
writer('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]
|
||||||
@@ -317,8 +325,8 @@ def dump_stats():
|
|||||||
# (3) New, group by project + severity,
|
# (3) New, group by project + severity,
|
||||||
# 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(writer):
|
||||||
print('<button class="button" onclick="expandCollapse(1);">'
|
writer('<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'
|
||||||
@@ -336,33 +344,32 @@ def all_patterns(category):
|
|||||||
return patterns
|
return patterns
|
||||||
|
|
||||||
|
|
||||||
def dump_fixed():
|
def dump_fixed(writer):
|
||||||
"""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>'
|
writer('\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>')
|
writer('<blockquote>')
|
||||||
fixed_patterns = []
|
fixed_patterns = []
|
||||||
for i in warn_patterns:
|
for i in warn_patterns:
|
||||||
if not i['members']:
|
if not i['members']:
|
||||||
fixed_patterns.append(i['description'] + ' (' +
|
fixed_patterns.append(i['description'] + ' (' + all_patterns(i) + ')')
|
||||||
all_patterns(i) + ')')
|
|
||||||
fixed_patterns = sorted(fixed_patterns)
|
fixed_patterns = sorted(fixed_patterns)
|
||||||
print('<div id="' + anchor + '" style="display:none;"><table>')
|
writer('<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>')
|
writer('<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>')
|
||||||
print('</table></div>')
|
writer('</table></div>')
|
||||||
print('</blockquote>')
|
writer('</blockquote>')
|
||||||
|
|
||||||
|
|
||||||
def find_project_index(line):
|
def find_project_index(line):
|
||||||
@@ -540,6 +547,7 @@ def parse_input_file(infile):
|
|||||||
prev_warning = 'unknown_source_file: ' + prev_warning
|
prev_warning = 'unknown_source_file: ' + prev_warning
|
||||||
warning_lines.add(normalize_warning_line(prev_warning))
|
warning_lines.add(normalize_warning_line(prev_warning))
|
||||||
prev_warning = ''
|
prev_warning = ''
|
||||||
|
|
||||||
if warning_pattern.match(line):
|
if warning_pattern.match(line):
|
||||||
if warning_without_file.match(line):
|
if warning_without_file.match(line):
|
||||||
# save this line and combine it with the next line
|
# save this line and combine it with the next line
|
||||||
@@ -547,6 +555,7 @@ def parse_input_file(infile):
|
|||||||
else:
|
else:
|
||||||
warning_lines.add(normalize_warning_line(line))
|
warning_lines.add(normalize_warning_line(line))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if line_counter < 100:
|
if line_counter < 100:
|
||||||
# save a little bit of time by only doing this for the first few lines
|
# save a little bit of time by only doing this for the first few lines
|
||||||
line_counter += 1
|
line_counter += 1
|
||||||
@@ -580,22 +589,22 @@ def strip_escape_string(s):
|
|||||||
return escape_string(s)
|
return escape_string(s)
|
||||||
|
|
||||||
|
|
||||||
def emit_warning_array(name):
|
def emit_warning_array(name, writer):
|
||||||
print('var warning_{} = ['.format(name))
|
writer('var warning_{} = ['.format(name))
|
||||||
for i in range(len(warn_patterns)):
|
for i in range(len(warn_patterns)):
|
||||||
print('{},'.format(warn_patterns[i][name]))
|
writer('{},'.format(warn_patterns[i][name]))
|
||||||
print('];')
|
writer('];')
|
||||||
|
|
||||||
|
|
||||||
def emit_warning_arrays():
|
def emit_warning_arrays(writer):
|
||||||
emit_warning_array('severity')
|
emit_warning_array('severity', writer)
|
||||||
print('var warning_description = [')
|
writer('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'])))
|
writer('"{}",'.format(escape_string(warn_patterns[i]['description'])))
|
||||||
else:
|
else:
|
||||||
print('"",') # no such warning
|
writer('"",') # no such warning
|
||||||
print('];')
|
writer('];')
|
||||||
|
|
||||||
|
|
||||||
scripts_for_warning_groups = """
|
scripts_for_warning_groups = """
|
||||||
@@ -701,7 +710,8 @@ scripts_for_warning_groups = """
|
|||||||
var result = "";
|
var result = "";
|
||||||
var groups = groupWarningsBySeverity();
|
var groups = groupWarningsBySeverity();
|
||||||
for (s=0; s<SeverityColors.length; s++) {
|
for (s=0; s<SeverityColors.length; s++) {
|
||||||
result += createWarningSection(SeverityHeaders[s], SeverityColors[s], groups[s]);
|
result += createWarningSection(SeverityHeaders[s], SeverityColors[s],
|
||||||
|
groups[s]);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -728,63 +738,67 @@ 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, writer):
|
||||||
print('const ' + name + ' = "' + escape_string(value) + '";')
|
writer('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, writer):
|
||||||
print('const ' + name + ' = [')
|
writer('const ' + name + ' = [')
|
||||||
for n in array:
|
for n in array:
|
||||||
print(str(n) + ',')
|
writer(str(n) + ',')
|
||||||
print('];')
|
writer('];')
|
||||||
|
|
||||||
|
|
||||||
# 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, writer):
|
||||||
print('const ' + name + ' = [')
|
writer('const ' + name + ' = [')
|
||||||
for s in array:
|
for s in array:
|
||||||
print('"' + strip_escape_string(s) + '",')
|
writer('"' + strip_escape_string(s) + '",')
|
||||||
print('];')
|
writer('];')
|
||||||
|
|
||||||
|
|
||||||
# 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, writer):
|
||||||
print('const ' + name + ' = [')
|
writer('const ' + name + ' = [')
|
||||||
for s in array:
|
for s in array:
|
||||||
# Not using html.escape yet, to work for both python 2 and 3,
|
# Not using html.escape yet, to work for both python 2 and 3,
|
||||||
# until all users switch to python 3.
|
# until all users switch to python 3.
|
||||||
# pylint:disable=deprecated-method
|
# pylint:disable=deprecated-method
|
||||||
print('"' + cgi.escape(strip_escape_string(s)) + '",')
|
writer('"' + cgi.escape(strip_escape_string(s)) + '",')
|
||||||
print('];')
|
writer('];')
|
||||||
|
|
||||||
|
|
||||||
# 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, writer):
|
||||||
print('const ' + name + ' = [')
|
writer('const ' + name + ' = [')
|
||||||
for x in array:
|
for x in array:
|
||||||
print(str(x) + ',')
|
writer(str(x) + ',')
|
||||||
print('];')
|
writer('];')
|
||||||
|
|
||||||
|
|
||||||
def emit_js_data():
|
def emit_js_data(writer):
|
||||||
"""Dump dynamic HTML page's static JavaScript data."""
|
"""Dump dynamic HTML page's static JavaScript data."""
|
||||||
emit_const_string('FlagURL', args.url if args.url else '')
|
emit_const_string('FlagURL',
|
||||||
emit_const_string('FlagSeparator', args.separator if args.separator else '')
|
args.url if args.url else '', writer)
|
||||||
emit_const_string_array('SeverityColors', [s.color for s in Severity.levels])
|
emit_const_string('FlagSeparator',
|
||||||
|
args.separator if args.separator else '', writer)
|
||||||
|
emit_const_string_array('SeverityColors',
|
||||||
|
[s.color for s in Severity.levels], writer)
|
||||||
emit_const_string_array('SeverityHeaders',
|
emit_const_string_array('SeverityHeaders',
|
||||||
[s.header for s in Severity.levels])
|
[s.header for s in Severity.levels], writer)
|
||||||
emit_const_string_array('SeverityColumnHeaders',
|
emit_const_string_array('SeverityColumnHeaders',
|
||||||
[s.column_header for s in Severity.levels])
|
[s.column_header for s in Severity.levels], writer)
|
||||||
emit_const_string_array('ProjectNames', project_names)
|
emit_const_string_array('ProjectNames', project_names, writer)
|
||||||
# pytype: disable=attribute-error
|
# pytype: disable=attribute-error
|
||||||
emit_const_int_array('WarnPatternsSeverity',
|
emit_const_int_array('WarnPatternsSeverity',
|
||||||
[w['severity'].value for w in warn_patterns])
|
[w['severity'].value for w in warn_patterns], writer)
|
||||||
# pytype: enable=attribute-error
|
# pytype: enable=attribute-error
|
||||||
emit_const_html_string_array('WarnPatternsDescription',
|
emit_const_html_string_array('WarnPatternsDescription',
|
||||||
[w['description'] for w in warn_patterns])
|
[w['description'] for w in warn_patterns],
|
||||||
emit_const_html_string_array('WarningMessages', warning_messages)
|
writer)
|
||||||
emit_const_object_array('Warnings', warning_records)
|
emit_const_html_string_array('WarningMessages', warning_messages, writer)
|
||||||
|
emit_const_object_array('Warnings', warning_records, writer)
|
||||||
|
|
||||||
draw_table_javascript = """
|
draw_table_javascript = """
|
||||||
google.charts.load('current', {'packages':['table']});
|
google.charts.load('current', {'packages':['table']});
|
||||||
@@ -801,31 +815,33 @@ function drawTable() {
|
|||||||
data.setProperty(i, j, 'style', 'border:1px solid black;');
|
data.setProperty(i, j, 'style', 'border:1px solid black;');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var table = new google.visualization.Table(document.getElementById('stats_table'));
|
var table = new google.visualization.Table(
|
||||||
|
document.getElementById('stats_table'));
|
||||||
table.draw(data, {allowHtml: true, alternatingRowStyle: true});
|
table.draw(data, {allowHtml: true, alternatingRowStyle: true});
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def dump_html():
|
def dump_html(output_stream):
|
||||||
"""Dump the html output to stdout."""
|
"""Dump the html output to output_stream."""
|
||||||
|
writer = make_writer(output_stream)
|
||||||
dump_html_prologue('Warnings for ' + platform_version + ' - ' +
|
dump_html_prologue('Warnings for ' + platform_version + ' - ' +
|
||||||
target_product + ' - ' + target_variant)
|
target_product + ' - ' + target_variant, writer)
|
||||||
dump_stats()
|
dump_stats(writer)
|
||||||
print('<br><div id="stats_table"></div><br>')
|
writer('<br><div id="stats_table"></div><br>')
|
||||||
print('\n<script>')
|
writer('\n<script>')
|
||||||
emit_js_data()
|
emit_js_data(writer)
|
||||||
print(scripts_for_warning_groups)
|
writer(scripts_for_warning_groups)
|
||||||
print('</script>')
|
writer('</script>')
|
||||||
emit_buttons()
|
emit_buttons(writer)
|
||||||
# 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>')
|
writer('<br><div id="warning_groups"></div>')
|
||||||
if args.byproject:
|
if args.byproject:
|
||||||
print('<script>groupByProject();</script>')
|
writer('<script>groupByProject();</script>')
|
||||||
else:
|
else:
|
||||||
print('<script>groupBySeverity();</script>')
|
writer('<script>groupBySeverity();</script>')
|
||||||
dump_fixed()
|
dump_fixed(writer)
|
||||||
dump_html_epilogue()
|
dump_html_epilogue(writer)
|
||||||
|
|
||||||
|
|
||||||
##### Functions to count warnings and dump csv file. #########################
|
##### Functions to count warnings and dump csv file. #########################
|
||||||
@@ -884,4 +900,4 @@ def common_main(parallel_process):
|
|||||||
if args.gencsv:
|
if args.gencsv:
|
||||||
dump_csv(csv.writer(sys.stdout, lineterminator='\n'))
|
dump_csv(csv.writer(sys.stdout, lineterminator='\n'))
|
||||||
else:
|
else:
|
||||||
dump_html()
|
dump_html(sys.stdout)
|
||||||
|
Reference in New Issue
Block a user