Skip to content

Commit 0e6f628

Browse files
authored
Merge pull request swiftlang#217 from dabelknap/auto-config
Automatically search for a '.swift-format' configuration file
2 parents 760fb36 + 1d67127 commit 0e6f628

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

Diff for: Sources/swift-format/main.swift

+39-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ fileprivate func main(_ arguments: [String]) -> Int32 {
2323
switch options.mode {
2424
case .format:
2525
var ret = 0
26-
let configuration = decodedConfiguration(fromFileAtPath: options.configurationPath)
2726
for path in options.paths {
27+
let configuration = loadConfiguration(
28+
forSwiftFile: path, configFilePath: options.configurationPath)
2829
ret |= formatMain(
2930
configuration: configuration,
3031
path: path,
@@ -34,8 +35,9 @@ fileprivate func main(_ arguments: [String]) -> Int32 {
3435
return Int32(ret)
3536
case .lint:
3637
var ret = 0
37-
let configuration = decodedConfiguration(fromFileAtPath: options.configurationPath)
3838
for path in options.paths {
39+
let configuration = loadConfiguration(
40+
forSwiftFile: path, configFilePath: options.configurationPath)
3941
ret |= lintMain(configuration: configuration, path: path)
4042
}
4143
return Int32(ret)
@@ -48,6 +50,41 @@ fileprivate func main(_ arguments: [String]) -> Int32 {
4850
}
4951
}
5052

53+
/// Load the configuration.
54+
private func loadConfiguration(
55+
forSwiftFile swiftFilePath: String, configFilePath: String?
56+
) -> Configuration {
57+
if let path = configFilePath {
58+
return decodedConfiguration(fromFileAtPath: path)
59+
}
60+
else {
61+
// Search for a ".swift-format" configuration file in the directory of the current .swift file,
62+
// or its nearest parent.
63+
let swiftFileDir = URL(fileURLWithPath: swiftFilePath)
64+
return decodedConfiguration(
65+
fromFileAtPath: findConfigurationFile(forSwiftFile: swiftFileDir.path))
66+
}
67+
}
68+
69+
/// Look for a ".swift-format" configuration file in the same directory as "forSwiftFile", or its
70+
/// nearest parent. If one is not found, return "nil".
71+
private func findConfigurationFile(forSwiftFile: String) -> String? {
72+
let cwd = FileManager.default.currentDirectoryPath
73+
var path = URL(
74+
fileURLWithPath: AbsolutePath(forSwiftFile, relativeTo: AbsolutePath(cwd)).asString)
75+
let configFilename = ".swift-format"
76+
77+
repeat {
78+
path = path.deletingLastPathComponent()
79+
let testPath = path.appendingPathComponent(configFilename).path
80+
if FileManager.default.isReadableFile(atPath: testPath) {
81+
return testPath
82+
}
83+
} while path.path != "/"
84+
85+
return nil
86+
}
87+
5188
/// Loads and returns a `Configuration` from the given JSON file if it is found and is valid. If the
5289
/// file does not exist or there was an error decoding it, the program exits with a non-zero exit
5390
/// code.

0 commit comments

Comments
 (0)