diff --git a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Headers/AGDescription.h b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Headers/AGDescription.h index d9d1b270..7ac1e82d 100644 --- a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Headers/AGDescription.h +++ b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Headers/AGDescription.h @@ -3,7 +3,11 @@ #include #if TARGET_OS_MAC +#ifdef __OBJC__ +#import +#else #include +#endif #else #include #endif @@ -16,19 +20,23 @@ AG_EXTERN_C_BEGIN #if TARGET_OS_MAC +#ifdef __OBJC__ +typedef NSString *AGDescriptionOption AG_SWIFT_STRUCT AG_SWIFT_NAME(DescriptionOption); +#else typedef CFStringRef AGDescriptionOption AG_SWIFT_STRUCT AG_SWIFT_NAME(DescriptionOption); +#endif AG_EXPORT -const AGDescriptionOption AGDescriptionFormat AG_SWIFT_NAME(AGDescriptionOption.format); +const AGDescriptionOption AGDescriptionFormat AG_SWIFT_NAME(DescriptionOption.format); AG_EXPORT -const AGDescriptionOption AGDescriptionMaxFrames AG_SWIFT_NAME(AGDescriptionOption.maxFrames); +const AGDescriptionOption AGDescriptionMaxFrames AG_SWIFT_NAME(DescriptionOption.maxFrames); AG_EXPORT -const AGDescriptionOption AGDescriptionIncludeValues AG_SWIFT_NAME(AGDescriptionOption.includeValues); +const AGDescriptionOption AGDescriptionIncludeValues AG_SWIFT_NAME(DescriptionOption.includeValues); AG_EXPORT -const AGDescriptionOption AGDescriptionTruncationLimit AG_SWIFT_NAME(AGDescriptionOption.truncationLimit); +const AGDescriptionOption AGDescriptionTruncationLimit AG_SWIFT_NAME(DescriptionOption.truncationLimit); #endif diff --git a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64-apple-ios-macabi.swiftinterface b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64-apple-ios-macabi.swiftinterface index e31fbbda..929c91cf 100644 --- a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64-apple-ios-macabi.swiftinterface +++ b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64-apple-ios-macabi.swiftinterface @@ -392,8 +392,10 @@ extension AttributeGraph.Rule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) } extension AttributeGraph.Rule { - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var attribute: AttributeGraph.Attribute { get @@ -420,8 +422,10 @@ extension AttributeGraph.StatefulRule { } extension AttributeGraph.StatefulRule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var value: Self.Value { unsafeAddress diff --git a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-ios-macabi.swiftinterface b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-ios-macabi.swiftinterface index ff23847d..e9231a7f 100644 --- a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-ios-macabi.swiftinterface +++ b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-ios-macabi.swiftinterface @@ -392,8 +392,10 @@ extension AttributeGraph.Rule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) } extension AttributeGraph.Rule { - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var attribute: AttributeGraph.Attribute { get @@ -420,8 +422,10 @@ extension AttributeGraph.StatefulRule { } extension AttributeGraph.StatefulRule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var value: Self.Value { unsafeAddress diff --git a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/x86_64-apple-ios-macabi.swiftinterface b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/x86_64-apple-ios-macabi.swiftinterface index 00c100b1..8094ffa5 100644 --- a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/x86_64-apple-ios-macabi.swiftinterface +++ b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/maccatalyst-arm64_arm64e_x86_64/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/x86_64-apple-ios-macabi.swiftinterface @@ -392,8 +392,10 @@ extension AttributeGraph.Rule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) } extension AttributeGraph.Rule { - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var attribute: AttributeGraph.Attribute { get @@ -420,8 +422,10 @@ extension AttributeGraph.StatefulRule { } extension AttributeGraph.StatefulRule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var value: Self.Value { unsafeAddress diff --git a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Headers/AGDescription.h b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Headers/AGDescription.h index d9d1b270..7ac1e82d 100644 --- a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Headers/AGDescription.h +++ b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Headers/AGDescription.h @@ -3,7 +3,11 @@ #include #if TARGET_OS_MAC +#ifdef __OBJC__ +#import +#else #include +#endif #else #include #endif @@ -16,19 +20,23 @@ AG_EXTERN_C_BEGIN #if TARGET_OS_MAC +#ifdef __OBJC__ +typedef NSString *AGDescriptionOption AG_SWIFT_STRUCT AG_SWIFT_NAME(DescriptionOption); +#else typedef CFStringRef AGDescriptionOption AG_SWIFT_STRUCT AG_SWIFT_NAME(DescriptionOption); +#endif AG_EXPORT -const AGDescriptionOption AGDescriptionFormat AG_SWIFT_NAME(AGDescriptionOption.format); +const AGDescriptionOption AGDescriptionFormat AG_SWIFT_NAME(DescriptionOption.format); AG_EXPORT -const AGDescriptionOption AGDescriptionMaxFrames AG_SWIFT_NAME(AGDescriptionOption.maxFrames); +const AGDescriptionOption AGDescriptionMaxFrames AG_SWIFT_NAME(DescriptionOption.maxFrames); AG_EXPORT -const AGDescriptionOption AGDescriptionIncludeValues AG_SWIFT_NAME(AGDescriptionOption.includeValues); +const AGDescriptionOption AGDescriptionIncludeValues AG_SWIFT_NAME(DescriptionOption.includeValues); AG_EXPORT -const AGDescriptionOption AGDescriptionTruncationLimit AG_SWIFT_NAME(AGDescriptionOption.truncationLimit); +const AGDescriptionOption AGDescriptionTruncationLimit AG_SWIFT_NAME(DescriptionOption.truncationLimit); #endif diff --git a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/arm64-apple-macos.swiftinterface b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/arm64-apple-macos.swiftinterface index d3cf0e72..066973fa 100644 --- a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/arm64-apple-macos.swiftinterface +++ b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/arm64-apple-macos.swiftinterface @@ -392,8 +392,10 @@ extension AttributeGraph.Rule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) } extension AttributeGraph.Rule { - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var attribute: AttributeGraph.Attribute { get @@ -420,8 +422,10 @@ extension AttributeGraph.StatefulRule { } extension AttributeGraph.StatefulRule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var value: Self.Value { unsafeAddress diff --git a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/arm64e-apple-macos.swiftinterface b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/arm64e-apple-macos.swiftinterface index 6befb4c7..48dd6ca6 100644 --- a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/arm64e-apple-macos.swiftinterface +++ b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/arm64e-apple-macos.swiftinterface @@ -392,8 +392,10 @@ extension AttributeGraph.Rule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) } extension AttributeGraph.Rule { - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var attribute: AttributeGraph.Attribute { get @@ -420,8 +422,10 @@ extension AttributeGraph.StatefulRule { } extension AttributeGraph.StatefulRule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var value: Self.Value { unsafeAddress diff --git a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/x86_64-apple-macos.swiftinterface b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/x86_64-apple-macos.swiftinterface index aaeda42b..af60871a 100644 --- a/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/x86_64-apple-macos.swiftinterface +++ b/CompatibilityTesting/Frameworks/AttributeGraph.xcframework/macos-arm64_arm64e_x86_64/AttributeGraph.framework/Versions/A/Modules/AttributeGraph.swiftmodule/x86_64-apple-macos.swiftinterface @@ -392,8 +392,10 @@ extension AttributeGraph.Rule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) } extension AttributeGraph.Rule { - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var attribute: AttributeGraph.Attribute { get @@ -420,8 +422,10 @@ extension AttributeGraph.StatefulRule { } extension AttributeGraph.StatefulRule { public static func _update(_ self: Swift.UnsafeMutableRawPointer, attribute: AttributeGraph.AnyAttribute) - public var bodyChanged: Swift.Bool { - get + @_alwaysEmitIntoClient public var bodyChanged: Swift.Bool { + get { + AnyAttribute.currentWasModified + } } public var value: Self.Value { unsafeAddress diff --git a/Sources/Compute/Attribute/Rule/Rule.swift b/Sources/Compute/Attribute/Rule/Rule.swift index e2a9a570..35e8845e 100644 --- a/Sources/Compute/Attribute/Rule/Rule.swift +++ b/Sources/Compute/Attribute/Rule/Rule.swift @@ -1,18 +1,15 @@ import ComputeCxx public protocol Rule: _AttributeBody { - associatedtype Value static var initialValue: Value? { get } var value: Value { get } - } extension Rule { - public static var initialValue: Value? { - return nil + nil } public static func _updateDefault(_ self: UnsafeMutableRawPointer) { @@ -31,23 +28,21 @@ extension Rule { Graph.setOutputValue(valuePointer) } } - } extension Rule { - + @_alwaysEmitIntoClient public var bodyChanged: Bool { - fatalError("not implemented") + AnyAttribute.currentWasModified } public var attribute: Attribute { - return Attribute(identifier: AnyAttribute.current!) + Attribute(identifier: AnyAttribute.current!) } public var context: RuleContext { - return RuleContext(attribute: attribute) + RuleContext(attribute: attribute) } - } @_silgen_name("IAGGraphReadCachedAttribute") @@ -63,7 +58,6 @@ func IAGGraphReadCachedAttribute( ) -> UnsafeRawPointer extension Rule where Self: Hashable { - public func cachedValue(options: CachedValueOptions, owner: AnyAttribute?) -> Value { return withUnsafePointer(to: self) { bodyPointer in Self._cachedValue( @@ -120,5 +114,4 @@ extension Rule where Self: Hashable { } return value.assumingMemoryBound(to: Value.self) } - } diff --git a/Sources/Compute/Attribute/Rule/StatefulRule.swift b/Sources/Compute/Attribute/Rule/StatefulRule.swift index d49b5f96..a29af01f 100644 --- a/Sources/Compute/Attribute/Rule/StatefulRule.swift +++ b/Sources/Compute/Attribute/Rule/StatefulRule.swift @@ -1,18 +1,15 @@ import ComputeCxx public protocol StatefulRule: _AttributeBody { - associatedtype Value static var initialValue: Value? { get } mutating func updateValue() - } extension StatefulRule { - public static var initialValue: Value? { - return nil + nil } public static func _updateDefault(_ default: UnsafeMutableRawPointer) { @@ -26,14 +23,14 @@ extension StatefulRule { } extension StatefulRule { - public static func _update(_ self: UnsafeMutableRawPointer, attribute: AnyAttribute) { let rule = self.assumingMemoryBound(to: Self.self) rule.pointee.updateValue() } + @_alwaysEmitIntoClient public var bodyChanged: Bool { - fatalError("not implemented") + AnyAttribute.currentWasModified } public var value: Value { @@ -50,15 +47,14 @@ extension StatefulRule { } public var hasValue: Bool { - return context.hasValue + context.hasValue } public var attribute: Attribute { - return Attribute(identifier: AnyAttribute.current!) + Attribute(identifier: AnyAttribute.current!) } public var context: RuleContext { - return RuleContext(attribute: attribute) + RuleContext(attribute: attribute) } - } diff --git a/Sources/Compute/Graph/Graph.swift b/Sources/Compute/Graph/Graph.swift index 94c54f30..8e1379bd 100644 --- a/Sources/Compute/Graph/Graph.swift +++ b/Sources/Compute/Graph/Graph.swift @@ -175,6 +175,15 @@ extension Graph { data: Data? = nil, flags: Graph.NamedTraceEventFlags = [] ) { + #if canImport(Darwin) + addNamedTraceEvent( + eventID: eventID, + eventArgCount: eventArgs.count, + eventArgs: eventArgs, + data: data as CFData?, + flags: flags + ) + #else addNamedTraceEvent( eventID: eventID, eventArgCount: eventArgs.count, @@ -182,6 +191,7 @@ extension Graph { data: data?.cfData, flags: flags ) + #endif } } diff --git a/Sources/Compute/Utility/FoundationExtensions/Data+CFData.swift b/Sources/Compute/Utility/FoundationExtensions/Data+CFData.swift index 7572d53a..061a75ce 100644 --- a/Sources/Compute/Utility/FoundationExtensions/Data+CFData.swift +++ b/Sources/Compute/Utility/FoundationExtensions/Data+CFData.swift @@ -1,11 +1,9 @@ import Foundation +#if !canImport(Darwin) extension Data { @usableFromInline var cfData: CFData { - #if canImport(Darwin) - self as CFData - #else withUnsafeBytes { raw -> CFData in CFDataCreate( kCFAllocatorDefault, @@ -13,6 +11,7 @@ extension Data { raw.count )! } - #endif + } } +#endif diff --git a/Tests/ComputeTests/Shared/Attribute/RuleTests.swift b/Tests/ComputeTests/Shared/Attribute/RuleTests.swift index 681ec6bd..c2d4264f 100644 --- a/Tests/ComputeTests/Shared/Attribute/RuleTests.swift +++ b/Tests/ComputeTests/Shared/Attribute/RuleTests.swift @@ -84,4 +84,47 @@ struct RuleTests { } } } + + @Suite + struct ModifyTests { + struct MutableRule: Rule { + var value: String { + return "bodyChanged = \(bodyChanged)" + } + } + + @Test + func modifyBody() { + let graph = Graph() + let subgraph = Subgraph(graph: graph) + let attribute = subgraph.apply { + Attribute(MutableRule()) + } + + let result1 = attribute.value + #expect(result1 == "bodyChanged = false") + + attribute.mutateBody(as: MutableRule.self, invalidating: false) { _ in } + + let result2 = attribute.value + #expect(result2 == "bodyChanged = false") + } + + @Test + func modifyBodyInvalidating() { + let graph = Graph() + let subgraph = Subgraph(graph: graph) + let attribute = subgraph.apply { + Attribute(MutableRule()) + } + + let result1 = attribute.value + #expect(result1 == "bodyChanged = false") + + attribute.mutateBody(as: MutableRule.self, invalidating: true) { _ in } + + let result2 = attribute.value + #expect(result2 == "bodyChanged = true") + } + } } diff --git a/Tests/ComputeTests/Shared/Attribute/StatefulRuleTests.swift b/Tests/ComputeTests/Shared/Attribute/StatefulRuleTests.swift new file mode 100644 index 00000000..ded58eeb --- /dev/null +++ b/Tests/ComputeTests/Shared/Attribute/StatefulRuleTests.swift @@ -0,0 +1,134 @@ +import Testing + +@Suite(.serialized(for: \Subgraph.Type.current)) +struct StatefulRuleTests { + @Suite + struct ValueTests { + struct TestRule: StatefulRule { + typealias Value = String + func updateValue() { + value = "computed" + } + } + + @Test + func value() { + withGraph { + let attribute = Attribute(TestRule()) + let value = attribute.value + #expect(value == "computed") + } + } + + @Test + func initialValue() { + withGraph { + let attribute = Attribute(TestRule(), initialValue: "initial") + let value = attribute.value + #expect(value == "initial") + } + } + + @Test + func invalidateValue() { + withGraph { + let attribute = Attribute(TestRule(), initialValue: "initial") + attribute.invalidateValue() + let value = attribute.value + #expect(value == "computed") + } + } + } + + @Suite + struct InputTests { + struct TestRule1: StatefulRule { + typealias Value = String + func updateValue() { + value = "rule 1 computed value" + } + } + struct TestRule2: StatefulRule { + typealias Value = String + @Attribute var property: String + func updateValue() { + value = "derived: \(property)" + } + } + + @Test + func value() { + withGraph { + let attribute1 = Attribute(TestRule1()) + let attribute2 = Attribute(TestRule2(property: attribute1)) + let value = attribute2.value + #expect(value == "derived: rule 1 computed value") + } + } + + @Test + func initialValue() { + withGraph { + let attribute1 = Attribute(TestRule1(), initialValue: "rule 1 initial value") + let attribute2 = Attribute(TestRule2(property: attribute1)) + let value = attribute2.value + #expect(value == "derived: rule 1 initial value") + } + } + + @Test + func invalidateValue() { + withGraph { + let attribute1 = Attribute(TestRule1(), initialValue: "rule 1 initial value") + let attribute2 = Attribute(TestRule2(property: attribute1)) + attribute1.invalidateValue() + let value = attribute2.value + #expect(value == "derived: rule 1 computed value") + } + } + } + + @Suite + struct ModifyTests { + struct MutableRule: StatefulRule { + typealias Value = String + func updateValue() { + value = "bodyChanged = \(bodyChanged)" + } + } + + @Test + func modifyBody() { + let graph = Graph() + let subgraph = Subgraph(graph: graph) + let attribute = subgraph.apply { + Attribute(MutableRule()) + } + + let result1 = attribute.value + #expect(result1 == "bodyChanged = false") + + attribute.mutateBody(as: MutableRule.self, invalidating: false) { _ in } + + let result2 = attribute.value + #expect(result2 == "bodyChanged = false") + } + + @Test + func modifyBodyInvalidating() { + let graph = Graph() + let subgraph = Subgraph(graph: graph) + let attribute = subgraph.apply { + Attribute(MutableRule()) + } + + let result1 = attribute.value + #expect(result1 == "bodyChanged = false") + + attribute.mutateBody(as: MutableRule.self, invalidating: true) { _ in } + + let result2 = attribute.value + #expect(result2 == "bodyChanged = true") + } + } +}