diff options
Diffstat (limited to 'lib/ASTMatchers/Dynamic/Diagnostics.cpp')
-rw-r--r-- | lib/ASTMatchers/Dynamic/Diagnostics.cpp | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/lib/ASTMatchers/Dynamic/Diagnostics.cpp new file mode 100644 index 0000000000..fb3cac370f --- /dev/null +++ b/lib/ASTMatchers/Dynamic/Diagnostics.cpp @@ -0,0 +1,113 @@ +//===--- Diagnostics.cpp - Helper class for error diagnostics -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/ASTMatchers/Dynamic/Diagnostics.h" + +namespace clang { +namespace ast_matchers { +namespace dynamic { + +Diagnostics::ArgStream & +Diagnostics::ArgStream::operator<<(const Twine &Arg) { + Out->push_back(Arg.str()); + return *this; +} + +Diagnostics::ArgStream Diagnostics::pushErrorFrame(const SourceRange &Range, + ErrorType Error) { + Frames.insert(Frames.begin(), ErrorFrame()); + ErrorFrame &Last = Frames.front(); + Last.Range = Range; + Last.Type = Error; + ArgStream Out = { &Last.Args }; + return Out; +} + +StringRef ErrorTypeToString(Diagnostics::ErrorType Type) { + switch (Type) { + case Diagnostics::ET_RegistryNotFound: + return "Matcher not found: $0"; + case Diagnostics::ET_RegistryWrongArgCount: + return "Incorrect argument count. (Expected = $0) != (Actual = $1)"; + case Diagnostics::ET_RegistryWrongArgType: + return "Incorrect type on function $0 for arg $1."; + + case Diagnostics::ET_ParserStringError: + return "Error parsing string token: <$0>"; + case Diagnostics::ET_ParserMatcherArgFailure: + return "Error parsing argument $0 for matcher $1."; + case Diagnostics::ET_ParserMatcherFailure: + return "Error building matcher $0."; + case Diagnostics::ET_ParserNoOpenParen: + return "Error parsing matcher. Found token <$0> while looking for '('."; + case Diagnostics::ET_ParserNoCloseParen: + return "Error parsing matcher. Found end-of-code while looking for ')'."; + case Diagnostics::ET_ParserNoComma: + return "Error parsing matcher. Found token <$0> while looking for ','."; + case Diagnostics::ET_ParserNoCode: + return "End of code found while looking for token."; + case Diagnostics::ET_ParserNotAMatcher: + return "Input value is not a matcher expression."; + case Diagnostics::ET_ParserInvalidToken: + return "Invalid token <$0> found when looking for a value."; + + case Diagnostics::ET_None: + return "<N/A>"; + } + llvm_unreachable("Unknown ErrorType value."); +} + +std::string FormatErrorString(StringRef FormatString, + ArrayRef<std::string> Args) { + std::string Out; + while (!FormatString.empty()) { + std::pair<StringRef, StringRef> Pieces = FormatString.split("$"); + Out += Pieces.first.str(); + if (Pieces.second.empty()) break; + + const char Next = Pieces.second.front(); + FormatString = Pieces.second.drop_front(); + if (Next >= '0' && Next <= '9') { + const unsigned Index = Next - '0'; + if (Index < Args.size()) { + Out += Args[Index]; + } else { + Out += "<Argument_Not_Provided>"; + } + } + } + return Out; +} + +std::string Diagnostics::ErrorFrame::ToString() const { + StringRef FormatString = ErrorTypeToString(Type); + std::string ErrorOut = FormatErrorString(FormatString, Args); + if (Range.Start.Line > 0 && Range.Start.Column > 0) + return (Twine(Range.Start.Line) + ":" + Twine(Range.Start.Column) + ": " + + ErrorOut).str(); + return ErrorOut; +} + +std::string Diagnostics::ToString() const { + if (Frames.empty()) return ""; + return Frames[Frames.size() - 1].ToString(); +} + +std::string Diagnostics::ToStringFull() const { + std::string Result; + for (size_t i = 0, end = Frames.size(); i != end; ++i) { + if (i > 0) Result += "\n"; + Result += Frames[i].ToString(); + } + return Result; +} + +} // namespace dynamic +} // namespace ast_matchers +} // namespace clang |