@@ -33,59 +33,13 @@ ENABLE_FEATURE_RE = re.compile(
3333FEATURE_LIT_MARKER_RE = re .compile (r"swift_feature_([A-Za-z0-9]*)" )
3434
3535
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+ }
8943
9044 had_error = False
9145
@@ -97,7 +51,7 @@ def check_test_file(test_file, existing_swift_features):
9751 # Be careful to not use RUN with a colon after it or Lit will pick
9852 # it up.
9953 print (
100- f"{ test_file } : error: unknown feature '{ feature } ' enabled in 'RUN"
54+ f"{ file_path } : error: unknown feature '{ feature } ' enabled in 'RUN"
10155 + ":' line"
10256 )
10357 had_error = True
@@ -108,7 +62,7 @@ def check_test_file(test_file, existing_swift_features):
10862 # Be careful to not use REQUIRES with a colon after it or Lit will pick
10963 # it up.
11064 print (
111- f"{ test_file } : error: unknown feature '{ feature } ' in 'REQUIRES"
65+ f"{ file_path } : error: unknown feature '{ feature } ' in 'REQUIRES"
11266 + f":' line: swift_feature_{ feature } "
11367 )
11468 had_error = True
@@ -123,20 +77,49 @@ def check_test_file(test_file, existing_swift_features):
12377 # Be careful to not use REQUIRES with a colon after it or Lit will pick
12478 # it up.
12579 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"
12781 + f": swift_feature_{ feature } '"
12882 )
12983 had_error = True
13084
13185 for feature in required_features .difference (enabled_features ):
13286 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 } '"
13488 )
13589 had_error = True
13690
13791 return had_error
13892
13993
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+
140123def main ():
141124 if len (sys .argv ) < 3 :
142125 print ("Invalid number of arguments." )
@@ -145,14 +128,23 @@ def main():
145128 swift_src_root = pathlib .Path (sys .argv [1 ])
146129 existing_swift_features = set (json .loads (sys .argv [2 ]))
147130
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 " )
149137
150- for test_file in find_test_files (swift_src_root ):
151138 # 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 :
153140 continue
154141
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 ):
156148 had_error = True
157149
158150 if had_error :
0 commit comments