diff --git a/Sources/SwiftFormat/API/Configuration.swift b/Sources/SwiftFormat/API/Configuration.swift index ab8a3e952..1f84feb6f 100644 --- a/Sources/SwiftFormat/API/Configuration.swift +++ b/Sources/SwiftFormat/API/Configuration.swift @@ -328,7 +328,7 @@ public struct Configuration: Codable, Equatable { if FileManager.default.isReadableFile(atPath: candidateFile.path) { return candidateFile } - } while candidateDirectory.path != "/" + } while !candidateDirectory.isRoot return nil } @@ -370,3 +370,17 @@ 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 + // On Linux, we may end up with an string for the path due to https://github.com/swiftlang/swift-foundation/issues/980 + // TODO: Remove the check for "" once https://github.com/swiftlang/swift-foundation/issues/980 is fixed. + return self.path == "/" || self.path == "" + #endif + } +} diff --git a/Tests/SwiftFormatTests/API/ConfigurationTests.swift b/Tests/SwiftFormatTests/API/ConfigurationTests.swift index 6834e9f55..e96331db9 100644 --- a/Tests/SwiftFormatTests/API/ConfigurationTests.swift +++ b/Tests/SwiftFormatTests/API/ConfigurationTests.swift @@ -17,4 +17,30 @@ 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))) + } + + func testMissingConfigurationFileInSubdirectory() { + #if os(Windows) + let path = #"C:\whatever\test.swift"# + #else + let path = "/whatever/test.swift" + #endif + XCTAssertNil(Configuration.url(forConfigurationFileApplyingTo: URL(fileURLWithPath: path))) + } + + func testMissingConfigurationFileMountedDirectory() throws { + #if !os(Windows) + try XCTSkipIf(true, #"\\ file mounts are only a concept on Windows"#) + #endif + let path = #"\\mount\test.swift"# + XCTAssertNil(Configuration.url(forConfigurationFileApplyingTo: URL(fileURLWithPath: path))) + } }