@@ -24,14 +24,15 @@ actor DiagnosticReportManager {
24
24
private nonisolated var keys : sourcekitd_keys { return sourcekitd. keys }
25
25
private nonisolated var requests : sourcekitd_requests { return sourcekitd. requests }
26
26
27
- /// The cache that stores reports for snapshot ids
27
+ /// The cache that stores reports for snapshot id and buildSettings
28
28
///
29
29
/// Conceptually, this is a dictionary. To prevent excessive memory usage we
30
30
/// only keep `cacheSize` entries within the array. Older entries are at the
31
31
/// end of the list, newer entries at the front.
32
32
private var reportCache :
33
33
[ (
34
34
snapshotID: DocumentSnapshot . ID ,
35
+ buildSettings: SwiftCompileCommand ? ,
35
36
report: RelatedFullDocumentDiagnosticReport
36
37
) ] = [ ]
37
38
@@ -55,30 +56,41 @@ actor DiagnosticReportManager {
55
56
func diagnosticReport( for snapshot: DocumentSnapshot , buildSettings: SwiftCompileCommand ? , useCache: Bool = false )
56
57
async throws -> RelatedFullDocumentDiagnosticReport
57
58
{
58
- if useCache, let report = report ( for: snapshot. id) {
59
+ if useCache, let report = report ( for: snapshot. id, buildSettings : buildSettings ) {
59
60
return report
60
61
}
61
- guard let buildSettings = buildSettings, !buildSettings. isFallback else {
62
+ guard let buildSettings = buildSettings else {
63
+ logger. log (
64
+ " Producing syntactic diagnostics from the built-in swift-syntax because we don't have buildSettings "
65
+ )
66
+ // If we don't have build settings,
67
+ // sourcekitd won't be able to give us accurate semantic diagnostics.
68
+ // Fall back to providing syntactic diagnostics from the built-in
69
+ // swift-syntax. That's the best we can do for now.
70
+ let report = try await requestFallbackReport ( with: snapshot)
71
+ setReport ( for: snapshot. id, buildSettings: nil , report: report)
72
+ return report
73
+ }
74
+ guard !buildSettings. isFallback else {
62
75
logger. log (
63
76
" Producing syntactic diagnostics from the built-in swift-syntax because we have fallback arguments "
64
77
)
65
- // If we don't have build settings or we only have fallback build settings,
78
+ // If we only have fallback build settings,
66
79
// sourcekitd won't be able to give us accurate semantic diagnostics.
67
80
// Fall back to providing syntactic diagnostics from the built-in
68
81
// swift-syntax. That's the best we can do for now.
69
- let report = try await fallbackReport ( with: snapshot)
70
- setReport ( for: snapshot. id, report: report)
82
+ let report = try await requestFallbackReport ( with: snapshot)
83
+ setReport ( for: snapshot. id, buildSettings : buildSettings , report: report)
71
84
return report
72
85
}
73
-
74
- let report = try await report ( with: snapshot, compilerArgs: buildSettings. compilerArgs)
75
- setReport ( for: snapshot. id, report: report)
86
+ let report = try await requestReport ( with: snapshot, compilerArgs: buildSettings. compilerArgs)
87
+ setReport ( for: snapshot. id, buildSettings: buildSettings, report: report)
76
88
return report
77
89
}
78
90
}
79
91
80
92
private extension DiagnosticReportManager {
81
- func report ( with snapshot: DocumentSnapshot , compilerArgs: [ String ] ) async throws
93
+ func requestReport ( with snapshot: DocumentSnapshot , compilerArgs: [ String ] ) async throws
82
94
-> LanguageServerProtocol . RelatedFullDocumentDiagnosticReport
83
95
{
84
96
try Task . checkCancellation ( )
@@ -114,7 +126,7 @@ private extension DiagnosticReportManager {
114
126
return RelatedFullDocumentDiagnosticReport ( items: diagnostics)
115
127
}
116
128
117
- func fallbackReport ( with snapshot: DocumentSnapshot ) async throws
129
+ func requestFallbackReport ( with snapshot: DocumentSnapshot ) async throws
118
130
-> LanguageServerProtocol . RelatedFullDocumentDiagnosticReport
119
131
{
120
132
// If we don't have build settings or we only have fallback build settings,
@@ -133,17 +145,23 @@ private extension DiagnosticReportManager {
133
145
return RelatedFullDocumentDiagnosticReport ( items: diagnostics)
134
146
}
135
147
136
- /// The report for the given document snapshot.
137
- func report( for snapshotID: DocumentSnapshot . ID ) -> RelatedFullDocumentDiagnosticReport ? {
138
- return reportCache. first ( where: { $0. snapshotID == snapshotID } ) ? . report
148
+ /// The report for the given document snapshot and buildSettings.
149
+ func report( for snapshotID: DocumentSnapshot . ID , buildSettings: SwiftCompileCommand ? )
150
+ -> RelatedFullDocumentDiagnosticReport ?
151
+ {
152
+ return reportCache. first ( where: { $0. snapshotID == snapshotID && $0. buildSettings == buildSettings } ) ? . report
139
153
}
140
154
141
- /// Set the report for the given document snapshot.
155
+ /// Set the report for the given document snapshot and buildSettings .
142
156
///
143
157
/// If we are already storing `cacheSize` many reports, the oldest one
144
158
/// will get discarded.
145
- func setReport( for snapshotID: DocumentSnapshot . ID , report: RelatedFullDocumentDiagnosticReport ) {
146
- reportCache. insert ( ( snapshotID, report) , at: 0 )
159
+ func setReport(
160
+ for snapshotID: DocumentSnapshot . ID ,
161
+ buildSettings: SwiftCompileCommand ? ,
162
+ report: RelatedFullDocumentDiagnosticReport
163
+ ) {
164
+ reportCache. insert ( ( snapshotID, buildSettings, report) , at: 0 )
147
165
148
166
// Remove any reports for old versions of this document.
149
167
reportCache. removeAll ( where: { $0. snapshotID < snapshotID } )
0 commit comments