1
0
Fork 0

Set the upper limit on warnings number

This way it will be possible to prevent users from introducing new
warnings. As new fixes will be upstreamed, the maximum limit of
allowed warnings should be taken lower and lower, so this script
could be eventually replaced by -Werror.
This commit is contained in:
Patryk Obara 2019-09-21 12:14:49 +02:00
parent 58857e25e2
commit 4c5b4faf2f
2 changed files with 108 additions and 10 deletions

View file

@ -20,8 +20,10 @@ jobs:
set -x
$CXX --version
./autogen.sh
./configure
make -j "$(nproc)"
./configure CXXFLAGS="-Wall -fdiagnostics-color=always"
make -j "$(nproc)" |& tee build.log
- name: Summarize warnings
run: python3 ./scripts/count-warnings.py build.log
build_gcc8:
name: "GCC 8 (ubuntu-18.04)"
@ -39,8 +41,10 @@ jobs:
set -x
$CXX --version
./autogen.sh
./configure
make -j "$(nproc)"
./configure CXXFLAGS="-Wall -fdiagnostics-color=always"
make -j "$(nproc)" |& tee build.log
- name: Summarize warnings
run: python3 ./scripts/count-warnings.py build.log
build_ubuntu:
name: "GCC"
@ -58,8 +62,10 @@ jobs:
set -x
g++ --version
./autogen.sh
./configure
make -j "$(nproc)"
./configure CXXFLAGS="-Wall -fdiagnostics-color=always"
make -j "$(nproc)" |& tee build.log
- name: Summarize warnings
run: python3 ./scripts/count-warnings.py build.log
build_clang:
name: "Clang 6 (ubuntu-18.04)"
@ -77,8 +83,10 @@ jobs:
set -x
$CXX --version
./autogen.sh
./configure
make -j "$(nproc)"
./configure CXXFLAGS="-Wall"
make -j "$(nproc)" |& tee build.log
- name: Summarize warnings
run: python3 ./scripts/count-warnings.py build.log
build_macos:
name: "Clang (macOS-10.14)"
@ -93,5 +101,7 @@ jobs:
set -x
clang++ --version
./autogen.sh
./configure
make -j "$(sysctl -n hw.physicalcpu)"
./configure CXXFLAGS="-Wall"
make -j "$(sysctl -n hw.physicalcpu)" 2>&1 | tee build.log
- name: Summarize warnings
run: python3 ./scripts/count-warnings.py build.log

88
scripts/count-warnings.py Normal file
View file

@ -0,0 +1,88 @@
#!/usr/bin/python3
# Copyright (c) 2019 Patryk Obara
# This script counts and all warnings and prints a summary.
#
# Usage: ./count-warnings.py build.log
# Usage: cat "*.log" | ./count-warnings.py -
#
# note: new compilers include additional flag -fdiagnostics-format=[text|json],
# which could be used instead of parsing using regex, but we want to preserve
# human-readable output in standard log.
# pylint: disable=invalid-name
# pylint: disable=missing-docstring
import os
import re
import sys
# Maximum allowed number of warnings; if build will include more warnings,
# then script will return with status 1. Simply change this line if you
# want to set a different limit.
#
MAX_WARNINGS = 357
# For recognizing warnings in GCC format in stderr:
#
WARNING_PATTERN = re.compile(r'([^:]+):(\d+):\d+: warning: .* \[-W(.+)\]')
# ~~~~~ ~~~ ~~~ ~~ ~~
# ↑ ↑ ↑ ↑ ↑
# file line column message type
# For removing color when GCC is invoked with -fdiagnostics-color=always
#
ANSI_COLOR_PATTERN = re.compile(r'\x1b\[[0-9;]*[mGKH]')
def remove_colors(line):
return re.sub(ANSI_COLOR_PATTERN, '', line)
def count_warning(line, warning_types):
line = remove_colors(line)
match = WARNING_PATTERN.match(line)
if not match:
return 0
# file = match.group(1)
# line = match.group(2)
wtype = match.group(3)
count = warning_types.get(wtype) or 0
warning_types[wtype] = count + 1
return 1
def get_input_lines(name):
if name == '-':
return sys.stdin.readlines()
if not os.path.isfile(name):
print('{}: no such file.'.format(name))
sys.exit(2)
with open(name, 'r') as logs:
return logs.readlines()
def print_summary(warning_types):
print("Warnings grouped by type:\n")
summary = list(warning_types.items())
for warning, count in sorted(summary, key=lambda x: -x[1]):
print(' {:28s}: {}'.format(warning, count))
print()
def main():
total = 0
warning_types = {}
for line in get_input_lines(sys.argv[1]):
total += count_warning(line, warning_types)
if warning_types:
print_summary(warning_types)
print('Total: {} warnings\n'.format(total))
if total > MAX_WARNINGS:
print('Error: upper limit of warnings is', MAX_WARNINGS)
sys.exit(1)
if __name__ == '__main__':
main()