@@ -27,25 +27,27 @@ EXCEPTIONAL_FILES = [
27
27
pathlib .Path ("test/IDE/complete_decl_attribute_feature_requirement.swift" ),
28
28
]
29
29
30
- FEATURE_USAGE_RE = re .compile (
30
+ ENABLE_FEATURE_RE = re .compile (
31
31
r"-enable-(?:experimental|upcoming)-feature (?:-Xfrontend )?([A-Za-z0-9]*)"
32
32
)
33
- # Be careful of not using REQUIRES or RUN with a colon after them or Lit will
34
- # pick them up.
35
33
FEATURE_LIT_MARKER_RE = re .compile (r"swift_feature_([A-Za-z0-9]*)" )
36
34
37
35
38
- def find_test_files_with_features_usage (swift_src_root ):
36
+ def find_test_files (swift_src_root ):
37
+ # Look for every test file in the test directories with `REQUIRES` lines
38
+ # that mention `swift_feature_`.
39
39
# Look for every test file in the test directories with `RUN` lines that
40
40
# mention `-enable-experimental-feature` or `-enable-upcoming-feature`.
41
- # Be careful of not using REQUIRES or RUN with a colon after them or Lit will
41
+ # Be careful to not use RUN or REQUIRES with a colon after them or Lit will
42
42
# pick them up.
43
43
output = subprocess .check_output (
44
44
[
45
45
"grep" ,
46
46
"--extended-regexp" ,
47
47
"--recursive" ,
48
48
"-e" ,
49
+ "REQUIRES[:].*swift_feature_" ,
50
+ "-e" ,
49
51
"RUN[:].*-enable-(experimental|upcoming)-feature" ,
50
52
"--files-with-matches" ,
51
53
str (swift_src_root / "test" ),
@@ -56,154 +58,68 @@ def find_test_files_with_features_usage(swift_src_root):
56
58
return output .splitlines ()
57
59
58
60
59
- def find_test_files_with_marker_usage (swift_src_root ):
60
- # Look for every test file in the test directories with `REQUIRES` lines
61
- # that mention `swift_feature_`.
62
- # Be careful of not using REQUIRES with a colon after them or Lit will
61
+ def find_run_and_requires_lines (test_file ):
62
+ # Be careful to not use RUN or REQUIRES with a colon after them or Lit will
63
63
# pick them up.
64
- output = subprocess .check_output (
65
- [
66
- "grep" ,
67
- "--extended-regexp" ,
68
- "--recursive" ,
69
- "-e" ,
70
- "REQUIRES[:].*swift_feature_" ,
71
- "--files-with-matches" ,
72
- str (swift_src_root / "test" ),
73
- str (swift_src_root / "validation-test" ),
74
- ],
75
- text = True ,
76
- )
77
- return output .splitlines ()
78
-
79
-
80
- def find_run_lines (test_file ):
81
64
output = subprocess .check_output (
82
65
[
83
66
"grep" ,
84
67
"--extended-regexp" ,
85
68
"--no-filename" ,
86
69
"-e" ,
87
70
"RUN[:]" ,
88
- str (test_file ),
89
- ],
90
- text = True ,
91
- )
92
- return output .splitlines ()
93
-
94
-
95
- def find_requires_lines (test_file ):
96
- output = subprocess .check_output (
97
- [
98
- "grep" ,
99
- "--extended-regexp" ,
100
- "--no-filename" ,
101
71
"-e" ,
102
72
"REQUIRES[:]" ,
103
- str ( test_file ) ,
73
+ test_file ,
104
74
],
105
75
text = True ,
106
76
)
107
77
return output .splitlines ()
108
78
109
79
110
- def check_existing_requires (test_file , feature ):
111
- returncode = subprocess .call (
112
- [
113
- "grep" ,
114
- "--extended-regexp" ,
115
- "--quiet" ,
116
- "-e" ,
117
- "REQUIRES[:].*swift_feature_" + feature ,
118
- str (test_file ),
119
- ]
120
- )
121
- return returncode != 0
80
+ def check_test_file (test_file , existing_swift_features ):
81
+ enabled_features = set ()
82
+ required_features = set ()
122
83
84
+ for line in find_run_and_requires_lines (test_file ):
85
+ enabled_features .update (feature for feature in ENABLE_FEATURE_RE .findall (line ))
86
+ required_features .update (
87
+ feature for feature in FEATURE_LIT_MARKER_RE .findall (line )
88
+ )
123
89
124
- def check_existing_feature_usage (test_file , feature ):
125
- returncode = subprocess .call (
126
- [
127
- "grep" ,
128
- "--extended-regexp" ,
129
- "--quiet" ,
130
- "-e" ,
131
- (
132
- "RUN[:].*-enable-(experimental|upcoming)-feature (-Xfrontend )?"
133
- + re .escape (feature )
134
- ),
135
- str (test_file ),
136
- ]
137
- )
138
- return returncode != 0
90
+ had_error = False
139
91
92
+ # First check for unknown features.
140
93
141
- def check_existing_error_message_checks (test_file , feature ):
142
- returncode = subprocess .call (
143
- [
144
- "grep" ,
145
- "--extended-regexp" ,
146
- "--quiet" ,
147
- "-e" ,
148
- "requires '-enable-(experimental|upcoming)-feature " + feature + "'" ,
149
- str (test_file ),
150
- ]
151
- )
152
- return returncode != 0
94
+ for feature in enabled_features .difference (existing_swift_features ):
95
+ enabled_features .remove (feature )
96
+ print (f"error: { test_file } : Unknown feature in RUN line: { feature } " )
97
+ had_error = True
153
98
99
+ for feature in required_features .difference (existing_swift_features ):
100
+ required_features .remove (feature )
101
+ print (f"error: { test_file } : Unknown feature in REQUIRES line: { feature } " )
102
+ had_error = True
154
103
155
- def check_test_file_feature_usage (test_file , existing_swift_features ):
156
- run_lines = find_run_lines (test_file )
157
- features = set (
158
- feature for line in run_lines for feature in FEATURE_USAGE_RE .findall (line )
159
- )
160
- num_failures = 0
161
- for feature in features :
162
- # First, check this is a valid feature
163
- if feature not in existing_swift_features :
164
- print ("error: {}: Unknown feature: {}" .format (str (test_file ), feature ))
165
- num_failures += 1
166
- continue
104
+ # If the sets are equal, we're fine.
105
+ if enabled_features == required_features :
106
+ return had_error
167
107
168
- # No warning if the necessary `REQUIRES` is already there
169
- if not check_existing_requires (test_file , feature ):
170
- continue
108
+ # Then check for imbalances between required and enabled features.
171
109
172
- # Some tests check for the errors themselves, so we can skip them as well
173
- if not check_existing_error_message_checks (test_file , feature ):
174
- continue
110
+ for feature in enabled_features .difference (required_features ):
111
+ # Be careful to not use REQUIRES with a colon after it or Lit will pick
112
+ # it up.
113
+ print (f"error: { test_file } : Missing 'REQUIRES" + f": swift_feature_{ feature } '" )
114
+ had_error = True
175
115
176
- # For everything else, print a warning and add to the invalid exit code
116
+ for feature in required_features . difference ( enabled_features ):
177
117
print (
178
- "error: {}: Missing '{}: swift_feature_{}'" .format (
179
- str (test_file ), "REQUIRES" , feature
180
- )
118
+ f"error: { test_file } : Missing '-enable-(experimental|upcoming)-feature: { feature } '"
181
119
)
182
- num_failures += 1
183
- return num_failures == 0
120
+ had_error = True
184
121
185
-
186
- def check_test_file_marker_usage (test_file ):
187
- require_lines = find_requires_lines (test_file )
188
- features = set (
189
- feature
190
- for line in require_lines
191
- for feature in FEATURE_LIT_MARKER_RE .findall (line )
192
- )
193
- num_failures = 0
194
- for feature in features :
195
- # No warning if -enable-experimental/upcoming-feature is there
196
- if not check_existing_feature_usage (test_file , feature ):
197
- continue
198
-
199
- # For everything else, print a warning and add to the invalid exit code
200
- print (
201
- "error: {}: Missing '-enable-experimental/upcoming-feature: {}'" .format (
202
- str (test_file ), feature
203
- )
204
- )
205
- num_failures += 1
206
- return num_failures == 0
122
+ return had_error
207
123
208
124
209
125
def main ():
@@ -214,29 +130,17 @@ def main():
214
130
swift_src_root = pathlib .Path (sys .argv [1 ])
215
131
existing_swift_features = set (json .loads (sys .argv [2 ]))
216
132
217
- num_failures = 0
218
- test_files_with_features_usage = find_test_files_with_features_usage (swift_src_root )
219
- for test_file in test_files_with_features_usage :
220
- test_file = pathlib .Path (test_file )
221
- # First lets check this is not one of the exceptional files
222
- if test_file .relative_to (swift_src_root ) in EXCEPTIONAL_FILES :
223
- continue
224
-
225
- if not check_test_file_feature_usage (test_file , existing_swift_features ):
226
- num_failures += 1
227
-
228
- test_files_with_marker_usage = find_test_files_with_marker_usage (swift_src_root )
229
- for test_file in test_files_with_marker_usage :
230
- test_file = pathlib .Path (test_file )
133
+ had_error = False
231
134
232
- # First lets check this is not one of the exceptional files
233
- if test_file .relative_to (swift_src_root ) in EXCEPTIONAL_FILES :
135
+ for test_file in find_test_files (swift_src_root ):
136
+ # Skip if this is one of the exceptional files.
137
+ if pathlib .Path (test_file ).relative_to (swift_src_root ) in EXCEPTIONAL_FILES :
234
138
continue
235
139
236
- if not check_test_file_marker_usage (test_file ):
237
- num_failures += 1
140
+ if check_test_file (test_file , existing_swift_features ):
141
+ had_error = True
238
142
239
- if num_failures > 0 :
143
+ if had_error :
240
144
sys .exit (1 )
241
145
242
146
0 commit comments