Skip to content

Commit 9916a6d

Browse files
committed
[Refactoring] Add a drop-in replacement for swift-refactor which checks that the code compiles after refactoring
1 parent c7b383c commit 9916a6d

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

test/lit.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ config.scale_test = make_path(config.swift_utils, 'scale-test')
334334
config.PathSanitizingFileCheck = make_path(config.swift_utils, 'PathSanitizingFileCheck')
335335
config.swift_lib_dir = make_path(config.swift, '..', '..', 'lib')
336336
config.round_trip_syntax_test = make_path(config.swift_utils, 'round-trip-syntax-test')
337+
config.refactor_check_compiles = make_path(config.swift_utils, 'refactor-check-compiles.py')
337338

338339
config.link = lit.util.which('link', config.environment.get('PATH', '')) or \
339340
lit.util.which('lld-link', config.environment.get('PATH', ''))

test/refactoring/lit.local.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ if 'OS=macosx' not in config.available_features:
22
config.unsupported = True
33

44
else:
5+
config.substitutions.append(('%refactor-check-compiles', '{} -swift-refactor {} -swift-frontend {} -temp-dir %t'.format(config.refactor_check_compiles, config.swift_refactor, config.swift_frontend)))
56
config.substitutions.append(('%refactor', config.swift_refactor))

utils/refactor-check-compiles.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env python
2+
from __future__ import print_function
3+
4+
import argparse
5+
import os
6+
import subprocess
7+
import sys
8+
9+
10+
def run_cmd(cmd, desc):
11+
try:
12+
return subprocess.check_output(cmd)
13+
except subprocess.CalledProcessError:
14+
print('FAILED ' + desc + ':', file=sys.stderr)
15+
print(' '.join(cmd), file=sys.stderr)
16+
sys.exit(1)
17+
18+
19+
def parse_args():
20+
parser = argparse.ArgumentParser(
21+
formatter_class=argparse.RawDescriptionHelpFormatter,
22+
description="""
23+
A drop-in replacement for a 'swift-refactor -dump-text' call that
24+
1. Checkes that the file still compiles after the refactoring by doing
25+
'swift-refactor -dump-rewritten' and feeding the result to
26+
'swift-frontend -typecheck'
27+
2. Outputting the result of the 'swift-refactor -dump-text' call
28+
29+
All arguments other than the following will be forwarded to :
30+
'swift-refactor':
31+
- swift-frontend
32+
- swift-refactor
33+
- temp-dir
34+
""")
35+
36+
parser.add_argument(
37+
'-swift-frontend',
38+
help='The path to the swift-frontend executable'
39+
)
40+
parser.add_argument(
41+
'-swift-refactor',
42+
help='The path to the swift-refactor executable'
43+
)
44+
parser.add_argument(
45+
'-temp-dir',
46+
help='A temporary directory to save the rewritten file in'
47+
)
48+
parser.add_argument(
49+
'-dump-text',
50+
action='store_true',
51+
help='''
52+
Required argument to indicate that the outputted text will be that of
53+
swift-refactor -dump-text. This makes this script a drop-in replacement.
54+
'''
55+
)
56+
parser.add_argument(
57+
'-source-filename',
58+
help='The file to refactor'
59+
)
60+
parser.add_argument(
61+
'-pos',
62+
help='The position to invoke the refactoring at'
63+
)
64+
65+
return parser.parse_known_args()
66+
67+
68+
def main():
69+
(args, unknown_args) = parse_args()
70+
temp_file_name = os.path.split(args.source_filename)[-1] + '.' + \
71+
args.pos.replace(':', '.')
72+
temp_file_path = os.path.join(args.temp_dir, temp_file_name)
73+
print(temp_file_path)
74+
dump_text_output = run_cmd([
75+
args.swift_refactor,
76+
'-dump-text',
77+
'-source-filename', args.source_filename,
78+
'-pos', args.pos
79+
] + unknown_args, desc='producing edit')
80+
81+
dump_rewritten_output = run_cmd([
82+
args.swift_refactor,
83+
'-dump-rewritten',
84+
'-source-filename', args.source_filename,
85+
'-pos', args.pos
86+
] + unknown_args, desc='producing rewritten file')
87+
with open(temp_file_path, 'wb') as f:
88+
f.write(dump_rewritten_output)
89+
90+
run_cmd([
91+
args.swift_frontend,
92+
'-typecheck',
93+
temp_file_path,
94+
'-disable-availability-checking'
95+
], desc='checking that rewritten file compiles')
96+
sys.stdout.write(dump_text_output)
97+
98+
99+
if __name__ == '__main__':
100+
main()

0 commit comments

Comments
 (0)