diff --git a/SwiftLintXcode.xcodeproj/project.pbxproj b/SwiftLintXcode.xcodeproj/project.pbxproj index 805fa73..84e7c18 100644 --- a/SwiftLintXcode.xcodeproj/project.pbxproj +++ b/SwiftLintXcode.xcodeproj/project.pbxproj @@ -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; diff --git a/SwiftLintXcode.xcodeproj/xcshareddata/xcschemes/SwiftLintXcode.xcscheme b/SwiftLintXcode.xcodeproj/xcshareddata/xcschemes/SwiftLintXcode.xcscheme index 6b8fd61..c8404e6 100755 --- a/SwiftLintXcode.xcodeproj/xcshareddata/xcschemes/SwiftLintXcode.xcscheme +++ b/SwiftLintXcode.xcodeproj/xcshareddata/xcschemes/SwiftLintXcode.xcscheme @@ -1,6 +1,6 @@ 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(@noescape callback: (filePath: String) throws -> T) throws -> T { + private func withTempporaryFile(_ 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 } } diff --git a/SwiftLintXcode/Info.plist b/SwiftLintXcode/Info.plist index 754fbb0..c317fbf 100644 --- a/SwiftLintXcode/Info.plist +++ b/SwiftLintXcode/Info.plist @@ -38,6 +38,7 @@ 0420B86A-AA43-4792-9ED0-6FE0F2B16A13 7265231C-39B4-402C-89E1-16167C4CC990 ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C + 8A66E736-A720-4B3C-92F1-33D9962C69DF LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) diff --git a/SwiftLintXcode/NSObject_Extension.swift b/SwiftLintXcode/NSObject_Extension.swift index 35da894..d875c66 100644 --- a/SwiftLintXcode/NSObject_Extension.swift +++ b/SwiftLintXcode/NSObject_Extension.swift @@ -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) } } } -} \ No newline at end of file +} diff --git a/SwiftLintXcode/SaveHook.swift b/SwiftLintXcode/SaveHook.swift index cfd9621..8d3b977 100644 --- a/SwiftLintXcode/SaveHook.swift +++ b/SwiftLintXcode/SaveHook.swift @@ -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 { + 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) } } -} \ No newline at end of file +} diff --git a/SwiftLintXcode/SwiftLintXcode.swift b/SwiftLintXcode/SwiftLintXcode.swift index f96886d..b435e6c 100755 --- a/SwiftLintXcode/SwiftLintXcode.swift +++ b/SwiftLintXcode/SwiftLintXcode.swift @@ -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 } } diff --git a/SwiftLintXcode/errorHelper.swift b/SwiftLintXcode/errorHelper.swift index 3e370b1..87c4e71 100644 --- a/SwiftLintXcode/errorHelper.swift +++ b/SwiftLintXcode/errorHelper.swift @@ -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 ])