blob: b72910e0ac4d0d51496c631f44701c1ee1158d97 [file] [log] [blame]
Manuel Klimek24db0f02013-05-14 09:13:00 +00001//===--- 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
12namespace clang {
13namespace ast_matchers {
14namespace dynamic {
15
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +000016Diagnostics::ArgStream Diagnostics::pushContextFrame(ContextType Type,
17 SourceRange Range) {
18 ContextStack.push_back(ContextFrame());
19 ContextFrame& data = ContextStack.back();
20 data.Type = Type;
21 data.Range = Range;
22 return ArgStream(&data.Args);
23}
24
25Diagnostics::Context::Context(ConstructMatcherEnum, Diagnostics *Error,
26 StringRef MatcherName,
27 const SourceRange &MatcherRange)
28 : Error(Error) {
29 Error->pushContextFrame(CT_MatcherConstruct, MatcherRange) << MatcherName;
30}
31
32Diagnostics::Context::Context(MatcherArgEnum, Diagnostics *Error,
33 StringRef MatcherName,
34 const SourceRange &MatcherRange,
35 unsigned ArgNumber)
36 : Error(Error) {
37 Error->pushContextFrame(CT_MatcherArg, MatcherRange) << ArgNumber
38 << MatcherName;
39}
40
41Diagnostics::Context::~Context() { Error->ContextStack.pop_back(); }
42
43Diagnostics::ArgStream &Diagnostics::ArgStream::operator<<(const Twine &Arg) {
Manuel Klimek24db0f02013-05-14 09:13:00 +000044 Out->push_back(Arg.str());
45 return *this;
46}
47
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +000048Diagnostics::ArgStream Diagnostics::addError(const SourceRange &Range,
49 ErrorType Error) {
50 Errors.push_back(ErrorContent());
51 ErrorContent &Last = Errors.back();
52 Last.ContextStack = ContextStack;
Manuel Klimek24db0f02013-05-14 09:13:00 +000053 Last.Range = Range;
54 Last.Type = Error;
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +000055 return ArgStream(&Last.Args);
56}
57
Samuel Benzaquenb8372482013-07-19 20:02:35 +000058StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +000059 switch (Type) {
60 case Diagnostics::CT_MatcherConstruct:
61 return "Error building matcher $0.";
62 case Diagnostics::CT_MatcherArg:
63 return "Error parsing argument $0 for matcher $1.";
64 }
65 llvm_unreachable("Unknown ContextType value.");
Manuel Klimek24db0f02013-05-14 09:13:00 +000066}
67
Samuel Benzaquenb8372482013-07-19 20:02:35 +000068StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
Manuel Klimek24db0f02013-05-14 09:13:00 +000069 switch (Type) {
70 case Diagnostics::ET_RegistryNotFound:
71 return "Matcher not found: $0";
72 case Diagnostics::ET_RegistryWrongArgCount:
73 return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
74 case Diagnostics::ET_RegistryWrongArgType:
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000075 return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
Samuel Benzaquen31edb512013-06-03 19:31:08 +000076 case Diagnostics::ET_RegistryNotBindable:
77 return "Matcher does not support binding.";
Manuel Klimek24db0f02013-05-14 09:13:00 +000078
79 case Diagnostics::ET_ParserStringError:
80 return "Error parsing string token: <$0>";
Manuel Klimek24db0f02013-05-14 09:13:00 +000081 case Diagnostics::ET_ParserNoOpenParen:
82 return "Error parsing matcher. Found token <$0> while looking for '('.";
83 case Diagnostics::ET_ParserNoCloseParen:
84 return "Error parsing matcher. Found end-of-code while looking for ')'.";
85 case Diagnostics::ET_ParserNoComma:
86 return "Error parsing matcher. Found token <$0> while looking for ','.";
87 case Diagnostics::ET_ParserNoCode:
88 return "End of code found while looking for token.";
89 case Diagnostics::ET_ParserNotAMatcher:
90 return "Input value is not a matcher expression.";
91 case Diagnostics::ET_ParserInvalidToken:
92 return "Invalid token <$0> found when looking for a value.";
Samuel Benzaquen31edb512013-06-03 19:31:08 +000093 case Diagnostics::ET_ParserMalformedBindExpr:
94 return "Malformed bind() expression.";
95 case Diagnostics::ET_ParserTrailingCode:
96 return "Expected end of code.";
Samuel Benzaquenc31b3522013-06-04 15:46:22 +000097 case Diagnostics::ET_ParserUnsignedError:
98 return "Error parsing unsigned token: <$0>";
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +000099 case Diagnostics::ET_ParserOverloadedType:
100 return "Input value has unresolved overloaded type: $0";
Manuel Klimek24db0f02013-05-14 09:13:00 +0000101
102 case Diagnostics::ET_None:
103 return "<N/A>";
104 }
105 llvm_unreachable("Unknown ErrorType value.");
106}
107
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000108void formatErrorString(StringRef FormatString, ArrayRef<std::string> Args,
109 llvm::raw_ostream &OS) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000110 while (!FormatString.empty()) {
111 std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000112 OS << Pieces.first.str();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000113 if (Pieces.second.empty()) break;
114
115 const char Next = Pieces.second.front();
116 FormatString = Pieces.second.drop_front();
117 if (Next >= '0' && Next <= '9') {
118 const unsigned Index = Next - '0';
119 if (Index < Args.size()) {
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000120 OS << Args[Index];
Manuel Klimek24db0f02013-05-14 09:13:00 +0000121 } else {
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000122 OS << "<Argument_Not_Provided>";
Manuel Klimek24db0f02013-05-14 09:13:00 +0000123 }
124 }
125 }
Manuel Klimek24db0f02013-05-14 09:13:00 +0000126}
127
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000128static void maybeAddLineAndColumn(const SourceRange &Range,
129 llvm::raw_ostream &OS) {
130 if (Range.Start.Line > 0 && Range.Start.Column > 0) {
131 OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000132 }
Manuel Klimek24db0f02013-05-14 09:13:00 +0000133}
134
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000135static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
136 llvm::raw_ostream &OS) {
137 maybeAddLineAndColumn(Frame.Range, OS);
138 formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
139}
140
141static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
142 llvm::raw_ostream &OS) {
143 maybeAddLineAndColumn(Content.Range, OS);
144 formatErrorString(errorTypeToFormatString(Content.Type), Content.Args, OS);
145}
146
147void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000148 for (size_t i = 0, e = Errors.size(); i != e; ++i) {
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000149 if (i != 0) OS << "\n";
150 printErrorContentToStream(Errors[i], OS);
151 }
152}
153
154std::string Diagnostics::toString() const {
155 std::string S;
156 llvm::raw_string_ostream OS(S);
157 printToStream(OS);
158 return OS.str();
159}
160
161void Diagnostics::printToStreamFull(llvm::raw_ostream &OS) const {
162 for (size_t i = 0, e = Errors.size(); i != e; ++i) {
163 if (i != 0) OS << "\n";
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000164 const ErrorContent &Error = Errors[i];
165 for (size_t i = 0, e = Error.ContextStack.size(); i != e; ++i) {
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000166 printContextFrameToStream(Error.ContextStack[i], OS);
167 OS << "\n";
Samuel Benzaquena37bb8c2013-07-18 19:47:59 +0000168 }
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000169 printErrorContentToStream(Error, OS);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000170 }
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000171}
172
173std::string Diagnostics::toStringFull() const {
174 std::string S;
175 llvm::raw_string_ostream OS(S);
176 printToStreamFull(OS);
177 return OS.str();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000178}
179
180} // namespace dynamic
181} // namespace ast_matchers
182} // namespace clang