From d4691ecfb65a435aa4951696642ef462319f844f Mon Sep 17 00:00:00 2001 From: Chih-Hung Hsieh Date: Mon, 27 Dec 2021 17:33:36 -0800 Subject: [PATCH] Show directories and files with most warnings. * Now with 4 sections that can be shown/hidden independently. * After the 'selected_projects' section, add two more sections: * 'top_directory_section' contains * a table of directories with at least 1% warnings. * a 'selected_directory_warnings' subsection to show all warnings in the clicked directory from the directory table * 'top_file_section' contains * a table of files with at least 100 or 1% warnings. * a 'selected_file_warnings' subsection to show all warnings in the clicked file from the file table * Adjust button/section spaces and reduce button font size to 100%. * Rename drawTable to genTables. Test: warn.py --url=http://cs/android --separator='?l=' build.log > warnings.html Test: warn.py --gencsv build.log > warnings.csv Change-Id: I765b09a46adc111cfe781719ba7aa0f917aa6ffc --- tools/warn/html_writer.py | 234 ++++++++++++++++++++++++++++++++++---- 1 file changed, 213 insertions(+), 21 deletions(-) diff --git a/tools/warn/html_writer.py b/tools/warn/html_writer.py index ef173bcb3f..3fa822a9b2 100644 --- a/tools/warn/html_writer.py +++ b/tools/warn/html_writer.py @@ -63,6 +63,11 @@ import sys from .severity import Severity +# Report files with this number of warnings or more. +LIMIT_WARNINGS_PER_FILE = 100 +# Report files/directories with this percentage of total warnings or more. +LIMIT_PERCENT_WARNINGS = 1 + HTML_HEAD_SCRIPTS = """\ """ @@ -287,14 +293,14 @@ def dump_stats(writer, warn_patterns): # sort by project, severity, warn_id, warning_message def emit_buttons(writer): """Write the button elements in HTML.""" - writer('\n' '\n' - '\n' '
') + 'Group warnings by project') def all_patterns(category): @@ -559,6 +565,11 @@ SCRIPTS_FOR_WARNING_GROUPS = """ """ +# Emit a JavaScript const number +def emit_const_number(name, value, writer): + writer('const ' + name + ' = ' + str(value) + ';') + + # Emit a JavaScript const string def emit_const_string(name, value, writer): writer('const ' + name + ' = "' + escape_string(value) + '";') @@ -602,6 +613,8 @@ def emit_js_data(writer, flags, warning_messages, warning_links, emit_const_string('FlagPlatform', flags.platform, writer) emit_const_string('FlagURL', flags.url, writer) emit_const_string('FlagSeparator', flags.separator, writer) + emit_const_number('LimitWarningsPerFile', LIMIT_WARNINGS_PER_FILE, writer) + emit_const_number('LimitPercentWarnings', LIMIT_PERCENT_WARNINGS, writer) emit_const_string_array('SeverityColors', [s.color for s in Severity.levels], writer) emit_const_string_array('SeverityHeaders', @@ -624,8 +637,8 @@ def emit_js_data(writer, flags, warning_messages, warning_links, DRAW_TABLE_JAVASCRIPT = """ google.charts.load('current', {'packages':['table']}); -google.charts.setOnLoadCallback(drawTable); -function drawTable() { +google.charts.setOnLoadCallback(genTables); +function genSelectedProjectsTable() { var data = new google.visualization.DataTable(); data.addColumn('string', StatsHeader[0]); for (var i=1; i, f:}, file_or_dir_name] + function countWarnings(minWarnings, warningsOf, isDir) { + var rows = []; + for (var name in warningsOf) { + if (isDir && name in subDirs && Object.keys(subDirs[name]).length < 2) { + continue; // skip a directory if it has only one subdir + } + var count = warningsOf[name]; + if (count >= minWarnings) { + name = isDir ? (name + "/...") : name; + var percent = (100*count/numWarnings).toFixed(1); + var countFormat = count + ' (' + percent + '%)'; + rows.push([0, {v:count, f:countFormat}, name]); + } + } + rows.sort((a,b) => b[1].v - a[1].v); + for (var i=0; i{2}

'); + formatter.format(data, [0, 1, 2], 2); + var view = new google.visualization.DataView(data); + view.setColumns([1,2]); // hide the index column + var table = new google.visualization.Table( + document.getElementById(divName)); + table.draw(view, {allowHtml: true, alternatingRowStyle: true}); + } + addTable("Directory", "top_dirs_table", TopDirs, "selectDir"); + addTable("File", "top_files_table", TopFiles, "selectFile"); +} +function selectDirFile(idx, rows, dirFile) { + if (rows.length <= idx) { + return; + } + var name = rows[idx][2]; + var spanName = "selected_" + dirFile + "_name"; + document.getElementById(spanName).innerHTML = name; + var divName = "selected_" + dirFile + "_warnings"; + var numWarnings = rows[idx][1].v; + var prefix = name.replace(/\\.\\.\\.$/, ""); + var data = new google.visualization.DataTable(); + data.addColumn('string', numWarnings + ' warnings in ' + name); + var getWarningMessage = (FlagPlatform == "chrome") + ? ((x) => addURLToLine(WarningMessages[Warnings[x][2]], + WarningLinks[Warnings[x][3]])) + : ((x) => addURL(WarningMessages[Warnings[x][2]])); + for (var i = 0; i < Warnings.length; i++) { + if (WarningMessages[Warnings[i][2]].startsWith(prefix)) { + data.addRow([getWarningMessage(i)]); + } + } + var table = new google.visualization.Table( + document.getElementById(divName)); + table.draw(data, {allowHtml: true, alternatingRowStyle: true}); +} +function selectDir(idx) { + selectDirFile(idx, TopDirs, "directory") +} +function selectFile(idx) { + selectDirFile(idx, TopFiles, "file"); +} +function genTables() { + genSelectedProjectsTable(); + if (WarningMessages.length > 1) { + genTopDirsFilesTables(); + } +} """ +def dump_boxed_section(writer, func): + writer('
') + func() + writer('
') + + +def dump_section_header(writer, table_name, section_title): + writer('

\n' + + section_title + '

') + + +def dump_table_section(writer, table_name, section_title): + dump_section_header(writer, table_name, section_title) + writer('') + + +def dump_dir_file_section(writer, dir_file, table_name, section_title): + section_name = 'top_' + dir_file + '_section' + dump_section_header(writer, section_name, section_title) + writer('') + + +# HTML output has the following major div elements: +# selected_projects_section +# top_directory_section +# top_dirs_table +# selected_directory_warnings +# top_file_section +# top_files_table +# selected_file_warnings +# all_warnings_section +# warning_groups +# fixed_warnings def dump_html(flags, output_stream, warning_messages, warning_links, warning_records, header_str, warn_patterns, project_names): """Dump the flags output to output_stream.""" @@ -651,20 +819,44 @@ def dump_html(flags, output_stream, warning_messages, warning_links, dump_html_prologue('Warnings for ' + header_str, writer, warn_patterns, project_names) dump_stats(writer, warn_patterns) - writer('

') - 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) + writer('

Press ⊕ to show section content,' + ' and ⊖ to hide the content.') + def section1(): + dump_table_section(writer, 'selected_projects_section', + 'Number of warnings in preselected project directories') + def section2(): + dump_dir_file_section( + writer, 'directory', 'top_dirs_table', + 'Directories with at least ' + + str(LIMIT_PERCENT_WARNINGS) + '% warnings') + def section3(): + dump_dir_file_section( + writer, 'file', 'top_files_table', + 'Files with at least ' + + str(LIMIT_PERCENT_WARNINGS) + '% or ' + + str(LIMIT_WARNINGS_PER_FILE) + ' warnings') + def section4(): + writer('') + dump_section_header(writer, 'all_warnings_section', + 'All warnings grouped by severities or projects') + writer('') + dump_boxed_section(writer, section1) + dump_boxed_section(writer, section2) + dump_boxed_section(writer, section3) + dump_boxed_section(writer, section4) dump_html_epilogue(writer)