@@ -136,35 +136,113 @@ class NullDiagnosticConsumer : public DiagnosticConsumer {
136
136
// / current file.
137
137
class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
138
138
public:
139
+ class Subconsumer ;
140
+
141
+ // / Given a vector of subconsumers, return the most specific
142
+ // / DiagnosticConsumer for that vector. That will be a
143
+ // / FileSpecificDiagnosticConsumer if the vector has > 1 subconsumer, the
144
+ // / subconsumer itself if the vector has just one, or a null pointer if there
145
+ // / are no subconsumers. Takes ownership of the DiagnosticConsumers specified
146
+ // / in \p subconsumers.
147
+ static std::unique_ptr<DiagnosticConsumer>
148
+ consolidateSubconsumers (SmallVectorImpl<Subconsumer> &subconsumers);
149
+
139
150
// / A diagnostic consumer, along with the name of the buffer that it should
140
- // / be associated with. An empty string means that a consumer is not
141
- // / associated with any particular buffer, and should only receive diagnostics
142
- // / that are not in any of the other consumers' files.
143
- // / A null pointer for the DiagnosticConsumer means that diagnostics for this
144
- // / file should not be emitted.
145
- using ConsumerPair =
146
- std::pair<std::string, std::unique_ptr<DiagnosticConsumer>>;
151
+ // / be associated with.
152
+ class Subconsumer {
153
+ friend std::unique_ptr<DiagnosticConsumer>
154
+ FileSpecificDiagnosticConsumer::consolidateSubconsumers (
155
+ SmallVectorImpl<Subconsumer> &subconsumers);
156
+
157
+ // / The name of the input file that a consumer and diagnostics should
158
+ // / be associated with. An empty string means that a consumer is not
159
+ // / associated with any particular buffer, and should only receive
160
+ // / diagnostics that are not in any of the other consumers' files.
161
+ std::string inputFileName;
162
+
163
+ // / The consumer (if any) for diagnostics associated with the inputFileName.
164
+ // / A null pointer for the DiagnosticConsumer means that diagnostics for
165
+ // / this file should not be emitted.
166
+ std::unique_ptr<DiagnosticConsumer> consumer;
167
+
168
+ // Has this subconsumer ever handled a diagnostic that is an error?
169
+ bool hasAnErrorBeenConsumed = false ;
170
+
171
+ public:
172
+ std::string getInputFileName () const { return inputFileName; }
173
+
174
+ DiagnosticConsumer *getConsumer () const { return consumer.get (); }
175
+
176
+ Subconsumer (std::string inputFileName,
177
+ std::unique_ptr<DiagnosticConsumer> consumer)
178
+ : inputFileName(inputFileName), consumer(std::move(consumer)) {}
179
+
180
+ void handleDiagnostic (SourceManager &SM, SourceLoc Loc,
181
+ DiagnosticKind Kind,
182
+ StringRef FormatString,
183
+ ArrayRef<DiagnosticArgument> FormatArgs,
184
+ const DiagnosticInfo &Info) {
185
+ if (!getConsumer ())
186
+ return ;
187
+ hasAnErrorBeenConsumed |= Kind == DiagnosticKind::Error;
188
+ getConsumer ()->handleDiagnostic (SM, Loc, Kind, FormatString, FormatArgs,
189
+ Info);
190
+ }
191
+
192
+ void informDriverOfIncompleteBatchModeCompilation () {
193
+ if (!hasAnErrorBeenConsumed && getConsumer ())
194
+ getConsumer ()->informDriverOfIncompleteBatchModeCompilation ();
195
+ }
196
+ };
147
197
148
198
private:
149
199
// / All consumers owned by this FileSpecificDiagnosticConsumer.
150
- const SmallVector<ConsumerPair , 4 > SubConsumers ;
200
+ SmallVector<Subconsumer , 4 > Subconsumers ;
151
201
152
202
public:
153
- // The commented-out consts are there because the data does not change
154
- // but the swap method gets called on this structure.
155
- struct ConsumerSpecificInformation {
203
+ class ConsumerAndRange {
204
+ private:
205
+ // / The range of SourceLoc's for which diagnostics should be directed to
206
+ // / this subconsumer.
207
+ // / Should be const but then the sort won't compile.
156
208
/* const*/ CharSourceRange range;
157
- // / The DiagnosticConsumer may be empty if those diagnostics are not to be
158
- // / emitted.
159
- DiagnosticConsumer * /* const*/ consumer;
160
- bool hasAnErrorBeenEmitted = false ;
161
-
162
- ConsumerSpecificInformation (const CharSourceRange range,
163
- DiagnosticConsumer *const consumer)
164
- : range(range), consumer(consumer) {}
209
+
210
+ // / Index into Subconsumers vector for this subconsumer.
211
+ // / Should be const but then the sort won't compile.
212
+ /* const*/ unsigned subconsumerIndex;
213
+
214
+ public:
215
+ unsigned getSubconsumerIndex () const { return subconsumerIndex; }
216
+
217
+ ConsumerAndRange (const CharSourceRange range, unsigned subconsumerIndex)
218
+ : range(range), subconsumerIndex(subconsumerIndex) {}
219
+
220
+ // / Compare according to range:
221
+ bool operator <(const ConsumerAndRange &right) const {
222
+ auto compare = std::less<const char *>();
223
+ return compare (getRawLoc (range.getEnd ()).getPointer (),
224
+ getRawLoc (right.range .getEnd ()).getPointer ());
225
+ }
226
+
227
+ // / Overlaps by range:
228
+ bool overlaps (const ConsumerAndRange &other) const {
229
+ return range.overlaps (other.range );
230
+ }
231
+
232
+ // / Does my range end after \p loc?
233
+ bool endsAfter (const SourceLoc loc) const {
234
+ auto compare = std::less<const char *>();
235
+ return compare (getRawLoc (range.getEnd ()).getPointer (),
236
+ getRawLoc (loc).getPointer ());
237
+ }
238
+
239
+ bool contains (const SourceLoc loc) const { return range.contains (loc); }
165
240
};
166
241
167
242
private:
243
+ Subconsumer &operator [](const ConsumerAndRange &consumerAndRange) {
244
+ return Subconsumers[consumerAndRange.getSubconsumerIndex ()];
245
+ }
168
246
// / The consumers owned by this FileSpecificDiagnosticConsumer, sorted by
169
247
// / the end locations of each file so that a lookup by position can be done
170
248
// / using binary search.
@@ -173,8 +251,8 @@ class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
173
251
// / This allows diagnostics to be emitted before files are actually opened,
174
252
// / as long as they don't have source locations.
175
253
// /
176
- // / \see #consumerSpecificInformationForLocation
177
- SmallVector<ConsumerSpecificInformation , 4 > ConsumersOrderedByRange;
254
+ // / \see #subconsumerForLocation
255
+ SmallVector<ConsumerAndRange , 4 > ConsumersOrderedByRange;
178
256
179
257
// / Indicates which consumer to send Note diagnostics too.
180
258
// /
@@ -183,19 +261,18 @@ class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
183
261
// /
184
262
// / If None, Note diagnostics are sent to every consumer.
185
263
// / If null, diagnostics are suppressed.
186
- Optional<ConsumerSpecificInformation *>
187
- ConsumerSpecificInfoForSubsequentNotes = None;
264
+ Optional<Subconsumer *> SubconsumerForSubsequentNotes = None;
188
265
189
266
bool HasAnErrorBeenConsumed = false ;
190
267
191
- public:
192
268
// / Takes ownership of the DiagnosticConsumers specified in \p consumers.
193
269
// /
194
270
// / There must not be two consumers for the same file (i.e., having the same
195
271
// / buffer name).
196
272
explicit FileSpecificDiagnosticConsumer (
197
- SmallVectorImpl<ConsumerPair > &consumers);
273
+ SmallVectorImpl<Subconsumer > &consumers);
198
274
275
+ public:
199
276
void handleDiagnostic (SourceManager &SM, SourceLoc Loc,
200
277
DiagnosticKind Kind,
201
278
StringRef FormatString,
@@ -209,16 +286,15 @@ class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
209
286
// / Xcode will only see an error for a particular primary in that primary's
210
287
// / serialized diagnostics file. So, tell the subconsumers to inform the
211
288
// / driver of incomplete batch mode compilation.
212
- void tellSubconsumersToInformDriverOfIncompleteBatchModeCompilation () const ;
289
+ void tellSubconsumersToInformDriverOfIncompleteBatchModeCompilation ();
213
290
214
291
void computeConsumersOrderedByRange (SourceManager &SM);
215
292
216
293
// / Returns nullptr if diagnostic is to be suppressed,
217
294
// / None if diagnostic is to be distributed to every consumer,
218
295
// / a particular consumer if diagnostic goes there.
219
- Optional<ConsumerSpecificInformation *>
220
- consumerSpecificInformationForLocation (SourceManager &SM,
221
- SourceLoc loc) const ;
296
+ Optional<FileSpecificDiagnosticConsumer::Subconsumer *>
297
+ subconsumerForLocation (SourceManager &SM, SourceLoc loc);
222
298
};
223
299
224
300
} // end namespace swift
0 commit comments