Skip to content

Commit

Permalink
Merge pull request #50 from IBDecodable/feature/plugin
Browse files Browse the repository at this point in the history
Add plugin feature
  • Loading branch information
kateinoigakukun committed Aug 13, 2018
2 parents d6f7a6a + 7751994 commit 5e83625
Show file tree
Hide file tree
Showing 19 changed files with 404 additions and 67 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/.build
/Packages
/*.xcodeproj
portable_iblinter.zip
6 changes: 3 additions & 3 deletions IBLinter.podspec
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
Pod::Spec.new do |s|
s.name = 'IBLinter'
s.version = '0.3.0'
s.version = '0.4.0'
s.summary = 'A linter tool for Interface Builder.'
s.homepage = 'https://github.com/IBDecodable/IBLinter'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Yuta Saito' => 'kateinoigakukun@gmail.com' }
s.source = { :git => "https://github.com/IBDecodable/IBLinter.git", :tag => s.version }
s.preserve_paths = 'bin/*'
s.source = { :http => "#{s.homepage}/releases/download/#{s.version}/portable_iblinter.zip" }
s.preserve_paths = '*'
end
24 changes: 18 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
PREFIX?=/usr/local
TEMPORARY_FOLDER=/tmp/IBLinter.dst
SWIFT_LIB_FILES = .build/release/libIBLinter.dylib .build/release/*.swiftmodule
C_LIB_DIRS = .build/release/CYaml.build

build:
swift build --disable-sandbox -c release -Xswiftc -static-stdlib
swift build --disable-sandbox -c release --static-swift-stdlib

clean_build:
rm -rf bin
make build
mkdir bin
cp -f .build/release/iblinter bin/
rm -rf .build
make build

portable_zip: build
rm -rf portable_iblinter
mkdir portable_iblinter
mkdir portable_iblinter/lib
mkdir portable_iblinter/bin
cp -f .build/release/main portable_iblinter/bin/iblinter
cp -rf $(C_LIB_DIRS) $(SWIFT_LIB_FILES) "portable_iblinter/lib"
cp -f LICENSE portable_iblinter
cd portable_iblinter
(cd portable_iblinter; zip -yr - "lib" "bin" "LICENSE") > "./portable_iblinter.zip"
rm -rf portable_iblinter

install: build
mkdir -p "$(PREFIX)/bin"
mkdir -p "$(PREFIX)/lib/iblinter"
cp -f ".build/release/iblinter" "$(PREFIX)/bin/iblinter"
cp -rf $(C_LIB_DIRS) $(SWIFT_LIB_FILES) "$(PREFIX)/lib/iblinter"

publish: clean_build
brew update && brew bump-formula-pr --tag=$(shell git describe --tags) --revision=$(shell git rev-parse HEAD) iblinter
Expand Down
66 changes: 60 additions & 6 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
"version": null
}
},
{
"package": "Files",
"repositoryURL": "https://github.com/JohnSundell/Files.git",
"state": {
"branch": null,
"revision": "06f95bd1bf4f8d5f50bc6bb30b808c253acd4c88",
"version": "2.2.1"
}
},
{
"package": "IBDecodable",
"repositoryURL": "https://github.com/IBDecodable/IBDecodable.git",
Expand All @@ -28,13 +37,22 @@
"version": null
}
},
{
"package": "Marathon",
"repositoryURL": "https://github.com/JohnSundell/Marathon.git",
"state": {
"branch": null,
"revision": "959e82b044f7dbb2680c6e7cdaa80d70e9dfa4ca",
"version": "3.0.0"
}
},
{
"package": "Nimble",
"repositoryURL": "https://github.com/Quick/Nimble.git",
"state": {
"branch": null,
"revision": "8023e3980d91b470ad073d6da843b73f2eeb1844",
"version": "7.1.2"
"revision": "9c1379fdcd58c4f2278aea5e029394ba9a2b8f07",
"version": "7.1.3"
}
},
{
Expand All @@ -51,8 +69,26 @@
"repositoryURL": "https://github.com/Quick/Quick.git",
"state": {
"branch": null,
"revision": "3e3023569c8d4c4a0d000f58db765df53041117f",
"version": "1.3.0"
"revision": "b060679e70d13c3c7dcd124201b5b1b34ce6f340",
"version": "1.3.1"
}
},
{
"package": "Releases",
"repositoryURL": "https://github.com/JohnSundell/Releases.git",
"state": {
"branch": null,
"revision": "e74f0895855b56147cb96f2d45aba3ec37da64fb",
"version": "3.0.0"
}
},
{
"package": "Require",
"repositoryURL": "https://github.com/JohnSundell/Require.git",
"state": {
"branch": null,
"revision": "7cfbd0d8a2dede0e01f6f0d8ab2c7acef1df112e",
"version": "2.0.1"
}
},
{
Expand Down Expand Up @@ -96,8 +132,26 @@
"repositoryURL": "https://github.com/drmohundro/SWXMLHash.git",
"state": {
"branch": null,
"revision": "2211b35c2e0e8b08493f86ba52b26e530cabb751",
"version": "4.7.0"
"revision": "24698592b581aef2bdbfc86ce18695708038c624",
"version": "4.7.1"
}
},
{
"package": "Unbox",
"repositoryURL": "https://github.com/JohnSundell/Unbox.git",
"state": {
"branch": null,
"revision": "17ad6aa1cc2f1efa27a0bbbdb66f79796708aa95",
"version": "2.5.0"
}
},
{
"package": "Wrap",
"repositoryURL": "https://github.com/JohnSundell/Wrap.git",
"state": {
"branch": null,
"revision": "8085c925060b84a1fc0caef444c130da2c8154c3",
"version": "3.0.1"
}
},
{
Expand Down
13 changes: 9 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import PackageDescription
let package = Package(
name: "IBLinter",
products: [
.executable(name: "iblinter", targets: ["iblinter"]),
.executable(name: "main", targets: ["main"]),
.library(name: "IBLinter", type: .dynamic, targets: ["IBLinter"]),
.library(name: "IBLinterKit", targets: ["IBLinterKit"]),
],
dependencies: [
Expand All @@ -15,17 +16,21 @@ let package = Package(
.package(url: "https://github.com/IBDecodable/IBDecodable.git", .branch("master")),
.package(url: "https://github.com/Carthage/Commandant.git", .branch("master")),
.package(url: "https://github.com/jpsim/SourceKitten.git", from: "0.21.1"),
.package(url: "https://github.com/xcodeswift/xcproj.git", from: "4.3.0")
.package(url: "https://github.com/xcodeswift/xcproj.git", from: "4.3.0"),
.package(url: "https://github.com/JohnSundell/Marathon.git", from: "3.0.0")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "iblinter",
name: "main",
dependencies: ["IBLinter"]),
.target(
name: "IBLinter",
dependencies: ["IBLinterKit"]),
.target(
name: "IBLinterKit",
dependencies: ["IBDecodable", "Commandant", "SourceKittenFramework", "xcproj"]),
dependencies: ["IBDecodable", "Commandant", "SourceKittenFramework", "xcproj", "MarathonCore"]),
.testTarget(name: "IBLinterKitTest",
dependencies: ["IBLinterKit"])
]
Expand Down
26 changes: 0 additions & 26 deletions Sources/IBLinterKit/App.swift

This file was deleted.

7 changes: 7 additions & 0 deletions Sources/IBLinterKit/Context.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,11 @@
public struct Context {
let config: Config
let workDirectory: String
let externalRules: [Rule.Type]

public init(config: Config, workDirectory: String, externalRules: [Rule.Type]) {
self.config = config
self.workDirectory = workDirectory
self.externalRules = externalRules
}
}
6 changes: 3 additions & 3 deletions Sources/IBLinterKit/Reporters/Reporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
// Created by SaitoYuta on 2017/12/11.
//

protocol Reporter {
public protocol Reporter {
static var identifier: String { get }

static func generateReport(violations: [Violation]) -> String
}

struct Reporters {
public struct Reporters {

static func reporter(from reporter: String) -> Reporter.Type {
public static func reporter(from reporter: String) -> Reporter.Type {
switch reporter {
case XcodeReporter.identifier:
return XcodeReporter.self
Expand Down
9 changes: 5 additions & 4 deletions Sources/IBLinterKit/Rules/Rule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public protocol Rule {

public struct Rules {

static var allRules: [Rule.Type] {
static var allRules: [Rule.Type] = {
return [
CustomClassNameRule.self,
RelativeToMarginRule.self,
Expand All @@ -27,7 +27,7 @@ public struct Rules {
ImageResourcesRule.self,
CustomModuleRule.self
]
}
}()

static var defaultRules: [Rule.Type] {
return [
Expand All @@ -37,11 +37,12 @@ public struct Rules {
]
}

static func rules(_ context: Context) -> [Rule] {
public static func rules(_ context: Context) -> [Rule] {
var identifiers = Set(defaultRules.map({ $0.identifier }))
identifiers.subtract(context.config.disabledRules)
identifiers.formUnion(context.config.enabledRules)
let rules = allRules + context.externalRules

return allRules.filter { identifiers.contains($0.identifier) }.map { $0.init(context: context) }
return rules.filter { identifiers.contains($0.identifier) }.map { $0.init(context: context) }
}
}
10 changes: 5 additions & 5 deletions Sources/IBLinterKit/Violation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import IBDecodable
import Foundation

public struct Violation {
let pathString: String
let message: String
let level: Level
public let pathString: String
public let message: String
public let level: Level

enum Level: String, Comparable {
public enum Level: String, Comparable {
case warning
case error

static func < (lhs: Violation.Level, rhs: Violation.Level) -> Bool {
public static func < (lhs: Violation.Level, rhs: Violation.Level) -> Bool {
return lhs == .warning && rhs == .error
}
}
Expand Down
72 changes: 72 additions & 0 deletions Sources/iblinter/Commands/EditCommand.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// EditCommand.swift
// IBLinterKit
//
// Created by SaitoYuta on 2018/05/27.
//

import Result
import Foundation
import Commandant
import Files
import PathKit
import xcproj

struct EditCommand: CommandProtocol {

let verb: String = "edit"
let function: String = "Edit the IBLinterfile.swift"

func run(_ options: NoOptions<CommandantError<()>>) -> Result<(), CommandantError<()>> {
let ibLinterfile = Runtime.ibLinterfile.exists ? Runtime.ibLinterfile : try! createIBLinterfile()
try! Runtime.resolvePackages(ibLinterfile: ibLinterfile)
guard let libPath = Runtime.libPath() else {
print("Could not find a libIBLinter to link against at any of: \(Runtime.potentialFolders)")
return Result.failure(.commandError(()))
}
let arguments = CommandLine.arguments
let scriptManager = try! Runtime.getScriptManager()
let script = try! scriptManager.script(atPath: ibLinterfile.string, allowRemote: true)
let xcodeprojPath = try! script.setupForEdit(arguments: arguments)

try! addLibPathToXcodeProj(xcodeprojPath: xcodeprojPath, libPath: libPath)
try! script.watch(arguments: arguments)
return .success(())
}

func addLibPathToXcodeProj(xcodeprojPath: String, libPath: Path) throws -> Void {
let xcodeProj = try XcodeProj(pathString: xcodeprojPath)
let sourceRoot = Path(xcodeprojPath).parent()

let otherSwiftFlagsKey = "OTHER_SWIFT_FLAGS"
xcodeProj.pbxproj.objects.buildConfigurations.forEach { (key, configuration) in
configuration.buildSettings["LIBRARY_SEARCH_PATHS"] = ["$(inherited)", libPath.string]
guard let flags = configuration.buildSettings[otherSwiftFlagsKey] as? [String] else {
return
}
configuration.buildSettings[otherSwiftFlagsKey] = flags + ["-I \(libPath.string)", "-L \(libPath.string)"]
}

let fileReference = try xcodeProj.pbxproj.objects.addFile(
at: libPath + Runtime.dylibName, toGroup: xcodeProj.pbxproj.rootGroup,
sourceRoot: sourceRoot
)
guard let target = xcodeProj.pbxproj.objects.targets(named: "IBLinterfile").first?.object else {
return
}
guard let buildFile = xcodeProj.pbxproj.objects
.addBuildFile(toTarget: target, reference: fileReference.reference) else { return }
xcodeProj.pbxproj.objects.frameworksBuildPhases.forEach { key, value in
value.files.append(buildFile.reference)
}

try xcodeProj.write(path: Path(xcodeprojPath))
}

func createIBLinterfile() throws -> Path {
let template = "import IBLinter \nlet linter = IBLinter()"
let data = template.data(using: .utf8)!
let pathString = try FileSystem().createFile(at: Runtime.ibLinterfile.string, contents: data).path
return Path(pathString)
}
}
Loading

0 comments on commit 5e83625

Please sign in to comment.