7
7
from pathlib import Path
8
8
import argparse
9
9
import json
10
+ import re
10
11
11
12
def extract_warnings_from_compiler_output (compiler_output : str ) -> list [dict ]:
12
13
"""
@@ -15,26 +16,17 @@ def extract_warnings_from_compiler_output(compiler_output: str) -> list[dict]:
15
16
Compiler output as a whole is not a valid json document, but includes many json
16
17
objects and may include other output that is not json.
17
18
"""
18
- compiler_output_json_objects = []
19
- stack = []
20
- start_index = None
21
- for index , char in enumerate (compiler_output ):
22
- if char == '[' :
23
- if len (stack ) == 0 :
24
- start_index = index # Start of a new JSON array
25
- stack .append (char )
26
- elif char == ']' :
27
- if len (stack ) > 0 :
28
- stack .pop ()
29
- if len (stack ) == 0 and start_index is not None :
30
- try :
31
- json_data = json .loads (compiler_output [start_index :index + 1 ])
32
- compiler_output_json_objects .extend (json_data )
33
- start_index = None
34
- except json .JSONDecodeError :
35
- continue # Skip malformed JSON
36
-
37
- compiler_warnings = [entry for entry in compiler_output_json_objects if entry .get ('kind' ) == 'warning' ]
19
+
20
+ # Regex to find json arrays at the top level of the file in the compiler output
21
+ json_arrays = re .findall (r'\[(?:[^\[\]]|\[(?:[^\[\]]|\[[^\[\]]*\])*\])*\]' , compiler_output )
22
+ compiler_warnings = []
23
+ for array in json_arrays :
24
+ try :
25
+ json_data = json .loads (array )
26
+ json_objects_in_array = [entry for entry in json_data ]
27
+ compiler_warnings .extend ([entry for entry in json_objects_in_array if entry .get ('kind' ) == 'warning' ])
28
+ except json .JSONDecodeError :
29
+ continue # Skip malformed JSON
38
30
39
31
return compiler_warnings
40
32
@@ -52,8 +44,9 @@ def get_unexpected_warnings(
52
44
for location in locations :
53
45
for key in ['caret' , 'start' , 'end' ]:
54
46
if key in location :
55
- filename = location [key ]['file' ]
56
- if filename not in files_with_expected_warnings :
47
+ file = location [key ]['file' ]
48
+ file = file .lstrip ('./' ) # Remove leading curdir if present
49
+ if file not in files_with_expected_warnings :
57
50
unexpected_warnings .append (warning )
58
51
59
52
if unexpected_warnings :
@@ -81,18 +74,19 @@ def get_unexpected_improvements(
81
74
for location in locations :
82
75
for key in ['caret' , 'start' , 'end' ]:
83
76
if key in location :
84
- filename = location [key ]['file' ]
85
- files_with_warnings .add (filename )
77
+ file = location [key ]['file' ]
78
+ file = file .lstrip ('./' ) # Remove leading curdir if present
79
+ files_with_warnings .add (file )
86
80
87
81
unexpected_improvements = []
88
- for filename in files_with_expected_warnings :
89
- if filename not in files_with_warnings :
90
- unexpected_improvements .append (filename )
82
+ for file in files_with_expected_warnings :
83
+ if file not in files_with_warnings :
84
+ unexpected_improvements .append (file )
91
85
92
86
if unexpected_improvements :
93
87
print ("Unexpected improvements:" )
94
- for filename in unexpected_improvements :
95
- print (filename )
88
+ for file in unexpected_improvements :
89
+ print (file )
96
90
return 1
97
91
98
92
return 0
@@ -143,22 +137,19 @@ def main(argv: list[str] | None = None) -> int:
143
137
144
138
with Path (args .warning_ignore_file_path ).open (encoding = "UTF-8" ) as clean_files :
145
139
files_with_expected_warnings = {
146
- filename .strip ()
147
- for filename in clean_files
148
- if filename .strip () and not filename .startswith ("#" )
140
+ file .strip ()
141
+ for file in clean_files
142
+ if file .strip () and not file .startswith ("#" )
149
143
}
150
144
151
- if not len (compiler_output_file_contents ) > 0 :exit_code = 1
152
-
153
145
warnings = extract_warnings_from_compiler_output (compiler_output_file_contents )
154
146
155
147
status = get_unexpected_warnings (warnings , files_with_expected_warnings )
156
148
if args .fail_on_regression : exit_code |= status
157
149
158
150
status = get_unexpected_improvements (warnings , files_with_expected_warnings )
159
151
if args .fail_on_improvement : exit_code |= status
160
-
161
- print ("Returning exit code: " , exit_code )
152
+
162
153
return exit_code
163
154
164
155
if __name__ == "__main__" :
0 commit comments