diff options
author | Nate Ohlson <nohlson@purdue.edu> | 2024-08-14 21:03:53 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-14 21:03:53 (GMT) |
commit | 1cf624be6dab5170f4ee40dfce729df7de1d5056 (patch) | |
tree | cdb110538066aab9ef221cd078bec25e8a727cbf /Tools/build | |
parent | 8e2dc7f380c7ffe6b0fe525b4d0558aaed9d7145 (diff) | |
download | cpython-1cf624be6dab5170f4ee40dfce729df7de1d5056.zip cpython-1cf624be6dab5170f4ee40dfce729df7de1d5056.tar.gz cpython-1cf624be6dab5170f4ee40dfce729df7de1d5056.tar.bz2 |
gh-112301: Add warning count to warning check tooling (#122711)
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Diffstat (limited to 'Tools/build')
-rw-r--r-- | Tools/build/.warningignore_macos | 2 | ||||
-rw-r--r-- | Tools/build/.warningignore_ubuntu | 2 | ||||
-rw-r--r-- | Tools/build/check_warnings.py | 54 |
3 files changed, 44 insertions, 14 deletions
diff --git a/Tools/build/.warningignore_macos b/Tools/build/.warningignore_macos index 1b504df..67f5011 100644 --- a/Tools/build/.warningignore_macos +++ b/Tools/build/.warningignore_macos @@ -1,3 +1,5 @@ # Files listed will be ignored by the compiler warning checker # for the macOS/build and test job. # Keep lines sorted lexicographically to help avoid merge conflicts. +# Format example: +# /path/to/file (number of warnings in file) diff --git a/Tools/build/.warningignore_ubuntu b/Tools/build/.warningignore_ubuntu index 8242c8d..469c727 100644 --- a/Tools/build/.warningignore_ubuntu +++ b/Tools/build/.warningignore_ubuntu @@ -1,3 +1,5 @@ # Files listed will be ignored by the compiler warning checker # for the Ubuntu/build and test job. # Keep lines sorted lexicographically to help avoid merge conflicts. +# Format example: +# /path/to/file (number of warnings in file) diff --git a/Tools/build/check_warnings.py b/Tools/build/check_warnings.py index 3125893..1ed8344 100644 --- a/Tools/build/check_warnings.py +++ b/Tools/build/check_warnings.py @@ -9,6 +9,11 @@ import json import re import sys from pathlib import Path +from typing import NamedTuple + +class FileWarnings(NamedTuple): + name: str + count: int def extract_warnings_from_compiler_output_clang( @@ -19,7 +24,8 @@ def extract_warnings_from_compiler_output_clang( """ # Regex to find warnings in the compiler output clang_warning_regex = re.compile( - r"(?P<file>.*):(?P<line>\d+):(?P<column>\d+): warning: (?P<message>.*)" + r"(?P<file>.*):(?P<line>\d+):(?P<column>\d+): warning: " + r"(?P<message>.*) (?P<option>\[-[^\]]+\])$" ) compiler_warnings = [] for line in compiler_output.splitlines(): @@ -30,6 +36,7 @@ def extract_warnings_from_compiler_output_clang( "line": match.group("line"), "column": match.group("column"), "message": match.group("message"), + "option": match.group("option").lstrip("[").rstrip("]"), } ) @@ -49,9 +56,7 @@ def extract_warnings_from_compiler_output_json( """ # Regex to find json arrays at the top level of the file # in the compiler output - json_arrays = re.findall( - r"\[(?:[^[\]]|\[[^\]]*\])*\]", compiler_output - ) + json_arrays = re.findall(r"\[(?:[^[\]]|\[[^]]*])*]", compiler_output) compiler_warnings = [] for array in json_arrays: try: @@ -74,6 +79,7 @@ def extract_warnings_from_compiler_output_json( "line": location[key]["line"], "column": location[key]["column"], "message": warning["message"], + "option": warning["option"], } ) # Found a caret, start, or end in location so @@ -92,18 +98,26 @@ def extract_warnings_from_compiler_output_json( def get_warnings_by_file(warnings: list[dict]) -> dict[str, list[dict]]: """ Returns a dictionary where the key is the file and the data is the warnings - in that file + in that file. Does not include duplicate warnings for a file from list of + provided warnings. """ warnings_by_file = defaultdict(list) + warnings_added = set() for warning in warnings: - warnings_by_file[warning["file"]].append(warning) + warning_key = ( + f"{warning['file']}-{warning['line']}-" + f"{warning['column']}-{warning['option']}" + ) + if warning_key not in warnings_added: + warnings_added.add(warning_key) + warnings_by_file[warning["file"]].append(warning) return warnings_by_file def get_unexpected_warnings( - files_with_expected_warnings: set[str], - files_with_warnings: dict[str, list[dict]], + files_with_expected_warnings: set[FileWarnings], + files_with_warnings: set[FileWarnings], ) -> int: """ Returns failure status if warnings discovered in list of warnings @@ -112,7 +126,14 @@ def get_unexpected_warnings( """ unexpected_warnings = [] for file in files_with_warnings.keys(): - if file not in files_with_expected_warnings: + found_file_in_ignore_list = False + for ignore_file in files_with_expected_warnings: + if file == ignore_file.name: + if len(files_with_warnings[file]) > ignore_file.count: + unexpected_warnings.extend(files_with_warnings[file]) + found_file_in_ignore_list = True + break + if not found_file_in_ignore_list: unexpected_warnings.extend(files_with_warnings[file]) if unexpected_warnings: @@ -125,8 +146,8 @@ def get_unexpected_warnings( def get_unexpected_improvements( - files_with_expected_warnings: set[str], - files_with_warnings: dict[str, list[dict]], + files_with_expected_warnings: set[FileWarnings], + files_with_warnings: set[FileWarnings], ) -> int: """ Returns failure status if there are no warnings in the list of warnings @@ -134,13 +155,15 @@ def get_unexpected_improvements( """ unexpected_improvements = [] for file in files_with_expected_warnings: - if file not in files_with_warnings.keys(): + if file.name not in files_with_warnings.keys(): unexpected_improvements.append(file) + elif len(files_with_warnings[file.name]) < file.count: + unexpected_improvements.append(file) if unexpected_improvements: print("Unexpected improvements:") for file in unexpected_improvements: - print(file) + print(file.name) return 1 return 0 @@ -214,8 +237,11 @@ def main(argv: list[str] | None = None) -> int: with Path(args.warning_ignore_file_path).open( encoding="UTF-8" ) as clean_files: + # Files with expected warnings are stored as a set of tuples + # where the first element is the file name and the second element + # is the number of warnings expected in that file files_with_expected_warnings = { - file.strip() + FileWarnings(file.strip().split()[0], int(file.strip().split()[1])) for file in clean_files if file.strip() and not file.startswith("#") } |