summaryrefslogtreecommitdiffstats
path: root/Tools/build
diff options
context:
space:
mode:
authorNate Ohlson <nohlson@purdue.edu>2024-08-14 21:03:53 (GMT)
committerGitHub <noreply@github.com>2024-08-14 21:03:53 (GMT)
commit1cf624be6dab5170f4ee40dfce729df7de1d5056 (patch)
treecdb110538066aab9ef221cd078bec25e8a727cbf /Tools/build
parent8e2dc7f380c7ffe6b0fe525b4d0558aaed9d7145 (diff)
downloadcpython-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_macos2
-rw-r--r--Tools/build/.warningignore_ubuntu2
-rw-r--r--Tools/build/check_warnings.py54
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("#")
}