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/ArrayRef.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
namespace clang { namespace clang {
namespace ast_matchers { namespace ast_matchers {
@ -125,8 +126,6 @@ public:
ContextType Type; ContextType Type;
SourceRange Range; SourceRange Range;
std::vector<std::string> Args; std::vector<std::string> Args;
std::string ToString() const;
}; };
/// \brief Information stored for each error found. /// \brief Information stored for each error found.
@ -135,20 +134,20 @@ public:
SourceRange Range; SourceRange Range;
ErrorType Type; ErrorType Type;
std::vector<std::string> Args; std::vector<std::string> Args;
std::string ToString() const;
}; };
ArrayRef<ErrorContent> errors() const { return Errors; } ArrayRef<ErrorContent> errors() const { return Errors; }
/// \brief Returns a simple string representation of each error. /// \brief Returns a simple string representation of each error.
/// ///
/// Each error only shows the error message without any context. /// 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. /// \brief Returns the full string representation of each error.
/// ///
/// Each error message contains the full context. /// Each error message contains the full context.
std::string ToStringFull() const; void printToStreamFull(llvm::raw_ostream &OS) const;
std::string toStringFull() const;
private: private:
/// \brief Helper function used by the constructors of ContextFrame. /// \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); return ArgStream(&Last.Args);
} }
StringRef ContextTypeToString(Diagnostics::ContextType Type) { StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
switch (Type) { switch (Type) {
case Diagnostics::CT_MatcherConstruct: case Diagnostics::CT_MatcherConstruct:
return "Error building matcher $0."; return "Error building matcher $0.";
@ -65,7 +65,7 @@ StringRef ContextTypeToString(Diagnostics::ContextType Type) {
llvm_unreachable("Unknown ContextType value."); llvm_unreachable("Unknown ContextType value.");
} }
StringRef ErrorTypeToString(Diagnostics::ErrorType Type) { StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
switch (Type) { switch (Type) {
case Diagnostics::ET_RegistryNotFound: case Diagnostics::ET_RegistryNotFound:
return "Matcher not found: $0"; return "Matcher not found: $0";
@ -105,12 +105,11 @@ StringRef ErrorTypeToString(Diagnostics::ErrorType Type) {
llvm_unreachable("Unknown ErrorType value."); llvm_unreachable("Unknown ErrorType value.");
} }
std::string FormatErrorString(StringRef FormatString, void formatErrorString(StringRef FormatString, ArrayRef<std::string> Args,
ArrayRef<std::string> Args) { llvm::raw_ostream &OS) {
std::string Out;
while (!FormatString.empty()) { while (!FormatString.empty()) {
std::pair<StringRef, StringRef> Pieces = FormatString.split("$"); std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
Out += Pieces.first.str(); OS << Pieces.first.str();
if (Pieces.second.empty()) break; if (Pieces.second.empty()) break;
const char Next = Pieces.second.front(); const char Next = Pieces.second.front();
@ -118,53 +117,64 @@ std::string FormatErrorString(StringRef FormatString,
if (Next >= '0' && Next <= '9') { if (Next >= '0' && Next <= '9') {
const unsigned Index = Next - '0'; const unsigned Index = Next - '0';
if (Index < Args.size()) { if (Index < Args.size()) {
Out += Args[Index]; OS << Args[Index];
} else { } else {
Out += "<Argument_Not_Provided>"; OS << "<Argument_Not_Provided>";
} }
} }
} }
return Out;
} }
static std::string MaybeAddLineAndColumn(Twine Input, static void maybeAddLineAndColumn(const SourceRange &Range,
const SourceRange &Range) { llvm::raw_ostream &OS) {
if (Range.Start.Line > 0 && Range.Start.Column > 0) if (Range.Start.Line > 0 && Range.Start.Column > 0) {
return (Twine(Range.Start.Line) + ":" + Twine(Range.Start.Column) + ": " + OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
Input).str(); }
return Input.str();
} }
std::string Diagnostics::ContextFrame::ToString() const { static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
return MaybeAddLineAndColumn( llvm::raw_ostream &OS) {
FormatErrorString(ContextTypeToString(Type), Args), Range); maybeAddLineAndColumn(Frame.Range, OS);
formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
} }
std::string Diagnostics::ErrorContent::ToString() const { static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
return MaybeAddLineAndColumn(FormatErrorString(ErrorTypeToString(Type), Args), llvm::raw_ostream &OS) {
Range); maybeAddLineAndColumn(Content.Range, OS);
formatErrorString(errorTypeToFormatString(Content.Type), Content.Args, OS);
} }
std::string Diagnostics::ToString() const { void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
std::string Result;
for (size_t i = 0, e = Errors.size(); i != e; ++i) { for (size_t i = 0, e = Errors.size(); i != e; ++i) {
if (i != 0) Result += "\n"; if (i != 0) OS << "\n";
Result += Errors[i].ToString(); printErrorContentToStream(Errors[i], OS);
} }
return Result;
} }
std::string Diagnostics::ToStringFull() const { std::string Diagnostics::toString() const {
std::string Result; 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) { for (size_t i = 0, e = Errors.size(); i != e; ++i) {
if (i != 0) Result += "\n"; if (i != 0) OS << "\n";
const ErrorContent &Error = Errors[i]; const ErrorContent &Error = Errors[i];
for (size_t i = 0, e = Error.ContextStack.size(); i != e; ++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 } // namespace dynamic

View File

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

View File

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