Skip to content

Commit 1cf624b

Browse files
nohlsonblurb-it[bot]hugovk
authored
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 <[email protected]>
1 parent 8e2dc7f commit 1cf624b

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add ability to ignore warnings per file with warning count in warning checking tooling.
2+
Patch by Nate Ohlson.

Tools/build/.warningignore_macos

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# Files listed will be ignored by the compiler warning checker
22
# for the macOS/build and test job.
33
# Keep lines sorted lexicographically to help avoid merge conflicts.
4+
# Format example:
5+
# /path/to/file (number of warnings in file)

Tools/build/.warningignore_ubuntu

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# Files listed will be ignored by the compiler warning checker
22
# for the Ubuntu/build and test job.
33
# Keep lines sorted lexicographically to help avoid merge conflicts.
4+
# Format example:
5+
# /path/to/file (number of warnings in file)

Tools/build/check_warnings.py

+40-14
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
import re
1010
import sys
1111
from pathlib import Path
12+
from typing import NamedTuple
13+
14+
class FileWarnings(NamedTuple):
15+
name: str
16+
count: int
1217

1318

1419
def extract_warnings_from_compiler_output_clang(
@@ -19,7 +24,8 @@ def extract_warnings_from_compiler_output_clang(
1924
"""
2025
# Regex to find warnings in the compiler output
2126
clang_warning_regex = re.compile(
22-
r"(?P<file>.*):(?P<line>\d+):(?P<column>\d+): warning: (?P<message>.*)"
27+
r"(?P<file>.*):(?P<line>\d+):(?P<column>\d+): warning: "
28+
r"(?P<message>.*) (?P<option>\[-[^\]]+\])$"
2329
)
2430
compiler_warnings = []
2531
for line in compiler_output.splitlines():
@@ -30,6 +36,7 @@ def extract_warnings_from_compiler_output_clang(
3036
"line": match.group("line"),
3137
"column": match.group("column"),
3238
"message": match.group("message"),
39+
"option": match.group("option").lstrip("[").rstrip("]"),
3340
}
3441
)
3542

@@ -49,9 +56,7 @@ def extract_warnings_from_compiler_output_json(
4956
"""
5057
# Regex to find json arrays at the top level of the file
5158
# in the compiler output
52-
json_arrays = re.findall(
53-
r"\[(?:[^[\]]|\[[^\]]*\])*\]", compiler_output
54-
)
59+
json_arrays = re.findall(r"\[(?:[^[\]]|\[[^]]*])*]", compiler_output)
5560
compiler_warnings = []
5661
for array in json_arrays:
5762
try:
@@ -74,6 +79,7 @@ def extract_warnings_from_compiler_output_json(
7479
"line": location[key]["line"],
7580
"column": location[key]["column"],
7681
"message": warning["message"],
82+
"option": warning["option"],
7783
}
7884
)
7985
# Found a caret, start, or end in location so
@@ -92,18 +98,26 @@ def extract_warnings_from_compiler_output_json(
9298
def get_warnings_by_file(warnings: list[dict]) -> dict[str, list[dict]]:
9399
"""
94100
Returns a dictionary where the key is the file and the data is the warnings
95-
in that file
101+
in that file. Does not include duplicate warnings for a file from list of
102+
provided warnings.
96103
"""
97104
warnings_by_file = defaultdict(list)
105+
warnings_added = set()
98106
for warning in warnings:
99-
warnings_by_file[warning["file"]].append(warning)
107+
warning_key = (
108+
f"{warning['file']}-{warning['line']}-"
109+
f"{warning['column']}-{warning['option']}"
110+
)
111+
if warning_key not in warnings_added:
112+
warnings_added.add(warning_key)
113+
warnings_by_file[warning["file"]].append(warning)
100114

101115
return warnings_by_file
102116

103117

104118
def get_unexpected_warnings(
105-
files_with_expected_warnings: set[str],
106-
files_with_warnings: dict[str, list[dict]],
119+
files_with_expected_warnings: set[FileWarnings],
120+
files_with_warnings: set[FileWarnings],
107121
) -> int:
108122
"""
109123
Returns failure status if warnings discovered in list of warnings
@@ -112,7 +126,14 @@ def get_unexpected_warnings(
112126
"""
113127
unexpected_warnings = []
114128
for file in files_with_warnings.keys():
115-
if file not in files_with_expected_warnings:
129+
found_file_in_ignore_list = False
130+
for ignore_file in files_with_expected_warnings:
131+
if file == ignore_file.name:
132+
if len(files_with_warnings[file]) > ignore_file.count:
133+
unexpected_warnings.extend(files_with_warnings[file])
134+
found_file_in_ignore_list = True
135+
break
136+
if not found_file_in_ignore_list:
116137
unexpected_warnings.extend(files_with_warnings[file])
117138

118139
if unexpected_warnings:
@@ -125,22 +146,24 @@ def get_unexpected_warnings(
125146

126147

127148
def get_unexpected_improvements(
128-
files_with_expected_warnings: set[str],
129-
files_with_warnings: dict[str, list[dict]],
149+
files_with_expected_warnings: set[FileWarnings],
150+
files_with_warnings: set[FileWarnings],
130151
) -> int:
131152
"""
132153
Returns failure status if there are no warnings in the list of warnings
133154
for a file that is in the list of files with expected warnings
134155
"""
135156
unexpected_improvements = []
136157
for file in files_with_expected_warnings:
137-
if file not in files_with_warnings.keys():
158+
if file.name not in files_with_warnings.keys():
138159
unexpected_improvements.append(file)
160+
elif len(files_with_warnings[file.name]) < file.count:
161+
unexpected_improvements.append(file)
139162

140163
if unexpected_improvements:
141164
print("Unexpected improvements:")
142165
for file in unexpected_improvements:
143-
print(file)
166+
print(file.name)
144167
return 1
145168

146169
return 0
@@ -214,8 +237,11 @@ def main(argv: list[str] | None = None) -> int:
214237
with Path(args.warning_ignore_file_path).open(
215238
encoding="UTF-8"
216239
) as clean_files:
240+
# Files with expected warnings are stored as a set of tuples
241+
# where the first element is the file name and the second element
242+
# is the number of warnings expected in that file
217243
files_with_expected_warnings = {
218-
file.strip()
244+
FileWarnings(file.strip().split()[0], int(file.strip().split()[1]))
219245
for file in clean_files
220246
if file.strip() and not file.startswith("#")
221247
}

0 commit comments

Comments
 (0)