Skip to content

Commit

Permalink
add current file's issues and errors
Browse files Browse the repository at this point in the history
  • Loading branch information
llsc12 committed Nov 28, 2024
1 parent 52f65b7 commit 37972bb
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,22 @@
uuid = "56FD24EC-8B81-45C4-A37F-8A8B759FA931"
type = "0"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "02311947-8DFE-41A9-A545-A6E51B5CBC90"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "XRPC/RPC.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "83"
endingLineNumber = "83"
landmarkName = "setPresence(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
117 changes: 113 additions & 4 deletions XRPC/AXScrape.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,53 @@ class AXScrape: ObservableObject {
let doc: URL? = docFilePath == nil ? nil : URL(fileURLWithPath: docFilePath!.replacingOccurrences(of: "file://", with: ""))

let currentSessionDate: Date? = {
switch presenceState {
case .working(let xcodeState):
if case .working(let xcodeState) = presenceState {
return xcodeState.sessionDate
default: return nil
}
return nil
}()

var warnings: Int, errors: Int, issues: Int
warnings = 0
errors = 0
issues = 0

// we need to get the ui elements for the header bar of xcode since thats where the warns and errors are displayed
if
let focusedWindow,
let sourceEditor = filterElements(of: focusedWindow, filter: {
(try? $0.role()) ?? .unknown == .textArea &&
(try? $0.attribute(.description) ?? "") == "Source Editor"
}).first

{
// editor shows errors, runtime warnings and warnings etc in "Line Annotation" id'd elements
let annotations = filterElements(of: sourceEditor, filter: {
(try? $0.role()) ?? .unknown == .button &&
(try? $0.attribute(.identifier)) == "Line Annotation"
})

for annotation in annotations {
issues += 1
let line = ((try? annotation.attribute(.description) ?? "") ?? "")
if line.starts(with: "Warning") && line.contains("Runtime Issue") {
warnings += 1
} else if line.starts(with: "Warning") {
warnings += 1
} else if line.starts(with: "Error") {
errors += 1
}
}
}

let xcState = XcodeState(
workspace: workspace,
editorFile: doc,
isEditingFile: isEditing,
sessionDate: currentSessionDate ?? xcodeProcess?.launchDate ?? .now /// preserve xcode last date or make new date, used for timings
sessionDate: currentSessionDate ?? xcodeProcess?.launchDate ?? .now, /// preserve xcode last date or make new date, used for timings
errors: errors,
warnings: warnings,
totalIssues: issues
)


Expand All @@ -86,6 +121,10 @@ struct XcodeState: Equatable {

var sessionDate: Date?

var errors: Int
var warnings: Int
var totalIssues: Int

/// Is true if xcode has no file open (sitting in xcodeproj or xcworkspace)
var isIdle: Bool {
editorFile?.lastPathComponent.contains("xcodeproj") ?? true || editorFile?.lastPathComponent.contains("xcworkspace") ?? true
Expand Down Expand Up @@ -115,3 +154,73 @@ fileprivate extension String {
self.components(separatedBy: string).count - 1
}
}


func traverseHierarchy(of element: UIElement, level: Int = 0) {
let indent = String(repeating: " ", count: level)

// Log the current (parent) element's details
do {
let role = try element.attribute(.role) as String? ?? "Unknown"
let title = try element.attribute(.title) as String? ?? "No Title"
let help = try element.attribute(.help) as String? ?? "No Help"
let desc = try element.attribute(.description) as String? ?? "No Description"
let vald = try element.attribute(.valueDescription) as String? ?? "No Value Description"

// print("\(indent)- [\(role) name] \(title)")
// print("\(indent)- [\(role) help] \(help)")
// print("\(indent)- [\(role) desc] \(desc)")
// print("\(indent)- [\(role) vald] \(vald)")
print("\(indent)- [\(role)] \(try! element.getMultipleAttributes(element.attributes()).map {($0.key.rawValue, $0.value)})")
print("")

// Any as String
} catch {
print("\(indent)- Error accessing attributes for element: \(error)")
}

// Get the children of the current element
if let children = try? element.children() {
for child in children {
// Recursive call to traverse and log children
traverseHierarchy(of: child, level: level + 1)
}
}
}

extension UIElement {
func children() throws -> [UIElement] {
let a: [AXUIElement] = (try attribute(.children)) ?? [AXUIElement]()
return a.map { UIElement($0) }
}
}

/// Recursively traverses the accessibility hierarchy and applies a closure to filter elements.
///
/// - Parameters:
/// - element: The root `UIElement` to start the traversal from.
/// - level: The current depth in the hierarchy (used for indentation/debugging purposes).
/// - filter: A closure that takes a `UIElement` and returns a `Bool`. If the closure returns `true`, the element is considered a match.
/// - Returns: A list of `UIElement` objects that match the filter condition.
func filterElements(
of element: UIElement,
level: Int = 0,
filter: (UIElement) -> Bool
) -> [UIElement] {
var matchingElements = [UIElement]()

// Check if the current element matches the filter
if filter(element) {
matchingElements.append(element)
}

// Recursively traverse the children of the element
if let children = try? element.children() {
for child in children {
let childMatches = filterElements(of: child, level: level + 1, filter: filter)
matchingElements.append(contentsOf: childMatches)
}
}

return matchingElements
}
3 changes: 2 additions & 1 deletion XRPC/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// self.window?.standardWindowButton(.closeButton)?.isHidden = true
self.window?.standardWindowButton(.miniaturizeButton)?.isHidden = true
self.window?.standardWindowButton(.zoomButton)?.isHidden = true
let titlebar = self.window?.standardWindowButton(.closeButton)?.superview
// let titlebar = self.window?.standardWindowButton(.closeButton)?.superview
// self.window?.titlebarAppearsTransparent = true
self.window?.makeKeyAndOrderFront(self)
SetupVM.shared.setupWindowClose = { self.window?.close(); self.window = nil}
}

}

class KillOnCloseViewController: NSViewController {
Expand Down
5 changes: 3 additions & 2 deletions XRPC/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23504"/>
</dependencies>
<scenes>
<!--Application-->
Expand Down
14 changes: 12 additions & 2 deletions XRPC/RPC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,24 @@ class RPC: ObservableObject, SwordRPCDelegate {
presence.details = "In \(ws)"
}

// if issues != 0
var issuesString = ""
if xcodeState.totalIssues != 0 {
if xcodeState.errors != 0 {
issuesString = "⛔️\(xcodeState.errors) "
} else if xcodeState.warnings != 0 {
issuesString = "⚠️\(xcodeState.totalIssues - xcodeState.errors) "
}
}

if xcodeState.isIdle {
presence.state = "Idling in Xcode"
} else {
if let filename = xcodeState.fileName {
if xcodeState.isEditingFile {
presence.state = "Editing \(filename)"
presence.state = "Editing \(filename) \(issuesString)"
} else {
presence.state = "Viewing \(filename)"
presence.state = "Viewing \(filename) \(issuesString)"
}
}
}
Expand Down

0 comments on commit 37972bb

Please sign in to comment.