Skip to content

Commit 9ed28d6

Browse files
philprimephilipphofmannarmcknight
authored
refactor(session-replay): Add separate files and missing type prefix (#5343)
Co-authored-by: Philipp Hofmann <[email protected]> Co-authored-by: Andrew McKnight <[email protected]>
1 parent c5d844f commit 9ed28d6

19 files changed

+782
-384
lines changed

Sentry.xcodeproj/project.pbxproj

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,7 @@
812812
A8F17B2E2901765900990B25 /* SentryRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F17B2D2901765900990B25 /* SentryRequest.m */; };
813813
A8F17B342902870300990B25 /* SentryHttpStatusCodeRange.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F17B332902870300990B25 /* SentryHttpStatusCodeRange.m */; };
814814
D4009EB22D771BC20007AF30 /* SentryFileIOTrackerSwiftHelpersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4009EB12D771BB90007AF30 /* SentryFileIOTrackerSwiftHelpersTests.swift */; };
815+
D41415A72DEEE532003B14D5 /* SentryRedactViewHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41415A62DEEE532003B14D5 /* SentryRedactViewHelper.swift */; };
815816
D4291A692DD61A3F00772088 /* SentryDispatchQueueProviderProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D4291A672DD61A3F00772088 /* SentryDispatchQueueProviderProtocol.h */; };
816817
D4291A6D2DD62ACE00772088 /* SentryDispatchFactoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4291A6C2DD62AC800772088 /* SentryDispatchFactoryTests.m */; };
817818
D42E48572D48DF1600D251BC /* SentryBuildAppStartSpansTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42E48562D48DF1600D251BC /* SentryBuildAppStartSpansTests.swift */; };
@@ -861,6 +862,8 @@
861862
D4C5F59A2D4249E6002A9BF6 /* DataSentryTracingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C5F5992D4249E0002A9BF6 /* DataSentryTracingIntegrationTests.swift */; };
862863
D4CBA2472DE06D0200581618 /* libSentryTestUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8431F00A29B284F200D8DC56 /* libSentryTestUtils.a */; };
863864
D4CBA2532DE06D1600581618 /* TestConstantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CBA2512DE06D1600581618 /* TestConstantTests.swift */; };
865+
D4CD2A802DE9F91900DA9F59 /* SentryRedactRegion.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CD2A7C2DE9F91900DA9F59 /* SentryRedactRegion.swift */; };
866+
D4CD2A812DE9F91900DA9F59 /* SentryRedactRegionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CD2A7D2DE9F91900DA9F59 /* SentryRedactRegionType.swift */; };
864867
D4E3F35D2D4A864600F79E2B /* SentryNSDictionarySanitizeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42E48582D48FC8F00D251BC /* SentryNSDictionarySanitizeTests.swift */; };
865868
D4E3F35E2D4A877300F79E2B /* SentryNSDictionarySanitize+Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = D41909942D490006002B83D0 /* SentryNSDictionarySanitize+Tests.m */; };
866869
D4EDF9842D0B2A210071E7B3 /* Data+SentryTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EDF9832D0B2A1D0071E7B3 /* Data+SentryTracing.swift */; };
@@ -1048,7 +1051,7 @@
10481051
FA67DD0A2DDBD4EA00896B02 /* SentryBaggageSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCC92DDBD4EA00896B02 /* SentryBaggageSerialization.swift */; };
10491052
FA67DD0B2DDBD4EA00896B02 /* UIViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCC52DDBD4EA00896B02 /* UIViewExtensions.swift */; };
10501053
FA67DD0C2DDBD4EA00896B02 /* SentryMaskRendererV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCE32DDBD4EA00896B02 /* SentryMaskRendererV2.swift */; };
1051-
FA67DD0D2DDBD4EA00896B02 /* UIRedactBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCE82DDBD4EA00896B02 /* UIRedactBuilder.swift */; };
1054+
FA67DD0D2DDBD4EA00896B02 /* SentryUIRedactBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCE82DDBD4EA00896B02 /* SentryUIRedactBuilder.swift */; };
10521055
FA67DD0E2DDBD4EA00896B02 /* SentryFileContents.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCCB2DDBD4EA00896B02 /* SentryFileContents.swift */; };
10531056
FA67DD0F2DDBD4EA00896B02 /* SentryViewControllerBreadcrumbTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCDD2DDBD4EA00896B02 /* SentryViewControllerBreadcrumbTracking.swift */; };
10541057
FA67DD102DDBD4EA00896B02 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCC42DDBD4EA00896B02 /* StringExtensions.swift */; };
@@ -2031,6 +2034,7 @@
20312034
A8F17B2D2901765900990B25 /* SentryRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryRequest.m; sourceTree = "<group>"; };
20322035
A8F17B332902870300990B25 /* SentryHttpStatusCodeRange.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryHttpStatusCodeRange.m; sourceTree = "<group>"; };
20332036
D4009EB12D771BB90007AF30 /* SentryFileIOTrackerSwiftHelpersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryFileIOTrackerSwiftHelpersTests.swift; sourceTree = "<group>"; };
2037+
D41415A62DEEE532003B14D5 /* SentryRedactViewHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRedactViewHelper.swift; sourceTree = "<group>"; };
20342038
D41909922D48FFF6002B83D0 /* SentryNSDictionarySanitize+Tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryNSDictionarySanitize+Tests.h"; sourceTree = "<group>"; };
20352039
D41909942D490006002B83D0 /* SentryNSDictionarySanitize+Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SentryNSDictionarySanitize+Tests.m"; sourceTree = "<group>"; };
20362040
D4291A672DD61A3F00772088 /* SentryDispatchQueueProviderProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDispatchQueueProviderProtocol.h; path = include/SentryDispatchQueueProviderProtocol.h; sourceTree = "<group>"; };
@@ -2088,6 +2092,8 @@
20882092
D4C5F5992D4249E0002A9BF6 /* DataSentryTracingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSentryTracingIntegrationTests.swift; sourceTree = "<group>"; };
20892093
D4CBA2432DE06D0200581618 /* SentryTestUtilsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SentryTestUtilsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
20902094
D4CBA2512DE06D1600581618 /* TestConstantTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestConstantTests.swift; sourceTree = "<group>"; };
2095+
D4CD2A7C2DE9F91900DA9F59 /* SentryRedactRegion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRedactRegion.swift; sourceTree = "<group>"; };
2096+
D4CD2A7D2DE9F91900DA9F59 /* SentryRedactRegionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRedactRegionType.swift; sourceTree = "<group>"; };
20912097
D4EDF9832D0B2A1D0071E7B3 /* Data+SentryTracing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+SentryTracing.swift"; sourceTree = "<group>"; };
20922098
D4F2B5342D0C69D100649E42 /* SentryCrashCTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashCTests.swift; sourceTree = "<group>"; };
20932099
D4FC68162DD632E7001B74FF /* SentryDispatchSourceProviderProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDispatchSourceProviderProtocol.h; path = include/SentryDispatchSourceProviderProtocol.h; sourceTree = "<group>"; };
@@ -2295,7 +2301,7 @@
22952301
FA67DCE52DDBD4EA00896B02 /* SentryViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryViewRenderer.swift; sourceTree = "<group>"; };
22962302
FA67DCE62DDBD4EA00896B02 /* SentryViewRendererV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryViewRendererV2.swift; sourceTree = "<group>"; };
22972303
FA67DCE72DDBD4EA00896B02 /* SentryViewScreenshotProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryViewScreenshotProvider.swift; sourceTree = "<group>"; };
2298-
FA67DCE82DDBD4EA00896B02 /* UIRedactBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIRedactBuilder.swift; sourceTree = "<group>"; };
2304+
FA67DCE82DDBD4EA00896B02 /* SentryUIRedactBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIRedactBuilder.swift; sourceTree = "<group>"; };
22992305
FA67DCEA2DDBD4EA00896B02 /* HTTPHeaderSanitizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPHeaderSanitizer.swift; sourceTree = "<group>"; };
23002306
FA67DCEB2DDBD4EA00896B02 /* SentryLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLog.swift; sourceTree = "<group>"; };
23012307
FA67DCEC2DDBD4EA00896B02 /* SentryLogOutput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogOutput.swift; sourceTree = "<group>"; };
@@ -2444,13 +2450,6 @@
24442450
path = Helper;
24452451
sourceTree = "<group>";
24462452
};
2447-
624729162DE597DB00DFEE00 /* SentryTestUtilsTests */ = {
2448-
isa = PBXGroup;
2449-
children = (
2450-
);
2451-
path = SentryTestUtilsTests;
2452-
sourceTree = "<group>";
2453-
};
24542453
62872B602BA1B84400A4FA7D /* Swift */ = {
24552454
isa = PBXGroup;
24562455
children = (
@@ -2875,7 +2874,6 @@
28752874
63FE71D220DA66C500CDBAE8 /* SentryCrash */,
28762875
7B944FAC2469B41600A10721 /* State */,
28772876
7BF536D224BEF240004FA6A2 /* TestUtils */,
2878-
624729162DE597DB00DFEE00 /* SentryTestUtilsTests */,
28792877
D81FDF0F280E9FEC0045E0E4 /* Tools */,
28802878
7B6C5ED4264E62B60010D138 /* Transaction */,
28812879
);
@@ -4550,6 +4548,8 @@
45504548
FA67DCE92DDBD4EA00896B02 /* ViewCapture */ = {
45514549
isa = PBXGroup;
45524550
children = (
4551+
D4CD2A7C2DE9F91900DA9F59 /* SentryRedactRegion.swift */,
4552+
D4CD2A7D2DE9F91900DA9F59 /* SentryRedactRegionType.swift */,
45534553
FA67DCDF2DDBD4EA00896B02 /* SentryDefaultMaskRenderer.swift */,
45544554
FA67DCE02DDBD4EA00896B02 /* SentryDefaultViewRenderer.swift */,
45554555
FA67DCE12DDBD4EA00896B02 /* SentryGraphicsImageRenderer.swift */,
@@ -4559,7 +4559,8 @@
45594559
FA67DCE52DDBD4EA00896B02 /* SentryViewRenderer.swift */,
45604560
FA67DCE62DDBD4EA00896B02 /* SentryViewRendererV2.swift */,
45614561
FA67DCE72DDBD4EA00896B02 /* SentryViewScreenshotProvider.swift */,
4562-
FA67DCE82DDBD4EA00896B02 /* UIRedactBuilder.swift */,
4562+
FA67DCE82DDBD4EA00896B02 /* SentryUIRedactBuilder.swift */,
4563+
D41415A62DEEE532003B14D5 /* SentryRedactViewHelper.swift */,
45634564
);
45644565
path = ViewCapture;
45654566
sourceTree = "<group>";
@@ -5418,6 +5419,7 @@
54185419
FA67DCFD2DDBD4EA00896B02 /* SentryANRTracker.swift in Sources */,
54195420
FA67DCFE2DDBD4EA00896B02 /* SentryANRTrackerV2Delegate.swift in Sources */,
54205421
FA67DCFF2DDBD4EA00896B02 /* SentryMXManager.swift in Sources */,
5422+
D41415A72DEEE532003B14D5 /* SentryRedactViewHelper.swift in Sources */,
54215423
FA67DD002DDBD4EA00896B02 /* SentryMaskRenderer.swift in Sources */,
54225424
FA67DD012DDBD4EA00896B02 /* SentryMXCallStackTree.swift in Sources */,
54235425
FA67DD022DDBD4EA00896B02 /* SentryViewScreenshotProvider.swift in Sources */,
@@ -5431,7 +5433,7 @@
54315433
FA67DD0A2DDBD4EA00896B02 /* SentryBaggageSerialization.swift in Sources */,
54325434
FA67DD0B2DDBD4EA00896B02 /* UIViewExtensions.swift in Sources */,
54335435
FA67DD0C2DDBD4EA00896B02 /* SentryMaskRendererV2.swift in Sources */,
5434-
FA67DD0D2DDBD4EA00896B02 /* UIRedactBuilder.swift in Sources */,
5436+
FA67DD0D2DDBD4EA00896B02 /* SentryUIRedactBuilder.swift in Sources */,
54355437
FA67DD0E2DDBD4EA00896B02 /* SentryFileContents.swift in Sources */,
54365438
FA67DD0F2DDBD4EA00896B02 /* SentryViewControllerBreadcrumbTracking.swift in Sources */,
54375439
FA67DD102DDBD4EA00896B02 /* StringExtensions.swift in Sources */,
@@ -5493,6 +5495,8 @@
54935495
03F84D3227DD4191008FE43F /* SentryProfiler.mm in Sources */,
54945496
635B3F391EBC6E2500A6176D /* SentryAsynchronousOperation.m in Sources */,
54955497
63FE717520DA4C1100CDBAE8 /* SentryCrash.m in Sources */,
5498+
D4CD2A802DE9F91900DA9F59 /* SentryRedactRegion.swift in Sources */,
5499+
D4CD2A812DE9F91900DA9F59 /* SentryRedactRegionType.swift in Sources */,
54965500
6344DDB11EC308E400D9160D /* SentryCrashInstallationReporter.m in Sources */,
54975501
84BA62272CAE2EEF0049F636 /* SentryUserFeedbackWidgetButtonView.swift in Sources */,
54985502
D85596F3280580F10041FF8B /* SentryScreenshotIntegration.m in Sources */,

Sources/Swift/Core/Tools/ViewCapture/SentryDefaultMaskRenderer.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import UIKit
55

66
class SentryDefaultMaskRenderer: NSObject, SentryMaskRenderer {
7-
func maskScreenshot(screenshot image: UIImage, size: CGSize, masking: [RedactRegion]) -> UIImage {
7+
func maskScreenshot(screenshot image: UIImage, size: CGSize, masking: [SentryRedactRegion]) -> UIImage {
88
let image = UIGraphicsImageRenderer(size: size, format: .init(for: .init(displayScale: 1))).image { context in
99
applyMasking(to: context, image: image, size: size, masking: masking)
1010
}
@@ -15,7 +15,7 @@ class SentryDefaultMaskRenderer: NSObject, SentryMaskRenderer {
1515
to context: SentryMaskRendererContext,
1616
image: UIImage,
1717
size: CGSize,
18-
masking: [RedactRegion]
18+
masking: [SentryRedactRegion]
1919
) {
2020
let clipOutPath = CGMutablePath(rect: CGRect(origin: .zero, size: size), transform: nil)
2121
var clipPaths = [CGPath]()
@@ -27,7 +27,7 @@ class SentryDefaultMaskRenderer: NSObject, SentryMaskRenderer {
2727
context.cgContext.interpolationQuality = .none
2828
image.draw(at: .zero)
2929

30-
var latestRegion: RedactRegion?
30+
var latestRegion: SentryRedactRegion?
3131
for region in masking {
3232
let rect = CGRect(origin: CGPoint.zero, size: region.size)
3333
var transform = region.transform

Sources/Swift/Core/Tools/ViewCapture/SentryMaskRenderer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import UIKit
55

66
protocol SentryMaskRenderer {
7-
func maskScreenshot(screenshot image: UIImage, size: CGSize, masking: [RedactRegion]) -> UIImage
7+
func maskScreenshot(screenshot image: UIImage, size: CGSize, masking: [SentryRedactRegion]) -> UIImage
88
}
99

1010
protocol SentryMaskRendererContext {

Sources/Swift/Core/Tools/ViewCapture/SentryMaskRendererV2.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import UIKit
55

66
class SentryMaskRendererV2: SentryDefaultMaskRenderer {
7-
override func maskScreenshot(screenshot image: UIImage, size: CGSize, masking: [RedactRegion]) -> UIImage {
7+
override func maskScreenshot(screenshot image: UIImage, size: CGSize, masking: [SentryRedactRegion]) -> UIImage {
88
// The `SentryDefaultMaskRenderer` is also using an display scale of 1, therefore we also use 1 here.
99
// This could be evaluated in future iterations to view performance impact vs quality.
1010
let image = SentryGraphicsImageRenderer(size: size, scale: 1).image { context in
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#if canImport(UIKit) && !SENTRY_NO_UIKIT
2+
#if os(iOS) || os(tvOS)
3+
import Foundation
4+
import ObjectiveC.NSObjCRuntime
5+
import UIKit
6+
7+
class SentryRedactRegion {
8+
let size: CGSize
9+
let transform: CGAffineTransform
10+
let type: SentryRedactRegionType
11+
let color: UIColor?
12+
let name: String
13+
14+
init(size: CGSize, transform: CGAffineTransform, type: SentryRedactRegionType, color: UIColor? = nil, name: String) {
15+
self.size = size
16+
self.transform = transform
17+
self.type = type
18+
self.color = color
19+
self.name = name
20+
}
21+
22+
func canReplace(as other: SentryRedactRegion) -> Bool {
23+
size == other.size && transform == other.transform && type == other.type
24+
}
25+
}
26+
#endif
27+
#endif
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
public enum SentryRedactRegionType: String, Codable {
2+
/// Redacts the region.
3+
case redact = "redact"
4+
5+
/// Marks a region to not draw anything.
6+
/// This is used for opaque views.
7+
case clipOut = "clip_out"
8+
9+
/// Push a clip region to the drawing context.
10+
/// This is used for views that clip to its bounds.
11+
case clipBegin = "clip_begin"
12+
13+
/// Pop the last Pushed region from the drawing context.
14+
/// Used after prossing every child of a view that clip to its bounds.
15+
case clipEnd = "clip_end"
16+
17+
/// These regions are redacted first, there is no way to avoid it.
18+
case redactSwiftUI = "redact_swiftui"
19+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#if canImport(UIKit) && !SENTRY_NO_UIKIT
2+
#if os(iOS) || os(tvOS)
3+
import Foundation
4+
import ObjectiveC.NSObjCRuntime
5+
import UIKit
6+
#if os(iOS)
7+
import WebKit
8+
#endif
9+
10+
@objcMembers
11+
public class SentryRedactViewHelper: NSObject {
12+
private static var associatedRedactObjectHandle: UInt8 = 0
13+
private static var associatedIgnoreObjectHandle: UInt8 = 0
14+
private static var associatedClipOutObjectHandle: UInt8 = 0
15+
private static var associatedSwiftUIRedactObjectHandle: UInt8 = 0
16+
17+
override private init() {}
18+
19+
static func maskView(_ view: UIView) {
20+
objc_setAssociatedObject(view, &associatedRedactObjectHandle, true, .OBJC_ASSOCIATION_ASSIGN)
21+
}
22+
23+
static func shouldMaskView(_ view: UIView) -> Bool {
24+
(objc_getAssociatedObject(view, &associatedRedactObjectHandle) as? NSNumber)?.boolValue ?? false
25+
}
26+
27+
static func shouldUnmask(_ view: UIView) -> Bool {
28+
(objc_getAssociatedObject(view, &associatedIgnoreObjectHandle) as? NSNumber)?.boolValue ?? false
29+
}
30+
31+
static func unmaskView(_ view: UIView) {
32+
objc_setAssociatedObject(view, &associatedIgnoreObjectHandle, true, .OBJC_ASSOCIATION_ASSIGN)
33+
}
34+
35+
static func shouldClipOut(_ view: UIView) -> Bool {
36+
(objc_getAssociatedObject(view, &associatedClipOutObjectHandle) as? NSNumber)?.boolValue ?? false
37+
}
38+
39+
static public func clipOutView(_ view: UIView) {
40+
objc_setAssociatedObject(view, &associatedClipOutObjectHandle, true, .OBJC_ASSOCIATION_ASSIGN)
41+
}
42+
43+
static func shouldRedactSwiftUI(_ view: UIView) -> Bool {
44+
(objc_getAssociatedObject(view, &associatedSwiftUIRedactObjectHandle) as? NSNumber)?.boolValue ?? false
45+
}
46+
47+
static public func maskSwiftUI(_ view: UIView) {
48+
objc_setAssociatedObject(view, &associatedSwiftUIRedactObjectHandle, true, .OBJC_ASSOCIATION_ASSIGN)
49+
}
50+
}
51+
52+
#endif
53+
#endif

0 commit comments

Comments
 (0)