├── .gitignore ├── Package.swift ├── README.md ├── Sources └── StackViewBackgroundChecker │ ├── Parser.swift │ └── main.swift └── Tests ├── LinuxMain.swift └── StackViewBackgroundCheckerTests ├── StackViewBackgroundCheckerTests.swift └── XCTestManifests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "StackViewBackgroundChecker", 8 | dependencies: [ 9 | // Dependencies declare other packages that this package depends on. 10 | // .package(url: /* package url */, from: "1.0.0"), 11 | ], 12 | targets: [ 13 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 14 | // Targets can depend on other targets in this package, and on products in packages this package depends on. 15 | .target( 16 | name: "StackViewBackgroundChecker", 17 | dependencies: []), 18 | .testTarget( 19 | name: "StackViewBackgroundCheckerTests", 20 | dependencies: ["StackViewBackgroundChecker"]), 21 | ] 22 | ) 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StackViewBackgroundChecker 2 | StackViewBackgroundChecker is a tool of printing filepath when any backgroundColor specified for UIStackView in xib, storyboard. 3 | 4 | ## Usage 5 | 6 | ```shell 7 | $ git clone git@github.com:bannzai/StackViewBackgroundChecker.git 8 | $ cd StackViewBackgroundChecker 9 | $ swift build 10 | $ .build/x86_64-apple-macosx/debug/StackViewBackgroundChecker {XIB_PATH} {STORYBOARD_PATH} 11 | XIB_PATH has background color attributes for stackView. level is 9 12 | ``` 13 | 14 | ## LICENSE 15 | MIT 16 | -------------------------------------------------------------------------------- /Sources/StackViewBackgroundChecker/Parser.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | enum ParserError: Swift.Error { 4 | case xmlParseError(url: URL) 5 | } 6 | 7 | struct Node { 8 | let level: Int 9 | } 10 | 11 | class Runner: NSObject { 12 | let parser: XMLParser 13 | let url: URL 14 | init(filepath: String) throws { 15 | self.url = URL(fileURLWithPath: filepath) 16 | guard let parser = XMLParser(contentsOf: url) else { 17 | throw ParserError.xmlParseError(url: url) 18 | } 19 | self.parser = parser 20 | 21 | super.init() 22 | parser.delegate = self 23 | } 24 | 25 | func run() throws { 26 | if !parser.parse() { 27 | throw ParserError.xmlParseError(url: url) 28 | } 29 | } 30 | 31 | var level: Int = 0 32 | var stackViewNodeList: [Node] = [] 33 | } 34 | 35 | extension Runner: XMLParserDelegate { 36 | func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { 37 | level += 1 38 | if elementName == "stackView" { 39 | stackViewNodeList.append(.init(level: level)) 40 | return 41 | } 42 | let isStackViewChild = stackViewNodeList.contains(where: { ($0.level + 1) == level }) 43 | if isStackViewChild { 44 | if elementName == "color" { 45 | print("\(url.absoluteString) has background color attributes for stackView at \(level) level") 46 | } 47 | } 48 | } 49 | 50 | func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 51 | level -= 1 52 | stackViewNodeList = stackViewNodeList.filter { $0.level <= level } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/StackViewBackgroundChecker/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | print("start") 4 | let filepaths = ProcessInfo.processInfo.arguments[1...] 5 | do { 6 | try filepaths.map(Runner.init(filepath:)).forEach{ try $0.run() } 7 | } catch { 8 | fatalError(error.localizedDescription) 9 | } 10 | print("end") 11 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import StackViewBackgroundCheckerTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += StackViewBackgroundCheckerTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /Tests/StackViewBackgroundCheckerTests/StackViewBackgroundCheckerTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import class Foundation.Bundle 3 | 4 | final class StackViewBackgroundCheckerTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | 10 | // Some of the APIs that we use below are available in macOS 10.13 and above. 11 | guard #available(macOS 10.13, *) else { 12 | return 13 | } 14 | 15 | let fooBinary = productsDirectory.appendingPathComponent("StackViewBackgroundChecker") 16 | 17 | let process = Process() 18 | process.executableURL = fooBinary 19 | 20 | let pipe = Pipe() 21 | process.standardOutput = pipe 22 | 23 | try process.run() 24 | process.waitUntilExit() 25 | 26 | let data = pipe.fileHandleForReading.readDataToEndOfFile() 27 | let output = String(data: data, encoding: .utf8) 28 | 29 | XCTAssertEqual(output, "Hello, world!\n") 30 | } 31 | 32 | /// Returns path to the built products directory. 33 | var productsDirectory: URL { 34 | #if os(macOS) 35 | for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") { 36 | return bundle.bundleURL.deletingLastPathComponent() 37 | } 38 | fatalError("couldn't find the products directory") 39 | #else 40 | return Bundle.main.bundleURL 41 | #endif 42 | } 43 | 44 | static var allTests = [ 45 | ("testExample", testExample), 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /Tests/StackViewBackgroundCheckerTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(StackViewBackgroundCheckerTests.allTests), 7 | ] 8 | } 9 | #endif 10 | --------------------------------------------------------------------------------