diff --git a/tools/warn/html_writer.py b/tools/warn/html_writer.py new file mode 100644 index 0000000000..b8d3fe6f5d --- /dev/null +++ b/tools/warn/html_writer.py @@ -0,0 +1,673 @@ +# Lint as: python3 +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Emit warning messages to html or csv files.""" + +# 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. +# FlagPlatform flags.platform +# FlagURL flags.url, used by 'android' +# FlagSeparator flags.separator, used by 'android' +# SeverityColors: list of colors for all severity levels +# SeverityHeaders: list of headers for all severity levels +# SeverityColumnHeaders: list of column_headers for all severity levels +# ProjectNames: project_names, or project_list[*][0] +# WarnPatternsSeverity: warn_patterns[*]['severity'] +# WarnPatternsDescription: warn_patterns[*]['description'] +# 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(): + +from __future__ import print_function +import cgi +import csv +import sys + +# pylint:disable=relative-beyond-top-level +# pylint:disable=g-importing-member +from .severity import Severity + + +html_head_scripts = """\ + + + +""" + + +def make_writer(output_stream): + + def writer(text): + return output_stream.write(text + '\n') + + return writer + + +def html_big(param): + return '' + param + '' + + +def dump_html_prologue(title, writer, warn_patterns, project_names): + writer('\n') + writer('' + title + '') + writer(html_head_scripts) + emit_stats_by_project(writer, warn_patterns, project_names) + writer('\n') + writer(html_big(title)) + writer('

') + + +def dump_html_epilogue(writer): + writer('\n\n') + + +def sort_warnings(warn_patterns): + for i in warn_patterns: + i['members'] = sorted(set(i['members'])) + + +def create_warnings(warn_patterns, project_names): + """Creates warnings s.t. + + warnings[p][s] is as specified in above docs. + + Args: + warn_patterns: list of warning patterns for specified platform + project_names: list of project names + + Returns: + 2D warnings array where warnings[p][s] is # of warnings in project name p of + severity level s + """ + # pylint:disable=g-complex-comprehension + warnings = {p: {s.value: 0 for s in Severity.levels} for p in project_names} + for i in warn_patterns: + s = i['severity'].value + for p in i['projects']: + warnings[p][s] += i['projects'][p] + return warnings + + +def get_total_by_project(warnings, project_names): + """Returns dict, project as key and # warnings for that project as value.""" + # pylint:disable=g-complex-comprehension + return { + p: sum(warnings[p][s.value] for s in Severity.levels) + for p in project_names + } + + +def get_total_by_severity(warnings, project_names): + """Returns dict, severity as key and # warnings of that severity as value.""" + # pylint:disable=g-complex-comprehension + return { + s.value: sum(warnings[p][s.value] for p in project_names) + for s in Severity.levels + } + + +def emit_table_header(total_by_severity): + """Returns list of HTML-formatted content for severity stats.""" + + stats_header = ['Project'] + for s in Severity.levels: + if total_by_severity[s.value]: + stats_header.append( + '{}'.format( + s.color, s.column_header)) + stats_header.append('TOTAL') + return stats_header + + +def emit_row_counts_per_project(warnings, total_by_project, total_by_severity, + project_names): + """Returns total project warnings and row of stats for each project. + + Args: + warnings: output of create_warnings(warn_patterns, project_names) + total_by_project: output of get_total_by_project(project_names) + total_by_severity: output of get_total_by_severity(project_names) + project_names: list of project names + + Returns: + total_all_projects, the total number of warnings over all projects + stats_rows, a 2d list where each row is [Project Name, , + total # warnings for this project] + """ + + total_all_projects = 0 + stats_rows = [] + for p in project_names: + if total_by_project[p]: + one_row = [p] + for s in Severity.levels: + if total_by_severity[s.value]: + one_row.append(warnings[p][s.value]) + one_row.append(total_by_project[p]) + stats_rows.append(one_row) + total_all_projects += total_by_project[p] + return total_all_projects, stats_rows + + +def emit_row_counts_per_severity(total_by_severity, stats_header, stats_rows, + total_all_projects, writer): + """Emits stats_header and stats_rows as specified above. + + Args: + total_by_severity: output of get_total_by_severity() + stats_header: output of emit_table_header() + stats_rows: output of emit_row_counts_per_project() + total_all_projects: output of emit_row_counts_per_project() + writer: writer returned by make_writer(output_stream) + """ + + total_all_severities = 0 + one_row = ['TOTAL'] + for s in Severity.levels: + if total_by_severity[s.value]: + one_row.append(total_by_severity[s.value]) + total_all_severities += total_by_severity[s.value] + one_row.append(total_all_projects) + stats_rows.append(one_row) + writer('') + + +def emit_stats_by_project(writer, warn_patterns, project_names): + """Dump a google chart table of warnings per project and severity.""" + + warnings = create_warnings(warn_patterns, project_names) + total_by_project = get_total_by_project(warnings, project_names) + total_by_severity = get_total_by_severity(warnings, project_names) + stats_header = emit_table_header(total_by_severity) + total_all_projects, stats_rows = \ + emit_row_counts_per_project(warnings, total_by_project, total_by_severity, project_names) + emit_row_counts_per_severity(total_by_severity, stats_header, stats_rows, + total_all_projects, writer) + + +def dump_stats(writer, warn_patterns): + """Dump some stats about total number of warnings and such.""" + + known = 0 + skipped = 0 + unknown = 0 + sort_warnings(warn_patterns) + for i in warn_patterns: + if i['severity'] == Severity.UNMATCHED: + unknown += len(i['members']) + elif i['severity'] == Severity.SKIP: + skipped += len(i['members']) + else: + known += len(i['members']) + writer('Number of classified warnings: ' + str(known) + '
') + writer('Number of skipped warnings: ' + str(skipped) + '
') + writer('Number of unclassified warnings: ' + str(unknown) + '
') + total = unknown + known + skipped + extra_msg = '' + if total < 1000: + extra_msg = ' (low count may indicate incremental build)' + writer('Total number of warnings: ' + str(total) + '' + extra_msg) + + +# New base table of warnings, [severity, warn_id, project, warning_message] +# Need buttons to show warnings in different grouping options. +# (1) Current, group by severity, id for each warning pattern +# sort by severity, warn_id, warning_message +# (2) Current --byproject, group by severity, +# id for each warning pattern + project name +# sort by severity, warn_id, project, warning_message +# (3) New, group by project + severity, +# id for each warning pattern +# sort by project, severity, warn_id, warning_message +def emit_buttons(writer): + writer('\n' + '\n' + '\n' + '
') + + +def all_patterns(category): + patterns = '' + for i in category['patterns']: + patterns += i + patterns += ' / ' + return patterns + + +def dump_fixed(writer, warn_patterns): + """Show which warnings no longer occur.""" + anchor = 'fixed_warnings' + mark = anchor + '_mark' + writer('\n

' + ' Fixed warnings. ' + 'No more occurrences. Please consider turning these into ' + 'errors if possible, before they are reintroduced in to the build' + ':

') + writer('
') + fixed_patterns = [] + for i in warn_patterns: + if not i['members']: + fixed_patterns.append(i['description'] + ' (' + all_patterns(i) + ')') + fixed_patterns = sorted(fixed_patterns) + writer('') + writer('
') + + +def write_severity(csvwriter, sev, kind, warn_patterns): + """Count warnings of given severity and write CSV entries to writer.""" + total = 0 + for pattern in warn_patterns: + if pattern['severity'] == sev and pattern['members']: + n = len(pattern['members']) + total += n + warning = kind + ': ' + (pattern['description'] or '?') + csvwriter.writerow([n, '', warning]) + # print number of warnings for each project, ordered by project name + projects = sorted(pattern['projects'].keys()) + for project in projects: + csvwriter.writerow([pattern['projects'][project], project, warning]) + csvwriter.writerow([total, '', kind + ' warnings']) + return total + + +def dump_csv(csvwriter, warn_patterns): + """Dump number of warnings in CSV format to writer.""" + sort_warnings(warn_patterns) + total = 0 + for s in Severity.levels: + total += write_severity(csvwriter, s, s.column_header, warn_patterns) + csvwriter.writerow([total, '', 'All warnings']) + + +# Return s with escaped backslash and quotation characters. +def escape_string(s): + return s.replace('\\', '\\\\').replace('"', '\\"') + + +# Return s without trailing '\n' and escape the quotation characters. +def strip_escape_string(s): + if not s: + return s + s = s[:-1] if s[-1] == '\n' else s + return escape_string(s) + + +def emit_warning_array(name, writer, warn_patterns): + writer('var warning_{} = ['.format(name)) + for w in warn_patterns: + if name == 'severity': + writer('{},'.format(w[name].value)) + else: + writer('{},'.format(w[name])) + writer('];') + + +def emit_warning_arrays(writer, warn_patterns): + emit_warning_array('severity', writer, warn_patterns) + writer('var warning_description = [') + for w in warn_patterns: + if w['members']: + writer('"{}",'.format(escape_string(w['description']))) + else: + writer('"",') # no such warning + writer('];') + + +scripts_for_warning_groups = """ + function compareMessages(x1, x2) { // of the same warning type + return (WarningMessages[x1[2]] <= WarningMessages[x2[2]]) ? -1 : 1; + } + function byMessageCount(x1, x2) { + return x2[2] - x1[2]; // reversed order + } + function bySeverityMessageCount(x1, x2) { + // orer by severity first + if (x1[1] != x2[1]) + return x1[1] - x2[1]; + return byMessageCount(x1, x2); + } + const ParseLinePattern = /^([^ :]+):(\\d+):(.+)/; + function addURL(line) { // used by Android + if (FlagURL == "") return line; + if (FlagSeparator == "") { + return line.replace(ParseLinePattern, + "$1:$2:$3"); + } + return line.replace(ParseLinePattern, + "$1:$2:$3"); + } + function addURLToLine(line, link) { // used by Chrome + let line_split = line.split(":"); + let path = line_split.slice(0,3).join(":"); + let msg = line_split.slice(3).join(":"); + let html_link = `${path}${msg}`; + return html_link; + } + function createArrayOfDictionaries(n) { + var result = []; + for (var i=0; i" + + " " + + description + " (" + messages.length + ")"; + result += ""; + } + if (result.length > 0) { + return "
" + + header + ": " + totalMessages + + "
" + + result + "
"; + + } + return ""; // empty section + } + function generateSectionsBySeverity() { + var result = ""; + var groups = groupWarningsBySeverity(); + for (s=0; s

') + writer('\n') + emit_buttons(writer) + # Warning messages are grouped by severities or project names. + writer('
') + if flags.byproject: + writer('') + else: + writer('') + dump_fixed(writer, warn_patterns) + dump_html_epilogue(writer) + + +def write_html(flags, project_names, warn_patterns, html_path, warning_messages, + warning_links, warning_records, header_str): + """Write warnings html file.""" + if html_path: + with open(html_path, 'w') as f: + dump_html(flags, f, warning_messages, warning_links, warning_records, + header_str, warn_patterns, project_names) + + +def write_out_csv(flags, warn_patterns, warning_messages, warning_links, + warning_records, header_str, project_names): + """Write warnings csv file.""" + if flags.csvpath: + with open(flags.csvpath, 'w') as f: + dump_csv(csv.writer(f, lineterminator='\n'), warn_patterns) + + if flags.gencsv: + dump_csv(csv.writer(sys.stdout, lineterminator='\n'), warn_patterns) + else: + dump_html(flags, sys.stdout, warning_messages, warning_links, + warning_records, header_str, warn_patterns, project_names) diff --git a/tools/warn/java_warn_patterns.py b/tools/warn/java_warn_patterns.py index b5b4d9a49a..17e3864daf 100644 --- a/tools/warn/java_warn_patterns.py +++ b/tools/warn/java_warn_patterns.py @@ -16,8 +16,8 @@ """Warning patterns for Java compiler tools.""" # pylint:disable=relative-beyond-top-level -from .cpp_warn_patterns import compile_patterns # pylint:disable=g-importing-member +from .cpp_warn_patterns import compile_patterns from .severity import Severity diff --git a/tools/warn/make_warn_patterns.py b/tools/warn/make_warn_patterns.py index dd6a1b0419..4b20493ba1 100644 --- a/tools/warn/make_warn_patterns.py +++ b/tools/warn/make_warn_patterns.py @@ -16,8 +16,8 @@ """Warning patterns for build make tools.""" # pylint:disable=relative-beyond-top-level -from .cpp_warn_patterns import compile_patterns # pylint:disable=g-importing-member +from .cpp_warn_patterns import compile_patterns from .severity import Severity warn_patterns = [ diff --git a/tools/warn/other_warn_patterns.py b/tools/warn/other_warn_patterns.py index cd55aaaf92..318c3d47f5 100644 --- a/tools/warn/other_warn_patterns.py +++ b/tools/warn/other_warn_patterns.py @@ -16,8 +16,8 @@ """Warning patterns from other tools.""" # pylint:disable=relative-beyond-top-level -from .cpp_warn_patterns import compile_patterns # pylint:disable=g-importing-member +from .cpp_warn_patterns import compile_patterns from .severity import Severity diff --git a/tools/warn/tidy_warn_patterns.py b/tools/warn/tidy_warn_patterns.py index 036e2bbfd6..5416cb23d7 100644 --- a/tools/warn/tidy_warn_patterns.py +++ b/tools/warn/tidy_warn_patterns.py @@ -16,8 +16,8 @@ """Warning patterns for clang-tidy.""" # pylint:disable=relative-beyond-top-level -from .cpp_warn_patterns import compile_patterns # pylint:disable=g-importing-member +from .cpp_warn_patterns import compile_patterns from .severity import Severity diff --git a/tools/warn/warn_common.py b/tools/warn/warn_common.py index 329f1e5524..68ed995c00 100755 --- a/tools/warn/warn_common.py +++ b/tools/warn/warn_common.py @@ -45,46 +45,7 @@ Default input file is build.log, which can be changed with the --log flag. # idx to warning_links] # 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. -# FlagPlatform flags.platform -# FlagURL flags.url, used by 'android' -# FlagSeparator flags.separator, used by 'android' -# SeverityColors: list of colors for all severity levels -# SeverityHeaders: list of headers for all severity levels -# SeverityColumnHeaders: list of column_headers for all severity levels -# ProjectNames: project_names, or project_list[*][0] -# WarnPatternsSeverity: warn_patterns[*]['severity'] -# WarnPatternsDescription: warn_patterns[*]['description'] -# 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(): - -from __future__ import print_function import argparse -import cgi -import csv import io import multiprocessing import os @@ -92,15 +53,15 @@ import re import sys # pylint:disable=relative-beyond-top-level +# pylint:disable=g-importing-member from . import android_project_list from . import chrome_project_list from . import cpp_warn_patterns as cpp_patterns +from . import html_writer from . import java_warn_patterns as java_patterns from . import make_warn_patterns as make_patterns from . import other_warn_patterns as other_patterns from . import tidy_warn_patterns as tidy_patterns -# pylint:disable=g-importing-member -from .severity import Severity def parse_args(use_google3): @@ -150,304 +111,6 @@ def get_project_names(project_list): return [p[0] for p in project_list] -html_head_scripts = """\ - - - -""" - - -def make_writer(output_stream): - - def writer(text): - return output_stream.write(text + '\n') - - return writer - - -def html_big(param): - return '' + param + '' - - -def dump_html_prologue(title, writer, warn_patterns, project_names): - writer('\n') - writer('' + title + '') - writer(html_head_scripts) - emit_stats_by_project(writer, warn_patterns, project_names) - writer('\n') - writer(html_big(title)) - writer('

') - - -def dump_html_epilogue(writer): - writer('\n\n') - - -def sort_warnings(warn_patterns): - for i in warn_patterns: - i['members'] = sorted(set(i['members'])) - - -def create_warnings(warn_patterns, project_names): - """Creates warnings s.t. - - warnings[p][s] is as specified in above docs. - - Args: - warn_patterns: list of warning patterns for specified platform - project_names: list of project names - - Returns: - 2D warnings array where warnings[p][s] is # of warnings in project name p of - severity level s - """ - # pylint:disable=g-complex-comprehension - warnings = {p: {s.value: 0 for s in Severity.levels} for p in project_names} - for i in warn_patterns: - s = i['severity'].value - for p in i['projects']: - warnings[p][s] += i['projects'][p] - return warnings - - -def get_total_by_project(warnings, project_names): - """Returns dict, project as key and # warnings for that project as value.""" - # pylint:disable=g-complex-comprehension - return { - p: sum(warnings[p][s.value] for s in Severity.levels) - for p in project_names - } - - -def get_total_by_severity(warnings, project_names): - """Returns dict, severity as key and # warnings of that severity as value.""" - # pylint:disable=g-complex-comprehension - return { - s.value: sum(warnings[p][s.value] for p in project_names) - for s in Severity.levels - } - - -def emit_table_header(total_by_severity): - """Returns list of HTML-formatted content for severity stats.""" - - stats_header = ['Project'] - for s in Severity.levels: - if total_by_severity[s.value]: - stats_header.append( - '{}'.format( - s.color, s.column_header)) - stats_header.append('TOTAL') - return stats_header - - -def emit_row_counts_per_project(warnings, total_by_project, total_by_severity, - project_names): - """Returns total project warnings and row of stats for each project. - - Args: - warnings: output of create_warnings(warn_patterns, project_names) - total_by_project: output of get_total_by_project(project_names) - total_by_severity: output of get_total_by_severity(project_names) - project_names: list of project names - - Returns: - total_all_projects, the total number of warnings over all projects - stats_rows, a 2d list where each row is [Project Name, , - total # warnings for this project] - """ - - total_all_projects = 0 - stats_rows = [] - for p in project_names: - if total_by_project[p]: - one_row = [p] - for s in Severity.levels: - if total_by_severity[s.value]: - one_row.append(warnings[p][s.value]) - one_row.append(total_by_project[p]) - stats_rows.append(one_row) - total_all_projects += total_by_project[p] - return total_all_projects, stats_rows - - -def emit_row_counts_per_severity(total_by_severity, stats_header, stats_rows, - total_all_projects, writer): - """Emits stats_header and stats_rows as specified above. - - Args: - total_by_severity: output of get_total_by_severity() - stats_header: output of emit_table_header() - stats_rows: output of emit_row_counts_per_project() - total_all_projects: output of emit_row_counts_per_project() - writer: writer returned by make_writer(output_stream) - """ - - total_all_severities = 0 - one_row = ['TOTAL'] - for s in Severity.levels: - if total_by_severity[s.value]: - one_row.append(total_by_severity[s.value]) - total_all_severities += total_by_severity[s.value] - one_row.append(total_all_projects) - stats_rows.append(one_row) - writer('') - - -def emit_stats_by_project(writer, warn_patterns, project_names): - """Dump a google chart table of warnings per project and severity.""" - - warnings = create_warnings(warn_patterns, project_names) - total_by_project = get_total_by_project(warnings, project_names) - total_by_severity = get_total_by_severity(warnings, project_names) - stats_header = emit_table_header(total_by_severity) - total_all_projects, stats_rows = \ - emit_row_counts_per_project(warnings, total_by_project, total_by_severity, project_names) - emit_row_counts_per_severity(total_by_severity, stats_header, stats_rows, - total_all_projects, writer) - - -def dump_stats(writer, warn_patterns): - """Dump some stats about total number of warnings and such.""" - - known = 0 - skipped = 0 - unknown = 0 - sort_warnings(warn_patterns) - for i in warn_patterns: - if i['severity'] == Severity.UNMATCHED: - unknown += len(i['members']) - elif i['severity'] == Severity.SKIP: - skipped += len(i['members']) - else: - known += len(i['members']) - writer('Number of classified warnings: ' + str(known) + '
') - writer('Number of skipped warnings: ' + str(skipped) + '
') - writer('Number of unclassified warnings: ' + str(unknown) + '
') - total = unknown + known + skipped - extra_msg = '' - if total < 1000: - extra_msg = ' (low count may indicate incremental build)' - writer('Total number of warnings: ' + str(total) + '' + extra_msg) - - -# New base table of warnings, [severity, warn_id, project, warning_message] -# Need buttons to show warnings in different grouping options. -# (1) Current, group by severity, id for each warning pattern -# sort by severity, warn_id, warning_message -# (2) Current --byproject, group by severity, -# id for each warning pattern + project name -# sort by severity, warn_id, project, warning_message -# (3) New, group by project + severity, -# id for each warning pattern -# sort by project, severity, warn_id, warning_message -def emit_buttons(writer): - writer('\n' - '\n' - '\n' - '
') - - -def all_patterns(category): - patterns = '' - for i in category['patterns']: - patterns += i - patterns += ' / ' - return patterns - - -def dump_fixed(writer, warn_patterns): - """Show which warnings no longer occur.""" - anchor = 'fixed_warnings' - mark = anchor + '_mark' - writer('\n

' - ' Fixed warnings. ' - 'No more occurrences. Please consider turning these into ' - 'errors if possible, before they are reintroduced in to the build' - ':

') - writer('
') - fixed_patterns = [] - for i in warn_patterns: - if not i['members']: - fixed_patterns.append(i['description'] + ' (' + all_patterns(i) + ')') - fixed_patterns = sorted(fixed_patterns) - writer('') - writer('
') - - -def write_severity(csvwriter, sev, kind, warn_patterns): - """Count warnings of given severity and write CSV entries to writer.""" - total = 0 - for pattern in warn_patterns: - if pattern['severity'] == sev and pattern['members']: - n = len(pattern['members']) - total += n - warning = kind + ': ' + (pattern['description'] or '?') - csvwriter.writerow([n, '', warning]) - # print number of warnings for each project, ordered by project name - projects = sorted(pattern['projects'].keys()) - for project in projects: - csvwriter.writerow([pattern['projects'][project], project, warning]) - csvwriter.writerow([total, '', kind + ' warnings']) - return total - - -def dump_csv(csvwriter, warn_patterns): - """Dump number of warnings in CSV format to writer.""" - sort_warnings(warn_patterns) - total = 0 - for s in Severity.levels: - total += write_severity(csvwriter, s, s.column_header, warn_patterns) - csvwriter.writerow([total, '', 'All warnings']) - - def find_project_index(line, project_patterns): for i, p in enumerate(project_patterns): if p.match(line): @@ -766,297 +429,6 @@ def parse_input_file(infile, flags): flags.platform) -# Return s with escaped backslash and quotation characters. -def escape_string(s): - return s.replace('\\', '\\\\').replace('"', '\\"') - - -# Return s without trailing '\n' and escape the quotation characters. -def strip_escape_string(s): - if not s: - return s - s = s[:-1] if s[-1] == '\n' else s - return escape_string(s) - - -def emit_warning_array(name, writer, warn_patterns): - writer('var warning_{} = ['.format(name)) - for w in warn_patterns: - if name == 'severity': - writer('{},'.format(w[name].value)) - else: - writer('{},'.format(w[name])) - writer('];') - - -def emit_warning_arrays(writer, warn_patterns): - emit_warning_array('severity', writer, warn_patterns) - writer('var warning_description = [') - for w in warn_patterns: - if w['members']: - writer('"{}",'.format(escape_string(w['description']))) - else: - writer('"",') # no such warning - writer('];') - - -scripts_for_warning_groups = """ - function compareMessages(x1, x2) { // of the same warning type - return (WarningMessages[x1[2]] <= WarningMessages[x2[2]]) ? -1 : 1; - } - function byMessageCount(x1, x2) { - return x2[2] - x1[2]; // reversed order - } - function bySeverityMessageCount(x1, x2) { - // orer by severity first - if (x1[1] != x2[1]) - return x1[1] - x2[1]; - return byMessageCount(x1, x2); - } - const ParseLinePattern = /^([^ :]+):(\\d+):(.+)/; - function addURL(line) { // used by Android - if (FlagURL == "") return line; - if (FlagSeparator == "") { - return line.replace(ParseLinePattern, - "$1:$2:$3"); - } - return line.replace(ParseLinePattern, - "$1:$2:$3"); - } - function addURLToLine(line, link) { // used by Chrome - let line_split = line.split(":"); - let path = line_split.slice(0,3).join(":"); - let msg = line_split.slice(3).join(":"); - let html_link = `${path}${msg}`; - return html_link; - } - function createArrayOfDictionaries(n) { - var result = []; - for (var i=0; i" + - " " + - description + " (" + messages.length + ")"; - result += ""; - } - if (result.length > 0) { - return "
" + - header + ": " + totalMessages + - "
" + - result + "
"; - - } - return ""; // empty section - } - function generateSectionsBySeverity() { - var result = ""; - var groups = groupWarningsBySeverity(); - for (s=0; s

') - writer('\n') - emit_buttons(writer) - # Warning messages are grouped by severities or project names. - writer('
') - if flags.byproject: - writer('') - else: - writer('') - dump_fixed(writer, warn_patterns) - dump_html_epilogue(writer) - - def parse_compiler_output(compiler_output): """Parse compiler output for relevant info.""" split_output = compiler_output.split(':', 3) # 3 = max splits @@ -1153,29 +525,6 @@ def parallel_classify_warnings(warning_data, args, project_names, return warning_messages, warning_links, warning_records -def write_html(flags, project_names, warn_patterns, html_path, warning_messages, - warning_links, warning_records, header_str): - """Write warnings html file.""" - if html_path: - with open(html_path, 'w') as f: - dump_html(flags, f, warning_messages, warning_links, warning_records, - header_str, warn_patterns, project_names) - - -def write_out_csv(flags, warn_patterns, warning_messages, warning_links, - warning_records, header_str, project_names): - """Write warnings csv file.""" - if flags.csvpath: - with open(flags.csvpath, 'w') as f: - dump_csv(csv.writer(f, lineterminator='\n'), warn_patterns) - - if flags.gencsv: - dump_csv(csv.writer(sys.stdout, lineterminator='\n'), warn_patterns) - else: - dump_html(flags, sys.stdout, warning_messages, warning_links, - warning_records, header_str, warn_patterns, project_names) - - def process_log(logfile, flags, project_names, project_patterns, warn_patterns, html_path, use_google3, create_launch_subprocs_fn, classify_warnings_fn, logfile_object): @@ -1200,9 +549,9 @@ def process_log(logfile, flags, project_names, project_patterns, warn_patterns, warn_patterns, use_google3, create_launch_subprocs_fn, classify_warnings_fn) - write_html(flags, project_names, warn_patterns, html_path, - warning_messages, warning_links, warning_records, - header_str) + html_writer.write_html(flags, project_names, warn_patterns, html_path, + warning_messages, warning_links, warning_records, + header_str) return warning_messages, warning_links, warning_records, header_str @@ -1226,8 +575,9 @@ def common_main(use_google3, create_launch_subprocs_fn, classify_warnings_fn, classify_warnings_fn=classify_warnings_fn, logfile_object=logfile_object) - write_out_csv(flags, warn_patterns, warning_messages, warning_links, - warning_records, header_str, project_names) + html_writer.write_out_csv(flags, warn_patterns, warning_messages, + warning_links, warning_records, header_str, + project_names) # Return these values, so that caller can use them, if desired. return flags, warning_messages, warning_records, warn_patterns