Skip to content

Commit cb3af7c

Browse files
committed
factoring and commenting
1 parent b4b3b0f commit cb3af7c

File tree

3 files changed

+93
-43
lines changed

3 files changed

+93
-43
lines changed

include/swift/AST/DiagnosticConsumer.h

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -136,41 +136,57 @@ class NullDiagnosticConsumer : public DiagnosticConsumer {
136136
/// current file.
137137
class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
138138
public:
139+
class Subconsumer;
140+
141+
/// Given a vector of subconsumers, return the most specific DiagnosticConsumer for that vector.
142+
/// That will be a FileSpecificDiagnosticConsumer if the vector has > 1 subconsumer,
143+
/// the subconsumer itself if the vector has just one, or a null pointer if there are no subconsumers.
144+
/// Takes ownership of the DiagnosticConsumers specified in \p subconsumers.
145+
static std::unique_ptr<DiagnosticConsumer> consolidateSubconsumers(SmallVectorImpl<Subconsumer> &subconsumers);
146+
139147
/// A diagnostic consumer, along with the name of the buffer that it should
140148
/// be associated with.
141149
class Subconsumer {
142-
public:
143-
/// The name of the buffer that a consumer should
150+
friend std::unique_ptr<DiagnosticConsumer> FileSpecificDiagnosticConsumer::consolidateSubconsumers(SmallVectorImpl<Subconsumer> &subconsumers);
151+
152+
/// The name of the input file that a consumer and diagnostics should
144153
/// be associated with. An empty string means that a consumer is not
145154
/// associated with any particular buffer, and should only receive
146155
/// diagnostics that are not in any of the other consumers' files.
147-
std::string bufferName;
148-
156+
std::string inputFileName;
157+
158+
/// The consumer (if any) for diagnostics associated with the inputFileName.
149159
/// A null pointer for the DiagnosticConsumer means that diagnostics for
150160
/// this file should not be emitted.
151161
std::unique_ptr<DiagnosticConsumer> consumer;
152-
162+
153163
// Has this subconsumer ever handled a diagnostic that is an error?
154-
bool handledError = false;
164+
bool hasAnErrorBeenConsumed = false;
155165

156-
Subconsumer(std::string bufferName,
166+
167+
public:
168+
std::string getInputFileName() const { return inputFileName; }
169+
170+
DiagnosticConsumer *getConsumer() const { return consumer.get(); }
171+
172+
Subconsumer(std::string inputFileName,
157173
std::unique_ptr<DiagnosticConsumer> consumer)
158-
: bufferName(bufferName), consumer(std::move(consumer)) {}
174+
: inputFileName(inputFileName), consumer(std::move(consumer)) {}
159175

160176
void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
161177
DiagnosticKind Kind,
162178
StringRef FormatString,
163179
ArrayRef<DiagnosticArgument> FormatArgs,
164180
const DiagnosticInfo &Info) {
165-
if (!consumer)
181+
if (!getConsumer())
166182
return; // Suppress non-primary diagnostic in batch mode.
167-
handledError |= Kind == DiagnosticKind::Error;
168-
consumer.get()->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info);
183+
hasAnErrorBeenConsumed |= Kind == DiagnosticKind::Error;
184+
getConsumer()->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info);
169185
}
170186

171187
void informDriverOfIncompleteBatchModeCompilation() {
172-
if (!handledError && consumer)
173-
consumer.get()->informDriverOfIncompleteBatchModeCompilation();
188+
if (!hasAnErrorBeenConsumed && getConsumer())
189+
getConsumer()->informDriverOfIncompleteBatchModeCompilation();
174190
}
175191
};
176192

@@ -181,19 +197,46 @@ class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
181197
public:
182198
// The commented-out consts are there because the data does not change
183199
// but the swap method gets called on this structure.
184-
struct ConsumerSpecificInformation {
200+
class ConsumerSpecificInformation {
201+
private:
202+
/// The range of SourceLoc's for which diagnostics should be directed to
203+
/// this subconsumer.
185204
/*const*/ CharSourceRange range;
186-
187-
/// Index into Subconsumers vector.
188-
unsigned subconsumerIndex;
189205

206+
/// Index into Subconsumers vector for this subconsumer.
207+
/*const*/ unsigned subconsumerIndex;
208+
209+
public:
190210
ConsumerSpecificInformation(const CharSourceRange range,
191211
unsigned subconsumerIndex)
192-
: range(range), subconsumerIndex(subconsumerIndex) {}
193-
212+
: range(range), subconsumerIndex(subconsumerIndex) {}
213+
194214
Subconsumer &subconsumer(FileSpecificDiagnosticConsumer &c) const {
195215
return c.Subconsumers[subconsumerIndex];
196216
}
217+
218+
/// Compare according to range:
219+
bool operator < (const ConsumerSpecificInformation &right) const {
220+
auto compare = std::less<const char *>();
221+
return compare(getRawLoc( range.getEnd()).getPointer(),
222+
getRawLoc(right.range.getEnd()).getPointer());
223+
}
224+
225+
/// Overlaps by range:
226+
bool overlaps(const ConsumerSpecificInformation &other) const {
227+
return range.overlaps(other.range);
228+
}
229+
230+
/// Does my range end after \p loc?
231+
bool endsAfter(const SourceLoc loc) const {
232+
auto compare = std::less<const char *>();
233+
return compare(getRawLoc(range.getEnd()).getPointer(),
234+
getRawLoc(loc).getPointer());
235+
}
236+
237+
bool contains(const SourceLoc loc) const {
238+
return range.contains(loc);
239+
}
197240
};
198241

199242
private:
@@ -219,15 +262,19 @@ class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
219262
ConsumerSpecificInfoForSubsequentNotes = None;
220263

221264
bool HasAnErrorBeenConsumed = false;
222-
223-
public:
265+
266+
224267
/// Takes ownership of the DiagnosticConsumers specified in \p consumers.
225268
///
226269
/// There must not be two consumers for the same file (i.e., having the same
227270
/// buffer name).
228271
explicit FileSpecificDiagnosticConsumer(
229-
SmallVectorImpl<Subconsumer> &consumers);
272+
SmallVectorImpl<Subconsumer> &consumers);
230273

274+
public:
275+
276+
277+
231278
void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
232279
DiagnosticKind Kind,
233280
StringRef FormatString,

lib/AST/DiagnosticConsumer.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,32 @@ static bool hasDuplicateFileNames(
3838
ArrayRef<FileSpecificDiagnosticConsumer::Subconsumer> subconsumers) {
3939
llvm::StringSet<> seenFiles;
4040
for (const auto &subconsumer : subconsumers) {
41-
if (subconsumer.bufferName.empty()) {
41+
if (subconsumer.getInputFileName().empty()) {
4242
// We can handle multiple subconsumers that aren't associated with any
4343
// file, because they only collect diagnostics that aren't in any of the
4444
// special files. This isn't an important use case to support, but also
4545
// SmallSet doesn't handle empty strings anyway!
4646
continue;
4747
}
4848

49-
bool isUnique = seenFiles.insert(subconsumer.bufferName).second;
49+
bool isUnique = seenFiles.insert(subconsumer.getInputFileName()).second;
5050
if (!isUnique)
5151
return true;
5252
}
5353
return false;
5454
}
5555

56+
std::unique_ptr<DiagnosticConsumer> FileSpecificDiagnosticConsumer::
57+
consolidateSubconsumers(SmallVectorImpl<Subconsumer> &subconsumers) {
58+
if (subconsumers.empty())
59+
return nullptr;
60+
if (subconsumers.size() == 1)
61+
return std::move(subconsumers.front()).consumer;
62+
// Cannot use return llvm::make_unique<FileSpecificDiagnosticConsumer>(subconsumers);
63+
// because the constructor is private.
64+
return std::unique_ptr<DiagnosticConsumer>(new FileSpecificDiagnosticConsumer(subconsumers));
65+
}
66+
5667
FileSpecificDiagnosticConsumer::FileSpecificDiagnosticConsumer(
5768
SmallVectorImpl<Subconsumer> &subconsumers)
5869
: Subconsumers(std::move(subconsumers)) {
@@ -67,11 +78,11 @@ void FileSpecificDiagnosticConsumer::computeConsumersOrderedByRange(
6778
// Look up each file's source range and add it to the "map" (to be sorted).
6879
for (const unsigned subconsumerIndex: indices(Subconsumers)) {
6980
const Subconsumer &subconsumer = Subconsumers[subconsumerIndex];
70-
if (subconsumer.bufferName.empty())
81+
if (subconsumer.getInputFileName().empty())
7182
continue;
7283

7384
Optional<unsigned> bufferID =
74-
SM.getIDForBufferIdentifier(subconsumer.bufferName);
85+
SM.getIDForBufferIdentifier(subconsumer.getInputFileName());
7586
assert(bufferID.hasValue() && "consumer registered for unknown file");
7687
CharSourceRange range = SM.getRangeForBuffer(bufferID.getValue());
7788
ConsumersOrderedByRange.emplace_back(
@@ -85,9 +96,7 @@ void FileSpecificDiagnosticConsumer::computeConsumersOrderedByRange(
8596
std::sort(ConsumersOrderedByRange.begin(), ConsumersOrderedByRange.end(),
8697
[](const ConsumerSpecificInformation &left,
8798
const ConsumerSpecificInformation &right) -> bool {
88-
auto compare = std::less<const char *>();
89-
return compare(getRawLoc(left.range.getEnd()).getPointer(),
90-
getRawLoc(right.range.getEnd()).getPointer());
99+
return left < right;
91100
});
92101

93102
// Check that the ranges are non-overlapping. If the files really are all
@@ -98,7 +107,7 @@ void FileSpecificDiagnosticConsumer::computeConsumersOrderedByRange(
98107
ConsumersOrderedByRange.end(),
99108
[](const ConsumerSpecificInformation &left,
100109
const ConsumerSpecificInformation &right) {
101-
return left.range.overlaps(right.range);
110+
return left.overlaps(right);
102111
}) &&
103112
"overlapping ranges despite having distinct files");
104113
}
@@ -122,10 +131,10 @@ FileSpecificDiagnosticConsumer::consumerSpecificInformationForLocation(
122131
// than trying to build a nonsensical map (and actually crashing since we
123132
// can't find buffers for the inputs).
124133
assert(!Subconsumers.empty());
125-
if (!SM.getIDForBufferIdentifier(Subconsumers.begin()->bufferName)
134+
if (!SM.getIDForBufferIdentifier(Subconsumers.begin()->getInputFileName())
126135
.hasValue()) {
127136
assert(llvm::none_of(Subconsumers, [&](const Subconsumer &subconsumer) {
128-
return SM.getIDForBufferIdentifier(subconsumer.bufferName).hasValue();
137+
return SM.getIDForBufferIdentifier(subconsumer.getInputFileName()).hasValue();
129138
}));
130139
return None;
131140
}
@@ -141,13 +150,11 @@ FileSpecificDiagnosticConsumer::consumerSpecificInformationForLocation(
141150
std::lower_bound(
142151
ConsumersOrderedByRange.begin(), ConsumersOrderedByRange.end(), loc,
143152
[](const ConsumerSpecificInformation &entry, SourceLoc loc) -> bool {
144-
auto compare = std::less<const char *>();
145-
return compare(getRawLoc(entry.range.getEnd()).getPointer(),
146-
getRawLoc(loc).getPointer());
153+
return entry.endsAfter(loc);
147154
});
148155

149156
if (possiblyContainingRangeIter != ConsumersOrderedByRange.end() &&
150-
possiblyContainingRangeIter->range.contains(loc)) {
157+
possiblyContainingRangeIter->contains(loc)) {
151158
return const_cast<ConsumerSpecificInformation *>(
152159
possiblyContainingRangeIter);
153160
}
@@ -191,7 +198,7 @@ bool FileSpecificDiagnosticConsumer::finishProcessing() {
191198
bool hadError = false;
192199
for (auto &subconsumer : Subconsumers)
193200
hadError |=
194-
subconsumer.consumer && subconsumer.consumer->finishProcessing();
201+
subconsumer.getConsumer() && subconsumer.getConsumer()->finishProcessing();
195202
return hadError;
196203
}
197204

lib/FrontendTool/FrontendTool.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,12 +1618,8 @@ createDispatchingDiagnosticConsumerIfNeeded(
16181618
return false;
16191619
});
16201620
}
1621-
1622-
if (subconsumers.empty())
1623-
return nullptr;
1624-
if (subconsumers.size() == 1)
1625-
return std::move(subconsumers.front()).consumer;
1626-
return llvm::make_unique<FileSpecificDiagnosticConsumer>(subconsumers);
1621+
1622+
return FileSpecificDiagnosticConsumer::consolidateSubconsumers(subconsumers);
16271623
}
16281624

16291625
/// Creates a diagnostic consumer that handles serializing diagnostics, based on

0 commit comments

Comments
 (0)