Skip to content

Commit

Permalink
Merge pull request inket#22 from inket/multi-target-support
Browse files Browse the repository at this point in the history
Multi target support
  • Loading branch information
inket committed May 7, 2021
2 parents 7a7b87a + 348fb97 commit 15f593a
Show file tree
Hide file tree
Showing 114 changed files with 5,912 additions and 3,527 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
## Build generated
build/
DerivedData/
*.mobileprovision

## Various settings
*.pbxuser
Expand All @@ -30,8 +31,8 @@ xcuserdata/
## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
# *.dSYM.zip
# *.dSYM

## Playgrounds
timeline.xctimeline
Expand Down
2 changes: 0 additions & 2 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,3 @@ file_length: 500
disabled_rules:
- type_body_length
- function_body_length
- type_name
- variable_name
90 changes: 42 additions & 48 deletions MacSymbolicator.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1100"
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -11,15 +11,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B2C2291E1EF223C50015AB33"
BuildableName = "MacSymbolicator.app"
BlueprintName = "MacSymbolicator"
ReferencedContainer = "container:MacSymbolicator.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
Expand Down Expand Up @@ -60,6 +51,15 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B2C2291E1EF223C50015AB33"
BuildableName = "MacSymbolicator.app"
BlueprintName = "MacSymbolicator"
ReferencedContainer = "container:MacSymbolicator.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
Expand Down
2 changes: 1 addition & 1 deletion MacSymbolicator/Controllers/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

func application(_ sender: NSApplication, openFile filename: String) -> Bool {
return mainController.openFile(filename)
mainController.openFile(filename)
}

func setupUpdater() {
Expand Down
40 changes: 0 additions & 40 deletions MacSymbolicator/Controllers/ErrorsController.swift

This file was deleted.

162 changes: 162 additions & 0 deletions MacSymbolicator/Controllers/InputCoordinator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
//
// InputCoordinator.swift
// MacSymbolicator
//

import Foundation

protocol InputCoordinatorDelegate: AnyObject {
func inputCoordinator(_ inputCoordinator: InputCoordinator, receivedNewInput newInput: Any?)
}

class InputCoordinator {
let crashFileDropZone = DropZone(
fileTypes: [".crash", ".txt"],
allowsMultipleFiles: false,
text: "Drop Crash Report or Sample",
activatesAppAfterDrop: true
)

let dsymFilesDropZone = DropZone(
fileTypes: [".dSYM"],
allowsMultipleFiles: true,
text: "Drop App DSYMs",
detailText: "(if not found automatically)",
activatesAppAfterDrop: true
)

private(set) var crashFile: CrashFile?
private(set) var dsymFiles: [DSYMFile] = []

private var isSearchingForDSYMs = false

weak var delegate: InputCoordinatorDelegate?

let logController = LogController()

private var expectedDSYMUUIDs: Set<String> {
guard let crashFile = crashFile else { return Set<String>() }

return Set<String>(crashFile.uuidsForSymbolication.map { $0.pretty })
}

private var foundDSYMUUIDs: Set<String> {
let addedDSYMUUIDs = dsymFiles.flatMap { $0.uuids.values }.map { $0.pretty }
return expectedDSYMUUIDs.intersection(addedDSYMUUIDs)
}

private var remainingDSYMUUIDs: Set<String> {
expectedDSYMUUIDs.subtracting(foundDSYMUUIDs)
}

init() {
crashFileDropZone.delegate = self
dsymFilesDropZone.delegate = self
}

func acceptCrashFile(url fileURL: URL) -> Bool {
crashFileDropZone.acceptFile(url: fileURL)
}

func acceptDSYMFile(url fileURL: URL) -> Bool {
dsymFilesDropZone.acceptFile(url: fileURL)
}

func startSearchForDSYMs() {
guard let crashFile = crashFile else { return }

let remainingUUIDs = Array(remainingDSYMUUIDs)

guard !remainingUUIDs.isEmpty else {
updateDSYMDetailText()
return
}

isSearchingForDSYMs = true
updateDSYMDetailText()

DSYMSearch.search(
forUUIDs: remainingUUIDs,
crashFileDirectory: crashFile.path.deletingLastPathComponent().path,
logHandler: logController.addLogMessages,
callback: { [weak self] finished, results in
DispatchQueue.main.async {
results?.forEach { dsymResult in
let dsymURL = URL(fileURLWithPath: dsymResult.path)
self?.dsymFilesDropZone.acceptFile(url: dsymURL)
}

if finished {
self?.isSearchingForDSYMs = false
}

self?.updateDSYMDetailText()
}
}
)
}

func updateCrashDetailText() {
guard crashFile != nil else {
crashFileDropZone.detailText = ""
return
}

let expectedCount = expectedDSYMUUIDs.count
switch expectedCount {
case 0:
crashFileDropZone.detailText = "(Symbolication not needed)"
case 1:
crashFileDropZone.detailText = "(1 DSYM necessary)"
default:
crashFileDropZone.detailText = "(\(expectedCount) DSYMs necessary)"
}
}

func updateDSYMDetailText() {
guard crashFile != nil else {
dsymFilesDropZone.detailText = "(if not found automatically)"
return
}

guard !expectedDSYMUUIDs.isEmpty else {
dsymFilesDropZone.detailText = ""
return
}

let prefix = isSearchingForDSYMs ? "Searching…" : "Found"
let count = "\(foundDSYMUUIDs.count)/\(expectedDSYMUUIDs.count)"

dsymFilesDropZone.detailText = "\(prefix) \(count)"
}
}

extension InputCoordinator: DropZoneDelegate {
func receivedFiles(dropZone: DropZone, fileURLs: [URL]) -> [URL] {
if dropZone == crashFileDropZone, let fileURL = fileURLs.last {
crashFile = CrashFile(path: fileURL)

logController.resetLogs()
updateCrashDetailText()

delegate?.inputCoordinator(self, receivedNewInput: crashFile)

if crashFile != nil {
startSearchForDSYMs()
}

return fileURLs
} else if dropZone == dsymFilesDropZone {
let dsymFiles = fileURLs.flatMap { DSYMFile.dsymFiles(from: $0) }
self.dsymFiles.append(contentsOf: dsymFiles)

updateDSYMDetailText()

delegate?.inputCoordinator(self, receivedNewInput: dsymFiles)

return dsymFiles.map { $0.path }
}

return []
}
}
47 changes: 47 additions & 0 deletions MacSymbolicator/Controllers/LogController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// LogController.swift
// MacSymbolicator
//

import Cocoa

protocol LogControllerDelegate: AnyObject {
func logController(_ controller: LogController, logsUpdated logMessages: [String])
}

class LogController: NSObject {
private let textWindowController = TextWindowController(title: "Logs")

weak var delegate: LogControllerDelegate?

private var logMessages = [String]() {
didSet {
delegate?.logController(self, logsUpdated: logMessages)

// Update the text here so that if the window is already open, the text gets updated
DispatchQueue.main.async {
self.textWindowController.text = self.logMessages.joined(separator: "\n")
}
}
}

@objc func viewLogs() {
textWindowController.showWindow()
}

func addLogMessage(_ message: String) {
logMessages.append(message)
}

func addLogMessages(_ newMessages: [String]) {
logMessages.append(contentsOf: newMessages)
}

func merge(_ logController: LogController) {
logMessages.append(contentsOf: logController.logMessages)
}

func resetLogs() {
logMessages = []
}
}
Loading

0 comments on commit 15f593a

Please sign in to comment.