mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
factoring and commenting
This commit is contained in:
@@ -136,41 +136,57 @@ public:
|
|||||||
/// current file.
|
/// current file.
|
||||||
class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
|
class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
|
||||||
public:
|
public:
|
||||||
|
class Subconsumer;
|
||||||
|
|
||||||
|
/// Given a vector of subconsumers, return the most specific DiagnosticConsumer for that vector.
|
||||||
|
/// That will be a FileSpecificDiagnosticConsumer if the vector has > 1 subconsumer,
|
||||||
|
/// the subconsumer itself if the vector has just one, or a null pointer if there are no subconsumers.
|
||||||
|
/// Takes ownership of the DiagnosticConsumers specified in \p subconsumers.
|
||||||
|
static std::unique_ptr<DiagnosticConsumer> consolidateSubconsumers(SmallVectorImpl<Subconsumer> &subconsumers);
|
||||||
|
|
||||||
/// A diagnostic consumer, along with the name of the buffer that it should
|
/// A diagnostic consumer, along with the name of the buffer that it should
|
||||||
/// be associated with.
|
/// be associated with.
|
||||||
class Subconsumer {
|
class Subconsumer {
|
||||||
public:
|
friend std::unique_ptr<DiagnosticConsumer> FileSpecificDiagnosticConsumer::consolidateSubconsumers(SmallVectorImpl<Subconsumer> &subconsumers);
|
||||||
/// The name of the buffer that a consumer should
|
|
||||||
|
/// The name of the input file that a consumer and diagnostics should
|
||||||
/// be associated with. An empty string means that a consumer is not
|
/// be associated with. An empty string means that a consumer is not
|
||||||
/// associated with any particular buffer, and should only receive
|
/// associated with any particular buffer, and should only receive
|
||||||
/// diagnostics that are not in any of the other consumers' files.
|
/// diagnostics that are not in any of the other consumers' files.
|
||||||
std::string bufferName;
|
std::string inputFileName;
|
||||||
|
|
||||||
|
/// The consumer (if any) for diagnostics associated with the inputFileName.
|
||||||
/// A null pointer for the DiagnosticConsumer means that diagnostics for
|
/// A null pointer for the DiagnosticConsumer means that diagnostics for
|
||||||
/// this file should not be emitted.
|
/// this file should not be emitted.
|
||||||
std::unique_ptr<DiagnosticConsumer> consumer;
|
std::unique_ptr<DiagnosticConsumer> consumer;
|
||||||
|
|
||||||
// Has this subconsumer ever handled a diagnostic that is an error?
|
// Has this subconsumer ever handled a diagnostic that is an error?
|
||||||
bool handledError = false;
|
bool hasAnErrorBeenConsumed = false;
|
||||||
|
|
||||||
Subconsumer(std::string bufferName,
|
|
||||||
|
public:
|
||||||
|
std::string getInputFileName() const { return inputFileName; }
|
||||||
|
|
||||||
|
DiagnosticConsumer *getConsumer() const { return consumer.get(); }
|
||||||
|
|
||||||
|
Subconsumer(std::string inputFileName,
|
||||||
std::unique_ptr<DiagnosticConsumer> consumer)
|
std::unique_ptr<DiagnosticConsumer> consumer)
|
||||||
: bufferName(bufferName), consumer(std::move(consumer)) {}
|
: inputFileName(inputFileName), consumer(std::move(consumer)) {}
|
||||||
|
|
||||||
void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
|
void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
|
||||||
DiagnosticKind Kind,
|
DiagnosticKind Kind,
|
||||||
StringRef FormatString,
|
StringRef FormatString,
|
||||||
ArrayRef<DiagnosticArgument> FormatArgs,
|
ArrayRef<DiagnosticArgument> FormatArgs,
|
||||||
const DiagnosticInfo &Info) {
|
const DiagnosticInfo &Info) {
|
||||||
if (!consumer)
|
if (!getConsumer())
|
||||||
return; // Suppress non-primary diagnostic in batch mode.
|
return; // Suppress non-primary diagnostic in batch mode.
|
||||||
handledError |= Kind == DiagnosticKind::Error;
|
hasAnErrorBeenConsumed |= Kind == DiagnosticKind::Error;
|
||||||
consumer.get()->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info);
|
getConsumer()->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void informDriverOfIncompleteBatchModeCompilation() {
|
void informDriverOfIncompleteBatchModeCompilation() {
|
||||||
if (!handledError && consumer)
|
if (!hasAnErrorBeenConsumed && getConsumer())
|
||||||
consumer.get()->informDriverOfIncompleteBatchModeCompilation();
|
getConsumer()->informDriverOfIncompleteBatchModeCompilation();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -181,12 +197,16 @@ private:
|
|||||||
public:
|
public:
|
||||||
// The commented-out consts are there because the data does not change
|
// The commented-out consts are there because the data does not change
|
||||||
// but the swap method gets called on this structure.
|
// but the swap method gets called on this structure.
|
||||||
struct ConsumerSpecificInformation {
|
class ConsumerSpecificInformation {
|
||||||
|
private:
|
||||||
|
/// The range of SourceLoc's for which diagnostics should be directed to
|
||||||
|
/// this subconsumer.
|
||||||
/*const*/ CharSourceRange range;
|
/*const*/ CharSourceRange range;
|
||||||
|
|
||||||
/// Index into Subconsumers vector.
|
/// Index into Subconsumers vector for this subconsumer.
|
||||||
unsigned subconsumerIndex;
|
/*const*/ unsigned subconsumerIndex;
|
||||||
|
|
||||||
|
public:
|
||||||
ConsumerSpecificInformation(const CharSourceRange range,
|
ConsumerSpecificInformation(const CharSourceRange range,
|
||||||
unsigned subconsumerIndex)
|
unsigned subconsumerIndex)
|
||||||
: range(range), subconsumerIndex(subconsumerIndex) {}
|
: range(range), subconsumerIndex(subconsumerIndex) {}
|
||||||
@@ -194,6 +214,29 @@ public:
|
|||||||
Subconsumer &subconsumer(FileSpecificDiagnosticConsumer &c) const {
|
Subconsumer &subconsumer(FileSpecificDiagnosticConsumer &c) const {
|
||||||
return c.Subconsumers[subconsumerIndex];
|
return c.Subconsumers[subconsumerIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compare according to range:
|
||||||
|
bool operator < (const ConsumerSpecificInformation &right) const {
|
||||||
|
auto compare = std::less<const char *>();
|
||||||
|
return compare(getRawLoc( range.getEnd()).getPointer(),
|
||||||
|
getRawLoc(right.range.getEnd()).getPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Overlaps by range:
|
||||||
|
bool overlaps(const ConsumerSpecificInformation &other) const {
|
||||||
|
return range.overlaps(other.range);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does my range end after \p loc?
|
||||||
|
bool endsAfter(const SourceLoc loc) const {
|
||||||
|
auto compare = std::less<const char *>();
|
||||||
|
return compare(getRawLoc(range.getEnd()).getPointer(),
|
||||||
|
getRawLoc(loc).getPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const SourceLoc loc) const {
|
||||||
|
return range.contains(loc);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -220,7 +263,7 @@ private:
|
|||||||
|
|
||||||
bool HasAnErrorBeenConsumed = false;
|
bool HasAnErrorBeenConsumed = false;
|
||||||
|
|
||||||
public:
|
|
||||||
/// Takes ownership of the DiagnosticConsumers specified in \p consumers.
|
/// Takes ownership of the DiagnosticConsumers specified in \p consumers.
|
||||||
///
|
///
|
||||||
/// There must not be two consumers for the same file (i.e., having the same
|
/// There must not be two consumers for the same file (i.e., having the same
|
||||||
@@ -228,6 +271,10 @@ public:
|
|||||||
explicit FileSpecificDiagnosticConsumer(
|
explicit FileSpecificDiagnosticConsumer(
|
||||||
SmallVectorImpl<Subconsumer> &consumers);
|
SmallVectorImpl<Subconsumer> &consumers);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
|
void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
|
||||||
DiagnosticKind Kind,
|
DiagnosticKind Kind,
|
||||||
StringRef FormatString,
|
StringRef FormatString,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ static bool hasDuplicateFileNames(
|
|||||||
ArrayRef<FileSpecificDiagnosticConsumer::Subconsumer> subconsumers) {
|
ArrayRef<FileSpecificDiagnosticConsumer::Subconsumer> subconsumers) {
|
||||||
llvm::StringSet<> seenFiles;
|
llvm::StringSet<> seenFiles;
|
||||||
for (const auto &subconsumer : subconsumers) {
|
for (const auto &subconsumer : subconsumers) {
|
||||||
if (subconsumer.bufferName.empty()) {
|
if (subconsumer.getInputFileName().empty()) {
|
||||||
// We can handle multiple subconsumers that aren't associated with any
|
// We can handle multiple subconsumers that aren't associated with any
|
||||||
// file, because they only collect diagnostics that aren't in any of the
|
// file, because they only collect diagnostics that aren't in any of the
|
||||||
// special files. This isn't an important use case to support, but also
|
// special files. This isn't an important use case to support, but also
|
||||||
@@ -46,13 +46,24 @@ static bool hasDuplicateFileNames(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isUnique = seenFiles.insert(subconsumer.bufferName).second;
|
bool isUnique = seenFiles.insert(subconsumer.getInputFileName()).second;
|
||||||
if (!isUnique)
|
if (!isUnique)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<DiagnosticConsumer> FileSpecificDiagnosticConsumer::
|
||||||
|
consolidateSubconsumers(SmallVectorImpl<Subconsumer> &subconsumers) {
|
||||||
|
if (subconsumers.empty())
|
||||||
|
return nullptr;
|
||||||
|
if (subconsumers.size() == 1)
|
||||||
|
return std::move(subconsumers.front()).consumer;
|
||||||
|
// Cannot use return llvm::make_unique<FileSpecificDiagnosticConsumer>(subconsumers);
|
||||||
|
// because the constructor is private.
|
||||||
|
return std::unique_ptr<DiagnosticConsumer>(new FileSpecificDiagnosticConsumer(subconsumers));
|
||||||
|
}
|
||||||
|
|
||||||
FileSpecificDiagnosticConsumer::FileSpecificDiagnosticConsumer(
|
FileSpecificDiagnosticConsumer::FileSpecificDiagnosticConsumer(
|
||||||
SmallVectorImpl<Subconsumer> &subconsumers)
|
SmallVectorImpl<Subconsumer> &subconsumers)
|
||||||
: Subconsumers(std::move(subconsumers)) {
|
: Subconsumers(std::move(subconsumers)) {
|
||||||
@@ -67,11 +78,11 @@ void FileSpecificDiagnosticConsumer::computeConsumersOrderedByRange(
|
|||||||
// Look up each file's source range and add it to the "map" (to be sorted).
|
// Look up each file's source range and add it to the "map" (to be sorted).
|
||||||
for (const unsigned subconsumerIndex: indices(Subconsumers)) {
|
for (const unsigned subconsumerIndex: indices(Subconsumers)) {
|
||||||
const Subconsumer &subconsumer = Subconsumers[subconsumerIndex];
|
const Subconsumer &subconsumer = Subconsumers[subconsumerIndex];
|
||||||
if (subconsumer.bufferName.empty())
|
if (subconsumer.getInputFileName().empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Optional<unsigned> bufferID =
|
Optional<unsigned> bufferID =
|
||||||
SM.getIDForBufferIdentifier(subconsumer.bufferName);
|
SM.getIDForBufferIdentifier(subconsumer.getInputFileName());
|
||||||
assert(bufferID.hasValue() && "consumer registered for unknown file");
|
assert(bufferID.hasValue() && "consumer registered for unknown file");
|
||||||
CharSourceRange range = SM.getRangeForBuffer(bufferID.getValue());
|
CharSourceRange range = SM.getRangeForBuffer(bufferID.getValue());
|
||||||
ConsumersOrderedByRange.emplace_back(
|
ConsumersOrderedByRange.emplace_back(
|
||||||
@@ -85,9 +96,7 @@ void FileSpecificDiagnosticConsumer::computeConsumersOrderedByRange(
|
|||||||
std::sort(ConsumersOrderedByRange.begin(), ConsumersOrderedByRange.end(),
|
std::sort(ConsumersOrderedByRange.begin(), ConsumersOrderedByRange.end(),
|
||||||
[](const ConsumerSpecificInformation &left,
|
[](const ConsumerSpecificInformation &left,
|
||||||
const ConsumerSpecificInformation &right) -> bool {
|
const ConsumerSpecificInformation &right) -> bool {
|
||||||
auto compare = std::less<const char *>();
|
return left < right;
|
||||||
return compare(getRawLoc(left.range.getEnd()).getPointer(),
|
|
||||||
getRawLoc(right.range.getEnd()).getPointer());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check that the ranges are non-overlapping. If the files really are all
|
// Check that the ranges are non-overlapping. If the files really are all
|
||||||
@@ -98,7 +107,7 @@ void FileSpecificDiagnosticConsumer::computeConsumersOrderedByRange(
|
|||||||
ConsumersOrderedByRange.end(),
|
ConsumersOrderedByRange.end(),
|
||||||
[](const ConsumerSpecificInformation &left,
|
[](const ConsumerSpecificInformation &left,
|
||||||
const ConsumerSpecificInformation &right) {
|
const ConsumerSpecificInformation &right) {
|
||||||
return left.range.overlaps(right.range);
|
return left.overlaps(right);
|
||||||
}) &&
|
}) &&
|
||||||
"overlapping ranges despite having distinct files");
|
"overlapping ranges despite having distinct files");
|
||||||
}
|
}
|
||||||
@@ -122,10 +131,10 @@ FileSpecificDiagnosticConsumer::consumerSpecificInformationForLocation(
|
|||||||
// than trying to build a nonsensical map (and actually crashing since we
|
// than trying to build a nonsensical map (and actually crashing since we
|
||||||
// can't find buffers for the inputs).
|
// can't find buffers for the inputs).
|
||||||
assert(!Subconsumers.empty());
|
assert(!Subconsumers.empty());
|
||||||
if (!SM.getIDForBufferIdentifier(Subconsumers.begin()->bufferName)
|
if (!SM.getIDForBufferIdentifier(Subconsumers.begin()->getInputFileName())
|
||||||
.hasValue()) {
|
.hasValue()) {
|
||||||
assert(llvm::none_of(Subconsumers, [&](const Subconsumer &subconsumer) {
|
assert(llvm::none_of(Subconsumers, [&](const Subconsumer &subconsumer) {
|
||||||
return SM.getIDForBufferIdentifier(subconsumer.bufferName).hasValue();
|
return SM.getIDForBufferIdentifier(subconsumer.getInputFileName()).hasValue();
|
||||||
}));
|
}));
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -141,13 +150,11 @@ FileSpecificDiagnosticConsumer::consumerSpecificInformationForLocation(
|
|||||||
std::lower_bound(
|
std::lower_bound(
|
||||||
ConsumersOrderedByRange.begin(), ConsumersOrderedByRange.end(), loc,
|
ConsumersOrderedByRange.begin(), ConsumersOrderedByRange.end(), loc,
|
||||||
[](const ConsumerSpecificInformation &entry, SourceLoc loc) -> bool {
|
[](const ConsumerSpecificInformation &entry, SourceLoc loc) -> bool {
|
||||||
auto compare = std::less<const char *>();
|
return entry.endsAfter(loc);
|
||||||
return compare(getRawLoc(entry.range.getEnd()).getPointer(),
|
|
||||||
getRawLoc(loc).getPointer());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (possiblyContainingRangeIter != ConsumersOrderedByRange.end() &&
|
if (possiblyContainingRangeIter != ConsumersOrderedByRange.end() &&
|
||||||
possiblyContainingRangeIter->range.contains(loc)) {
|
possiblyContainingRangeIter->contains(loc)) {
|
||||||
return const_cast<ConsumerSpecificInformation *>(
|
return const_cast<ConsumerSpecificInformation *>(
|
||||||
possiblyContainingRangeIter);
|
possiblyContainingRangeIter);
|
||||||
}
|
}
|
||||||
@@ -191,7 +198,7 @@ bool FileSpecificDiagnosticConsumer::finishProcessing() {
|
|||||||
bool hadError = false;
|
bool hadError = false;
|
||||||
for (auto &subconsumer : Subconsumers)
|
for (auto &subconsumer : Subconsumers)
|
||||||
hadError |=
|
hadError |=
|
||||||
subconsumer.consumer && subconsumer.consumer->finishProcessing();
|
subconsumer.getConsumer() && subconsumer.getConsumer()->finishProcessing();
|
||||||
return hadError;
|
return hadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1619,11 +1619,7 @@ createDispatchingDiagnosticConsumerIfNeeded(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subconsumers.empty())
|
return FileSpecificDiagnosticConsumer::consolidateSubconsumers(subconsumers);
|
||||||
return nullptr;
|
|
||||||
if (subconsumers.size() == 1)
|
|
||||||
return std::move(subconsumers.front()).consumer;
|
|
||||||
return llvm::make_unique<FileSpecificDiagnosticConsumer>(subconsumers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a diagnostic consumer that handles serializing diagnostics, based on
|
/// Creates a diagnostic consumer that handles serializing diagnostics, based on
|
||||||
|
|||||||
Reference in New Issue
Block a user