1*9e94795aSAndroid Build Coastguard Worker# Lint as: python3 2*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2019 The Android Open Source Project 3*9e94795aSAndroid Build Coastguard Worker# 4*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*9e94795aSAndroid Build Coastguard Worker# 8*9e94795aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*9e94795aSAndroid Build Coastguard Worker# 10*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*9e94795aSAndroid Build Coastguard Worker# limitations under the License. 15*9e94795aSAndroid Build Coastguard Worker 16*9e94795aSAndroid Build Coastguard Worker"""Emit warning messages to html or csv files.""" 17*9e94795aSAndroid Build Coastguard Worker 18*9e94795aSAndroid Build Coastguard Worker# Many functions in this module have too many arguments to be refactored. 19*9e94795aSAndroid Build Coastguard Worker# pylint:disable=too-many-arguments,missing-function-docstring 20*9e94795aSAndroid Build Coastguard Worker 21*9e94795aSAndroid Build Coastguard Worker# To emit html page of warning messages: 22*9e94795aSAndroid Build Coastguard Worker# flags: --byproject, --url, --separator 23*9e94795aSAndroid Build Coastguard Worker# Old stuff for static html components: 24*9e94795aSAndroid Build Coastguard Worker# html_script_style: static html scripts and styles 25*9e94795aSAndroid Build Coastguard Worker# htmlbig: 26*9e94795aSAndroid Build Coastguard Worker# dump_stats, dump_html_prologue, dump_html_epilogue: 27*9e94795aSAndroid Build Coastguard Worker# emit_buttons: 28*9e94795aSAndroid Build Coastguard Worker# dump_fixed 29*9e94795aSAndroid Build Coastguard Worker# sort_warnings: 30*9e94795aSAndroid Build Coastguard Worker# emit_stats_by_project: 31*9e94795aSAndroid Build Coastguard Worker# all_patterns, 32*9e94795aSAndroid Build Coastguard Worker# findproject, classify_warning 33*9e94795aSAndroid Build Coastguard Worker# dump_html 34*9e94795aSAndroid Build Coastguard Worker# 35*9e94795aSAndroid Build Coastguard Worker# New dynamic HTML page's static JavaScript data: 36*9e94795aSAndroid Build Coastguard Worker# Some data are copied from Python to JavaScript, to generate HTML elements. 37*9e94795aSAndroid Build Coastguard Worker# FlagPlatform flags.platform 38*9e94795aSAndroid Build Coastguard Worker# FlagURL flags.url, used by 'android' 39*9e94795aSAndroid Build Coastguard Worker# FlagSeparator flags.separator, used by 'android' 40*9e94795aSAndroid Build Coastguard Worker# SeverityColors: list of colors for all severity levels 41*9e94795aSAndroid Build Coastguard Worker# SeverityHeaders: list of headers for all severity levels 42*9e94795aSAndroid Build Coastguard Worker# SeverityColumnHeaders: list of column_headers for all severity levels 43*9e94795aSAndroid Build Coastguard Worker# ProjectNames: project_names, or project_list[*][0] 44*9e94795aSAndroid Build Coastguard Worker# WarnPatternsSeverity: warn_patterns[*]['severity'] 45*9e94795aSAndroid Build Coastguard Worker# WarnPatternsDescription: warn_patterns[*]['description'] 46*9e94795aSAndroid Build Coastguard Worker# WarningMessages: warning_messages 47*9e94795aSAndroid Build Coastguard Worker# Warnings: warning_records 48*9e94795aSAndroid Build Coastguard Worker# StatsHeader: warning count table header row 49*9e94795aSAndroid Build Coastguard Worker# StatsRows: array of warning count table rows 50*9e94795aSAndroid Build Coastguard Worker# 51*9e94795aSAndroid Build Coastguard Worker# New dynamic HTML page's dynamic JavaScript data: 52*9e94795aSAndroid Build Coastguard Worker# 53*9e94795aSAndroid Build Coastguard Worker# New dynamic HTML related function to emit data: 54*9e94795aSAndroid Build Coastguard Worker# escape_string, strip_escape_string, emit_warning_arrays 55*9e94795aSAndroid Build Coastguard Worker# emit_js_data(): 56*9e94795aSAndroid Build Coastguard Worker 57*9e94795aSAndroid Build Coastguard Workerfrom __future__ import print_function 58*9e94795aSAndroid Build Coastguard Workerimport csv 59*9e94795aSAndroid Build Coastguard Workerimport datetime 60*9e94795aSAndroid Build Coastguard Workerimport html 61*9e94795aSAndroid Build Coastguard Workerimport sys 62*9e94795aSAndroid Build Coastguard Worker 63*9e94795aSAndroid Build Coastguard Worker# pylint:disable=relative-beyond-top-level 64*9e94795aSAndroid Build Coastguard Workerfrom .severity import Severity 65*9e94795aSAndroid Build Coastguard Worker 66*9e94795aSAndroid Build Coastguard Worker 67*9e94795aSAndroid Build Coastguard Worker# Report files with this number of warnings or more. 68*9e94795aSAndroid Build Coastguard WorkerLIMIT_WARNINGS_PER_FILE = 100 69*9e94795aSAndroid Build Coastguard Worker# Report files/directories with this percentage of total warnings or more. 70*9e94795aSAndroid Build Coastguard WorkerLIMIT_PERCENT_WARNINGS = 1 71*9e94795aSAndroid Build Coastguard Worker 72*9e94795aSAndroid Build Coastguard WorkerHTML_HEAD_SCRIPTS = """\ 73*9e94795aSAndroid Build Coastguard Worker <script type="text/javascript"> 74*9e94795aSAndroid Build Coastguard Worker function expand(id) { 75*9e94795aSAndroid Build Coastguard Worker var e = document.getElementById(id); 76*9e94795aSAndroid Build Coastguard Worker var f = document.getElementById(id + "_mark"); 77*9e94795aSAndroid Build Coastguard Worker if (e.style.display == 'block') { 78*9e94795aSAndroid Build Coastguard Worker e.style.display = 'none'; 79*9e94795aSAndroid Build Coastguard Worker f.innerHTML = '⊕'; 80*9e94795aSAndroid Build Coastguard Worker } 81*9e94795aSAndroid Build Coastguard Worker else { 82*9e94795aSAndroid Build Coastguard Worker e.style.display = 'block'; 83*9e94795aSAndroid Build Coastguard Worker f.innerHTML = '⊖'; 84*9e94795aSAndroid Build Coastguard Worker } 85*9e94795aSAndroid Build Coastguard Worker }; 86*9e94795aSAndroid Build Coastguard Worker function expandCollapse(show) { 87*9e94795aSAndroid Build Coastguard Worker for (var id = 1; ; id++) { 88*9e94795aSAndroid Build Coastguard Worker var e = document.getElementById(id + ""); 89*9e94795aSAndroid Build Coastguard Worker var f = document.getElementById(id + "_mark"); 90*9e94795aSAndroid Build Coastguard Worker if (!e || !f) break; 91*9e94795aSAndroid Build Coastguard Worker e.style.display = (show ? 'block' : 'none'); 92*9e94795aSAndroid Build Coastguard Worker f.innerHTML = (show ? '⊖' : '⊕'); 93*9e94795aSAndroid Build Coastguard Worker } 94*9e94795aSAndroid Build Coastguard Worker }; 95*9e94795aSAndroid Build Coastguard Worker </script> 96*9e94795aSAndroid Build Coastguard Worker <style type="text/css"> 97*9e94795aSAndroid Build Coastguard Worker th,td{border-collapse:collapse; border:1px solid black;} 98*9e94795aSAndroid Build Coastguard Worker .button{color:blue;font-size:100%;font-weight:bolder;} 99*9e94795aSAndroid Build Coastguard Worker .bt{color:black;background-color:transparent;border:none;outline:none; 100*9e94795aSAndroid Build Coastguard Worker font-size:140%;font-weight:bolder;} 101*9e94795aSAndroid Build Coastguard Worker .c0{background-color:#e0e0e0;} 102*9e94795aSAndroid Build Coastguard Worker .c1{background-color:#d0d0d0;} 103*9e94795aSAndroid Build Coastguard Worker .t1{border-collapse:collapse; width:100%; border:1px solid black;} 104*9e94795aSAndroid Build Coastguard Worker .box{margin:5pt; padding:5pt; border:1px solid;} 105*9e94795aSAndroid Build Coastguard Worker </style> 106*9e94795aSAndroid Build Coastguard Worker <script src="https://www.gstatic.com/charts/loader.js"></script> 107*9e94795aSAndroid Build Coastguard Worker""" 108*9e94795aSAndroid Build Coastguard Worker 109*9e94795aSAndroid Build Coastguard Worker 110*9e94795aSAndroid Build Coastguard Workerdef make_writer(output_stream): 111*9e94795aSAndroid Build Coastguard Worker 112*9e94795aSAndroid Build Coastguard Worker def writer(text): 113*9e94795aSAndroid Build Coastguard Worker return output_stream.write(text + '\n') 114*9e94795aSAndroid Build Coastguard Worker 115*9e94795aSAndroid Build Coastguard Worker return writer 116*9e94795aSAndroid Build Coastguard Worker 117*9e94795aSAndroid Build Coastguard Worker 118*9e94795aSAndroid Build Coastguard Workerdef html_big(param): 119*9e94795aSAndroid Build Coastguard Worker return '<font size="+2">' + param + '</font>' 120*9e94795aSAndroid Build Coastguard Worker 121*9e94795aSAndroid Build Coastguard Worker 122*9e94795aSAndroid Build Coastguard Workerdef dump_html_prologue(title, writer, warn_patterns, project_names): 123*9e94795aSAndroid Build Coastguard Worker writer('<html>\n<head>') 124*9e94795aSAndroid Build Coastguard Worker writer('<title>' + title + '</title>') 125*9e94795aSAndroid Build Coastguard Worker writer(HTML_HEAD_SCRIPTS) 126*9e94795aSAndroid Build Coastguard Worker emit_stats_by_project(writer, warn_patterns, project_names) 127*9e94795aSAndroid Build Coastguard Worker writer('</head>\n<body>') 128*9e94795aSAndroid Build Coastguard Worker writer(html_big(title)) 129*9e94795aSAndroid Build Coastguard Worker writer('<p>') 130*9e94795aSAndroid Build Coastguard Worker 131*9e94795aSAndroid Build Coastguard Worker 132*9e94795aSAndroid Build Coastguard Workerdef dump_html_epilogue(writer): 133*9e94795aSAndroid Build Coastguard Worker writer('</body>\n</head>\n</html>') 134*9e94795aSAndroid Build Coastguard Worker 135*9e94795aSAndroid Build Coastguard Worker 136*9e94795aSAndroid Build Coastguard Workerdef sort_warnings(warn_patterns): 137*9e94795aSAndroid Build Coastguard Worker for i in warn_patterns: 138*9e94795aSAndroid Build Coastguard Worker i['members'] = sorted(set(i['members'])) 139*9e94795aSAndroid Build Coastguard Worker 140*9e94795aSAndroid Build Coastguard Worker 141*9e94795aSAndroid Build Coastguard Workerdef create_warnings(warn_patterns, project_names): 142*9e94795aSAndroid Build Coastguard Worker """Creates warnings s.t. 143*9e94795aSAndroid Build Coastguard Worker 144*9e94795aSAndroid Build Coastguard Worker warnings[p][s] is as specified in above docs. 145*9e94795aSAndroid Build Coastguard Worker 146*9e94795aSAndroid Build Coastguard Worker Args: 147*9e94795aSAndroid Build Coastguard Worker warn_patterns: list of warning patterns for specified platform 148*9e94795aSAndroid Build Coastguard Worker project_names: list of project names 149*9e94795aSAndroid Build Coastguard Worker 150*9e94795aSAndroid Build Coastguard Worker Returns: 151*9e94795aSAndroid Build Coastguard Worker 2D warnings array where warnings[p][s] is # of warnings in project name p of 152*9e94795aSAndroid Build Coastguard Worker severity level s 153*9e94795aSAndroid Build Coastguard Worker """ 154*9e94795aSAndroid Build Coastguard Worker warnings = {p: {s.value: 0 for s in Severity.levels} for p in project_names} 155*9e94795aSAndroid Build Coastguard Worker for pattern in warn_patterns: 156*9e94795aSAndroid Build Coastguard Worker value = pattern['severity'].value 157*9e94795aSAndroid Build Coastguard Worker for project in pattern['projects']: 158*9e94795aSAndroid Build Coastguard Worker warnings[project][value] += pattern['projects'][project] 159*9e94795aSAndroid Build Coastguard Worker return warnings 160*9e94795aSAndroid Build Coastguard Worker 161*9e94795aSAndroid Build Coastguard Worker 162*9e94795aSAndroid Build Coastguard Workerdef get_total_by_project(warnings, project_names): 163*9e94795aSAndroid Build Coastguard Worker """Returns dict, project as key and # warnings for that project as value.""" 164*9e94795aSAndroid Build Coastguard Worker return { 165*9e94795aSAndroid Build Coastguard Worker p: sum(warnings[p][s.value] for s in Severity.levels) 166*9e94795aSAndroid Build Coastguard Worker for p in project_names 167*9e94795aSAndroid Build Coastguard Worker } 168*9e94795aSAndroid Build Coastguard Worker 169*9e94795aSAndroid Build Coastguard Worker 170*9e94795aSAndroid Build Coastguard Workerdef get_total_by_severity(warnings, project_names): 171*9e94795aSAndroid Build Coastguard Worker """Returns dict, severity as key and # warnings of that severity as value.""" 172*9e94795aSAndroid Build Coastguard Worker return { 173*9e94795aSAndroid Build Coastguard Worker s.value: sum(warnings[p][s.value] for p in project_names) 174*9e94795aSAndroid Build Coastguard Worker for s in Severity.levels 175*9e94795aSAndroid Build Coastguard Worker } 176*9e94795aSAndroid Build Coastguard Worker 177*9e94795aSAndroid Build Coastguard Worker 178*9e94795aSAndroid Build Coastguard Workerdef emit_table_header(total_by_severity): 179*9e94795aSAndroid Build Coastguard Worker """Returns list of HTML-formatted content for severity stats.""" 180*9e94795aSAndroid Build Coastguard Worker 181*9e94795aSAndroid Build Coastguard Worker stats_header = ['Project'] 182*9e94795aSAndroid Build Coastguard Worker for severity in Severity.levels: 183*9e94795aSAndroid Build Coastguard Worker if total_by_severity[severity.value]: 184*9e94795aSAndroid Build Coastguard Worker stats_header.append( 185*9e94795aSAndroid Build Coastguard Worker '<span style=\'background-color:{}\'>{}</span>'.format( 186*9e94795aSAndroid Build Coastguard Worker severity.color, severity.column_header)) 187*9e94795aSAndroid Build Coastguard Worker stats_header.append('TOTAL') 188*9e94795aSAndroid Build Coastguard Worker return stats_header 189*9e94795aSAndroid Build Coastguard Worker 190*9e94795aSAndroid Build Coastguard Worker 191*9e94795aSAndroid Build Coastguard Workerdef emit_row_counts_per_project(warnings, total_by_project, total_by_severity, 192*9e94795aSAndroid Build Coastguard Worker project_names): 193*9e94795aSAndroid Build Coastguard Worker """Returns total project warnings and row of stats for each project. 194*9e94795aSAndroid Build Coastguard Worker 195*9e94795aSAndroid Build Coastguard Worker Args: 196*9e94795aSAndroid Build Coastguard Worker warnings: output of create_warnings(warn_patterns, project_names) 197*9e94795aSAndroid Build Coastguard Worker total_by_project: output of get_total_by_project(project_names) 198*9e94795aSAndroid Build Coastguard Worker total_by_severity: output of get_total_by_severity(project_names) 199*9e94795aSAndroid Build Coastguard Worker project_names: list of project names 200*9e94795aSAndroid Build Coastguard Worker 201*9e94795aSAndroid Build Coastguard Worker Returns: 202*9e94795aSAndroid Build Coastguard Worker total_all_projects, the total number of warnings over all projects 203*9e94795aSAndroid Build Coastguard Worker stats_rows, a 2d list where each row is [Project Name, <severity counts>, 204*9e94795aSAndroid Build Coastguard Worker total # warnings for this project] 205*9e94795aSAndroid Build Coastguard Worker """ 206*9e94795aSAndroid Build Coastguard Worker 207*9e94795aSAndroid Build Coastguard Worker total_all_projects = 0 208*9e94795aSAndroid Build Coastguard Worker stats_rows = [] 209*9e94795aSAndroid Build Coastguard Worker for p_name in project_names: 210*9e94795aSAndroid Build Coastguard Worker if total_by_project[p_name]: 211*9e94795aSAndroid Build Coastguard Worker one_row = [p_name] 212*9e94795aSAndroid Build Coastguard Worker for severity in Severity.levels: 213*9e94795aSAndroid Build Coastguard Worker if total_by_severity[severity.value]: 214*9e94795aSAndroid Build Coastguard Worker one_row.append(warnings[p_name][severity.value]) 215*9e94795aSAndroid Build Coastguard Worker one_row.append(total_by_project[p_name]) 216*9e94795aSAndroid Build Coastguard Worker stats_rows.append(one_row) 217*9e94795aSAndroid Build Coastguard Worker total_all_projects += total_by_project[p_name] 218*9e94795aSAndroid Build Coastguard Worker return total_all_projects, stats_rows 219*9e94795aSAndroid Build Coastguard Worker 220*9e94795aSAndroid Build Coastguard Worker 221*9e94795aSAndroid Build Coastguard Workerdef emit_row_counts_per_severity(total_by_severity, stats_header, stats_rows, 222*9e94795aSAndroid Build Coastguard Worker total_all_projects, writer): 223*9e94795aSAndroid Build Coastguard Worker """Emits stats_header and stats_rows as specified above. 224*9e94795aSAndroid Build Coastguard Worker 225*9e94795aSAndroid Build Coastguard Worker Args: 226*9e94795aSAndroid Build Coastguard Worker total_by_severity: output of get_total_by_severity() 227*9e94795aSAndroid Build Coastguard Worker stats_header: output of emit_table_header() 228*9e94795aSAndroid Build Coastguard Worker stats_rows: output of emit_row_counts_per_project() 229*9e94795aSAndroid Build Coastguard Worker total_all_projects: output of emit_row_counts_per_project() 230*9e94795aSAndroid Build Coastguard Worker writer: writer returned by make_writer(output_stream) 231*9e94795aSAndroid Build Coastguard Worker """ 232*9e94795aSAndroid Build Coastguard Worker 233*9e94795aSAndroid Build Coastguard Worker total_all_severities = 0 234*9e94795aSAndroid Build Coastguard Worker one_row = ['<b>TOTAL</b>'] 235*9e94795aSAndroid Build Coastguard Worker for severity in Severity.levels: 236*9e94795aSAndroid Build Coastguard Worker if total_by_severity[severity.value]: 237*9e94795aSAndroid Build Coastguard Worker one_row.append(total_by_severity[severity.value]) 238*9e94795aSAndroid Build Coastguard Worker total_all_severities += total_by_severity[severity.value] 239*9e94795aSAndroid Build Coastguard Worker one_row.append(total_all_projects) 240*9e94795aSAndroid Build Coastguard Worker stats_rows.append(one_row) 241*9e94795aSAndroid Build Coastguard Worker writer('<script>') 242*9e94795aSAndroid Build Coastguard Worker emit_const_string_array('StatsHeader', stats_header, writer) 243*9e94795aSAndroid Build Coastguard Worker emit_const_object_array('StatsRows', stats_rows, writer) 244*9e94795aSAndroid Build Coastguard Worker writer(DRAW_TABLE_JAVASCRIPT) 245*9e94795aSAndroid Build Coastguard Worker writer('</script>') 246*9e94795aSAndroid Build Coastguard Worker 247*9e94795aSAndroid Build Coastguard Worker 248*9e94795aSAndroid Build Coastguard Workerdef emit_stats_by_project(writer, warn_patterns, project_names): 249*9e94795aSAndroid Build Coastguard Worker """Dump a google chart table of warnings per project and severity.""" 250*9e94795aSAndroid Build Coastguard Worker 251*9e94795aSAndroid Build Coastguard Worker warnings = create_warnings(warn_patterns, project_names) 252*9e94795aSAndroid Build Coastguard Worker total_by_project = get_total_by_project(warnings, project_names) 253*9e94795aSAndroid Build Coastguard Worker total_by_severity = get_total_by_severity(warnings, project_names) 254*9e94795aSAndroid Build Coastguard Worker stats_header = emit_table_header(total_by_severity) 255*9e94795aSAndroid Build Coastguard Worker total_all_projects, stats_rows = emit_row_counts_per_project( 256*9e94795aSAndroid Build Coastguard Worker warnings, total_by_project, total_by_severity, project_names) 257*9e94795aSAndroid Build Coastguard Worker emit_row_counts_per_severity(total_by_severity, stats_header, stats_rows, 258*9e94795aSAndroid Build Coastguard Worker total_all_projects, writer) 259*9e94795aSAndroid Build Coastguard Worker 260*9e94795aSAndroid Build Coastguard Worker 261*9e94795aSAndroid Build Coastguard Workerdef dump_stats(writer, warn_patterns): 262*9e94795aSAndroid Build Coastguard Worker """Dump some stats about total number of warnings and date.""" 263*9e94795aSAndroid Build Coastguard Worker 264*9e94795aSAndroid Build Coastguard Worker known = 0 265*9e94795aSAndroid Build Coastguard Worker skipped = 0 266*9e94795aSAndroid Build Coastguard Worker unknown = 0 267*9e94795aSAndroid Build Coastguard Worker sort_warnings(warn_patterns) 268*9e94795aSAndroid Build Coastguard Worker for i in warn_patterns: 269*9e94795aSAndroid Build Coastguard Worker if i['severity'] == Severity.UNMATCHED: 270*9e94795aSAndroid Build Coastguard Worker unknown += len(i['members']) 271*9e94795aSAndroid Build Coastguard Worker elif i['severity'] == Severity.SKIP: 272*9e94795aSAndroid Build Coastguard Worker skipped += len(i['members']) 273*9e94795aSAndroid Build Coastguard Worker else: 274*9e94795aSAndroid Build Coastguard Worker known += len(i['members']) 275*9e94795aSAndroid Build Coastguard Worker writer('Number of classified warnings: <b>' + str(known) + '</b><br>') 276*9e94795aSAndroid Build Coastguard Worker writer('Number of skipped warnings: <b>' + str(skipped) + '</b><br>') 277*9e94795aSAndroid Build Coastguard Worker writer('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>') 278*9e94795aSAndroid Build Coastguard Worker total = unknown + known + skipped 279*9e94795aSAndroid Build Coastguard Worker extra_msg = '' 280*9e94795aSAndroid Build Coastguard Worker if total < 1000: 281*9e94795aSAndroid Build Coastguard Worker extra_msg = ' (low count may indicate incremental build)' 282*9e94795aSAndroid Build Coastguard Worker writer('Total number of warnings: <b>' + str(total) + '</b>' + extra_msg) 283*9e94795aSAndroid Build Coastguard Worker date_time_str = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S') 284*9e94795aSAndroid Build Coastguard Worker writer('<p>(generated on ' + date_time_str + ')') 285*9e94795aSAndroid Build Coastguard Worker 286*9e94795aSAndroid Build Coastguard Worker 287*9e94795aSAndroid Build Coastguard Worker# New base table of warnings, [severity, warn_id, project, warning_message] 288*9e94795aSAndroid Build Coastguard Worker# Need buttons to show warnings in different grouping options. 289*9e94795aSAndroid Build Coastguard Worker# (1) Current, group by severity, id for each warning pattern 290*9e94795aSAndroid Build Coastguard Worker# sort by severity, warn_id, warning_message 291*9e94795aSAndroid Build Coastguard Worker# (2) Current --byproject, group by severity, 292*9e94795aSAndroid Build Coastguard Worker# id for each warning pattern + project name 293*9e94795aSAndroid Build Coastguard Worker# sort by severity, warn_id, project, warning_message 294*9e94795aSAndroid Build Coastguard Worker# (3) New, group by project + severity, 295*9e94795aSAndroid Build Coastguard Worker# id for each warning pattern 296*9e94795aSAndroid Build Coastguard Worker# sort by project, severity, warn_id, warning_message 297*9e94795aSAndroid Build Coastguard Workerdef emit_buttons(writer): 298*9e94795aSAndroid Build Coastguard Worker """Write the button elements in HTML.""" 299*9e94795aSAndroid Build Coastguard Worker writer('<p><button class="button" onclick="expandCollapse(1);">' 300*9e94795aSAndroid Build Coastguard Worker 'Expand all warnings</button>\n' 301*9e94795aSAndroid Build Coastguard Worker '<button class="button" onclick="expandCollapse(0);">' 302*9e94795aSAndroid Build Coastguard Worker 'Collapse all warnings</button>\n' 303*9e94795aSAndroid Build Coastguard Worker '<p><button class="button" onclick="groupBySeverity();">' 304*9e94795aSAndroid Build Coastguard Worker 'Group warnings by severity</button>\n' 305*9e94795aSAndroid Build Coastguard Worker '<button class="button" onclick="groupByProject();">' 306*9e94795aSAndroid Build Coastguard Worker 'Group warnings by project</button>') 307*9e94795aSAndroid Build Coastguard Worker 308*9e94795aSAndroid Build Coastguard Worker 309*9e94795aSAndroid Build Coastguard Workerdef all_patterns(category): 310*9e94795aSAndroid Build Coastguard Worker patterns = '' 311*9e94795aSAndroid Build Coastguard Worker for i in category['patterns']: 312*9e94795aSAndroid Build Coastguard Worker patterns += i 313*9e94795aSAndroid Build Coastguard Worker patterns += ' / ' 314*9e94795aSAndroid Build Coastguard Worker return patterns 315*9e94795aSAndroid Build Coastguard Worker 316*9e94795aSAndroid Build Coastguard Worker 317*9e94795aSAndroid Build Coastguard Workerdef dump_fixed(writer, warn_patterns): 318*9e94795aSAndroid Build Coastguard Worker """Show which warnings no longer occur.""" 319*9e94795aSAndroid Build Coastguard Worker anchor = 'fixed_warnings' 320*9e94795aSAndroid Build Coastguard Worker mark = anchor + '_mark' 321*9e94795aSAndroid Build Coastguard Worker writer('\n<br><p style="background-color:lightblue"><b>' 322*9e94795aSAndroid Build Coastguard Worker '<button id="' + mark + '" ' 323*9e94795aSAndroid Build Coastguard Worker 'class="bt" onclick="expand(\'' + anchor + '\');">' 324*9e94795aSAndroid Build Coastguard Worker '⊕</button> Fixed warnings. ' 325*9e94795aSAndroid Build Coastguard Worker 'No more occurrences. Please consider turning these into ' 326*9e94795aSAndroid Build Coastguard Worker 'errors if possible, before they are reintroduced in to the build' 327*9e94795aSAndroid Build Coastguard Worker ':</b></p>') 328*9e94795aSAndroid Build Coastguard Worker writer('<blockquote>') 329*9e94795aSAndroid Build Coastguard Worker fixed_patterns = [] 330*9e94795aSAndroid Build Coastguard Worker for i in warn_patterns: 331*9e94795aSAndroid Build Coastguard Worker if not i['members']: 332*9e94795aSAndroid Build Coastguard Worker fixed_patterns.append(i['description'] + ' (' + all_patterns(i) + ')') 333*9e94795aSAndroid Build Coastguard Worker fixed_patterns = sorted(fixed_patterns) 334*9e94795aSAndroid Build Coastguard Worker writer('<div id="' + anchor + '" style="display:none;"><table>') 335*9e94795aSAndroid Build Coastguard Worker cur_row_class = 0 336*9e94795aSAndroid Build Coastguard Worker for text in fixed_patterns: 337*9e94795aSAndroid Build Coastguard Worker cur_row_class = 1 - cur_row_class 338*9e94795aSAndroid Build Coastguard Worker # remove last '\n' 339*9e94795aSAndroid Build Coastguard Worker out_text = text[:-1] if text[-1] == '\n' else text 340*9e94795aSAndroid Build Coastguard Worker writer('<tr><td class="c' + str(cur_row_class) + '">' 341*9e94795aSAndroid Build Coastguard Worker + out_text + '</td></tr>') 342*9e94795aSAndroid Build Coastguard Worker writer('</table></div>') 343*9e94795aSAndroid Build Coastguard Worker writer('</blockquote>') 344*9e94795aSAndroid Build Coastguard Worker 345*9e94795aSAndroid Build Coastguard Worker 346*9e94795aSAndroid Build Coastguard Workerdef write_severity(csvwriter, sev, kind, warn_patterns): 347*9e94795aSAndroid Build Coastguard Worker """Count warnings of given severity and write CSV entries to writer.""" 348*9e94795aSAndroid Build Coastguard Worker total = 0 349*9e94795aSAndroid Build Coastguard Worker for pattern in warn_patterns: 350*9e94795aSAndroid Build Coastguard Worker if pattern['severity'] == sev and pattern['members']: 351*9e94795aSAndroid Build Coastguard Worker num_members = len(pattern['members']) 352*9e94795aSAndroid Build Coastguard Worker total += num_members 353*9e94795aSAndroid Build Coastguard Worker warning = kind + ': ' + (pattern['description'] or '?') 354*9e94795aSAndroid Build Coastguard Worker csvwriter.writerow([num_members, '', warning]) 355*9e94795aSAndroid Build Coastguard Worker # print number of warnings for each project, ordered by project name 356*9e94795aSAndroid Build Coastguard Worker projects = sorted(pattern['projects'].keys()) 357*9e94795aSAndroid Build Coastguard Worker for project in projects: 358*9e94795aSAndroid Build Coastguard Worker csvwriter.writerow([pattern['projects'][project], project, warning]) 359*9e94795aSAndroid Build Coastguard Worker csvwriter.writerow([total, '', kind + ' warnings']) 360*9e94795aSAndroid Build Coastguard Worker return total 361*9e94795aSAndroid Build Coastguard Worker 362*9e94795aSAndroid Build Coastguard Worker 363*9e94795aSAndroid Build Coastguard Workerdef dump_csv(csvwriter, warn_patterns): 364*9e94795aSAndroid Build Coastguard Worker """Dump number of warnings in CSV format to writer.""" 365*9e94795aSAndroid Build Coastguard Worker sort_warnings(warn_patterns) 366*9e94795aSAndroid Build Coastguard Worker total = 0 367*9e94795aSAndroid Build Coastguard Worker for severity in Severity.levels: 368*9e94795aSAndroid Build Coastguard Worker total += write_severity( 369*9e94795aSAndroid Build Coastguard Worker csvwriter, severity, severity.column_header, warn_patterns) 370*9e94795aSAndroid Build Coastguard Worker csvwriter.writerow([total, '', 'All warnings']) 371*9e94795aSAndroid Build Coastguard Worker 372*9e94795aSAndroid Build Coastguard Worker 373*9e94795aSAndroid Build Coastguard Workerdef dump_csv_with_description(csvwriter, warning_records, warning_messages, 374*9e94795aSAndroid Build Coastguard Worker warn_patterns, project_names): 375*9e94795aSAndroid Build Coastguard Worker """Outputs all the warning messages by project.""" 376*9e94795aSAndroid Build Coastguard Worker csv_output = [] 377*9e94795aSAndroid Build Coastguard Worker for record in warning_records: 378*9e94795aSAndroid Build Coastguard Worker project_name = project_names[record[1]] 379*9e94795aSAndroid Build Coastguard Worker pattern = warn_patterns[record[0]] 380*9e94795aSAndroid Build Coastguard Worker severity = pattern['severity'].header 381*9e94795aSAndroid Build Coastguard Worker category = pattern['category'] 382*9e94795aSAndroid Build Coastguard Worker description = pattern['description'] 383*9e94795aSAndroid Build Coastguard Worker warning = warning_messages[record[2]] 384*9e94795aSAndroid Build Coastguard Worker csv_output.append([project_name, severity, 385*9e94795aSAndroid Build Coastguard Worker category, description, 386*9e94795aSAndroid Build Coastguard Worker warning]) 387*9e94795aSAndroid Build Coastguard Worker csv_output = sorted(csv_output) 388*9e94795aSAndroid Build Coastguard Worker for output in csv_output: 389*9e94795aSAndroid Build Coastguard Worker csvwriter.writerow(output) 390*9e94795aSAndroid Build Coastguard Worker 391*9e94795aSAndroid Build Coastguard Worker 392*9e94795aSAndroid Build Coastguard Worker# Return line with escaped backslash and quotation characters. 393*9e94795aSAndroid Build Coastguard Workerdef escape_string(line): 394*9e94795aSAndroid Build Coastguard Worker return line.replace('\\', '\\\\').replace('"', '\\"') 395*9e94795aSAndroid Build Coastguard Worker 396*9e94795aSAndroid Build Coastguard Worker 397*9e94795aSAndroid Build Coastguard Worker# Return line without trailing '\n' and escape the quotation characters. 398*9e94795aSAndroid Build Coastguard Workerdef strip_escape_string(line): 399*9e94795aSAndroid Build Coastguard Worker if not line: 400*9e94795aSAndroid Build Coastguard Worker return line 401*9e94795aSAndroid Build Coastguard Worker line = line[:-1] if line[-1] == '\n' else line 402*9e94795aSAndroid Build Coastguard Worker return escape_string(line) 403*9e94795aSAndroid Build Coastguard Worker 404*9e94795aSAndroid Build Coastguard Worker 405*9e94795aSAndroid Build Coastguard Workerdef emit_warning_array(name, writer, warn_patterns): 406*9e94795aSAndroid Build Coastguard Worker writer('var warning_{} = ['.format(name)) 407*9e94795aSAndroid Build Coastguard Worker for pattern in warn_patterns: 408*9e94795aSAndroid Build Coastguard Worker if name == 'severity': 409*9e94795aSAndroid Build Coastguard Worker writer('{},'.format(pattern[name].value)) 410*9e94795aSAndroid Build Coastguard Worker else: 411*9e94795aSAndroid Build Coastguard Worker writer('{},'.format(pattern[name])) 412*9e94795aSAndroid Build Coastguard Worker writer('];') 413*9e94795aSAndroid Build Coastguard Worker 414*9e94795aSAndroid Build Coastguard Worker 415*9e94795aSAndroid Build Coastguard Workerdef emit_warning_arrays(writer, warn_patterns): 416*9e94795aSAndroid Build Coastguard Worker emit_warning_array('severity', writer, warn_patterns) 417*9e94795aSAndroid Build Coastguard Worker writer('var warning_description = [') 418*9e94795aSAndroid Build Coastguard Worker for pattern in warn_patterns: 419*9e94795aSAndroid Build Coastguard Worker if pattern['members']: 420*9e94795aSAndroid Build Coastguard Worker writer('"{}",'.format(escape_string(pattern['description']))) 421*9e94795aSAndroid Build Coastguard Worker else: 422*9e94795aSAndroid Build Coastguard Worker writer('"",') # no such warning 423*9e94795aSAndroid Build Coastguard Worker writer('];') 424*9e94795aSAndroid Build Coastguard Worker 425*9e94795aSAndroid Build Coastguard Worker 426*9e94795aSAndroid Build Coastguard WorkerSCRIPTS_FOR_WARNING_GROUPS = """ 427*9e94795aSAndroid Build Coastguard Worker function compareMessages(x1, x2) { // of the same warning type 428*9e94795aSAndroid Build Coastguard Worker return (WarningMessages[x1[2]] <= WarningMessages[x2[2]]) ? -1 : 1; 429*9e94795aSAndroid Build Coastguard Worker } 430*9e94795aSAndroid Build Coastguard Worker function byMessageCount(x1, x2) { 431*9e94795aSAndroid Build Coastguard Worker return x2[2] - x1[2]; // reversed order 432*9e94795aSAndroid Build Coastguard Worker } 433*9e94795aSAndroid Build Coastguard Worker function bySeverityMessageCount(x1, x2) { 434*9e94795aSAndroid Build Coastguard Worker // orer by severity first 435*9e94795aSAndroid Build Coastguard Worker if (x1[1] != x2[1]) 436*9e94795aSAndroid Build Coastguard Worker return x1[1] - x2[1]; 437*9e94795aSAndroid Build Coastguard Worker return byMessageCount(x1, x2); 438*9e94795aSAndroid Build Coastguard Worker } 439*9e94795aSAndroid Build Coastguard Worker const ParseLinePattern = /^([^ :]+):(\\d+):(.+)/; 440*9e94795aSAndroid Build Coastguard Worker function addURL(line) { // used by Android 441*9e94795aSAndroid Build Coastguard Worker if (FlagURL == "") return line; 442*9e94795aSAndroid Build Coastguard Worker if (FlagSeparator == "") { 443*9e94795aSAndroid Build Coastguard Worker return line.replace(ParseLinePattern, 444*9e94795aSAndroid Build Coastguard Worker "<a target='_blank' href='" + FlagURL + "/$1'>$1</a>:$2:$3"); 445*9e94795aSAndroid Build Coastguard Worker } 446*9e94795aSAndroid Build Coastguard Worker return line.replace(ParseLinePattern, 447*9e94795aSAndroid Build Coastguard Worker "<a target='_blank' href='" + FlagURL + "/$1" + FlagSeparator + 448*9e94795aSAndroid Build Coastguard Worker "$2'>$1:$2</a>:$3"); 449*9e94795aSAndroid Build Coastguard Worker } 450*9e94795aSAndroid Build Coastguard Worker function addURLToLine(line, link) { // used by Chrome 451*9e94795aSAndroid Build Coastguard Worker let line_split = line.split(":"); 452*9e94795aSAndroid Build Coastguard Worker let path = line_split.slice(0,3).join(":"); 453*9e94795aSAndroid Build Coastguard Worker let msg = line_split.slice(3).join(":"); 454*9e94795aSAndroid Build Coastguard Worker let html_link = `<a target="_blank" href="${link}">${path}</a>${msg}`; 455*9e94795aSAndroid Build Coastguard Worker return html_link; 456*9e94795aSAndroid Build Coastguard Worker } 457*9e94795aSAndroid Build Coastguard Worker function createArrayOfDictionaries(n) { 458*9e94795aSAndroid Build Coastguard Worker var result = []; 459*9e94795aSAndroid Build Coastguard Worker for (var i=0; i<n; i++) result.push({}); 460*9e94795aSAndroid Build Coastguard Worker return result; 461*9e94795aSAndroid Build Coastguard Worker } 462*9e94795aSAndroid Build Coastguard Worker function groupWarningsBySeverity() { 463*9e94795aSAndroid Build Coastguard Worker // groups is an array of dictionaries, 464*9e94795aSAndroid Build Coastguard Worker // each dictionary maps from warning type to array of warning messages. 465*9e94795aSAndroid Build Coastguard Worker var groups = createArrayOfDictionaries(SeverityColors.length); 466*9e94795aSAndroid Build Coastguard Worker for (var i=0; i<Warnings.length; i++) { 467*9e94795aSAndroid Build Coastguard Worker var w = Warnings[i][0]; 468*9e94795aSAndroid Build Coastguard Worker var s = WarnPatternsSeverity[w]; 469*9e94795aSAndroid Build Coastguard Worker var k = w.toString(); 470*9e94795aSAndroid Build Coastguard Worker if (!(k in groups[s])) 471*9e94795aSAndroid Build Coastguard Worker groups[s][k] = []; 472*9e94795aSAndroid Build Coastguard Worker groups[s][k].push(Warnings[i]); 473*9e94795aSAndroid Build Coastguard Worker } 474*9e94795aSAndroid Build Coastguard Worker return groups; 475*9e94795aSAndroid Build Coastguard Worker } 476*9e94795aSAndroid Build Coastguard Worker function groupWarningsByProject() { 477*9e94795aSAndroid Build Coastguard Worker var groups = createArrayOfDictionaries(ProjectNames.length); 478*9e94795aSAndroid Build Coastguard Worker for (var i=0; i<Warnings.length; i++) { 479*9e94795aSAndroid Build Coastguard Worker var w = Warnings[i][0]; 480*9e94795aSAndroid Build Coastguard Worker var p = Warnings[i][1]; 481*9e94795aSAndroid Build Coastguard Worker var k = w.toString(); 482*9e94795aSAndroid Build Coastguard Worker if (!(k in groups[p])) 483*9e94795aSAndroid Build Coastguard Worker groups[p][k] = []; 484*9e94795aSAndroid Build Coastguard Worker groups[p][k].push(Warnings[i]); 485*9e94795aSAndroid Build Coastguard Worker } 486*9e94795aSAndroid Build Coastguard Worker return groups; 487*9e94795aSAndroid Build Coastguard Worker } 488*9e94795aSAndroid Build Coastguard Worker var GlobalAnchor = 0; 489*9e94795aSAndroid Build Coastguard Worker function createWarningSection(header, color, group) { 490*9e94795aSAndroid Build Coastguard Worker var result = ""; 491*9e94795aSAndroid Build Coastguard Worker var groupKeys = []; 492*9e94795aSAndroid Build Coastguard Worker var totalMessages = 0; 493*9e94795aSAndroid Build Coastguard Worker for (var k in group) { 494*9e94795aSAndroid Build Coastguard Worker totalMessages += group[k].length; 495*9e94795aSAndroid Build Coastguard Worker groupKeys.push([k, WarnPatternsSeverity[parseInt(k)], group[k].length]); 496*9e94795aSAndroid Build Coastguard Worker } 497*9e94795aSAndroid Build Coastguard Worker groupKeys.sort(bySeverityMessageCount); 498*9e94795aSAndroid Build Coastguard Worker for (var idx=0; idx<groupKeys.length; idx++) { 499*9e94795aSAndroid Build Coastguard Worker var k = groupKeys[idx][0]; 500*9e94795aSAndroid Build Coastguard Worker var messages = group[k]; 501*9e94795aSAndroid Build Coastguard Worker var w = parseInt(k); 502*9e94795aSAndroid Build Coastguard Worker var wcolor = SeverityColors[WarnPatternsSeverity[w]]; 503*9e94795aSAndroid Build Coastguard Worker var description = WarnPatternsDescription[w]; 504*9e94795aSAndroid Build Coastguard Worker if (description.length == 0) 505*9e94795aSAndroid Build Coastguard Worker description = "???"; 506*9e94795aSAndroid Build Coastguard Worker GlobalAnchor += 1; 507*9e94795aSAndroid Build Coastguard Worker result += "<table class='t1'><tr bgcolor='" + wcolor + "'><td>" + 508*9e94795aSAndroid Build Coastguard Worker "<button class='bt' id='" + GlobalAnchor + "_mark" + 509*9e94795aSAndroid Build Coastguard Worker "' onclick='expand(\\"" + GlobalAnchor + "\\");'>" + 510*9e94795aSAndroid Build Coastguard Worker "⊕</button> " + 511*9e94795aSAndroid Build Coastguard Worker description + " (" + messages.length + ")</td></tr></table>"; 512*9e94795aSAndroid Build Coastguard Worker result += "<div id='" + GlobalAnchor + 513*9e94795aSAndroid Build Coastguard Worker "' style='display:none;'><table class='t1'>"; 514*9e94795aSAndroid Build Coastguard Worker var c = 0; 515*9e94795aSAndroid Build Coastguard Worker messages.sort(compareMessages); 516*9e94795aSAndroid Build Coastguard Worker if (FlagPlatform == "chrome") { 517*9e94795aSAndroid Build Coastguard Worker for (var i=0; i<messages.length; i++) { 518*9e94795aSAndroid Build Coastguard Worker result += "<tr><td class='c" + c + "'>" + 519*9e94795aSAndroid Build Coastguard Worker addURLToLine(WarningMessages[messages[i][2]], WarningLinks[messages[i][3]]) + "</td></tr>"; 520*9e94795aSAndroid Build Coastguard Worker c = 1 - c; 521*9e94795aSAndroid Build Coastguard Worker } 522*9e94795aSAndroid Build Coastguard Worker } else { 523*9e94795aSAndroid Build Coastguard Worker for (var i=0; i<messages.length; i++) { 524*9e94795aSAndroid Build Coastguard Worker result += "<tr><td class='c" + c + "'>" + 525*9e94795aSAndroid Build Coastguard Worker addURL(WarningMessages[messages[i][2]]) + "</td></tr>"; 526*9e94795aSAndroid Build Coastguard Worker c = 1 - c; 527*9e94795aSAndroid Build Coastguard Worker } 528*9e94795aSAndroid Build Coastguard Worker } 529*9e94795aSAndroid Build Coastguard Worker result += "</table></div>"; 530*9e94795aSAndroid Build Coastguard Worker } 531*9e94795aSAndroid Build Coastguard Worker if (result.length > 0) { 532*9e94795aSAndroid Build Coastguard Worker return "<br><span style='background-color:" + color + "'><b>" + 533*9e94795aSAndroid Build Coastguard Worker header + ": " + totalMessages + 534*9e94795aSAndroid Build Coastguard Worker "</b></span><blockquote><table class='t1'>" + 535*9e94795aSAndroid Build Coastguard Worker result + "</table></blockquote>"; 536*9e94795aSAndroid Build Coastguard Worker 537*9e94795aSAndroid Build Coastguard Worker } 538*9e94795aSAndroid Build Coastguard Worker return ""; // empty section 539*9e94795aSAndroid Build Coastguard Worker } 540*9e94795aSAndroid Build Coastguard Worker function generateSectionsBySeverity() { 541*9e94795aSAndroid Build Coastguard Worker var result = ""; 542*9e94795aSAndroid Build Coastguard Worker var groups = groupWarningsBySeverity(); 543*9e94795aSAndroid Build Coastguard Worker for (s=0; s<SeverityColors.length; s++) { 544*9e94795aSAndroid Build Coastguard Worker result += createWarningSection(SeverityHeaders[s], SeverityColors[s], 545*9e94795aSAndroid Build Coastguard Worker groups[s]); 546*9e94795aSAndroid Build Coastguard Worker } 547*9e94795aSAndroid Build Coastguard Worker return result; 548*9e94795aSAndroid Build Coastguard Worker } 549*9e94795aSAndroid Build Coastguard Worker function generateSectionsByProject() { 550*9e94795aSAndroid Build Coastguard Worker var result = ""; 551*9e94795aSAndroid Build Coastguard Worker var groups = groupWarningsByProject(); 552*9e94795aSAndroid Build Coastguard Worker for (i=0; i<groups.length; i++) { 553*9e94795aSAndroid Build Coastguard Worker result += createWarningSection(ProjectNames[i], 'lightgrey', groups[i]); 554*9e94795aSAndroid Build Coastguard Worker } 555*9e94795aSAndroid Build Coastguard Worker return result; 556*9e94795aSAndroid Build Coastguard Worker } 557*9e94795aSAndroid Build Coastguard Worker function groupWarnings(generator) { 558*9e94795aSAndroid Build Coastguard Worker GlobalAnchor = 0; 559*9e94795aSAndroid Build Coastguard Worker var e = document.getElementById("warning_groups"); 560*9e94795aSAndroid Build Coastguard Worker e.innerHTML = generator(); 561*9e94795aSAndroid Build Coastguard Worker } 562*9e94795aSAndroid Build Coastguard Worker function groupBySeverity() { 563*9e94795aSAndroid Build Coastguard Worker groupWarnings(generateSectionsBySeverity); 564*9e94795aSAndroid Build Coastguard Worker } 565*9e94795aSAndroid Build Coastguard Worker function groupByProject() { 566*9e94795aSAndroid Build Coastguard Worker groupWarnings(generateSectionsByProject); 567*9e94795aSAndroid Build Coastguard Worker } 568*9e94795aSAndroid Build Coastguard Worker""" 569*9e94795aSAndroid Build Coastguard Worker 570*9e94795aSAndroid Build Coastguard Worker 571*9e94795aSAndroid Build Coastguard Worker# Emit a JavaScript const number 572*9e94795aSAndroid Build Coastguard Workerdef emit_const_number(name, value, writer): 573*9e94795aSAndroid Build Coastguard Worker writer('const ' + name + ' = ' + str(value) + ';') 574*9e94795aSAndroid Build Coastguard Worker 575*9e94795aSAndroid Build Coastguard Worker 576*9e94795aSAndroid Build Coastguard Worker# Emit a JavaScript const string 577*9e94795aSAndroid Build Coastguard Workerdef emit_const_string(name, value, writer): 578*9e94795aSAndroid Build Coastguard Worker writer('const ' + name + ' = "' + escape_string(value) + '";') 579*9e94795aSAndroid Build Coastguard Worker 580*9e94795aSAndroid Build Coastguard Worker 581*9e94795aSAndroid Build Coastguard Worker# Emit a JavaScript const integer array. 582*9e94795aSAndroid Build Coastguard Workerdef emit_const_int_array(name, array, writer): 583*9e94795aSAndroid Build Coastguard Worker writer('const ' + name + ' = [') 584*9e94795aSAndroid Build Coastguard Worker for item in array: 585*9e94795aSAndroid Build Coastguard Worker writer(str(item) + ',') 586*9e94795aSAndroid Build Coastguard Worker writer('];') 587*9e94795aSAndroid Build Coastguard Worker 588*9e94795aSAndroid Build Coastguard Worker 589*9e94795aSAndroid Build Coastguard Worker# Emit a JavaScript const string array. 590*9e94795aSAndroid Build Coastguard Workerdef emit_const_string_array(name, array, writer): 591*9e94795aSAndroid Build Coastguard Worker writer('const ' + name + ' = [') 592*9e94795aSAndroid Build Coastguard Worker for item in array: 593*9e94795aSAndroid Build Coastguard Worker writer('"' + strip_escape_string(item) + '",') 594*9e94795aSAndroid Build Coastguard Worker writer('];') 595*9e94795aSAndroid Build Coastguard Worker 596*9e94795aSAndroid Build Coastguard Worker 597*9e94795aSAndroid Build Coastguard Worker# Emit a JavaScript const string array for HTML. 598*9e94795aSAndroid Build Coastguard Workerdef emit_const_html_string_array(name, array, writer): 599*9e94795aSAndroid Build Coastguard Worker writer('const ' + name + ' = [') 600*9e94795aSAndroid Build Coastguard Worker for item in array: 601*9e94795aSAndroid Build Coastguard Worker writer('"' + html.escape(strip_escape_string(item)) + '",') 602*9e94795aSAndroid Build Coastguard Worker writer('];') 603*9e94795aSAndroid Build Coastguard Worker 604*9e94795aSAndroid Build Coastguard Worker 605*9e94795aSAndroid Build Coastguard Worker# Emit a JavaScript const object array. 606*9e94795aSAndroid Build Coastguard Workerdef emit_const_object_array(name, array, writer): 607*9e94795aSAndroid Build Coastguard Worker writer('const ' + name + ' = [') 608*9e94795aSAndroid Build Coastguard Worker for item in array: 609*9e94795aSAndroid Build Coastguard Worker writer(str(item) + ',') 610*9e94795aSAndroid Build Coastguard Worker writer('];') 611*9e94795aSAndroid Build Coastguard Worker 612*9e94795aSAndroid Build Coastguard Worker 613*9e94795aSAndroid Build Coastguard Workerdef emit_js_data(writer, flags, warning_messages, warning_links, 614*9e94795aSAndroid Build Coastguard Worker warning_records, warn_patterns, project_names): 615*9e94795aSAndroid Build Coastguard Worker """Dump dynamic HTML page's static JavaScript data.""" 616*9e94795aSAndroid Build Coastguard Worker emit_const_string('FlagPlatform', flags.platform, writer) 617*9e94795aSAndroid Build Coastguard Worker emit_const_string('FlagURL', flags.url, writer) 618*9e94795aSAndroid Build Coastguard Worker emit_const_string('FlagSeparator', flags.separator, writer) 619*9e94795aSAndroid Build Coastguard Worker emit_const_number('LimitWarningsPerFile', LIMIT_WARNINGS_PER_FILE, writer) 620*9e94795aSAndroid Build Coastguard Worker emit_const_number('LimitPercentWarnings', LIMIT_PERCENT_WARNINGS, writer) 621*9e94795aSAndroid Build Coastguard Worker emit_const_string_array('SeverityColors', [s.color for s in Severity.levels], 622*9e94795aSAndroid Build Coastguard Worker writer) 623*9e94795aSAndroid Build Coastguard Worker emit_const_string_array('SeverityHeaders', 624*9e94795aSAndroid Build Coastguard Worker [s.header for s in Severity.levels], writer) 625*9e94795aSAndroid Build Coastguard Worker emit_const_string_array('SeverityColumnHeaders', 626*9e94795aSAndroid Build Coastguard Worker [s.column_header for s in Severity.levels], writer) 627*9e94795aSAndroid Build Coastguard Worker emit_const_string_array('ProjectNames', project_names, writer) 628*9e94795aSAndroid Build Coastguard Worker # pytype: disable=attribute-error 629*9e94795aSAndroid Build Coastguard Worker emit_const_int_array('WarnPatternsSeverity', 630*9e94795aSAndroid Build Coastguard Worker [w['severity'].value for w in warn_patterns], writer) 631*9e94795aSAndroid Build Coastguard Worker # pytype: enable=attribute-error 632*9e94795aSAndroid Build Coastguard Worker emit_const_html_string_array('WarnPatternsDescription', 633*9e94795aSAndroid Build Coastguard Worker [w['description'] for w in warn_patterns], 634*9e94795aSAndroid Build Coastguard Worker writer) 635*9e94795aSAndroid Build Coastguard Worker emit_const_html_string_array('WarningMessages', warning_messages, writer) 636*9e94795aSAndroid Build Coastguard Worker emit_const_object_array('Warnings', warning_records, writer) 637*9e94795aSAndroid Build Coastguard Worker if flags.platform == 'chrome': 638*9e94795aSAndroid Build Coastguard Worker emit_const_html_string_array('WarningLinks', warning_links, writer) 639*9e94795aSAndroid Build Coastguard Worker 640*9e94795aSAndroid Build Coastguard Worker 641*9e94795aSAndroid Build Coastguard WorkerDRAW_TABLE_JAVASCRIPT = """ 642*9e94795aSAndroid Build Coastguard Workergoogle.charts.load('current', {'packages':['table']}); 643*9e94795aSAndroid Build Coastguard Workergoogle.charts.setOnLoadCallback(genTables); 644*9e94795aSAndroid Build Coastguard Workerfunction genSelectedProjectsTable() { 645*9e94795aSAndroid Build Coastguard Worker var data = new google.visualization.DataTable(); 646*9e94795aSAndroid Build Coastguard Worker data.addColumn('string', StatsHeader[0]); 647*9e94795aSAndroid Build Coastguard Worker for (var i=1; i<StatsHeader.length; i++) { 648*9e94795aSAndroid Build Coastguard Worker data.addColumn('number', StatsHeader[i]); 649*9e94795aSAndroid Build Coastguard Worker } 650*9e94795aSAndroid Build Coastguard Worker data.addRows(StatsRows); 651*9e94795aSAndroid Build Coastguard Worker for (var i=0; i<StatsRows.length; i++) { 652*9e94795aSAndroid Build Coastguard Worker for (var j=0; j<StatsHeader.length; j++) { 653*9e94795aSAndroid Build Coastguard Worker data.setProperty(i, j, 'style', 'border:1px solid black;'); 654*9e94795aSAndroid Build Coastguard Worker } 655*9e94795aSAndroid Build Coastguard Worker } 656*9e94795aSAndroid Build Coastguard Worker var table = new google.visualization.Table( 657*9e94795aSAndroid Build Coastguard Worker document.getElementById('selected_projects_section')); 658*9e94795aSAndroid Build Coastguard Worker table.draw(data, {allowHtml: true, alternatingRowStyle: true}); 659*9e94795aSAndroid Build Coastguard Worker} 660*9e94795aSAndroid Build Coastguard Worker// Global TopDirs and TopFiles are computed later by genTables. 661*9e94795aSAndroid Build Coastguard Workerwindow.TopDirs = []; 662*9e94795aSAndroid Build Coastguard Workerwindow.TopFiles = []; 663*9e94795aSAndroid Build Coastguard Workerfunction computeTopDirsFiles() { 664*9e94795aSAndroid Build Coastguard Worker var numWarnings = WarningMessages.length; 665*9e94795aSAndroid Build Coastguard Worker var warningsOfFiles = {}; 666*9e94795aSAndroid Build Coastguard Worker var warningsOfDirs = {}; 667*9e94795aSAndroid Build Coastguard Worker var subDirs = {}; 668*9e94795aSAndroid Build Coastguard Worker function addOneWarning(map, key, type, unique) { 669*9e94795aSAndroid Build Coastguard Worker function increaseCounter(idx) { 670*9e94795aSAndroid Build Coastguard Worker map[idx] = 1 + ((idx in map) ? map[idx] : 0); 671*9e94795aSAndroid Build Coastguard Worker } 672*9e94795aSAndroid Build Coastguard Worker increaseCounter(key) 673*9e94795aSAndroid Build Coastguard Worker if (type != "") { 674*9e94795aSAndroid Build Coastguard Worker increaseCounter(type + " " + key) 675*9e94795aSAndroid Build Coastguard Worker if (unique) { 676*9e94795aSAndroid Build Coastguard Worker increaseCounter(type + " *") 677*9e94795aSAndroid Build Coastguard Worker } 678*9e94795aSAndroid Build Coastguard Worker } 679*9e94795aSAndroid Build Coastguard Worker } 680*9e94795aSAndroid Build Coastguard Worker for (var i = 0; i < numWarnings; i++) { 681*9e94795aSAndroid Build Coastguard Worker var message = WarningMessages[i] 682*9e94795aSAndroid Build Coastguard Worker var file = message.replace(/:.*/, ""); 683*9e94795aSAndroid Build Coastguard Worker var warningType = message.endsWith("]") ? message.replace(/.*\[/, "[") : ""; 684*9e94795aSAndroid Build Coastguard Worker addOneWarning(warningsOfFiles, file, warningType, true); 685*9e94795aSAndroid Build Coastguard Worker var dirs = file.split("/"); 686*9e94795aSAndroid Build Coastguard Worker var dir = dirs[0]; 687*9e94795aSAndroid Build Coastguard Worker addOneWarning(warningsOfDirs, dir, warningType, true); 688*9e94795aSAndroid Build Coastguard Worker for (var d = 1; d < dirs.length - 1; d++) { 689*9e94795aSAndroid Build Coastguard Worker var subDir = dir + "/" + dirs[d]; 690*9e94795aSAndroid Build Coastguard Worker if (!(dir in subDirs)) { 691*9e94795aSAndroid Build Coastguard Worker subDirs[dir] = {}; 692*9e94795aSAndroid Build Coastguard Worker } 693*9e94795aSAndroid Build Coastguard Worker subDirs[dir][subDir] = 1; 694*9e94795aSAndroid Build Coastguard Worker dir = subDir; 695*9e94795aSAndroid Build Coastguard Worker addOneWarning(warningsOfDirs, dir, warningType, false); 696*9e94795aSAndroid Build Coastguard Worker } 697*9e94795aSAndroid Build Coastguard Worker } 698*9e94795aSAndroid Build Coastguard Worker var minDirWarnings = numWarnings*(LimitPercentWarnings/100); 699*9e94795aSAndroid Build Coastguard Worker var minFileWarnings = Math.min(LimitWarningsPerFile, minDirWarnings); 700*9e94795aSAndroid Build Coastguard Worker // Each row in TopDirs and TopFiles has 701*9e94795aSAndroid Build Coastguard Worker // [index, {v:<num_of_warnings>, f:<percent>}, file_or_dir_name] 702*9e94795aSAndroid Build Coastguard Worker function countWarnings(minWarnings, warningsOf, isDir) { 703*9e94795aSAndroid Build Coastguard Worker var rows = []; 704*9e94795aSAndroid Build Coastguard Worker for (var name in warningsOf) { 705*9e94795aSAndroid Build Coastguard Worker if (isDir && name in subDirs && Object.keys(subDirs[name]).length < 2) { 706*9e94795aSAndroid Build Coastguard Worker continue; // skip a directory if it has only one subdir 707*9e94795aSAndroid Build Coastguard Worker } 708*9e94795aSAndroid Build Coastguard Worker var count = warningsOf[name]; 709*9e94795aSAndroid Build Coastguard Worker if (count >= minWarnings) { 710*9e94795aSAndroid Build Coastguard Worker name = isDir ? (name + "/...") : name; 711*9e94795aSAndroid Build Coastguard Worker var percent = (100*count/numWarnings).toFixed(1); 712*9e94795aSAndroid Build Coastguard Worker var countFormat = count + ' (' + percent + '%)'; 713*9e94795aSAndroid Build Coastguard Worker rows.push([0, {v:count, f:countFormat}, name]); 714*9e94795aSAndroid Build Coastguard Worker } 715*9e94795aSAndroid Build Coastguard Worker } 716*9e94795aSAndroid Build Coastguard Worker rows.sort((a,b) => b[1].v - a[1].v); 717*9e94795aSAndroid Build Coastguard Worker for (var i=0; i<rows.length; i++) { 718*9e94795aSAndroid Build Coastguard Worker rows[i][0] = i; 719*9e94795aSAndroid Build Coastguard Worker } 720*9e94795aSAndroid Build Coastguard Worker return rows; 721*9e94795aSAndroid Build Coastguard Worker } 722*9e94795aSAndroid Build Coastguard Worker TopDirs = countWarnings(minDirWarnings, warningsOfDirs, true); 723*9e94795aSAndroid Build Coastguard Worker TopFiles = countWarnings(minFileWarnings, warningsOfFiles, false); 724*9e94795aSAndroid Build Coastguard Worker} 725*9e94795aSAndroid Build Coastguard Workerfunction genTopDirsFilesTables() { 726*9e94795aSAndroid Build Coastguard Worker computeTopDirsFiles(); 727*9e94795aSAndroid Build Coastguard Worker function addTable(name, divName, rows, clickFunction) { 728*9e94795aSAndroid Build Coastguard Worker var data = new google.visualization.DataTable(); 729*9e94795aSAndroid Build Coastguard Worker data.addColumn("number", "index"); // not shown in view 730*9e94795aSAndroid Build Coastguard Worker data.addColumn("number", "# of warnings"); 731*9e94795aSAndroid Build Coastguard Worker data.addColumn("string", name); 732*9e94795aSAndroid Build Coastguard Worker data.addRows(rows); 733*9e94795aSAndroid Build Coastguard Worker var formatter = new google.visualization.PatternFormat( 734*9e94795aSAndroid Build Coastguard Worker '<p onclick="' + clickFunction + '({0})">{2}</p>'); 735*9e94795aSAndroid Build Coastguard Worker formatter.format(data, [0, 1, 2], 2); 736*9e94795aSAndroid Build Coastguard Worker var view = new google.visualization.DataView(data); 737*9e94795aSAndroid Build Coastguard Worker view.setColumns([1,2]); // hide the index column 738*9e94795aSAndroid Build Coastguard Worker var table = new google.visualization.Table( 739*9e94795aSAndroid Build Coastguard Worker document.getElementById(divName)); 740*9e94795aSAndroid Build Coastguard Worker table.draw(view, {allowHtml: true, alternatingRowStyle: true}); 741*9e94795aSAndroid Build Coastguard Worker } 742*9e94795aSAndroid Build Coastguard Worker addTable("[Warning Type] Directory", "top_dirs_table", TopDirs, "selectDir"); 743*9e94795aSAndroid Build Coastguard Worker addTable("[Warning Type] File", "top_files_table", TopFiles, "selectFile"); 744*9e94795aSAndroid Build Coastguard Worker} 745*9e94795aSAndroid Build Coastguard Workerfunction selectDirFile(idx, rows, dirFile) { 746*9e94795aSAndroid Build Coastguard Worker if (rows.length <= idx) { 747*9e94795aSAndroid Build Coastguard Worker return; 748*9e94795aSAndroid Build Coastguard Worker } 749*9e94795aSAndroid Build Coastguard Worker var name = rows[idx][2]; 750*9e94795aSAndroid Build Coastguard Worker var type = ""; 751*9e94795aSAndroid Build Coastguard Worker if (name.startsWith("[")) { 752*9e94795aSAndroid Build Coastguard Worker type = " " + name.replace(/ .*/, ""); 753*9e94795aSAndroid Build Coastguard Worker name = name.replace(/.* /, ""); 754*9e94795aSAndroid Build Coastguard Worker } 755*9e94795aSAndroid Build Coastguard Worker var spanName = "selected_" + dirFile + "_name"; 756*9e94795aSAndroid Build Coastguard Worker document.getElementById(spanName).innerHTML = name + type; 757*9e94795aSAndroid Build Coastguard Worker var divName = "selected_" + dirFile + "_warnings"; 758*9e94795aSAndroid Build Coastguard Worker var numWarnings = rows[idx][1].v; 759*9e94795aSAndroid Build Coastguard Worker var prefix = name.replace(/\\.\\.\\.$/, ""); 760*9e94795aSAndroid Build Coastguard Worker var data = new google.visualization.DataTable(); 761*9e94795aSAndroid Build Coastguard Worker data.addColumn('string', numWarnings + type + ' warnings in ' + name); 762*9e94795aSAndroid Build Coastguard Worker var getWarningMessage = (FlagPlatform == "chrome") 763*9e94795aSAndroid Build Coastguard Worker ? ((x) => addURLToLine(WarningMessages[Warnings[x][2]], 764*9e94795aSAndroid Build Coastguard Worker WarningLinks[Warnings[x][3]])) 765*9e94795aSAndroid Build Coastguard Worker : ((x) => addURL(WarningMessages[Warnings[x][2]])); 766*9e94795aSAndroid Build Coastguard Worker for (var i = 0; i < Warnings.length; i++) { 767*9e94795aSAndroid Build Coastguard Worker if ((prefix.startsWith("*") || WarningMessages[Warnings[i][2]].startsWith(prefix)) && 768*9e94795aSAndroid Build Coastguard Worker (type == "" || WarningMessages[Warnings[i][2]].endsWith(type))) { 769*9e94795aSAndroid Build Coastguard Worker data.addRow([getWarningMessage(i)]); 770*9e94795aSAndroid Build Coastguard Worker } 771*9e94795aSAndroid Build Coastguard Worker } 772*9e94795aSAndroid Build Coastguard Worker var table = new google.visualization.Table( 773*9e94795aSAndroid Build Coastguard Worker document.getElementById(divName)); 774*9e94795aSAndroid Build Coastguard Worker table.draw(data, {allowHtml: true, alternatingRowStyle: true}); 775*9e94795aSAndroid Build Coastguard Worker} 776*9e94795aSAndroid Build Coastguard Workerfunction selectDir(idx) { 777*9e94795aSAndroid Build Coastguard Worker selectDirFile(idx, TopDirs, "directory") 778*9e94795aSAndroid Build Coastguard Worker} 779*9e94795aSAndroid Build Coastguard Workerfunction selectFile(idx) { 780*9e94795aSAndroid Build Coastguard Worker selectDirFile(idx, TopFiles, "file"); 781*9e94795aSAndroid Build Coastguard Worker} 782*9e94795aSAndroid Build Coastguard Workerfunction genTables() { 783*9e94795aSAndroid Build Coastguard Worker genSelectedProjectsTable(); 784*9e94795aSAndroid Build Coastguard Worker if (WarningMessages.length > 1) { 785*9e94795aSAndroid Build Coastguard Worker genTopDirsFilesTables(); 786*9e94795aSAndroid Build Coastguard Worker } 787*9e94795aSAndroid Build Coastguard Worker} 788*9e94795aSAndroid Build Coastguard Worker""" 789*9e94795aSAndroid Build Coastguard Worker 790*9e94795aSAndroid Build Coastguard Worker 791*9e94795aSAndroid Build Coastguard Workerdef dump_boxed_section(writer, func): 792*9e94795aSAndroid Build Coastguard Worker writer('<div class="box">') 793*9e94795aSAndroid Build Coastguard Worker func() 794*9e94795aSAndroid Build Coastguard Worker writer('</div>') 795*9e94795aSAndroid Build Coastguard Worker 796*9e94795aSAndroid Build Coastguard Worker 797*9e94795aSAndroid Build Coastguard Workerdef dump_section_header(writer, table_name, section_title): 798*9e94795aSAndroid Build Coastguard Worker writer('<h3><b><button id="' + table_name + '_mark" class="bt"\n' + 799*9e94795aSAndroid Build Coastguard Worker ' onclick="expand(\'' + table_name + '\');">⊕</button></b>\n' + 800*9e94795aSAndroid Build Coastguard Worker section_title + '</h3>') 801*9e94795aSAndroid Build Coastguard Worker 802*9e94795aSAndroid Build Coastguard Worker 803*9e94795aSAndroid Build Coastguard Workerdef dump_table_section(writer, table_name, section_title): 804*9e94795aSAndroid Build Coastguard Worker dump_section_header(writer, table_name, section_title) 805*9e94795aSAndroid Build Coastguard Worker writer('<div id="' + table_name + '" style="display:none;"></div>') 806*9e94795aSAndroid Build Coastguard Worker 807*9e94795aSAndroid Build Coastguard Worker 808*9e94795aSAndroid Build Coastguard Workerdef dump_dir_file_section(writer, dir_file, table_name, section_title): 809*9e94795aSAndroid Build Coastguard Worker section_name = 'top_' + dir_file + '_section' 810*9e94795aSAndroid Build Coastguard Worker dump_section_header(writer, section_name, section_title) 811*9e94795aSAndroid Build Coastguard Worker writer('<div id="' + section_name + '" style="display:none;">') 812*9e94795aSAndroid Build Coastguard Worker writer('<div id="' + table_name + '"></div>') 813*9e94795aSAndroid Build Coastguard Worker def subsection(): 814*9e94795aSAndroid Build Coastguard Worker subsection_name = 'selected_' + dir_file + '_warnings' 815*9e94795aSAndroid Build Coastguard Worker subsection_title = ('Warnings in <span id="selected_' + dir_file + 816*9e94795aSAndroid Build Coastguard Worker '_name">(click a ' + dir_file + 817*9e94795aSAndroid Build Coastguard Worker ' in the above table)</span>') 818*9e94795aSAndroid Build Coastguard Worker dump_section_header(writer, subsection_name, subsection_title) 819*9e94795aSAndroid Build Coastguard Worker writer('<div id="' + subsection_name + '" style="display:none;"></div>') 820*9e94795aSAndroid Build Coastguard Worker dump_boxed_section(writer, subsection) 821*9e94795aSAndroid Build Coastguard Worker writer('</div>') 822*9e94795aSAndroid Build Coastguard Worker 823*9e94795aSAndroid Build Coastguard Worker 824*9e94795aSAndroid Build Coastguard Worker# HTML output has the following major div elements: 825*9e94795aSAndroid Build Coastguard Worker# selected_projects_section 826*9e94795aSAndroid Build Coastguard Worker# top_directory_section 827*9e94795aSAndroid Build Coastguard Worker# top_dirs_table 828*9e94795aSAndroid Build Coastguard Worker# selected_directory_warnings 829*9e94795aSAndroid Build Coastguard Worker# top_file_section 830*9e94795aSAndroid Build Coastguard Worker# top_files_table 831*9e94795aSAndroid Build Coastguard Worker# selected_file_warnings 832*9e94795aSAndroid Build Coastguard Worker# all_warnings_section 833*9e94795aSAndroid Build Coastguard Worker# warning_groups 834*9e94795aSAndroid Build Coastguard Worker# fixed_warnings 835*9e94795aSAndroid Build Coastguard Workerdef dump_html(flags, output_stream, warning_messages, warning_links, 836*9e94795aSAndroid Build Coastguard Worker warning_records, header_str, warn_patterns, project_names): 837*9e94795aSAndroid Build Coastguard Worker """Dump the flags output to output_stream.""" 838*9e94795aSAndroid Build Coastguard Worker writer = make_writer(output_stream) 839*9e94795aSAndroid Build Coastguard Worker dump_html_prologue('Warnings for ' + header_str, writer, warn_patterns, 840*9e94795aSAndroid Build Coastguard Worker project_names) 841*9e94795aSAndroid Build Coastguard Worker dump_stats(writer, warn_patterns) 842*9e94795aSAndroid Build Coastguard Worker writer('<br><br>Press ⊕ to show section content,' 843*9e94795aSAndroid Build Coastguard Worker ' and ⊖ to hide the content.') 844*9e94795aSAndroid Build Coastguard Worker def section1(): 845*9e94795aSAndroid Build Coastguard Worker dump_table_section(writer, 'selected_projects_section', 846*9e94795aSAndroid Build Coastguard Worker 'Number of warnings in preselected project directories') 847*9e94795aSAndroid Build Coastguard Worker def section2(): 848*9e94795aSAndroid Build Coastguard Worker dump_dir_file_section( 849*9e94795aSAndroid Build Coastguard Worker writer, 'directory', 'top_dirs_table', 850*9e94795aSAndroid Build Coastguard Worker 'Directories/Warnings with at least ' + 851*9e94795aSAndroid Build Coastguard Worker str(LIMIT_PERCENT_WARNINGS) + '% of all cases') 852*9e94795aSAndroid Build Coastguard Worker def section3(): 853*9e94795aSAndroid Build Coastguard Worker dump_dir_file_section( 854*9e94795aSAndroid Build Coastguard Worker writer, 'file', 'top_files_table', 855*9e94795aSAndroid Build Coastguard Worker 'Files/Warnings with at least ' + 856*9e94795aSAndroid Build Coastguard Worker str(LIMIT_PERCENT_WARNINGS) + '% of all or ' + 857*9e94795aSAndroid Build Coastguard Worker str(LIMIT_WARNINGS_PER_FILE) + ' cases') 858*9e94795aSAndroid Build Coastguard Worker def section4(): 859*9e94795aSAndroid Build Coastguard Worker writer('<script>') 860*9e94795aSAndroid Build Coastguard Worker emit_js_data(writer, flags, warning_messages, warning_links, 861*9e94795aSAndroid Build Coastguard Worker warning_records, warn_patterns, project_names) 862*9e94795aSAndroid Build Coastguard Worker writer(SCRIPTS_FOR_WARNING_GROUPS) 863*9e94795aSAndroid Build Coastguard Worker writer('</script>') 864*9e94795aSAndroid Build Coastguard Worker dump_section_header(writer, 'all_warnings_section', 865*9e94795aSAndroid Build Coastguard Worker 'All warnings grouped by severities or projects') 866*9e94795aSAndroid Build Coastguard Worker writer('<div id="all_warnings_section" style="display:none;">') 867*9e94795aSAndroid Build Coastguard Worker emit_buttons(writer) 868*9e94795aSAndroid Build Coastguard Worker # Warning messages are grouped by severities or project names. 869*9e94795aSAndroid Build Coastguard Worker writer('<br><div id="warning_groups"></div>') 870*9e94795aSAndroid Build Coastguard Worker if flags.byproject: 871*9e94795aSAndroid Build Coastguard Worker writer('<script>groupByProject();</script>') 872*9e94795aSAndroid Build Coastguard Worker else: 873*9e94795aSAndroid Build Coastguard Worker writer('<script>groupBySeverity();</script>') 874*9e94795aSAndroid Build Coastguard Worker dump_fixed(writer, warn_patterns) 875*9e94795aSAndroid Build Coastguard Worker writer('</div>') 876*9e94795aSAndroid Build Coastguard Worker dump_boxed_section(writer, section1) 877*9e94795aSAndroid Build Coastguard Worker dump_boxed_section(writer, section2) 878*9e94795aSAndroid Build Coastguard Worker dump_boxed_section(writer, section3) 879*9e94795aSAndroid Build Coastguard Worker dump_boxed_section(writer, section4) 880*9e94795aSAndroid Build Coastguard Worker dump_html_epilogue(writer) 881*9e94795aSAndroid Build Coastguard Worker 882*9e94795aSAndroid Build Coastguard Worker 883*9e94795aSAndroid Build Coastguard Workerdef write_html(flags, project_names, warn_patterns, html_path, warning_messages, 884*9e94795aSAndroid Build Coastguard Worker warning_links, warning_records, header_str): 885*9e94795aSAndroid Build Coastguard Worker """Write warnings html file.""" 886*9e94795aSAndroid Build Coastguard Worker if html_path: 887*9e94795aSAndroid Build Coastguard Worker with open(html_path, 'w') as outf: 888*9e94795aSAndroid Build Coastguard Worker dump_html(flags, outf, warning_messages, warning_links, warning_records, 889*9e94795aSAndroid Build Coastguard Worker header_str, warn_patterns, project_names) 890*9e94795aSAndroid Build Coastguard Worker 891*9e94795aSAndroid Build Coastguard Worker 892*9e94795aSAndroid Build Coastguard Workerdef write_out_csv(flags, warn_patterns, warning_messages, warning_links, 893*9e94795aSAndroid Build Coastguard Worker warning_records, header_str, project_names): 894*9e94795aSAndroid Build Coastguard Worker """Write warnings csv file.""" 895*9e94795aSAndroid Build Coastguard Worker if flags.csvpath: 896*9e94795aSAndroid Build Coastguard Worker with open(flags.csvpath, 'w') as outf: 897*9e94795aSAndroid Build Coastguard Worker dump_csv(csv.writer(outf, lineterminator='\n'), warn_patterns) 898*9e94795aSAndroid Build Coastguard Worker 899*9e94795aSAndroid Build Coastguard Worker if flags.csvwithdescription: 900*9e94795aSAndroid Build Coastguard Worker with open(flags.csvwithdescription, 'w') as outf: 901*9e94795aSAndroid Build Coastguard Worker dump_csv_with_description(csv.writer(outf, lineterminator='\n'), 902*9e94795aSAndroid Build Coastguard Worker warning_records, warning_messages, 903*9e94795aSAndroid Build Coastguard Worker warn_patterns, project_names) 904*9e94795aSAndroid Build Coastguard Worker 905*9e94795aSAndroid Build Coastguard Worker if flags.gencsv: 906*9e94795aSAndroid Build Coastguard Worker dump_csv(csv.writer(sys.stdout, lineterminator='\n'), warn_patterns) 907*9e94795aSAndroid Build Coastguard Worker else: 908*9e94795aSAndroid Build Coastguard Worker dump_html(flags, sys.stdout, warning_messages, warning_links, 909*9e94795aSAndroid Build Coastguard Worker warning_records, header_str, warn_patterns, project_names) 910