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."; 40 case Diagnostics::ET_RegistryNotBindable: 41 return "Matcher does not support binding."; 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."; 61 case Diagnostics::ET_ParserMalformedBindExpr: 62 return "Malformed bind() expression."; 63 case Diagnostics::ET_ParserTrailingCode: 64 return "Expected end of code."; 65 case Diagnostics::ET_ParserUnsignedError: 66 return "Error parsing unsigned token: <$0>"; 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 122