@@ -33,59 +33,13 @@ ENABLE_FEATURE_RE = re.compile(
33
33
FEATURE_LIT_MARKER_RE = re .compile (r"swift_feature_([A-Za-z0-9]*)" )
34
34
35
35
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
- # Look for every test file in the test directories with `RUN` lines that
40
- # mention `-enable-experimental-feature` or `-enable-upcoming-feature`.
41
- # Be careful to not use RUN or REQUIRES with a colon after them or Lit will
42
- # pick them up.
43
- output = subprocess .check_output (
44
- [
45
- "grep" ,
46
- "--extended-regexp" ,
47
- "--recursive" ,
48
- "-e" ,
49
- "REQUIRES[:].*swift_feature_" ,
50
- "-e" ,
51
- "RUN[:].*-enable-(experimental|upcoming)-feature" ,
52
- "--files-with-matches" ,
53
- str (swift_src_root / "test" ),
54
- str (swift_src_root / "validation-test" ),
55
- ],
56
- text = True ,
57
- )
58
- return output .splitlines ()
59
-
60
-
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
- # pick them up.
64
- output = subprocess .check_output (
65
- [
66
- "grep" ,
67
- "--extended-regexp" ,
68
- "--no-filename" ,
69
- "-e" ,
70
- "RUN[:]" ,
71
- "-e" ,
72
- "REQUIRES[:]" ,
73
- test_file ,
74
- ],
75
- text = True ,
76
- )
77
- return output .splitlines ()
78
-
79
-
80
- def check_test_file (test_file , existing_swift_features ):
81
- enabled_features = set ()
82
- required_features = set ()
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
- )
36
+ def check_test_file (file_path , lines , existing_swift_features ):
37
+ enabled_features = {
38
+ feature for line in lines for feature in ENABLE_FEATURE_RE .findall (line )
39
+ }
40
+ required_features = {
41
+ feature for line in lines for feature in FEATURE_LIT_MARKER_RE .findall (line )
42
+ }
89
43
90
44
had_error = False
91
45
@@ -97,7 +51,7 @@ def check_test_file(test_file, existing_swift_features):
97
51
# Be careful to not use RUN with a colon after it or Lit will pick
98
52
# it up.
99
53
print (
100
- f"{ test_file } : error: unknown feature '{ feature } ' enabled in 'RUN"
54
+ f"{ file_path } : error: unknown feature '{ feature } ' enabled in 'RUN"
101
55
+ ":' line"
102
56
)
103
57
had_error = True
@@ -108,7 +62,7 @@ def check_test_file(test_file, existing_swift_features):
108
62
# Be careful to not use REQUIRES with a colon after it or Lit will pick
109
63
# it up.
110
64
print (
111
- f"{ test_file } : error: unknown feature '{ feature } ' in 'REQUIRES"
65
+ f"{ file_path } : error: unknown feature '{ feature } ' in 'REQUIRES"
112
66
+ f":' line: swift_feature_{ feature } "
113
67
)
114
68
had_error = True
@@ -123,20 +77,49 @@ def check_test_file(test_file, existing_swift_features):
123
77
# Be careful to not use REQUIRES with a colon after it or Lit will pick
124
78
# it up.
125
79
print (
126
- f"{ test_file } : error: file enables '{ feature } ' but is missing '// REQUIRES"
80
+ f"{ file_path } : error: file enables '{ feature } ' but is missing '// REQUIRES"
127
81
+ f": swift_feature_{ feature } '"
128
82
)
129
83
had_error = True
130
84
131
85
for feature in required_features .difference (enabled_features ):
132
86
print (
133
- f"{ test_file } : error: file requires 'swift_feature_{ feature } ' but does not enable '{ feature } '"
87
+ f"{ file_path } : error: file requires 'swift_feature_{ feature } ' but does not enable '{ feature } '"
134
88
)
135
89
had_error = True
136
90
137
91
return had_error
138
92
139
93
94
+ def find_matches (swift_src_root ):
95
+ # Look for every `REQUIRES` line that mentions `swift_feature_` in the
96
+ # test directories.
97
+ # Look for every `RUN` line that mentions `-enable-experimental-feature` or
98
+ # `-enable-upcoming-feature` in the test directories.
99
+ output = subprocess .check_output (
100
+ [
101
+ "grep" ,
102
+ "--extended-regexp" ,
103
+ "--recursive" ,
104
+ # Separate paths from lines with a null char.
105
+ "--null" ,
106
+ "-e" ,
107
+ # Be careful to not use REQUIRES with a colon after it or Lit will
108
+ # pick it up.
109
+ "REQUIRES[:].*swift_feature_" ,
110
+ "-e" ,
111
+ # Be careful to not use RUN with a colon after it or Lit will pick
112
+ # it up.
113
+ "RUN[:].*-enable-(experimental|upcoming)-feature" ,
114
+ "test" ,
115
+ "validation-test" ,
116
+ ],
117
+ text = True ,
118
+ cwd = str (swift_src_root ),
119
+ )
120
+ return output .splitlines ()
121
+
122
+
140
123
def main ():
141
124
if len (sys .argv ) < 3 :
142
125
print ("Invalid number of arguments." )
@@ -145,14 +128,23 @@ def main():
145
128
swift_src_root = pathlib .Path (sys .argv [1 ])
146
129
existing_swift_features = set (json .loads (sys .argv [2 ]))
147
130
148
- had_error = False
131
+ file_paths_to_lines = dict ()
132
+
133
+ # Build a dictionary that maps file paths to lists of matching lines.
134
+ for match in find_matches (swift_src_root ):
135
+ # '<path><zero-byte><line>'
136
+ relative_file_path , line = match .split ("\0 " )
149
137
150
- for test_file in find_test_files (swift_src_root ):
151
138
# Skip if this is one of the exceptional files.
152
- if pathlib .Path (test_file ). relative_to ( swift_src_root ) in EXCEPTIONAL_FILES :
139
+ if pathlib .Path (relative_file_path ) in EXCEPTIONAL_FILES :
153
140
continue
154
141
155
- if check_test_file (test_file , existing_swift_features ):
142
+ abs_file_path = swift_src_root / relative_file_path
143
+ file_paths_to_lines .setdefault (abs_file_path , list ()).append (line )
144
+
145
+ had_error = False
146
+ for file_path , lines in file_paths_to_lines .items ():
147
+ if check_test_file (file_path , lines , existing_swift_features ):
156
148
had_error = True
157
149
158
150
if had_error :
0 commit comments