Skip to content

Commit 1f54909

Browse files
committed
Add swift-format configuration options
1 parent a664165 commit 1f54909

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed

.swift-format

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": 1,
3+
"lineLength": 1000,
4+
"indentation": {
5+
"spaces": 2
6+
},
7+
"lineBreakBeforeEachArgument": true,
8+
"indentConditionalCompilationBlocks": false,
9+
"rules": {
10+
"AlwaysUseLowerCamelCase": false,
11+
"AmbiguousTrailingClosureOverload": false,
12+
"DontRepeatTypeInStaticProperties": false,
13+
"NoBlockComments": false,
14+
"Spacing": false,
15+
"UseLetInEveryBoundCaseVariable": false,
16+
"UseSynthesizedInitializer": false
17+
}
18+
}

format.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import subprocess
5+
from pathlib import Path
6+
from textwrap import dedent
7+
from typing import List
8+
9+
10+
def parse_args() -> argparse.Namespace:
11+
parser = argparse.ArgumentParser(description='''
12+
Format files in SwiftSyntax using swift-format. If swift-format is installed in your
13+
PATH or passed using --swift-format that executable is used to format the files.
14+
Otherwise swift-format is cloned and built by this script into /tmp
15+
''')
16+
parser.add_argument(
17+
'--swift-format', default='swift-format',
18+
help='''
19+
The path to the swift-format executable.
20+
Looks for swift-format in PATH by default.
21+
''')
22+
parser.add_argument(
23+
'--lint', action='store_true',
24+
help='''
25+
Instead of formatting in-place verify that the files are correctly formatted.
26+
Exit with 1 if files are not correctly formatted.
27+
'''
28+
)
29+
30+
return parser.parse_args()
31+
32+
33+
def clone_and_build_swiftformat() -> Path:
34+
"""
35+
Clone the swift-format repository into /tmp, build it and return the path to the
36+
swift-format executable. This allows format.py to be fully standalone and run even
37+
if swift-format is not installed on your system yet.
38+
"""
39+
print(dedent('''\
40+
swift-format was not found on your system. Cloning and building swift-format in /tmp/swift-format.
41+
42+
To skip this step in the future build swift-format (https://github.com/apple/swift-format) yourself and
43+
- put it in your PATH or
44+
- pass the path to it to this script via --swift-format
45+
''')) # noqa: E501
46+
try:
47+
swift_format_dir = Path('/tmp/swift-format')
48+
if swift_format_dir.exists():
49+
subprocess.check_call(['git', 'pull'], cwd=swift_format_dir)
50+
else:
51+
subprocess.check_call([
52+
'git', 'clone',
53+
'https://github.com/apple/swift-format.git'
54+
], cwd=swift_format_dir.parent)
55+
subprocess.check_call([
56+
'swift', 'build',
57+
'--product', 'swift-format'
58+
], cwd=swift_format_dir)
59+
bin_dir = subprocess.check_output([
60+
'swift', 'build',
61+
'--show-bin-path'
62+
], encoding='utf-8', cwd=swift_format_dir)
63+
return Path(bin_dir.rstrip()) / 'swift-format'
64+
except subprocess.CalledProcessError:
65+
print(dedent('''
66+
format.py failed to build swift-format.
67+
68+
Please build it yourself and pass the swift-format executable to format.py
69+
using the --swift-format parameter.
70+
'''))
71+
raise SystemExit(1)
72+
73+
74+
def find_swiftformat(swift_format: str) -> Path:
75+
"""
76+
Return a fully resolved path to the swift-format executable named or located at
77+
`swift_format`.
78+
If swift-format couldn't be found, this clones and builds swift-format.
79+
"""
80+
try:
81+
output = subprocess.check_output(['which', swift_format], encoding='utf-8')
82+
return Path(output.rstrip())
83+
except subprocess.CalledProcessError:
84+
return clone_and_build_swiftformat()
85+
86+
87+
def get_files_to_format() -> List[Path]:
88+
package_dir = Path(__file__).parent
89+
files_to_format: List[Path] = []
90+
for swift_file_path in (package_dir / "Sources").glob('**/*.swift'):
91+
if swift_file_path.match('**/generated/**') or \
92+
swift_file_path.match('**/gyb_generated/syntax_nodes/**') or \
93+
swift_file_path.match('**/gyb_generated/**'):
94+
# Don't format generated files
95+
continue
96+
files_to_format.append(swift_file_path)
97+
98+
for swift_file_path in (package_dir / "Tests").glob('**/*.swift'):
99+
if swift_file_path.match('**/Inputs/**'):
100+
# Don't format test input files
101+
continue
102+
files_to_format.append(swift_file_path)
103+
104+
return files_to_format
105+
106+
107+
def main() -> None:
108+
args = parse_args()
109+
swift_format = find_swiftformat(args.swift_format)
110+
files_to_format = get_files_to_format()
111+
112+
if args.lint:
113+
try:
114+
subprocess.check_call([swift_format, 'lint', '--parallel', '--strict'] +
115+
files_to_format)
116+
except subprocess.CalledProcessError:
117+
print(dedent('''\
118+
The swift-syntax repo is not formatted according to the style guides.
119+
Run the following command to format swift-syntax
120+
121+
swift-syntax/format.py --swift-format /path/to/executable/swift-format
122+
123+
If the issue persists, fix any remaining issues manually and verify they
124+
match the swift-format style using
125+
126+
swift-syntax/format.py --swift-format /path/to/executable/swift-format --lint
127+
''')) # noqa: E501
128+
raise SystemExit(1)
129+
else:
130+
subprocess.check_call([swift_format, 'format', '--in-place', '--parallel'] +
131+
files_to_format)
132+
133+
134+
if __name__ == '__main__':
135+
main()

0 commit comments

Comments
 (0)