@@ -154,16 +154,27 @@ fileprivate extension String {
154
154
extension Diagnostic {
155
155
156
156
/// Creates a diagnostic from a sourcekitd response dictionary.
157
+ ///
158
+ /// `snapshot` is the snapshot of the document for which the diagnostics are generated.
159
+ /// `documentManager` is used to resolve positions of notes in secondary files.
157
160
init ? (
158
161
_ diag: SKDResponseDictionary ,
159
162
in snapshot: DocumentSnapshot ,
163
+ documentManager: DocumentManager ,
160
164
useEducationalNoteAsCode: Bool
161
165
) {
162
- // FIXME: this assumes that the diagnostics are all in the same file.
163
-
164
166
let keys = diag. sourcekitd. keys
165
167
let values = diag. sourcekitd. values
166
168
169
+ guard let filePath: String = diag [ keys. filePath] else {
170
+ logger. fault ( " Missing file path in diagnostic " )
171
+ return nil
172
+ }
173
+ guard filePath == snapshot. uri. pseudoPath else {
174
+ logger. error ( " Ignoring diagnostic from a different file: \( filePath) " )
175
+ return nil
176
+ }
177
+
167
178
guard let message: String = diag [ keys. description] ? . withFirstLetterUppercased ( ) else { return nil }
168
179
169
180
var range : Range < Position > ? = nil
@@ -237,7 +248,13 @@ extension Diagnostic {
237
248
if let sknotes: SKDResponseArray = diag [ keys. diagnostics] {
238
249
notes = [ ]
239
250
sknotes. forEach { ( _, sknote) -> Bool in
240
- guard let note = DiagnosticRelatedInformation ( sknote, in: snapshot) else { return true }
251
+ guard
252
+ let note = DiagnosticRelatedInformation (
253
+ sknote,
254
+ primaryDocumentSnapshot: snapshot,
255
+ documentManager: documentManager
256
+ )
257
+ else { return true }
241
258
notes? . append ( note)
242
259
return true
243
260
}
@@ -309,9 +326,28 @@ extension Diagnostic {
309
326
extension DiagnosticRelatedInformation {
310
327
311
328
/// Creates related information from a sourcekitd note response dictionary.
312
- init ? ( _ diag: SKDResponseDictionary , in snapshot: DocumentSnapshot ) {
329
+ ///
330
+ /// `primaryDocumentSnapshot` is the snapshot of the document for which the diagnostics are generated.
331
+ /// `documentManager` is used to resolve positions of notes in secondary files.
332
+ init ? ( _ diag: SKDResponseDictionary , primaryDocumentSnapshot: DocumentSnapshot , documentManager: DocumentManager ) {
313
333
let keys = diag. sourcekitd. keys
314
334
335
+ guard let filePath: String = diag [ keys. filePath] else {
336
+ logger. fault ( " Missing file path in related diagnostic information " )
337
+ return nil
338
+ }
339
+ let uri = DocumentURI ( filePath: filePath, isDirectory: false )
340
+ let snapshot : DocumentSnapshot
341
+ if filePath == primaryDocumentSnapshot. uri. pseudoPath {
342
+ snapshot = primaryDocumentSnapshot
343
+ } else if let inMemorySnapshot = try ? documentManager. latestSnapshot ( uri) {
344
+ snapshot = inMemorySnapshot
345
+ } else if let snapshotFromDisk = try ? DocumentSnapshot ( withContentsFromDisk: uri, language: . swift) {
346
+ snapshot = snapshotFromDisk
347
+ } else {
348
+ return nil
349
+ }
350
+
315
351
var position : Position ? = nil
316
352
if let line: Int = diag [ keys. line] ,
317
353
let utf8Column: Int = diag [ keys. column] ,
0 commit comments