@@ -23,8 +23,9 @@ fileprivate func main(_ arguments: [String]) -> Int32 {
23
23
switch options. mode {
24
24
case . format:
25
25
var ret = 0
26
- let configuration = decodedConfiguration ( fromFileAtPath: options. configurationPath)
27
26
for path in options. paths {
27
+ let configuration = loadConfiguration (
28
+ forSwiftFile: path, configFilePath: options. configurationPath)
28
29
ret |= formatMain (
29
30
configuration: configuration,
30
31
path: path,
@@ -34,8 +35,9 @@ fileprivate func main(_ arguments: [String]) -> Int32 {
34
35
return Int32 ( ret)
35
36
case . lint:
36
37
var ret = 0
37
- let configuration = decodedConfiguration ( fromFileAtPath: options. configurationPath)
38
38
for path in options. paths {
39
+ let configuration = loadConfiguration (
40
+ forSwiftFile: path, configFilePath: options. configurationPath)
39
41
ret |= lintMain ( configuration: configuration, path: path)
40
42
}
41
43
return Int32 ( ret)
@@ -48,6 +50,41 @@ fileprivate func main(_ arguments: [String]) -> Int32 {
48
50
}
49
51
}
50
52
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
+
51
88
/// Loads and returns a `Configuration` from the given JSON file if it is found and is valid. If the
52
89
/// file does not exist or there was an error decoding it, the program exits with a non-zero exit
53
90
/// code.
0 commit comments