diff --git a/BuildTimeAnalyzer.xcodeproj/project.pbxproj b/BuildTimeAnalyzer.xcodeproj/project.pbxproj index 1b6afa6..da2e3ab 100644 --- a/BuildTimeAnalyzer.xcodeproj/project.pbxproj +++ b/BuildTimeAnalyzer.xcodeproj/project.pbxproj @@ -454,9 +454,17 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + AUTOMATION_APPLE_EVENTS = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; + ENABLE_RESOURCE_ACCESS_CALENDARS = NO; + ENABLE_RESOURCE_ACCESS_CAMERA = NO; + ENABLE_RESOURCE_ACCESS_CONTACTS = NO; + ENABLE_RESOURCE_ACCESS_LOCATION = NO; + ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO; INFOPLIST_FILE = BuildTimeAnalyzer/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -465,6 +473,12 @@ MACOSX_DEPLOYMENT_TARGET = 26.0; PRODUCT_BUNDLE_IDENTIFIER = uk.co.canemedia.BuildTimeAnalyzer; PRODUCT_NAME = "$(TARGET_NAME)"; + RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO; + RUNTIME_EXCEPTION_ALLOW_JIT = NO; + RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY = NO; + RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO; + RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO; + RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO; SWIFT_OBJC_BRIDGING_HEADER = ""; }; name = Debug; @@ -473,9 +487,17 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + AUTOMATION_APPLE_EVENTS = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; + ENABLE_RESOURCE_ACCESS_CALENDARS = NO; + ENABLE_RESOURCE_ACCESS_CAMERA = NO; + ENABLE_RESOURCE_ACCESS_CONTACTS = NO; + ENABLE_RESOURCE_ACCESS_LOCATION = NO; + ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO; INFOPLIST_FILE = BuildTimeAnalyzer/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -484,6 +506,12 @@ MACOSX_DEPLOYMENT_TARGET = 26.0; PRODUCT_BUNDLE_IDENTIFIER = uk.co.canemedia.BuildTimeAnalyzer; PRODUCT_NAME = "$(TARGET_NAME)"; + RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO; + RUNTIME_EXCEPTION_ALLOW_JIT = NO; + RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY = NO; + RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO; + RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO; + RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO; SWIFT_OBJC_BRIDGING_HEADER = ""; }; name = Release; diff --git a/BuildTimeAnalyzer/Info.plist b/BuildTimeAnalyzer/Info.plist index 7f529ac..84e5d89 100644 --- a/BuildTimeAnalyzer/Info.plist +++ b/BuildTimeAnalyzer/Info.plist @@ -26,6 +26,10 @@ $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright Copyright © 2016 Cane Media Ltd. All rights reserved. + NSAppleEventsUsageDescription + BuildTimeAnalyzer needs to control Xcode to jump to the selected file and line. + NSAccessibilityUsageDescription + BuildTimeAnalyzer needs Accessibility to jump to the selected file and line. NSMainStoryboardFile Main NSPrincipalClass diff --git a/BuildTimeAnalyzer/ViewController.swift b/BuildTimeAnalyzer/ViewController.swift index 2bae11d..bc2abfc 100644 --- a/BuildTimeAnalyzer/ViewController.swift +++ b/BuildTimeAnalyzer/ViewController.swift @@ -76,7 +76,9 @@ class ViewController: NSViewController { } @objc func windowWillClose(notification: NSNotification) { - guard let object = notification.object, !(object is NSPanel) else { return } + guard let closingWindow = notification.object as? NSWindow, + closingWindow == view.window else { return } + NotificationCenter.default.removeObserver(self) processor.shouldCancel = true @@ -307,25 +309,35 @@ extension ViewController: NSTableViewDataSource { func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool { guard let item = dataSource.measure(index: row) else { return false } - let url = URL(fileURLWithPath: item.path, isDirectory: true) - NSWorkspace.shared.open(url) + let escapedPath = item.path.replacingOccurrences(of: "\"", with: "\\\"") let gotoLineScript = "tell application \"Xcode\"\n" + " activate\n" + + " open POSIX file \"\(escapedPath)\"\n" + "end tell\n" + "tell application \"System Events\"\n" + - " keystroke \"l\" using command down\n" + - " keystroke \"\(item.location)\"\n" + - " keystroke return\n" + + " repeat until (frontmost of process \"Xcode\")\n" + + " delay 0.05\n" + + " end repeat\n" + + " tell process \"Xcode\"\n" + + " keystroke \"l\" using command down\n" + + " delay 0.2\n" + + " keystroke \"\(item.location)\"\n" + + " keystroke return\n" + + " end tell\n" + "end tell" DispatchQueue.global().async { + var error: NSDictionary? if let script = NSAppleScript(source: gotoLineScript) { - script.executeAndReturnError(nil) + script.executeAndReturnError(&error) + } + if let error = error { + print("Failed to jump to line in Xcode: \(error)") } } - + return true } }