Skip to content

Commit bdad1ba

Browse files
committed
Update ViewDebug serialize data
1 parent 165d4a1 commit bdad1ba

File tree

2 files changed

+117
-86
lines changed

2 files changed

+117
-86
lines changed

Sources/OpenSwiftUICore/View/Debug/ViewDebug.swift

Lines changed: 91 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// OpenSwiftUICore
44
//
55
// Audited for iOS 18.0
6-
// Status: WIP
6+
// Status: Blocked by TreeElement
77
// ID: 5A14269649C60F846422EA0FA4C5E535 (SwiftUI)
88
// ID: 43DA1754B0518AF1D72B90677BF266DB (SwiftUICore)
99

@@ -260,49 +260,56 @@ extension _ViewDebug.Data: Encodable {
260260
try container.encode(serializedProperties(), forKey: .properties)
261261
try container.encode(childData, forKey: .children)
262262
}
263-
263+
264264
private func serializedProperties() -> [SerializedProperty] {
265265
data.compactMap { key, value -> SerializedProperty? in
266-
if key == .value {
267-
if let attribute = serializedAttribute(for: value, label: nil, reflectionDepth: 6) {
268-
return SerializedProperty(id: key.rawValue, attribute: attribute)
269-
} else {
270-
return nil
271-
}
272-
} else if key == .type {
273-
let type = value as? Any.Type ?? type(of: value)
274-
let attribute = SerializedAttribute(type: type)
275-
return SerializedProperty(id: 0, attribute: attribute)
276-
} else {
277-
if let attribute = serializedAttribute(for: value, label: nil, reflectionDepth: 4) {
278-
return SerializedProperty(id: key.rawValue, attribute: attribute)
279-
} else {
280-
return nil
281-
}
266+
let attribute: SerializedAttribute? = switch key {
267+
case .type: SerializedAttribute(type: value as? Any.Type ?? type(of: value))
268+
case .value: serializedAttribute(for: value, label: nil, reflectionDepth: 6)
269+
default: serializedAttribute(for: value, label: nil, reflectionDepth: 4)
282270
}
271+
guard let attribute else { return nil }
272+
return SerializedProperty(id: key.rawValue, attribute: attribute)
283273
}
284274
}
285-
286-
// TODO
287-
// Mirror API
275+
288276
private func serializedAttribute(for value: Any, label: String?, reflectionDepth depth: Int) -> SerializedAttribute? {
289-
// let unwrapped = unwrapped(value)
290-
291-
return nil
292-
293-
// let mirror = Mirror(reflecting: value)
294-
// mirror.displayStyle = .tuple
295-
277+
guard let unwrappedValue = unwrapped(value) else {
278+
return nil
279+
}
280+
if unwrappedValue is Encodable || unwrappedValue is CustomViewDebugValueConvertible || depth == 0 {
281+
return SerializedAttribute(value: unwrappedValue, serializeValue: true, label: label, subattributes: nil)
282+
} else if let mirror = effectiveMirror(for: unwrappedValue) {
283+
guard !mirror.children.isEmpty else {
284+
return SerializedAttribute(value: unwrappedValue, serializeValue: true, label: label, subattributes: nil)
285+
}
286+
let depth = depth - 1
287+
let subattributes = mirror.children.compactMap { child in
288+
serializedAttribute(for: child.value, label: child.label, reflectionDepth: depth)
289+
}
290+
return SerializedAttribute(value: unwrappedValue, serializeValue: false, label: label, subattributes: subattributes)
291+
} else {
292+
return SerializedAttribute(value: unwrappedValue, serializeValue: false, label: label, subattributes: nil)
293+
}
296294
}
297295

298296
private func unwrapped(_ value: Any) -> Any? {
299-
if let value = value as? ValueWrapper {
300-
return value.wrappedValue
297+
if let valueWrapper = value as? ValueWrapper {
298+
return valueWrapper.wrappedValue
301299
} else {
302-
return nil
300+
return value
303301
}
304302
}
305303

304+
private func effectiveMirror(for value: Any) -> Mirror? {
305+
if case let customized as CustomViewDebugReflectable = value {
306+
customized.customViewDebugMirror
307+
} else if case let customized as CustomReflectable = value {
308+
customized.customMirror
309+
} else {
310+
Mirror(reflecting: value)
311+
}
312+
}
306313
}
307314

308315
// MARK: _ViewDebug.Data.SerializedProperty
@@ -328,57 +335,21 @@ extension _ViewDebug.Data {
328335
// MARK: _ViewDebug.Data.SerializedAttribute
329336

330337
extension _ViewDebug.Data {
331-
// Size: 0x60
332338
private struct SerializedAttribute: Encodable {
333-
// TODO:
334-
static func serialize(value _: Any) -> Any? {
335-
// Mirror API
336-
nil
337-
}
338-
339-
init(type anyType: Any.Type) {
340-
name = nil
341-
type = String(reflecting: anyType)
342-
readableType = OGTypeID(anyType).description
343-
flags = [
344-
conformsToProtocol(anyType, _OpenSwiftUI_viewProtocolDescriptor()) ? .view : [],
345-
conformsToProtocol(anyType, _OpenSwiftUI_viewModifierProtocolDescriptor()) ? .viewModifier : [],
346-
]
347-
value = nil
348-
subattributes = nil
349-
}
350-
351-
init(value inputValue: Any, serializeValue: Bool, label: String?, subattributes inputSubattributes: [SerializedAttribute]) {
352-
name = label
353-
let anyType = Swift.type(of: inputValue)
354-
type = String(reflecting: anyType)
355-
readableType = OGTypeID(anyType).description
356-
flags = [
357-
conformsToProtocol(anyType, _OpenSwiftUI_viewProtocolDescriptor()) ? .view : [],
358-
conformsToProtocol(anyType, _OpenSwiftUI_viewModifierProtocolDescriptor()) ? .viewModifier : [],
359-
]
360-
if serializeValue {
361-
value = SerializedAttribute.serialize(value: inputValue)
362-
} else {
363-
value = nil
364-
}
365-
subattributes = inputSubattributes
366-
}
367-
368-
struct Flags: OptionSet, Encodable {
369-
let rawValue: Int
370-
371-
static let view = Flags(rawValue: 1 << 0)
372-
static let viewModifier = Flags(rawValue: 1 << 1)
373-
}
374-
375339
let name: String?
376340
let type: String
377341
let readableType: String
378342
let flags: Flags
379343
let value: Any?
380344
let subattributes: [SerializedAttribute]?
381345

346+
struct Flags: OptionSet, Encodable {
347+
let rawValue: Int
348+
349+
static let view = Flags(rawValue: 1 << 0)
350+
static let viewModifier = Flags(rawValue: 1 << 1)
351+
}
352+
382353
enum CodingKeys: CodingKey {
383354
case name
384355
case type
@@ -399,6 +370,52 @@ extension _ViewDebug.Data {
399370
}
400371
try container.encodeIfPresent(subattributes, forKey: .subattributes)
401372
}
373+
374+
static func serialize(value: Any) -> Any? {
375+
let viewDebugValue: Any
376+
if let customValue = value as? CustomViewDebugValueConvertible {
377+
viewDebugValue = customValue.viewDebugValue
378+
} else {
379+
viewDebugValue = value
380+
}
381+
if let encodable = viewDebugValue as? Encodable {
382+
return encodable
383+
} else if let customDebugStringConvertible = viewDebugValue as? CustomDebugStringConvertible {
384+
return customDebugStringConvertible.debugDescription
385+
} else {
386+
let mirror = Mirror(reflecting: viewDebugValue)
387+
if let displayStyle = mirror.displayStyle, displayStyle == .enum {
388+
return String(describing: viewDebugValue)
389+
} else {
390+
return nil
391+
}
392+
}
393+
}
394+
395+
init(type anyType: Any.Type) {
396+
self.name = nil
397+
self.type = String(reflecting: anyType)
398+
self.readableType = OGTypeID(anyType).description
399+
self.flags = [
400+
conformsToProtocol(anyType, _OpenSwiftUI_viewProtocolDescriptor()) ? .view : [],
401+
conformsToProtocol(anyType, _OpenSwiftUI_viewModifierProtocolDescriptor()) ? .viewModifier : [],
402+
]
403+
self.value = nil
404+
self.subattributes = nil
405+
}
406+
407+
init(value: Any, serializeValue: Bool, label: String?, subattributes: [SerializedAttribute]?) {
408+
self.name = label
409+
let anyType = Swift.type(of: value)
410+
self.type = String(reflecting: anyType)
411+
self.readableType = OGTypeID(anyType).description
412+
self.flags = [
413+
conformsToProtocol(anyType, _OpenSwiftUI_viewProtocolDescriptor()) ? .view : [],
414+
conformsToProtocol(anyType, _OpenSwiftUI_viewModifierProtocolDescriptor()) ? .viewModifier : [],
415+
]
416+
self.value = serializeValue ? SerializedAttribute.serialize(value: value) : nil
417+
self.subattributes = subattributes
418+
}
402419
}
403420
}
404421

Tests/OpenSwiftUICoreTests/View/Debug/ViewDebugTests.swift

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,44 @@
55
// Created by Kyle on 2023/10/6.
66
//
77

8-
@testable import OpenSwiftUICore
8+
import OpenSwiftUICore
9+
import OpenGraphShims
910
import Testing
1011
import Foundation
1112

1213
struct ViewDebugTests {
13-
@Test(.disabled("Skip the test until we finish the implementation of _ViewDebug"))
14-
func type() throws {
14+
private func checkJSONEqual(data: Data, expected expectedData: Data) -> Bool {
15+
let json = try? JSONSerialization.jsonObject(with: data)
16+
let expectedJSON = try? JSONSerialization.jsonObject(with: expectedData)
17+
guard let json = json as? [[String: AnyHashable]], let expectedJSON = expectedJSON as? [[String: AnyHashable]] else {
18+
return false
19+
}
20+
return json == expectedJSON
21+
}
22+
23+
@Test(.enabled(if: attributeGraphEnabled ,"Only enable the test when AG is enabled"))
24+
func serializeData() throws {
1525
var rawData = _ViewDebug.Data()
1626
rawData.data = [.type: CGSize.self]
1727
let data = try #require(_ViewDebug.serializedData([rawData]))
18-
let content = String(decoding: data, as: UTF8.self)
19-
#expect(content == #"""
20-
[{"properties":[{"id":0,"attribute":{"type":"__C.CGSize","flags":0,"readableType":""}}],"children":[]}]
21-
"""#)
28+
#expect(checkJSONEqual(
29+
data: data,
30+
expected: #"""
31+
[{"properties":[{"id":0,"attribute":{"type":"__C.CGSize","flags":0,"readableType":"CGSize"}}],"children":[]}]
32+
"""#.data(using: .utf8)!
33+
))
2234
}
2335

24-
@Test(.disabled("Skip the test until we finish the implementation of _ViewDebug"))
36+
@Test(.enabled(if: attributeGraphEnabled ,"Only enable the test when AG is enabled"))
2537
func size() throws {
2638
var rawData = _ViewDebug.Data()
2739
rawData.data = [.size: CGSize(width: 20, height: 20)]
2840
let data = try #require(_ViewDebug.serializedData([rawData]))
29-
let content = String(decoding: data, as: UTF8.self)
30-
#expect(content == #"""
31-
[{"properties":[],"children":[]}]
32-
"""#)
41+
#expect(checkJSONEqual(
42+
data: data,
43+
expected: #"""
44+
[{"properties":[{"id":4,"attribute":{"value":[20,20],"type":"__C.CGSize","flags":0,"readableType":"CGSize"}}],"children":[]}]
45+
"""#.data(using: .utf8)!
46+
))
3347
}
3448
}

0 commit comments

Comments
 (0)