mirror of
https://github.com/ypresto/SwiftLintXcode.git
synced 2026-03-25 08:55:51 +00:00
Migrate code to Swift 3 and Xcode 8
This commit is contained in:
parent
7bccda5767
commit
c6421c4132
8 changed files with 60 additions and 51 deletions
|
|
@ -103,11 +103,12 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 0730;
|
||||
LastUpgradeCheck = 0800;
|
||||
ORGANIZATIONNAME = "Yuya Tanaka";
|
||||
TargetAttributes = {
|
||||
04E4BF2E1CB25D3100BC7305 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -171,8 +172,10 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
|
|
@ -212,8 +215,10 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
|
|
@ -229,17 +234,18 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
04E4BF3D1CB25D3200BC7305 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEPLOYMENT_LOCATION = YES;
|
||||
DSTROOT = "$(HOME)";
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
|
||||
INFOPLIST_FILE = SwiftLintXcode/Info.plist;
|
||||
INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(DT_TOOLCHAIN_DIR)/usr/lib/swift/macosx";
|
||||
|
|
@ -248,6 +254,7 @@
|
|||
PRODUCT_NAME = SwiftLintXcode;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "SwiftLintXcode/SwiftLintXcode-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
WRAPPER_EXTENSION = xcplugin;
|
||||
};
|
||||
name = Debug;
|
||||
|
|
@ -255,11 +262,11 @@
|
|||
04E4BF3E1CB25D3200BC7305 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEPLOYMENT_LOCATION = YES;
|
||||
DSTROOT = "$(HOME)";
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
|
||||
INFOPLIST_FILE = SwiftLintXcode/Info.plist;
|
||||
INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(DT_TOOLCHAIN_DIR)/usr/lib/swift/macosx";
|
||||
|
|
@ -267,6 +274,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.ypresto.SwiftLintXcode;
|
||||
PRODUCT_NAME = SwiftLintXcode;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "SwiftLintXcode/SwiftLintXcode-Bridging-Header.h";
|
||||
SWIFT_VERSION = 3.0;
|
||||
WRAPPER_EXTENSION = xcplugin;
|
||||
};
|
||||
name = Release;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0500"
|
||||
LastUpgradeVersion = "0800"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@ final class Formatter {
|
|||
static var sharedInstance = Formatter()
|
||||
|
||||
private static let pathExtension = "SwiftLintXcode"
|
||||
private let fileManager = NSFileManager.defaultManager()
|
||||
private let fileManager = FileManager.default
|
||||
|
||||
private struct CursorPosition {
|
||||
let line: Int
|
||||
let column: Int
|
||||
}
|
||||
|
||||
class func isFormattableDocument(document: NSDocument) -> Bool {
|
||||
return (document.fileURL?.pathExtension?.lowercaseString == "swift") ?? false
|
||||
class func isFormattableDocument(_ document: NSDocument) -> Bool {
|
||||
return document.fileURL?.pathExtension.lowercased() == "swift"
|
||||
}
|
||||
|
||||
func tryFormatDocument(document: IDESourceCodeDocument) -> Bool {
|
||||
func tryFormatDocument(_ document: IDESourceCodeDocument) -> Bool {
|
||||
do {
|
||||
try formatDocument(document)
|
||||
return true
|
||||
|
|
@ -36,7 +36,7 @@ final class Formatter {
|
|||
return false
|
||||
}
|
||||
|
||||
func formatDocument(document: IDESourceCodeDocument) throws {
|
||||
func formatDocument(_ document: IDESourceCodeDocument) throws {
|
||||
let textStorage: DVTSourceTextStorage = document.textStorage()
|
||||
let originalString = textStorage.string
|
||||
let formattedString = try formatString(originalString)
|
||||
|
|
@ -46,39 +46,39 @@ final class Formatter {
|
|||
let cursorPosition = cursorPositionForSelectedRange(selectedRange, textStorage: textStorage)
|
||||
|
||||
textStorage.beginEditing()
|
||||
textStorage.replaceCharactersInRange(NSRange(location: 0, length: textStorage.length), withString: formattedString, withUndoManager: document.undoManager())
|
||||
textStorage.replaceCharacters(in: NSRange(location: 0, length: textStorage.length), with: formattedString, withUndoManager: document.undoManager())
|
||||
textStorage.endEditing()
|
||||
|
||||
let newLocation = locationForCursorPosition(cursorPosition, textStorage: textStorage)
|
||||
SwiftLintXcodeTRVSXcode.textView().setSelectedRange(NSRange(location: newLocation, length: 0))
|
||||
}
|
||||
|
||||
private func cursorPositionForSelectedRange(selectedRange: NSRange, textStorage: DVTSourceTextStorage) -> CursorPosition {
|
||||
let line = textStorage.lineRangeForCharacterRange(selectedRange).location
|
||||
private func cursorPositionForSelectedRange(_ selectedRange: NSRange, textStorage: DVTSourceTextStorage) -> CursorPosition {
|
||||
let line = textStorage.lineRange(forCharacterRange: selectedRange).location
|
||||
let column = selectedRange.location - startLocationOfLine(line, textStorage: textStorage)
|
||||
return CursorPosition(line: line, column: column)
|
||||
}
|
||||
|
||||
private func locationForCursorPosition(cursorPosition: CursorPosition, textStorage: DVTSourceTextStorage) -> Int {
|
||||
private func locationForCursorPosition(_ cursorPosition: CursorPosition, textStorage: DVTSourceTextStorage) -> Int {
|
||||
let startOfLine = startLocationOfLine(cursorPosition.line, textStorage: textStorage)
|
||||
let locationOfNextLine = textStorage.characterRangeForLineRange(NSRange(location: cursorPosition.line + 1, length: 0)).location
|
||||
let locationOfNextLine = textStorage.characterRange(forLineRange: NSRange(location: cursorPosition.line + 1, length: 0)).location
|
||||
// XXX: Can reach EOF..? Cursor position may be trimmed one charactor when cursor is on EOF.
|
||||
return min(startOfLine + cursorPosition.column, locationOfNextLine - 1)
|
||||
}
|
||||
|
||||
private func startLocationOfLine(line: Int, textStorage: DVTSourceTextStorage) -> Int {
|
||||
return textStorage.characterRangeForLineRange(NSRange(location: line, length: 0)).location
|
||||
private func startLocationOfLine(_ line: Int, textStorage: DVTSourceTextStorage) -> Int {
|
||||
return textStorage.characterRange(forLineRange: NSRange(location: line, length: 0)).location
|
||||
}
|
||||
|
||||
private func formatString(string: String) throws -> String {
|
||||
guard let workspaceRootDirectory = SwiftLintXcodeIDEHelper.currentWorkspaceURL()?.URLByDeletingLastPathComponent?.path else {
|
||||
private func formatString(_ string: String) throws -> String {
|
||||
guard let workspaceRootDirectory = SwiftLintXcodeIDEHelper.currentWorkspaceURL()?.deletingLastPathComponent().path else {
|
||||
throw errorWithMessage("Cannot determine project directory.")
|
||||
}
|
||||
|
||||
return try withTempporaryFile { (filePath) in
|
||||
try string.writeToFile(filePath, atomically: false, encoding: NSUTF8StringEncoding)
|
||||
try string.write(toFile: filePath, atomically: false, encoding: String.Encoding.utf8)
|
||||
let swiftlintPath = try self.getExecutableOnPath(name: "swiftlint", workingDirectory: workspaceRootDirectory)
|
||||
let task = NSTask()
|
||||
let task = Process()
|
||||
task.launchPath = swiftlintPath
|
||||
task.arguments = ["autocorrect", "--path", filePath]
|
||||
task.currentDirectoryPath = workspaceRootDirectory
|
||||
|
|
@ -87,13 +87,13 @@ final class Formatter {
|
|||
if task.terminationStatus != 0 {
|
||||
throw errorWithMessage("Executing swiftlint exited with non-zero status.")
|
||||
}
|
||||
return try String(contentsOfFile: filePath, encoding: NSUTF8StringEncoding)
|
||||
return try String(contentsOfFile: filePath, encoding: String.Encoding.utf8)
|
||||
}
|
||||
}
|
||||
|
||||
private func getExecutableOnPath(name name: String, workingDirectory: String) throws -> String {
|
||||
let pipe = NSPipe()
|
||||
let task = NSTask()
|
||||
private func getExecutableOnPath(name: String, workingDirectory: String) throws -> String {
|
||||
let pipe = Pipe()
|
||||
let task = Process()
|
||||
task.launchPath = "/bin/bash"
|
||||
task.arguments = [
|
||||
"-l", "-c", "which \(name)"
|
||||
|
|
@ -107,27 +107,27 @@ final class Formatter {
|
|||
}
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
guard let pathString = String(data: data, encoding: NSUTF8StringEncoding) else {
|
||||
guard let pathString = String(data: data, encoding: String.Encoding.utf8) else {
|
||||
throw errorWithMessage("Cannot read result of `which swiftlint`.")
|
||||
}
|
||||
let path = pathString.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
|
||||
if !fileManager.isExecutableFileAtPath(path) {
|
||||
let path = pathString.trimmingCharacters(in: CharacterSet.newlines)
|
||||
if !fileManager.isExecutableFile(atPath: path) {
|
||||
throw errorWithMessage("swiftlint at \(path) is not executable.")
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
private func withTempporaryFile<T>(@noescape callback: (filePath: String) throws -> T) throws -> T {
|
||||
private func withTempporaryFile<T>(_ callback: (_ filePath: String) throws -> T) throws -> T {
|
||||
let filePath = createTemporaryPath()
|
||||
if fileManager.fileExistsAtPath(filePath) {
|
||||
if fileManager.fileExists(atPath: filePath) {
|
||||
throw errorWithMessage("Cannot write to \(filePath), file already exists.")
|
||||
}
|
||||
defer { _ = try? fileManager.removeItemAtPath(filePath) }
|
||||
return try callback(filePath: filePath)
|
||||
defer { _ = try? fileManager.removeItem(atPath: filePath) }
|
||||
return try callback(filePath)
|
||||
}
|
||||
|
||||
private func createTemporaryPath() -> String {
|
||||
return NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
||||
.URLByAppendingPathComponent("SwiftLintXcode_\(NSUUID().UUIDString).swift").path!
|
||||
return URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
||||
.appendingPathComponent("SwiftLintXcode_\(UUID().uuidString).swift").path
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
<string>0420B86A-AA43-4792-9ED0-6FE0F2B16A13</string>
|
||||
<string>7265231C-39B4-402C-89E1-16167C4CC990</string>
|
||||
<string>ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C</string>
|
||||
<string>8A66E736-A720-4B3C-92F1-33D9962C69DF</string>
|
||||
</array>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@
|
|||
import Foundation
|
||||
|
||||
extension NSObject {
|
||||
class func pluginDidLoad(bundle: NSBundle) {
|
||||
let appName = NSBundle.mainBundle().infoDictionary?["CFBundleName"] as? NSString
|
||||
class func pluginDidLoad(_ bundle: Bundle) {
|
||||
let appName = Bundle.main.infoDictionary?["CFBundleName"] as? NSString
|
||||
if appName == "Xcode" {
|
||||
if sharedPlugin == nil {
|
||||
sharedPlugin = SwiftLintXcode(bundle: bundle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ final class SaveHook {
|
|||
if swizzled { return }
|
||||
swizzled = true
|
||||
|
||||
let fromMethod = class_getInstanceMethod(NSDocument.self, #selector(NSDocument.saveDocumentWithDelegate(_:didSaveSelector:contextInfo:)))
|
||||
let toMethod = class_getInstanceMethod(NSDocument.self, #selector(NSDocument.SwiftLintXcodeSaveDocumentWithDelegate(_:didSaveSelector:contextInfo:)))
|
||||
let fromMethod = class_getInstanceMethod(NSDocument.self, #selector(NSDocument.save(withDelegate:didSave:contextInfo:)))
|
||||
let toMethod = class_getInstanceMethod(NSDocument.self, #selector(NSDocument.swiftLintXcodeSaveDocument(delegate:didSaveSelector:contextInfo:)))
|
||||
method_exchangeImplementations(fromMethod, toMethod)
|
||||
}
|
||||
|
||||
class func tryOnSaveDocument(document: NSDocument) -> Bool {
|
||||
class func tryOnSaveDocument(_ document: NSDocument) -> Bool {
|
||||
if !enabled { return true }
|
||||
if !Formatter.isFormattableDocument(document) { return true }
|
||||
let sourceCodeDocument: IDESourceCodeDocument = SwiftLintXcodeTRVSXcode.sourceCodeDocument()
|
||||
|
|
@ -41,10 +41,10 @@ final class SaveHook {
|
|||
// https://github.com/travisjeffery/ClangFormat-Xcode/blob/a22114907592fb5d5b1043a4919d7be3e1496741/ClangFormat/NSDocument+TRVSClangFormat.m
|
||||
extension NSDocument {
|
||||
|
||||
dynamic func SwiftLintXcodeSaveDocumentWithDelegate(delegate: AnyObject?, didSaveSelector: Selector, contextInfo: UnsafeMutablePointer<Void>) -> Void {
|
||||
dynamic func swiftLintXcodeSaveDocument(delegate: AnyObject?, didSaveSelector: Selector, contextInfo: UnsafeMutableRawPointer) -> Void {
|
||||
if SaveHook.tryOnSaveDocument(self) {
|
||||
// NOTE: Call original method
|
||||
SwiftLintXcodeSaveDocumentWithDelegate(delegate, didSaveSelector: didSaveSelector, contextInfo: contextInfo);
|
||||
swiftLintXcodeSaveDocument(delegate: delegate, didSaveSelector: didSaveSelector, contextInfo: contextInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,17 +11,17 @@ var sharedPlugin: SwiftLintXcode?
|
|||
|
||||
class SwiftLintXcode: NSObject {
|
||||
|
||||
var bundle: NSBundle
|
||||
lazy var center = NSNotificationCenter.defaultCenter()
|
||||
var bundle: Bundle
|
||||
lazy var center = NotificationCenter.default
|
||||
|
||||
var enableMenuItem: NSMenuItem!
|
||||
var disableMenuItem: NSMenuItem!
|
||||
|
||||
init(bundle: NSBundle) {
|
||||
init(bundle: Bundle) {
|
||||
self.bundle = bundle
|
||||
|
||||
super.init()
|
||||
center.addObserver(self, selector: #selector(SwiftLintXcode.onApplicationDidFinishLaunching), name: NSApplicationDidFinishLaunchingNotification, object: nil)
|
||||
center.addObserver(self, selector: #selector(SwiftLintXcode.onApplicationDidFinishLaunching), name: NSNotification.Name.NSApplicationDidFinishLaunching, object: nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
@ -40,7 +40,7 @@ class SwiftLintXcode: NSObject {
|
|||
private func createMenuItems() {
|
||||
removeObserver()
|
||||
|
||||
guard let item = NSApp.mainMenu!.itemWithTitle("Edit") else { return }
|
||||
guard let item = NSApp.mainMenu!.item(withTitle: "Edit") else { return }
|
||||
|
||||
let pluginMenu = NSMenu(title:"SwiftLintXcode")
|
||||
let pluginMenuItem = NSMenuItem(title:"SwiftLintXcode", action: nil, keyEquivalent: "")
|
||||
|
|
@ -60,7 +60,7 @@ class SwiftLintXcode: NSObject {
|
|||
pluginMenu.addItem(disableMenuItem)
|
||||
self.disableMenuItem = disableMenuItem
|
||||
|
||||
item.submenu!.addItem(NSMenuItem.separatorItem())
|
||||
item.submenu!.addItem(NSMenuItem.separator())
|
||||
item.submenu!.addItem(pluginMenuItem)
|
||||
|
||||
updateMenuVisibility()
|
||||
|
|
@ -83,7 +83,7 @@ class SwiftLintXcode: NSObject {
|
|||
}
|
||||
|
||||
func updateMenuVisibility() {
|
||||
self.enableMenuItem.hidden = SaveHook.enabled
|
||||
self.disableMenuItem.hidden = !SaveHook.enabled
|
||||
self.enableMenuItem.isHidden = SaveHook.enabled
|
||||
self.disableMenuItem.isHidden = !SaveHook.enabled
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
func errorWithMessage(message: String) -> NSError {
|
||||
func errorWithMessage(_ message: String) -> NSError {
|
||||
return NSError(domain: "net.ypresto.SwiftLintXcode", code: 0, userInfo: [
|
||||
NSLocalizedDescriptionKey: message
|
||||
])
|
||||
|
|
|
|||
Loading…
Reference in a new issue