#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 {
ContextType Type;
SourceRange Range;
std::vector<std::string> Args;
-
- std::string ToString() const;
};
/// \brief Information stored for each error found.
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.
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.";
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";
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();
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();
+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 << ": ";
+ }
}
-std::string Diagnostics::ContextFrame::ToString() const {
- return MaybeAddLineAndColumn(
- FormatErrorString(ContextTypeToString(Type), Args), Range);
+static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
+ llvm::raw_ostream &OS) {
+ maybeAddLineAndColumn(Frame.Range, OS);
+ formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
}
-std::string Diagnostics::ErrorContent::ToString() const {
- return MaybeAddLineAndColumn(FormatErrorString(ErrorTypeToString(Type), Args),
- Range);
+static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
+ llvm::raw_ostream &OS) {
+ maybeAddLineAndColumn(Content.Range, OS);
+ formatErrorString(errorTypeToFormatString(Content.Type), Content.Args, OS);
}
-std::string Diagnostics::ToString() const {
- std::string Result;
+void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
for (size_t i = 0, e = Errors.size(); i != e; ++i) {
- if (i != 0) Result += "\n";
- Result += Errors[i].ToString();
+ if (i != 0) OS << "\n";
+ printErrorContentToStream(Errors[i], OS);
}
- return Result;
}
-std::string Diagnostics::ToStringFull() const {
- std::string Result;
+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) Result += "\n";
+ 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
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,
"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));
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));
"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) {
if (!Error) Error = &DummyError;
const MatcherList Out =
Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error);
- EXPECT_EQ("", DummyError.ToStringFull());
+ EXPECT_EQ("", DummyError.toStringFull());
return Out;
}
if (!Error) Error = &DummyError;
const MatcherList Out = Registry::constructMatcher(
MatcherName, SourceRange(), Args(Arg1), Error);
- EXPECT_EQ("", DummyError.ToStringFull());
+ EXPECT_EQ("", DummyError.toStringFull());
return Out;
}
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;
}
};
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