@@ -70,8 +70,10 @@ extension SerializedDiagnostics {
70
70
public var level : Level
71
71
/// The location the diagnostic was emitted at in the source file.
72
72
public var location : SourceLocation ?
73
- /// The diagnostic category. Currently only Clang emits this.
73
+ /// The diagnostic category.
74
74
public var category : String ?
75
+ /// The diagnostic category documentation URL.
76
+ public var categoryURL : String ?
75
77
/// The corresponding diagnostic command-line flag. Currently only Clang emits this.
76
78
public var flag : String ?
77
79
/// Ranges in the source file associated with the diagnostic.
@@ -82,11 +84,12 @@ extension SerializedDiagnostics {
82
84
fileprivate init ( records: [ SerializedDiagnostics . OwnedRecord ] ,
83
85
filenameMap: [ UInt64 : String ] ,
84
86
flagMap: [ UInt64 : String ] ,
85
- categoryMap: [ UInt64 : String ] ) throws {
87
+ categoryMap: CategoryMap ) throws {
86
88
var text : String ? = nil
87
89
var level : Level ? = nil
88
90
var location : SourceLocation ? = nil
89
91
var category : String ? = nil
92
+ var categoryURL : String ? = nil
90
93
var flag : String ? = nil
91
94
var ranges : [ ( SourceLocation , SourceLocation ) ] = [ ]
92
95
var fixIts : [ FixIt ] = [ ]
@@ -103,7 +106,14 @@ extension SerializedDiagnostics {
103
106
level = Level ( rawValue: record. fields [ 0 ] )
104
107
location = SourceLocation ( fields: record. fields [ 1 ... 4 ] ,
105
108
filenameMap: filenameMap)
106
- category = categoryMap [ record. fields [ 5 ] ]
109
+
110
+ if let categoryEntry = categoryMap [ record. fields [ 5 ] ] {
111
+ category = categoryEntry. text
112
+ categoryURL = categoryEntry. url
113
+ } else {
114
+ category = nil
115
+ categoryURL = nil
116
+ }
107
117
flag = flagMap [ record. fields [ 6 ] ]
108
118
109
119
case . sourceRange:
@@ -142,6 +152,7 @@ extension SerializedDiagnostics {
142
152
self . level = level
143
153
self . location = location
144
154
self . category = category
155
+ self . categoryURL = categoryURL
145
156
self . flag = flag
146
157
self . fixIts = fixIts
147
158
self . ranges = ranges
@@ -185,6 +196,8 @@ extension SerializedDiagnostics.Diagnostic: UnsafeSendable {}
185
196
#endif
186
197
187
198
extension SerializedDiagnostics {
199
+ typealias CategoryMap = [ UInt64 : ( text: String , url: String ? ) ]
200
+
188
201
private struct Reader : BitstreamVisitor {
189
202
var diagnosticRecords : [ [ OwnedRecord ] ] = [ ]
190
203
var activeBlocks : [ BlockID ] = [ ]
@@ -194,7 +207,7 @@ extension SerializedDiagnostics {
194
207
var versionNumber : Int ? = nil
195
208
var filenameMap = [ UInt64: String] ( )
196
209
var flagMap = [ UInt64: String] ( )
197
- var categoryMap = [ UInt64 : String ] ( )
210
+ var categoryMap = CategoryMap ( )
198
211
199
212
func validate( signature: Bitcode . Signature ) throws {
200
213
guard signature == . init( string: " DIAG " ) else { throw Error . badMagic }
@@ -244,9 +257,28 @@ extension SerializedDiagnostics {
244
257
case . blob( let categoryBlob) = record. payload
245
258
else { throw Error . malformedRecord }
246
259
247
- let categoryText = String ( decoding: categoryBlob, as: UTF8 . self)
260
+ let categoryTextBlob = String ( decoding: categoryBlob, as: UTF8 . self)
248
261
let categoryID = record. fields [ 0 ]
249
- categoryMap [ categoryID] = categoryText
262
+
263
+ let categoryTextLength = Int ( record. fields [ 1 ] )
264
+ if categoryTextLength > categoryTextBlob. count {
265
+ throw Error . malformedRecord
266
+ }
267
+
268
+ let categoryText = String ( categoryTextBlob. prefix ( categoryTextLength) )
269
+ let afterCategoryText = categoryTextBlob. index (
270
+ categoryTextBlob. startIndex,
271
+ offsetBy: categoryTextLength
272
+ )
273
+ let categoryURL : String ?
274
+ if afterCategoryText < categoryTextBlob. endIndex &&
275
+ categoryTextBlob [ afterCategoryText] == " @ " {
276
+ categoryURL = String ( categoryTextBlob [ afterCategoryText... ] . dropFirst ( ) )
277
+ } else {
278
+ categoryURL = nil
279
+ }
280
+
281
+ categoryMap [ categoryID] = ( categoryText, categoryURL)
250
282
case . flag:
251
283
guard record. fields. count == 2 ,
252
284
case . blob( let flagBlob) = record. payload
0 commit comments