diff --git a/Sources/IBLinterKit/Config.swift b/Sources/IBLinterKit/Config.swift index b1f511a..569ed57 100644 --- a/Sources/IBLinterKit/Config.swift +++ b/Sources/IBLinterKit/Config.swift @@ -16,6 +16,7 @@ public struct Config: Codable { public let customModuleRule: [CustomModuleConfig] public let useBaseClassRule: [UseBaseClassConfig] public let reporter: String + public let disableWhileBuildingForIB: Bool enum CodingKeys: String, CodingKey { case disabledRules = "disabled_rules" @@ -25,6 +26,7 @@ public struct Config: Codable { case customModuleRule = "custom_module_rule" case useBaseClassRule = "use_base_class_rule" case reporter = "reporter" + case disableWhileBuildingForIB = "disable_while_building_for_ib" } public static let fileName = ".iblinter.yml" @@ -38,9 +40,10 @@ public struct Config: Codable { customModuleRule = [] useBaseClassRule = [] reporter = "xcode" + disableWhileBuildingForIB = true } - init(disabledRules: [String], enabledRules: [String], excluded: [String], included: [String], customModuleRule: [CustomModuleConfig], baseClassRule: [UseBaseClassConfig], reporter: String) { + init(disabledRules: [String], enabledRules: [String], excluded: [String], included: [String], customModuleRule: [CustomModuleConfig], baseClassRule: [UseBaseClassConfig], reporter: String, disableWhileBuildingForIB: Bool = true) { self.disabledRules = disabledRules self.enabledRules = enabledRules self.excluded = excluded @@ -48,6 +51,7 @@ public struct Config: Codable { self.customModuleRule = customModuleRule self.useBaseClassRule = baseClassRule self.reporter = reporter + self.disableWhileBuildingForIB = disableWhileBuildingForIB } public init(from decoder: Decoder) throws { @@ -58,7 +62,8 @@ public struct Config: Codable { included = try container.decodeIfPresent(Optional<[String]>.self, forKey: .included).flatMap { $0 } ?? [] customModuleRule = try container.decodeIfPresent(Optional<[CustomModuleConfig]>.self, forKey: .customModuleRule).flatMap { $0 } ?? [] useBaseClassRule = try container.decodeIfPresent(Optional<[UseBaseClassConfig]>.self, forKey: .useBaseClassRule)?.flatMap { $0 } ?? [] - reporter = try container.decodeIfPresent(Optional.self, forKey: .reporter).flatMap { $0 } ?? "xcode" + reporter = try container.decodeIfPresent(String.self, forKey: .reporter) ?? "xcode" + disableWhileBuildingForIB = try container.decodeIfPresent(Bool.self, forKey: .disableWhileBuildingForIB) ?? true } public static func load(_ url: URL) throws -> Config { diff --git a/Sources/IBLinterKit/Glob.swift b/Sources/IBLinterKit/Glob.swift index 01307a4..c766423 100644 --- a/Sources/IBLinterKit/Glob.swift +++ b/Sources/IBLinterKit/Glob.swift @@ -75,15 +75,14 @@ public class Glob { } guard let (head, tail) = splitFirstStar(pattern: pattern) else { return [] } - func recursiveChildren(current: String) -> [String] { + func childDirectories(current: String) -> [String] { do { return try fileManager.subpathsOfDirectory(atPath: current) .compactMap { let path = URL(fileURLWithPath: current).appendingPathComponent($0).path guard fileManager.isDirectory(path) else { return nil } return path - } - .flatMap { recursiveChildren(current: $0) } + [current] + } + [current] } catch { return [] } @@ -96,18 +95,13 @@ public class Glob { return [] } } - let children = recursiveChildren(current: head) + let children = childDirectories(current: head) let result = children.map { URL(fileURLWithPath: $0).appendingPathComponent(tailComponent).path } .flatMap { expandRecursiveStars(pattern: $0) } return Set(result) } } -@available(*, deprecated) -func expandGlobstar(pattern: String, fileManager: GlobFileManager = FileManager.default) -> Set { - return Glob(fileManager: fileManager).expandRecursiveStars(pattern: pattern) -} - public func glob(pattern: String, fileManager: GlobFileManager = FileManager.default) -> Set { return Glob(fileManager: fileManager).glob(pattern: pattern) } diff --git a/Sources/iblinter/Commands/ValidateCommand.swift b/Sources/iblinter/Commands/ValidateCommand.swift index 697aec0..69355a0 100644 --- a/Sources/iblinter/Commands/ValidateCommand.swift +++ b/Sources/iblinter/Commands/ValidateCommand.swift @@ -54,6 +54,10 @@ struct ValidateCommand: CommandProtocol { fatalError("\(workDirectoryString) is not directory.") } let config = (try? Config.load(from: workDirectory)) ?? Config.default + if config.disableWhileBuildingForIB && + ProcessInfo.processInfo.compiledForInterfaceBuilder { + return .success(()) + } let violations = validate(workDirectory: workDirectory, config: config) let reporter = Reporters.reporter(from: options.reporter ?? config.reporter) @@ -147,3 +151,9 @@ struct ValidateOptions: OptionsProtocol { <*> mode <| Option(key: "script", defaultValue: nil, usage: "custom IBLinterfile.swift") } } + +extension ProcessInfo { + var compiledForInterfaceBuilder: Bool { + return environment["COMPILED_FOR_INTERFACE_BUILDER"] != nil + } +} diff --git a/Tests/IBLinterKitTest/GlobTests.swift b/Tests/IBLinterKitTest/GlobTests.swift index 94f1316..b4f1bb4 100644 --- a/Tests/IBLinterKitTest/GlobTests.swift +++ b/Tests/IBLinterKitTest/GlobTests.swift @@ -140,7 +140,7 @@ class GlobTests: XCTestCase { XCTAssertEqual(expended, []) } recursive: do { - let multiRecursivePath = projectPath.appendingPathComponent("**/foo/**") + let recursivePath = projectPath.appendingPathComponent("foo/**") let fileManager = MockFileManager( projectPath: projectPath, tree: .root([ @@ -150,19 +150,14 @@ class GlobTests: XCTestCase { .file("baz")]), .directory("bar_3", [ .file("baz")])]), - .directory("baz", [ - .directory("bar", [ - .directory("foo", [ - .file("xxx")])])]) ] ) ) - let expanded = Glob(fileManager: fileManager).expandRecursiveStars(pattern: multiRecursivePath.path) + let expanded = Glob(fileManager: fileManager).expandRecursiveStars(pattern: recursivePath.path) XCTAssertEqual( Set(expanded.map { URL(fileURLWithPath: $0).path }), Set([ projectPath.appendingPathComponent("foo/*").path, - projectPath.appendingPathComponent("baz/bar/foo/*").path, ]) ) }