Skip to content

Commit

Permalink
Update Graph and DebugServer API (#1)
Browse files Browse the repository at this point in the history
* Update Graph and DebugServer API

* Update DemoApp

* Add DebugClientApp

* DebugServer + graph/description complete

* Update DebugServerMode

* Update Package.swift

* Add output info area

* Update README
  • Loading branch information
Kyle-Ye authored Jan 21, 2024
1 parent 1f21754 commit 1ed4f0c
Show file tree
Hide file tree
Showing 19 changed files with 630 additions and 54 deletions.
22 changes: 20 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,26 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/OpenSwiftUIProject/OpenGraph.git",
"state" : {
"revision" : "a236ef8724918dc7cd3e94e0fa492852ee0e1165",
"version" : "0.0.1"
"revision" : "f88a3c15c0385d580d61b43d8af32923ef2667f6",
"version" : "0.0.3"
}
},
{
"identity" : "socket",
"kind" : "remoteSourceControl",
"location" : "https://github.com/OpenSwiftUIProject/Socket.git",
"state" : {
"revision" : "e81b4bd0415060e89decb90461cfc117f0e6d8d0",
"version" : "0.3.3"
}
},
{
"identity" : "swift-system",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-system",
"state" : {
"revision" : "025bcb1165deab2e20d4eaba79967ce73013f496",
"version" : "1.2.1"
}
}
],
Expand Down
24 changes: 17 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,10 @@ let package = Package(
.library(name: "AGDebugKit", targets: ["AGDebugKit"]),
],
dependencies: [
.package(url: "https://github.com/OpenSwiftUIProject/OpenGraph.git", from: "0.0.1"),
.package(url: "https://github.com/OpenSwiftUIProject/OpenGraph.git", from: "0.0.3"),
.package(url: "https://github.com/OpenSwiftUIProject/Socket.git", from: "0.3.3"),
],
targets: [
.executableTarget(
name: "DemoApp",
dependencies: [
"AGDebugKit"
]
),
.target(
name: "AGDebugKit",
dependencies: [
Expand All @@ -35,6 +30,21 @@ let package = Package(
.enableExperimentalFeature("AccessLevelOnImport"),
]
),
// A demo app showing how to use AGDebugKit
.executableTarget(
name: "DemoApp",
dependencies: [
"AGDebugKit",
]
),
// A client sending command to AGDebugServer
.executableTarget(
name: "DebugClient",
dependencies: [
"AGDebugKit",
.product(name: "Socket", package: "Socket"),
]
),
.testTarget(
name: "AGDebugKitTests",
dependencies: ["AGDebugKit"]
Expand Down
16 changes: 6 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,16 @@

A package to get debug information from the private AttributeGraph framework behind SwiftUI.

For visualization the JSON result, see [GraphConverter](https://github.com/OpenSwiftUIProject/GraphConverter)
If you need JSON result visualization, you can refer to [GraphConverter](https://github.com/OpenSwiftUIProject/GraphConverter)

For SwiftUI debug information, see [SwiftUIViewDebug](https://github.com/OpenSwiftUIProject/SwiftUIViewDebug)
If you need SwiftUI debug information, you can refer to [SwiftUIViewDebug](https://github.com/OpenSwiftUIProject/SwiftUIViewDebug)

## Example

![Demo App](Resources/demo_app.png)
![Demo App Console](Resources/demo_app.png)

![Demo JSON](Resources/demo_json.png)
![Demo App Screenshot](Resources/demo_app_2.png)

## TODO
![Demo JSON](Resources/demo_json.png)

- [ ] AGDescriptionFormat
- [ ] AGGraphGetAttributeGraph
- [ ] AGGraphDescription
- [ ] AGGraphCreate
- [ ] AGDebugServer
![Debug Client Screenshot](Resources/debug_client.png)
Binary file added Resources/debug_client.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/demo_app_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 0 additions & 13 deletions Sources/AGDebugKit/AGDebugKit.swift

This file was deleted.

45 changes: 45 additions & 0 deletions Sources/AGDebugKit/DebugServer/DebugServer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// DebugServer.swift
//
//
// Created by Kyle on 2024/1/21.
//

private import AttributeGraph
import Foundation

public final class DebugServer {
private var server: UnsafeRawPointer?

public static let shared = DebugServer()

public func start(_ mode: Mode = .local) {
server = debugServerStart(mode.rawValue)
}

public func stop() {
debugServerStop()
server = nil
}

public func run(timeout: Int) {
guard let _ = server else { return }
debugServerRun(timeout)
}

public var url: URL? {
guard let _ = server,
let url = debugServerCopyURL() as? URL
else { return nil }
return url
}

/// A Bool value indicating whether the server has been started successfully
///
/// To make AttributeGraph start debugServer successfully, we need to pass its internal diagnostics check.
/// In debug mode, add a symbolic breakpoint on `_ZN2AG11DebugServer5startEj`, run `start(_:)` and
/// executable `reg write w0 1` after `os_variant_has_internal_diagnostics` call.
public var startSuccess: Bool {
server != nil
}
}
18 changes: 18 additions & 0 deletions Sources/AGDebugKit/DebugServer/DebugServerCommand.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// DebugServerCommand.swift
//
//
// Created by Kyle on 2024/1/22.
//

extension DebugServer {
public enum Command: String, CaseIterable, Hashable, Identifiable {
case graphDescription = "graph/description"
case profilerStart = "profiler/start"
case profilerStop = "profiler/stop"
case profilerReset = "profiler/reset"
case profilerMark = "profiler/mark"

public var id: String { rawValue }
}
}
23 changes: 23 additions & 0 deletions Sources/AGDebugKit/DebugServer/DebugServerMessageHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// DebugServerMessageHeader.swift
//
//
// Created by Kyle on 2024/1/22.
//

extension DebugServer {
public struct MessageHeader: Codable {
public var token: UInt32
public var reserved: UInt32
public var length: UInt32
public var reserved2: UInt32
public init(token: UInt32, length: UInt32) {
self.token = token
self.reserved = 0
self.length = length
self.reserved2 = 0
}

public static var size: Int { MemoryLayout<Self>.size }
}
}
24 changes: 24 additions & 0 deletions Sources/AGDebugKit/DebugServer/DebugServerMode.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// DebugServerMode.swift
//
//
// Created by Kyle on 2024/1/22.
//

extension DebugServer {
/// The run mode of DebugServer
///
public struct Mode: RawRepresentable, Hashable {
public let rawValue: UInt

public init(rawValue: UInt) {
self.rawValue = rawValue
}

/// Localhost mode: example host is `127.0.0.1`
public static let local = Mode(rawValue: 1)

/// Network mode: example host is `192.168.8.230`
public static let network = Mode(rawValue: 3)
}
}
52 changes: 52 additions & 0 deletions Sources/AGDebugKit/Graph.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// Graph.swift
//
//
// Created by Kyle on 2024/1/21.
//

private import AttributeGraph
import Foundation

/// A wrapper class for AGGraph
public final class Graph {
let graph: UnsafeRawPointer?

public init() {
graph = nil
}

public init(_ pointer: UnsafeRawPointer?) {
graph = graphCreateShared(pointer)
}

public var dict: NSDictionary? {
let options = ["format": "graph/dict"] as NSDictionary
guard let description = graphDescription(options: options) else {
return nil
}
return Unmanaged<NSDictionary>.fromOpaque(description).takeUnretainedValue()
}

public var dot: String? {
let options = ["format": "graph/dot"] as NSDictionary
guard let graph,
let description = graphDescription(graph, options: options)
else {
return nil
}
return Unmanaged<NSString>.fromOpaque(description).takeUnretainedValue() as String
}

/// Archive the current AGGraph's state to temporary directory
///
/// After calling the method, you will see the following message on Xcode console:
///
/// Wrote graph data to "`$NSTemporaryDirectory()`+`name`".
///
/// You can then consume the exported JSON file directly or via
/// [GraphConverter](https://github.com/OpenSwiftUIProject/GraphConverter)
public static func archiveGraph(name: String) {
name.withCString { graphArchiveJSON($0) }
}
}
Loading

0 comments on commit 1ed4f0c

Please sign in to comment.