1616
1717import Swift
1818
19+ @_spi ( Formatting)
1920public struct BacktraceJSONFormatterOptions : OptionSet {
2021 public let rawValue : Int
2122
@@ -28,18 +29,21 @@ public struct BacktraceJSONFormatterOptions: OptionSet {
2829 public static let sanitize = BacktraceJSONFormatterOptions ( rawValue: 1 <<2 )
2930 public static let mentionedImages = BacktraceJSONFormatterOptions ( rawValue: 1 <<3 )
3031 public static let allThreads = BacktraceJSONFormatterOptions ( rawValue: 1 <<4 )
32+ public static let images = BacktraceJSONFormatterOptions ( rawValue: 1 <<5 )
3133}
3234
33- extension BacktraceJSONFormatterOptions {
35+ internal extension BacktraceJSONFormatterOptions {
3436 // this is not the form we want but will do for now
3537 // we are going to turn this into an OptionSet or similar
3638 var showAllRegisters : Bool { contains ( . allRegisters) }
3739 var shouldDemangle : Bool { contains ( . demangle) }
3840 var shouldSanitize : Bool { contains ( . sanitize) }
3941 var showMentionedImages : Bool { contains ( . mentionedImages) }
4042 var showAllThreads : Bool { contains ( . allThreads) }
43+ var showImages : Bool { contains ( . images) }
4144}
4245
46+ @_spi ( Formatting)
4347public protocol BacktraceJSONWriter {
4448 func write( _ string: String , flush: Bool )
4549 func writeln( _ string: String , flush: Bool )
@@ -73,7 +77,7 @@ Writer: BacktraceJSONWriter> {
7377 }
7478}
7579
76- extension BacktraceJSONFormatter {
80+ internal extension BacktraceJSONFormatter {
7781 func write( _ string: String , flush: Bool ) {
7882 writer. write ( string, flush: flush)
7983 }
@@ -96,26 +100,16 @@ extension BacktraceJSONFormatter {
96100 func getFaultAddress( ) -> String ? {
97101 crashLog. faultAddress
98102 }
103+ }
99104
100- // settings for the output format
101- func getShouldShowAllThreads( ) -> Bool {
102- options. showAllThreads
103- }
104-
105- func getShouldShowAllRegisters( ) -> Bool {
106- options. showAllRegisters
107- }
108-
109- func getShouldDemangle( ) -> Bool {
110- options. shouldDemangle
111- }
112-
113- func getShouldSanitize( ) -> Bool {
114- options. shouldDemangle
115- }
116-
117- func getShowMentionedImages( ) -> Bool {
118- options. showMentionedImages
105+ @_spi ( Formatting)
106+ public extension BacktraceJSONFormatter {
107+ mutating func writeCrashLog( now: String ) {
108+ writePreamble ( now: now)
109+ writeThreads ( )
110+ writeCapturedMemory ( )
111+ writeImages ( )
112+ writeFooter ( )
119113 }
120114}
121115
@@ -145,9 +139,8 @@ public extension BacktraceJSONFormatter {
145139 mutating func writeThreads( ) {
146140
147141 write ( #", "threads": [ "# , flush: false )
148- let showAllThreads = getShouldShowAllThreads ( )
149142
150- let threads = crashLog. threads. filter { showAllThreads || $0. crashed }
143+ let threads = crashLog. threads. filter { options . showAllThreads || $0. crashed }
151144
152145 var first = true
153146 for thread in threads {
@@ -162,12 +155,17 @@ public extension BacktraceJSONFormatter {
162155
163156 write ( " ] " , flush: false )
164157
165- if !showAllThreads && crashLog. threads. count > 1 {
158+ if !options . showAllThreads && crashLog. threads. count > 1 {
166159 write ( " , \" omittedThreads \" : \( crashLog. threads. count - 1 ) " , flush: false )
167160 }
168161
169- if let images = crashLog. images, getShowMentionedImages ( ) {
162+ // if omittedImages is nil, try to calculate it.
163+ if let images = crashLog. images,
164+ options. showMentionedImages,
165+ self . crashLog. omittedImages == nil {
166+
170167 self . crashLog. omittedImages = images. count - mentionedImages. count
168+
171169 }
172170 }
173171
@@ -176,7 +174,7 @@ public extension BacktraceJSONFormatter {
176174 if !options. shouldSanitize, let capturedMemory = crashLog. capturedMemory {
177175 write ( #", "capturedMemory": {"# , flush: false )
178176 var first = true
179- for (address, bytes) in capturedMemory {
177+ for (address, bytes) in capturedMemory. sorted ( by : < ) {
180178 if first {
181179 first = false
182180 } else {
@@ -190,10 +188,10 @@ public extension BacktraceJSONFormatter {
190188
191189 // note: this updates the crash log with the ommitted image count
192190 func writeImages( ) {
193- if let images = crashLog. images {
191+ if options . showImages , let images = crashLog. images {
194192 var imagesToWrite = images
195193
196- if getShowMentionedImages ( ) {
194+ if options . showMentionedImages {
197195 let mentioned =
198196 images. enumerated ( )
199197 . filter { mentionedImages. contains ( $0. 0 ) }
@@ -220,11 +218,11 @@ public extension BacktraceJSONFormatter {
220218 func writeFooter( ) {
221219 write ( " , \" backtraceTime \" : \( crashLog. backtraceTime) " , flush: false )
222220
223- writeln ( " } " , flush: false )
221+ write ( " } " , flush: false )
224222 }
225223}
226224
227- extension BacktraceJSONFormatter {
225+ internal extension BacktraceJSONFormatter {
228226 func writeThreadRegisters( thread: Log . Thread ) {
229227 guard let registers = thread. registers else { return }
230228
@@ -264,7 +262,7 @@ extension BacktraceJSONFormatter {
264262 write ( #""crashed": true, "# , flush: false )
265263 }
266264
267- if getShouldShowAllRegisters ( ) || isCrashingThread {
265+ if options . showAllRegisters || isCrashingThread {
268266 write ( #""registers": {"# , flush: false )
269267 writeThreadRegisters ( thread: thread)
270268 write ( " }, " , flush: false )
@@ -302,7 +300,7 @@ extension BacktraceJSONFormatter {
302300 , " offset " : \( frame. offset ?? 0 )
303301 """ , flush: false )
304302
305- if getShouldDemangle ( ) {
303+ if options . shouldDemangle , let demangledName = frame . demangledName {
306304 let formattedOffset : String
307305 if ( frame. offset ?? 0 ) > 0 {
308306 formattedOffset = " + \( frame. offset!) "
@@ -313,7 +311,7 @@ extension BacktraceJSONFormatter {
313311 }
314312
315313 write ( """
316- , " description " : \" \( escapeJSON ( symbol ) ) \( formattedOffset) \"
314+ , " description " : \" \( escapeJSON ( demangledName ) ) \( formattedOffset) \"
317315 """ , flush: false )
318316 }
319317
@@ -322,7 +320,7 @@ extension BacktraceJSONFormatter {
322320 }
323321
324322 if var sourceLocation = frame. sourceLocation {
325- if getShouldSanitize ( ) {
323+ if options . shouldSanitize {
326324 sourceLocation. file = sanitizePath ( sourceLocation. file)
327325 }
328326 write ( #", "sourceLocation": { "# , flush: false )
@@ -343,7 +341,7 @@ extension BacktraceJSONFormatter {
343341
344342 write ( " } " , flush: false )
345343
346- if getShowMentionedImages ( ) {
344+ if options . showMentionedImages {
347345 for frame in thread. frames {
348346 if let imageName = frame. image,
349347 let imageIndex = crashLog. images?
0 commit comments