blob: 53218360a6390a98be7ee0d76648f2dd0362020d [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# After turning on -Wconversion globally, run a fuchsia build, but save
# the output.
#
# $ fx build > /tmp/output 2>&1 # Can also use `ninja`
# $ ./scripts/wconversion/wconversion-checks.py /tmp/output -i=-Wsign-conversion
# 2815 errors in unique locations
# source files: 2073
# header files: 741
# other: 1
# third party: 180
# Counter({'-Wshorten-64-to-32': 1144, '-Wimplicit-int-conversion': 1038, ...})
# No. of failed targets: 679
import os.path
import re
import sys
WERROR_PATTERN = re.compile("\[-Werror,(.+)\]")
TARGET_PATTERN = re.compile("\[(\d+)/\d+\]")
def parse_args():
from argparse import ArgumentParser, FileType
parser = ArgumentParser(description="Script for grabbing statistics on -Wconversion errors from an `fx build` or `ninja` output")
parser.add_argument("infile",
type=FileType('r'),
help="File containing ninja logs")
# Ignore the `-W` because python will interpret it as an argument, even if it
# is wrapped in single quotes in bash.
parser.add_argument("-i", "--ignore",
action="append",
default=[],
help="Set of warnings to ignore (\"-Wshorten-64-to-32\", \"-Wsign-conversion\", etc.)")
return parser.parse_args()
def main():
args = parse_args()
ignored = set(args.ignore)
failed_targets = set()
errors = set()
third_party = 0
source_files = 0
header_files = 0
other = 0
cur_target = None
for line in args.infile:
if TARGET_PATTERN.search(line):
step, action, target = line.split(maxsplit=2)
cur_target = target.strip()
match = WERROR_PATTERN.search(line)
if not match:
continue
err = match.group(1)
if err in ignored:
continue
error_loc = line.find(": error: ")
assert error_loc >= 0, "Could not find error line"
path = line[:error_loc]
path, line, col = path.split(":")
line = int(line)
col = int(col)
errors.add((path, line, col, err))
assert cur_target is not None, "Expected a target"
if cur_target not in failed_targets:
failed_targets.add(cur_target)
for path, line, col, err in errors:
if path.startswith("../../third_party/"):
third_party += 1
if path.endswith(".c") or path.endswith(".cc") or path.endswith(".cpp"):
source_files += 1
elif path.endswith(".h") or path.endswith(".hpp"):
header_files += 1
else:
other += 1
print(len(errors), "errors in unique locations")
print("source files:", source_files)
print("header files:", header_files)
print("other:", other)
print("third party:", third_party)
# Distribution of errors
from collections import Counter
print(Counter((x[3] for x in errors)))
print("No. of failed targets:", len(failed_targets))
return 0
if __name__ == "__main__":
sys.exit(main())