mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
It turns out that we need to have the diagnostic consumers set up before we've actually opened the input files, which makes sense because we might want to emit diagnostics about not being able to open an input file. Switch to using file names instead, and mapping those over to source ranges only once we actually need to handle a diagnostic with a valid source location.
534 lines
22 KiB
C++
534 lines
22 KiB
C++
//===--- DiagnosticConsumerTests.cpp --------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2018 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/DiagnosticConsumer.h"
|
|
#include "swift/Basic/SourceManager.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace swift;
|
|
|
|
namespace {
|
|
using ExpectedDiagnostic = std::pair<SourceLoc, StringRef>;
|
|
|
|
class ExpectationDiagnosticConsumer: public DiagnosticConsumer {
|
|
ExpectationDiagnosticConsumer *previous;
|
|
SmallVector<ExpectedDiagnostic, 4> expected;
|
|
bool hasFinished = false;
|
|
|
|
public:
|
|
ExpectationDiagnosticConsumer(ExpectationDiagnosticConsumer *previous,
|
|
ArrayRef<ExpectedDiagnostic> expected)
|
|
: previous(previous), expected(expected.begin(), expected.end()) {}
|
|
|
|
~ExpectationDiagnosticConsumer() override {
|
|
EXPECT_TRUE(hasFinished);
|
|
EXPECT_TRUE(expected.empty());
|
|
}
|
|
|
|
void handleDiagnostic(SourceManager &SM, SourceLoc loc, DiagnosticKind kind,
|
|
StringRef formatString,
|
|
ArrayRef<DiagnosticArgument> formatArgs,
|
|
const DiagnosticInfo &info) override {
|
|
ASSERT_FALSE(expected.empty());
|
|
EXPECT_EQ(std::make_pair(loc, formatString), expected.front());
|
|
expected.erase(expected.begin());
|
|
}
|
|
|
|
bool finishProcessing() override {
|
|
EXPECT_FALSE(hasFinished);
|
|
if (previous)
|
|
EXPECT_TRUE(previous->hasFinished);
|
|
hasFinished = true;
|
|
return false;
|
|
}
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
TEST(FileSpecificDiagnosticConsumer, SubConsumersFinishInOrder) {
|
|
SourceManager sourceMgr;
|
|
(void)sourceMgr.addMemBufferCopy("abcde", "A");
|
|
(void)sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, None);
|
|
auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), None);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("", std::move(consumerUnaffiliated));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
TEST(FileSpecificDiagnosticConsumer, InvalidLocDiagsGoToEveryConsumer) {
|
|
SourceManager sourceMgr;
|
|
(void)sourceMgr.addMemBufferCopy("abcde", "A");
|
|
(void)sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
ExpectedDiagnostic expected[] = { {SourceLoc(), "dummy"} };
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expected);
|
|
auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expected);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("", std::move(consumerUnaffiliated));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Error,
|
|
"dummy", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
TEST(FileSpecificDiagnosticConsumer, ErrorsWithLocationsGoToExpectedConsumers) {
|
|
SourceManager sourceMgr;
|
|
// 01234
|
|
unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
|
|
unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
|
|
SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
|
|
SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
|
|
|
|
SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
|
|
SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
|
|
SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
|
|
|
|
ExpectedDiagnostic expectedA[] = {
|
|
{frontOfA, "front"},
|
|
{middleOfA, "middle"},
|
|
{backOfA, "back"},
|
|
};
|
|
ExpectedDiagnostic expectedB[] = {
|
|
{frontOfB, "front"},
|
|
{middleOfB, "middle"},
|
|
{backOfB, "back"}
|
|
};
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expectedA);
|
|
auto consumerB = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expectedB);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("B", std::move(consumerB));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"front", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
|
|
"front", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Error,
|
|
"middle", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Error,
|
|
"middle", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Error,
|
|
"back", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Error,
|
|
"back", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
TEST(FileSpecificDiagnosticConsumer,
|
|
ErrorsInUnaffiliatedFilesGoToEveryConsumer) {
|
|
SourceManager sourceMgr;
|
|
// 01234
|
|
unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
|
|
unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
|
|
SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
|
|
SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
|
|
|
|
SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
|
|
SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
|
|
SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
|
|
|
|
ExpectedDiagnostic expectedA[] = {
|
|
{frontOfA, "front"},
|
|
{frontOfB, "front"},
|
|
{middleOfA, "middle"},
|
|
{middleOfB, "middle"},
|
|
{backOfA, "back"},
|
|
{backOfB, "back"}
|
|
};
|
|
ExpectedDiagnostic expectedUnaffiliated[] = {
|
|
{frontOfB, "front"},
|
|
{middleOfB, "middle"},
|
|
{backOfB, "back"}
|
|
};
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expectedA);
|
|
auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expectedUnaffiliated);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("", std::move(consumerUnaffiliated));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"front", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
|
|
"front", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Error,
|
|
"middle", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Error,
|
|
"middle", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Error,
|
|
"back", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Error,
|
|
"back", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
TEST(FileSpecificDiagnosticConsumer, WarningsAndRemarksAreTreatedLikeErrors) {
|
|
SourceManager sourceMgr;
|
|
// 01234
|
|
unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
|
|
unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
SourceLoc frontOfA = sourceMgr.getLocForBufferStart(bufferA);
|
|
SourceLoc frontOfB = sourceMgr.getLocForBufferStart(bufferB);
|
|
|
|
ExpectedDiagnostic expectedA[] = {
|
|
{frontOfA, "warning"},
|
|
{frontOfB, "warning"},
|
|
{frontOfA, "remark"},
|
|
{frontOfB, "remark"},
|
|
};
|
|
ExpectedDiagnostic expectedUnaffiliated[] = {
|
|
{frontOfB, "warning"},
|
|
{frontOfB, "remark"},
|
|
};
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expectedA);
|
|
auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expectedUnaffiliated);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("", std::move(consumerUnaffiliated));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Warning,
|
|
"warning", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Warning,
|
|
"warning", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Remark,
|
|
"remark", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Remark,
|
|
"remark", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
TEST(FileSpecificDiagnosticConsumer, NotesAreAttachedToErrors) {
|
|
SourceManager sourceMgr;
|
|
// 01234
|
|
unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
|
|
unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
|
|
SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
|
|
SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
|
|
|
|
SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
|
|
SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
|
|
SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
|
|
|
|
ExpectedDiagnostic expectedA[] = {
|
|
{frontOfA, "error"},
|
|
{middleOfA, "note"},
|
|
{backOfA, "note"},
|
|
{frontOfB, "error"},
|
|
{middleOfB, "note"},
|
|
{backOfB, "note"},
|
|
{frontOfA, "error"},
|
|
{middleOfA, "note"},
|
|
{backOfA, "note"},
|
|
};
|
|
ExpectedDiagnostic expectedUnaffiliated[] = {
|
|
{frontOfB, "error"},
|
|
{middleOfB, "note"},
|
|
{backOfB, "note"},
|
|
};
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expectedA);
|
|
auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expectedUnaffiliated);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("", std::move(consumerUnaffiliated));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
TEST(FileSpecificDiagnosticConsumer, NotesAreAttachedToWarningsAndRemarks) {
|
|
SourceManager sourceMgr;
|
|
// 01234
|
|
unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
|
|
unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
|
|
SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
|
|
SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
|
|
|
|
SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
|
|
SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
|
|
SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
|
|
|
|
ExpectedDiagnostic expectedA[] = {
|
|
{frontOfA, "warning"},
|
|
{middleOfA, "note"},
|
|
{backOfA, "note"},
|
|
{frontOfB, "warning"},
|
|
{middleOfB, "note"},
|
|
{backOfB, "note"},
|
|
{frontOfA, "remark"},
|
|
{middleOfA, "note"},
|
|
{backOfA, "note"},
|
|
};
|
|
ExpectedDiagnostic expectedUnaffiliated[] = {
|
|
{frontOfB, "warning"},
|
|
{middleOfB, "note"},
|
|
{backOfB, "note"},
|
|
};
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expectedA);
|
|
auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expectedUnaffiliated);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("", std::move(consumerUnaffiliated));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Warning,
|
|
"warning", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Warning,
|
|
"warning", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Remark,
|
|
"remark", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
TEST(FileSpecificDiagnosticConsumer, NotesAreAttachedToErrorsEvenAcrossFiles) {
|
|
SourceManager sourceMgr;
|
|
// 01234
|
|
unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
|
|
unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
|
|
SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
|
|
SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
|
|
|
|
SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
|
|
SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
|
|
SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
|
|
|
|
ExpectedDiagnostic expectedA[] = {
|
|
{frontOfA, "error"},
|
|
{middleOfB, "note"},
|
|
{backOfA, "note"},
|
|
{frontOfA, "error"},
|
|
{middleOfB, "note"},
|
|
{backOfA, "note"},
|
|
};
|
|
ExpectedDiagnostic expectedB[] = {
|
|
{frontOfB, "error"},
|
|
{middleOfA, "note"},
|
|
{backOfB, "note"},
|
|
};
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expectedA);
|
|
auto consumerB = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expectedB);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("B", std::move(consumerB));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
TEST(FileSpecificDiagnosticConsumer,
|
|
NotesAreAttachedToErrorsEvenAcrossFilesWithUnaffiliatedConsumer) {
|
|
SourceManager sourceMgr;
|
|
// 01234
|
|
unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
|
|
unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
|
|
SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
|
|
SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
|
|
|
|
SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
|
|
SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
|
|
SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
|
|
|
|
ExpectedDiagnostic expectedA[] = {
|
|
{frontOfA, "error"},
|
|
{middleOfB, "note"},
|
|
{backOfA, "note"},
|
|
{frontOfB, "error"},
|
|
{middleOfA, "note"},
|
|
{backOfB, "note"},
|
|
{frontOfA, "error"},
|
|
{middleOfB, "note"},
|
|
{backOfA, "note"},
|
|
};
|
|
ExpectedDiagnostic expectedUnaffiliated[] = {
|
|
{frontOfB, "error"},
|
|
{middleOfA, "note"},
|
|
{backOfB, "note"},
|
|
};
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expectedA);
|
|
auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expectedUnaffiliated);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("", std::move(consumerUnaffiliated));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|
|
|
|
|
|
TEST(FileSpecificDiagnosticConsumer,
|
|
NotesWithInvalidLocsAreStillAttachedToErrors) {
|
|
SourceManager sourceMgr;
|
|
// 01234
|
|
unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
|
|
unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
|
|
|
|
SourceLoc frontOfA = sourceMgr.getLocForBufferStart(bufferA);
|
|
SourceLoc frontOfB = sourceMgr.getLocForBufferStart(bufferB);
|
|
|
|
ExpectedDiagnostic expectedA[] = {
|
|
{frontOfA, "error"},
|
|
{SourceLoc(), "note"},
|
|
{frontOfB, "error"},
|
|
{SourceLoc(), "note"},
|
|
{frontOfA, "error"},
|
|
{SourceLoc(), "note"},
|
|
};
|
|
ExpectedDiagnostic expectedUnaffiliated[] = {
|
|
{frontOfB, "error"},
|
|
{SourceLoc(), "note"},
|
|
};
|
|
|
|
auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
nullptr, expectedA);
|
|
auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
|
|
consumerA.get(), expectedUnaffiliated);
|
|
|
|
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
|
|
consumers.emplace_back("A", std::move(consumerA));
|
|
consumers.emplace_back("", std::move(consumerUnaffiliated));
|
|
|
|
FileSpecificDiagnosticConsumer topConsumer(consumers);
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
|
|
"error", {}, DiagnosticInfo());
|
|
topConsumer.handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
|
|
"note", {}, DiagnosticInfo());
|
|
topConsumer.finishProcessing();
|
|
}
|