Manuel Klimek | f7f295f | 2013-05-14 09:13:00 +0000 | [diff] [blame] | 1 | //===--- Diagnostics.cpp - Helper class for error diagnostics -----*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #include "clang/ASTMatchers/Dynamic/Diagnostics.h" |
| 11 | |
| 12 | namespace clang { |
| 13 | namespace ast_matchers { |
| 14 | namespace dynamic { |
| 15 | |
| 16 | Diagnostics::ArgStream & |
| 17 | Diagnostics::ArgStream::operator<<(const Twine &Arg) { |
| 18 | Out->push_back(Arg.str()); |
| 19 | return *this; |
| 20 | } |
| 21 | |
| 22 | Diagnostics::ArgStream Diagnostics::pushErrorFrame(const SourceRange &Range, |
| 23 | ErrorType Error) { |
| 24 | Frames.insert(Frames.begin(), ErrorFrame()); |
| 25 | ErrorFrame &Last = Frames.front(); |
| 26 | Last.Range = Range; |
| 27 | Last.Type = Error; |
| 28 | ArgStream Out = { &Last.Args }; |
| 29 | return Out; |
| 30 | } |
| 31 | |
| 32 | StringRef ErrorTypeToString(Diagnostics::ErrorType Type) { |
| 33 | switch (Type) { |
| 34 | case Diagnostics::ET_RegistryNotFound: |
| 35 | return "Matcher not found: $0"; |
| 36 | case Diagnostics::ET_RegistryWrongArgCount: |
| 37 | return "Incorrect argument count. (Expected = $0) != (Actual = $1)"; |
| 38 | case Diagnostics::ET_RegistryWrongArgType: |
| 39 | return "Incorrect type on function $0 for arg $1."; |
Samuel Benzaquen | 4f37d92 | 2013-06-03 19:31:08 +0000 | [diff] [blame] | 40 | case Diagnostics::ET_RegistryNotBindable: |
| 41 | return "Matcher does not support binding."; |
Manuel Klimek | f7f295f | 2013-05-14 09:13:00 +0000 | [diff] [blame] | 42 | |
| 43 | case Diagnostics::ET_ParserStringError: |
| 44 | return "Error parsing string token: <$0>"; |
| 45 | case Diagnostics::ET_ParserMatcherArgFailure: |
| 46 | return "Error parsing argument $0 for matcher $1."; |
| 47 | case Diagnostics::ET_ParserMatcherFailure: |
| 48 | return "Error building matcher $0."; |
| 49 | case Diagnostics::ET_ParserNoOpenParen: |
| 50 | return "Error parsing matcher. Found token <$0> while looking for '('."; |
| 51 | case Diagnostics::ET_ParserNoCloseParen: |
| 52 | return "Error parsing matcher. Found end-of-code while looking for ')'."; |
| 53 | case Diagnostics::ET_ParserNoComma: |
| 54 | return "Error parsing matcher. Found token <$0> while looking for ','."; |
| 55 | case Diagnostics::ET_ParserNoCode: |
| 56 | return "End of code found while looking for token."; |
| 57 | case Diagnostics::ET_ParserNotAMatcher: |
| 58 | return "Input value is not a matcher expression."; |
| 59 | case Diagnostics::ET_ParserInvalidToken: |
| 60 | return "Invalid token <$0> found when looking for a value."; |
Samuel Benzaquen | 4f37d92 | 2013-06-03 19:31:08 +0000 | [diff] [blame] | 61 | case Diagnostics::ET_ParserMalformedBindExpr: |
| 62 | return "Malformed bind() expression."; |
| 63 | case Diagnostics::ET_ParserTrailingCode: |
| 64 | return "Expected end of code."; |
Samuel Benzaquen | 7a337af | 2013-06-04 15:46:22 +0000 | [diff] [blame] | 65 | case Diagnostics::ET_ParserUnsignedError: |
| 66 | return "Error parsing unsigned token: <$0>"; |
Manuel Klimek | f7f295f | 2013-05-14 09:13:00 +0000 | [diff] [blame] | 67 | |
| 68 | case Diagnostics::ET_None: |
| 69 | return "<N/A>"; |
| 70 | } |
| 71 | llvm_unreachable("Unknown ErrorType value."); |
| 72 | } |
| 73 | |
| 74 | std::string FormatErrorString(StringRef FormatString, |
| 75 | ArrayRef<std::string> Args) { |
| 76 | std::string Out; |
| 77 | while (!FormatString.empty()) { |
| 78 | std::pair<StringRef, StringRef> Pieces = FormatString.split("$"); |
| 79 | Out += Pieces.first.str(); |
| 80 | if (Pieces.second.empty()) break; |
| 81 | |
| 82 | const char Next = Pieces.second.front(); |
| 83 | FormatString = Pieces.second.drop_front(); |
| 84 | if (Next >= '0' && Next <= '9') { |
| 85 | const unsigned Index = Next - '0'; |
| 86 | if (Index < Args.size()) { |
| 87 | Out += Args[Index]; |
| 88 | } else { |
| 89 | Out += "<Argument_Not_Provided>"; |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | return Out; |
| 94 | } |
| 95 | |
| 96 | std::string Diagnostics::ErrorFrame::ToString() const { |
| 97 | StringRef FormatString = ErrorTypeToString(Type); |
| 98 | std::string ErrorOut = FormatErrorString(FormatString, Args); |
| 99 | if (Range.Start.Line > 0 && Range.Start.Column > 0) |
| 100 | return (Twine(Range.Start.Line) + ":" + Twine(Range.Start.Column) + ": " + |
| 101 | ErrorOut).str(); |
| 102 | return ErrorOut; |
| 103 | } |
| 104 | |
| 105 | std::string Diagnostics::ToString() const { |
| 106 | if (Frames.empty()) return ""; |
| 107 | return Frames[Frames.size() - 1].ToString(); |
| 108 | } |
| 109 | |
| 110 | std::string Diagnostics::ToStringFull() const { |
| 111 | std::string Result; |
| 112 | for (size_t i = 0, end = Frames.size(); i != end; ++i) { |
| 113 | if (i > 0) Result += "\n"; |
| 114 | Result += Frames[i].ToString(); |
| 115 | } |
| 116 | return Result; |
| 117 | } |
| 118 | |
| 119 | } // namespace dynamic |
| 120 | } // namespace ast_matchers |
| 121 | } // namespace clang |