1
1
#! /usr/bin/env python3
2
2
# -*- python -*-
3
- # RUN: %{python} %s '%swift_src_root'
3
+ # RUN: %{python} %s '%swift_src_root' %existing-swift-features
4
4
5
+ import json
5
6
import pathlib
6
7
import re
7
8
import subprocess
@@ -11,8 +12,14 @@ import sys
11
12
# Tests that check for the behaviour of experimental/upcoming features, so
12
13
# they cannot automatically be checked.
13
14
EXCEPTIONAL_FILES = [
15
+ # Tests for ParserValidation not being defined in no-asserts compilers
14
16
pathlib .Path ("test/Frontend/experimental-features-no-asserts.swift" ),
17
+ # Tests for UnknownFeature not existing
15
18
pathlib .Path ("test/Frontend/upcoming_feature.swift" ),
19
+ # Tests for ModuleInterfaceExportAs being ignored
20
+ pathlib .Path ("test/ModuleInterface/swift-export-as.swift" ),
21
+ # Uses the pseudo-feature AvailabilityMacro=
22
+ pathlib .Path ("test/Sema/availability_define.swift" ),
16
23
]
17
24
18
25
FEATURE_USAGE_RE = re .compile (
@@ -28,16 +35,19 @@ def find_test_files_with_features_usage(swift_src_root):
28
35
# mention `-enable-experimental-feature` or `-enable-upcoming-feature`.
29
36
# Be careful of not using REQUIRES or RUN with a colon after them or Lit will
30
37
# pick them up.
31
- output = subprocess .check_output ([
32
- "grep" ,
33
- "--extended-regexp" ,
34
- "--recursive" ,
35
- "-e" ,
36
- "RUN[:].*-enable-(experimental|upcoming)-feature" ,
37
- "--files-with-matches" ,
38
- str (swift_src_root / "test" ),
39
- str (swift_src_root / "validation-test" ),
40
- ], text = True )
38
+ output = subprocess .check_output (
39
+ [
40
+ "grep" ,
41
+ "--extended-regexp" ,
42
+ "--recursive" ,
43
+ "-e" ,
44
+ "RUN[:].*-enable-(experimental|upcoming)-feature" ,
45
+ "--files-with-matches" ,
46
+ str (swift_src_root / "test" ),
47
+ str (swift_src_root / "validation-test" ),
48
+ ],
49
+ text = True ,
50
+ )
41
51
return output .splitlines ()
42
52
43
53
@@ -46,91 +56,110 @@ def find_test_files_with_marker_usage(swift_src_root):
46
56
# that mention `swift_feature_`.
47
57
# Be careful of not using REQUIRES with a colon after them or Lit will
48
58
# pick them up.
49
- output = subprocess .check_output ([
50
- "grep" ,
51
- "--extended-regexp" ,
52
- "--recursive" ,
53
- "-e" ,
54
- "REQUIRES[:].*swift_feature_" ,
55
- "--files-with-matches" ,
56
- str (swift_src_root / "test" ),
57
- str (swift_src_root / "validation-test" ),
58
- ], text = True )
59
+ output = subprocess .check_output (
60
+ [
61
+ "grep" ,
62
+ "--extended-regexp" ,
63
+ "--recursive" ,
64
+ "-e" ,
65
+ "REQUIRES[:].*swift_feature_" ,
66
+ "--files-with-matches" ,
67
+ str (swift_src_root / "test" ),
68
+ str (swift_src_root / "validation-test" ),
69
+ ],
70
+ text = True ,
71
+ )
59
72
return output .splitlines ()
60
73
61
74
62
75
def find_run_lines (test_file ):
63
- output = subprocess .check_output ([
64
- "grep" ,
65
- "--extended-regexp" ,
66
- "--no-filename" ,
67
- "-e" ,
68
- "RUN[:]" ,
69
- str (test_file ),
70
- ], text = True )
76
+ output = subprocess .check_output (
77
+ [
78
+ "grep" ,
79
+ "--extended-regexp" ,
80
+ "--no-filename" ,
81
+ "-e" ,
82
+ "RUN[:]" ,
83
+ str (test_file ),
84
+ ],
85
+ text = True ,
86
+ )
71
87
return output .splitlines ()
72
88
73
89
74
90
def find_requires_lines (test_file ):
75
- output = subprocess .check_output ([
76
- "grep" ,
77
- "--extended-regexp" ,
78
- "--no-filename" ,
79
- "-e" ,
80
- "REQUIRES[:]" ,
81
- str (test_file ),
82
- ], text = True )
91
+ output = subprocess .check_output (
92
+ [
93
+ "grep" ,
94
+ "--extended-regexp" ,
95
+ "--no-filename" ,
96
+ "-e" ,
97
+ "REQUIRES[:]" ,
98
+ str (test_file ),
99
+ ],
100
+ text = True ,
101
+ )
83
102
return output .splitlines ()
84
103
85
104
86
105
def check_existing_requires (test_file , feature ):
87
- returncode = subprocess .call ([
88
- "grep" ,
89
- "--extended-regexp" ,
90
- "--quiet" ,
91
- "-e" ,
92
- "REQUIRES[:].*swift_feature_" + feature ,
93
- str (test_file ),
94
- ])
106
+ returncode = subprocess .call (
107
+ [
108
+ "grep" ,
109
+ "--extended-regexp" ,
110
+ "--quiet" ,
111
+ "-e" ,
112
+ "REQUIRES[:].*swift_feature_" + feature ,
113
+ str (test_file ),
114
+ ]
115
+ )
95
116
return returncode != 0
96
117
97
118
98
119
def check_existing_feature_usage (test_file , feature ):
99
- returncode = subprocess .call ([
100
- "grep" ,
101
- "--extended-regexp" ,
102
- "--quiet" ,
103
- "-e" ,
104
- (
105
- "RUN[:].*-enable-(experimental|upcoming)-feature (-Xfrontend )?"
106
- + re .escape (feature )
107
- ),
108
- str (test_file ),
109
- ])
120
+ returncode = subprocess .call (
121
+ [
122
+ "grep" ,
123
+ "--extended-regexp" ,
124
+ "--quiet" ,
125
+ "-e" ,
126
+ (
127
+ "RUN[:].*-enable-(experimental|upcoming)-feature (-Xfrontend )?"
128
+ + re .escape (feature )
129
+ ),
130
+ str (test_file ),
131
+ ]
132
+ )
110
133
return returncode != 0
111
134
112
135
113
136
def check_existing_error_message_checks (test_file , feature ):
114
- returncode = subprocess .call ([
115
- "grep" ,
116
- "--extended-regexp" ,
117
- "--quiet" ,
118
- "-e" ,
119
- "requires '-enable-(experimental|upcoming)-feature " + feature + "'" ,
120
- str (test_file ),
121
- ])
137
+ returncode = subprocess .call (
138
+ [
139
+ "grep" ,
140
+ "--extended-regexp" ,
141
+ "--quiet" ,
142
+ "-e" ,
143
+ "requires '-enable-(experimental|upcoming)-feature " + feature + "'" ,
144
+ str (test_file ),
145
+ ]
146
+ )
122
147
return returncode != 0
123
148
124
149
125
- def check_test_file_feature_usage (test_file ):
150
+ def check_test_file_feature_usage (test_file , existing_swift_features ):
126
151
run_lines = find_run_lines (test_file )
127
152
features = set (
128
- feature
129
- for line in run_lines
130
- for feature in FEATURE_USAGE_RE .findall (line )
153
+ feature for line in run_lines for feature in FEATURE_USAGE_RE .findall (line )
131
154
)
132
155
num_failures = 0
133
156
for feature in features :
157
+ # First, check this is a valid feature
158
+ if feature not in existing_swift_features :
159
+ print ("error: {}: Unknown feature: {}" .format (str (test_file ), feature ))
160
+ num_failures += 1
161
+ continue
162
+
134
163
# No warning if the necessary `REQUIRES` is already there
135
164
if not check_existing_requires (test_file , feature ):
136
165
continue
@@ -142,9 +171,7 @@ def check_test_file_feature_usage(test_file):
142
171
# For everything else, print a warning and add to the invalid exit code
143
172
print (
144
173
"error: {}: Missing '{}: swift_feature_{}'" .format (
145
- str (test_file ),
146
- "REQUIRES" ,
147
- feature
174
+ str (test_file ), "REQUIRES" , feature
148
175
)
149
176
)
150
177
num_failures += 1
@@ -167,20 +194,20 @@ def check_test_file_marker_usage(test_file):
167
194
# For everything else, print a warning and add to the invalid exit code
168
195
print (
169
196
"error: {}: Missing '-enable-experimental/upcoming-feature: {}'" .format (
170
- str (test_file ),
171
- feature
197
+ str (test_file ), feature
172
198
)
173
199
)
174
200
num_failures += 1
175
201
return num_failures == 0
176
202
177
203
178
204
def main ():
179
- if len (sys .argv ) < 2 :
180
- print (' Invalid number of arguments.' )
205
+ if len (sys .argv ) < 3 :
206
+ print (" Invalid number of arguments." )
181
207
sys .exit (1 )
182
208
183
209
swift_src_root = pathlib .Path (sys .argv [1 ])
210
+ existing_swift_features = set (json .loads (sys .argv [2 ]))
184
211
185
212
num_failures = 0
186
213
test_files_with_features_usage = find_test_files_with_features_usage (swift_src_root )
@@ -190,7 +217,7 @@ def main():
190
217
if test_file .relative_to (swift_src_root ) in EXCEPTIONAL_FILES :
191
218
continue
192
219
193
- if not check_test_file_feature_usage (test_file ):
220
+ if not check_test_file_feature_usage (test_file , existing_swift_features ):
194
221
num_failures += 1
195
222
196
223
test_files_with_marker_usage = find_test_files_with_marker_usage (swift_src_root )
@@ -208,5 +235,5 @@ def main():
208
235
sys .exit (1 )
209
236
210
237
211
- if __name__ == ' __main__' :
238
+ if __name__ == " __main__" :
212
239
main ()
0 commit comments