From dc6d59080d7f45f0bfd43605b77546a00ea2afb6 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Sun, 6 Mar 2022 21:33:41 +0000 Subject: [PATCH] Fix bug in --exclude when using --stdinpath --- Sources/Options.swift | 16 +++- Tests/CommandLineTests.swift | 178 +++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 4 deletions(-) diff --git a/Sources/Options.swift b/Sources/Options.swift index cae97a3c..bb525294 100644 --- a/Sources/Options.swift +++ b/Sources/Options.swift @@ -627,11 +627,19 @@ public struct FileOptions { } public func shouldSkipFile(_ inputURL: URL) -> Bool { - let path = inputURL.standardizedFileURL.path - for excluded in excludedGlobs where excluded.matches(path) { - return !unexcludedGlobs.contains(where: { $0.matches(path) }) + let parts = inputURL.standardizedFileURL.path.components(separatedBy: "/") + var path: String! + var shouldSkip = false + for part in parts { + path = path.map { "\($0)/\(part)" } ?? part + if !shouldSkip, excludedGlobs.contains(where: { $0.matches(path) }) { + shouldSkip = true + } + if shouldSkip, unexcludedGlobs.contains(where: { $0.matches(path) }) { + shouldSkip = false + } } - return false + return shouldSkip } } diff --git a/Tests/CommandLineTests.swift b/Tests/CommandLineTests.swift index 650fb1f7..e1850741 100644 --- a/Tests/CommandLineTests.swift +++ b/Tests/CommandLineTests.swift @@ -35,6 +35,43 @@ import XCTest private let projectDirectory = URL(fileURLWithPath: #file) .deletingLastPathComponent().deletingLastPathComponent() +private func createTmpFile(_ path: String? = nil, contents: String) throws -> URL { + let path = path ?? (UUID().uuidString + ".swift") + let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(path) + let directory = url.deletingLastPathComponent() + if !FileManager.default.fileExists(atPath: directory.path) { + try FileManager.default.createDirectory( + at: directory, + withIntermediateDirectories: true, + attributes: nil + ) + } + try contents.write(to: url, atomically: true, encoding: .utf8) + return url +} + +private func withTmpFile(_ path: String? = nil, contents: String, fn: (URL) -> Void) throws { + let path = path ?? (UUID().uuidString + ".swift") + let prefix = UUID().uuidString + let url = try createTmpFile("\(prefix)/\(path)", contents: contents) + fn(url) + try FileManager.default.removeItem(at: url) +} + +private func withTmpFiles(_ files: [String: String], fn: (URL) throws -> Void) throws { + var urls = [URL]() + let prefix = UUID().uuidString + for (path, contents) in files { + try urls.append(createTmpFile("\(prefix)/\(path)", contents: contents)) + } + for url in urls where url.pathExtension == "swift" { + try fn(url) + } + for url in urls { + try FileManager.default.removeItem(at: url) + } +} + class CommandLineTests: XCTestCase { // MARK: stdin @@ -70,6 +107,147 @@ class CommandLineTests: XCTestCase { _ = processArguments(["", "stdin"], in: "") } + func testExcludeStdinPath() throws { + CLI.print = { message, type in + switch type { + case .raw, .content: + XCTAssertEqual(message, "func foo() {\n}\n") + case .error, .warning: + XCTFail() + case .info, .success: + break + } + } + var readCount = 0 + CLI.readLine = { + readCount += 1 + switch readCount { + case 1: + return "func foo() {\n" + case 2: + return "}\n" + default: + return nil + } + } + try withTmpFile(contents: "") { url in + _ = processArguments([ + "", + "stdin", + "--stdinpath", url.path, + "--exclude", url.path, + ], in: "") + } + } + + func testExcludeStdinPath2() throws { + CLI.print = { message, type in + switch type { + case .raw, .content: + XCTAssertEqual(message, "func foo() {\n}\n") + case .error, .warning: + XCTFail() + case .info, .success: + break + } + } + var readCount = 0 + CLI.readLine = { + readCount += 1 + switch readCount { + case 1: + return "func foo() {\n" + case 2: + return "}\n" + default: + return nil + } + } + try withTmpFiles([ + ".swiftformat": "--exclude *", + "foo.swift": "", + ]) { url in + _ = processArguments([ + "", + "stdin", + "--stdinpath", url.path, + ], in: "") + } + } + + func testExcludeStdinPath3() throws { + CLI.print = { message, type in + switch type { + case .raw, .content: + XCTAssertEqual(message, "func foo() {\n}\n") + case .error, .warning: + XCTFail() + case .info, .success: + break + } + } + var readCount = 0 + CLI.readLine = { + readCount += 1 + switch readCount { + case 1: + return "func foo() {\n" + case 2: + return "}\n" + default: + return nil + } + } + try withTmpFiles([ + ".swiftformat": "--exclude foo", + "foo/bar/baz.swift": "", + ]) { url in + _ = processArguments([ + "", + "stdin", + "--stdinpath", url.path, + ], in: "") + } + } + + func testUnexcludeStdinPath() throws { + CLI.print = { message, type in + switch type { + case .raw, .content: + XCTAssertEqual(message, "func foo() {}\n") + case .error, .warning: + XCTFail() + case .info, .success: + break + } + } + var readCount = 0 + CLI.readLine = { + readCount += 1 + switch readCount { + case 1: + return "func foo() {\n" + case 2: + return "}\n" + default: + return nil + } + } + try withTmpFiles([ + ".swiftformat": """ + --exclude foo + --unexclude **/baz.* + """, + "foo/bar/baz.swift": "", + ]) { url in + _ = processArguments([ + "", + "stdin", + "--stdinpath", url.path, + ], in: "") + } + } + // MARK: help func testHelpLineLength() {