diff --git a/Sources/SwiftFormat/API/Configuration.swift b/Sources/SwiftFormat/API/Configuration.swift index e1584a5c5..9d90ee38e 100644 --- a/Sources/SwiftFormat/API/Configuration.swift +++ b/Sources/SwiftFormat/API/Configuration.swift @@ -425,17 +425,12 @@ public struct Configuration: Codable, Equatable { candidateDirectory.appendPathComponent("placeholder") } repeat { - let previousDirectory = candidateDirectory candidateDirectory.deleteLastPathComponent() - // if deleting a path component resulted in no change, terminate the loop - if candidateDirectory == previousDirectory { - break - } let candidateFile = candidateDirectory.appendingPathComponent(".swift-format") if FileManager.default.isReadableFile(atPath: candidateFile.path) { return candidateFile } - } while true + } while !candidateDirectory.isRoot return nil } @@ -477,3 +472,15 @@ public struct NoAssignmentInExpressionsConfiguration: Codable, Equatable { public init() {} } + +fileprivate extension URL { + var isRoot: Bool { + #if os(Windows) + // FIXME: We should call into Windows' native check to check if this path is a root once https://github.com/swiftlang/swift-foundation/issues/976 is fixed. + // https://github.com/swiftlang/swift-format/issues/844 + return self.pathComponents.count == 1 + #else + return self.path == "/" + #endif + } +} diff --git a/Tests/SwiftFormatTests/API/ConfigurationTests.swift b/Tests/SwiftFormatTests/API/ConfigurationTests.swift index 6834e9f55..2df50aa3b 100644 --- a/Tests/SwiftFormatTests/API/ConfigurationTests.swift +++ b/Tests/SwiftFormatTests/API/ConfigurationTests.swift @@ -17,4 +17,13 @@ final class ConfigurationTests: XCTestCase { XCTAssertEqual(defaultInitConfig, emptyJSONConfig) } + + func testMissingConfigurationFile() { + #if os(Windows) + let path = #"C:\test.swift"# + #else + let path = "/test.swift" + #endif + XCTAssertNil(Configuration.url(forConfigurationFileApplyingTo: URL(fileURLWithPath: path))) + } }