Add support for raw_ostream on the printing methods of Diagnostics.

Summary:
Add printToStream*(llvm::raw_ostream&) methods to Diagnostics, and reimplement everything based on streams instead of concatenating strings.
Also, fix some functions to start with lowercase to match the style guide.

Reviewers: klimek

CC: cfe-commits, revane

Differential Revision: http://llvm-reviews.chandlerc.com/D1187

llvm-svn: 186715
This commit is contained in:
Samuel Benzaquen 2013-07-19 20:02:35 +00:00
parent 569b8f83a4
commit b837248ad4
4 changed files with 67 additions and 58 deletions

View File

@ -23,6 +23,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace ast_matchers {
@ -125,8 +126,6 @@ public:
ContextType Type;
SourceRange Range;
std::vector<std::string> Args;
std::string ToString() const;
};
/// \brief Information stored for each error found.
@ -135,20 +134,20 @@ public:
SourceRange Range;
ErrorType Type;
std::vector<std::string> Args;
std::string ToString() const;
};
ArrayRef<ErrorContent> errors() const { return Errors; }
/// \brief Returns a simple string representation of each error.
///
/// Each error only shows the error message without any context.
std::string ToString() const;
void printToStream(llvm::raw_ostream &OS) const;
std::string toString() const;
/// \brief Returns the full string representation of each error.
///
/// Each error message contains the full context.
std::string ToStringFull() const;
void printToStreamFull(llvm::raw_ostream &OS) const;
std::string toStringFull() const;
private:
/// \brief Helper function used by the constructors of ContextFrame.

View File

@ -55,7 +55,7 @@ Diagnostics::ArgStream Diagnostics::addError(const SourceRange &Range,
return ArgStream(&Last.Args);
}
StringRef ContextTypeToString(Diagnostics::ContextType Type) {
StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
switch (Type) {
case Diagnostics::CT_MatcherConstruct:
return "Error building matcher $0.";
@ -65,7 +65,7 @@ StringRef ContextTypeToString(Diagnostics::ContextType Type) {
llvm_unreachable("Unknown ContextType value.");
}
StringRef ErrorTypeToString(Diagnostics::ErrorType Type) {
StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
switch (Type) {
case Diagnostics::ET_RegistryNotFound:
return "Matcher not found: $0";
@ -105,12 +105,11 @@ StringRef ErrorTypeToString(Diagnostics::ErrorType Type) {
llvm_unreachable("Unknown ErrorType value.");
}
std::string FormatErrorString(StringRef FormatString,
ArrayRef<std::string> Args) {
std::string Out;
void formatErrorString(StringRef FormatString, ArrayRef<std::string> Args,
llvm::raw_ostream &OS) {
while (!FormatString.empty()) {
std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
Out += Pieces.first.str();
OS << Pieces.first.str();
if (Pieces.second.empty()) break;
const char Next = Pieces.second.front();
@ -118,53 +117,64 @@ std::string FormatErrorString(StringRef FormatString,
if (Next >= '0' && Next <= '9') {
const unsigned Index = Next - '0';
if (Index < Args.size()) {
Out += Args[Index];
OS << Args[Index];
} else {
Out += "<Argument_Not_Provided>";
OS << "<Argument_Not_Provided>";
}
}
}
return Out;
}
static std::string MaybeAddLineAndColumn(Twine Input,
const SourceRange &Range) {
if (Range.Start.Line > 0 && Range.Start.Column > 0)
return (Twine(Range.Start.Line) + ":" + Twine(Range.Start.Column) + ": " +
Input).str();
return Input.str();
}
std::string Diagnostics::ContextFrame::ToString() const {
return MaybeAddLineAndColumn(
FormatErrorString(ContextTypeToString(Type), Args), Range);
}
std::string Diagnostics::ErrorContent::ToString() const {
return MaybeAddLineAndColumn(FormatErrorString(ErrorTypeToString(Type), Args),
Range);
}
std::string Diagnostics::ToString() const {
std::string Result;
for (size_t i = 0, e = Errors.size(); i != e; ++i) {
if (i != 0) Result += "\n";
Result += Errors[i].ToString();
static void maybeAddLineAndColumn(const SourceRange &Range,
llvm::raw_ostream &OS) {
if (Range.Start.Line > 0 && Range.Start.Column > 0) {
OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
}
return Result;
}
std::string Diagnostics::ToStringFull() const {
std::string Result;
static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
llvm::raw_ostream &OS) {
maybeAddLineAndColumn(Frame.Range, OS);
formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
}
static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
llvm::raw_ostream &OS) {
maybeAddLineAndColumn(Content.Range, OS);
formatErrorString(errorTypeToFormatString(Content.Type), Content.Args, OS);
}
void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
for (size_t i = 0, e = Errors.size(); i != e; ++i) {
if (i != 0) Result += "\n";
if (i != 0) OS << "\n";
printErrorContentToStream(Errors[i], OS);
}
}
std::string Diagnostics::toString() const {
std::string S;
llvm::raw_string_ostream OS(S);
printToStream(OS);
return OS.str();
}
void Diagnostics::printToStreamFull(llvm::raw_ostream &OS) const {
for (size_t i = 0, e = Errors.size(); i != e; ++i) {
if (i != 0) OS << "\n";
const ErrorContent &Error = Errors[i];
for (size_t i = 0, e = Error.ContextStack.size(); i != e; ++i) {
Result += Error.ContextStack[i].ToString() + "\n";
printContextFrameToStream(Error.ContextStack[i], OS);
OS << "\n";
}
Result += Error.ToString();
printErrorContentToStream(Error, OS);
}
return Result;
}
std::string Diagnostics::toStringFull() const {
std::string S;
llvm::raw_string_ostream OS(S);
printToStreamFull(OS);
return OS.str();
}
} // namespace dynamic

View File

@ -73,7 +73,7 @@ public:
VariantValue Value;
Parser::parseExpression(Code, this, &Value, &Error);
Values.push_back(Value);
Errors.push_back(Error.ToStringFull());
Errors.push_back(Error.toStringFull());
}
MatcherList actOnMatcherExpression(StringRef MatcherName,
@ -184,7 +184,7 @@ TEST(ParserTest, FullParserTest) {
"varDecl(hasInitializer(binaryOperator(hasLHS(integerLiteral()),"
" hasOperatorName(\"+\"))))",
&Error));
EXPECT_EQ("", Error.ToStringFull());
EXPECT_EQ("", Error.toStringFull());
Matcher<Decl> M = Matcher<Decl>::constructFrom(*VarDecl);
EXPECT_TRUE(matches("int x = 1 + false;", M));
EXPECT_FALSE(matches("int x = true + 1;", M));
@ -193,7 +193,7 @@ TEST(ParserTest, FullParserTest) {
OwningPtr<DynTypedMatcher> HasParameter(Parser::parseMatcherExpression(
"functionDecl(hasParameter(1, hasName(\"x\")))", &Error));
EXPECT_EQ("", Error.ToStringFull());
EXPECT_EQ("", Error.toStringFull());
M = Matcher<Decl>::constructFrom(*HasParameter);
EXPECT_TRUE(matches("void f(int a, int x);", M));
@ -206,20 +206,20 @@ TEST(ParserTest, FullParserTest) {
"2:20: Error building matcher hasLHS.\n"
"2:27: Incorrect type for arg 1. "
"(Expected = Matcher<Expr>) != (Actual = String)",
Error.ToStringFull());
Error.toStringFull());
}
std::string ParseWithError(StringRef Code) {
Diagnostics Error;
VariantValue Value;
Parser::parseExpression(Code, &Value, &Error);
return Error.ToStringFull();
return Error.toStringFull();
}
std::string ParseMatcherWithError(StringRef Code) {
Diagnostics Error;
Parser::parseMatcherExpression(Code, &Error);
return Error.ToStringFull();
return Error.toStringFull();
}
TEST(ParserTest, Errors) {

View File

@ -42,7 +42,7 @@ public:
if (!Error) Error = &DummyError;
const MatcherList Out =
Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error);
EXPECT_EQ("", DummyError.ToStringFull());
EXPECT_EQ("", DummyError.toStringFull());
return Out;
}
@ -52,7 +52,7 @@ public:
if (!Error) Error = &DummyError;
const MatcherList Out = Registry::constructMatcher(
MatcherName, SourceRange(), Args(Arg1), Error);
EXPECT_EQ("", DummyError.ToStringFull());
EXPECT_EQ("", DummyError.toStringFull());
return Out;
}
@ -63,7 +63,7 @@ public:
if (!Error) Error = &DummyError;
const MatcherList Out = Registry::constructMatcher(
MatcherName, SourceRange(), Args(Arg1, Arg2), Error);
EXPECT_EQ("", DummyError.ToStringFull());
EXPECT_EQ("", DummyError.toStringFull());
return Out;
}
};
@ -203,24 +203,24 @@ TEST_F(RegistryTest, Errors) {
OwningPtr<Diagnostics> Error(new Diagnostics());
EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).empty());
EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
Error->ToString());
Error->toString());
Error.reset(new Diagnostics());
EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).empty());
EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
Error->ToString());
Error->toString());
// Bad argument type
Error.reset(new Diagnostics());
EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).empty());
EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
"(Actual = String)",
Error->ToString());
Error->toString());
Error.reset(new Diagnostics());
EXPECT_TRUE(constructMatcher("recordDecl", recordDecl(), parameterCountIs(3),
Error.get()).empty());
EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
"(Actual = Matcher<FunctionDecl>)",
Error->ToString());
Error->toString());
}
} // end anonymous namespace