blob: fb3cac370f53c12f58581e150099bbe65623073a [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
16Diagnostics::ArgStream &
17Diagnostics::ArgStream::operator<<(const Twine &Arg) {
18 Out->push_back(Arg.str());
19 return *this;
20}
21
22Diagnostics::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
32StringRef 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
41 case Diagnostics::ET_ParserStringError:
42 return "Error parsing string token: <$0>";
43 case Diagnostics::ET_ParserMatcherArgFailure:
44 return "Error parsing argument $0 for matcher $1.";
45 case Diagnostics::ET_ParserMatcherFailure:
46 return "Error building matcher $0.";
47 case Diagnostics::ET_ParserNoOpenParen:
48 return "Error parsing matcher. Found token <$0> while looking for '('.";
49 case Diagnostics::ET_ParserNoCloseParen:
50 return "Error parsing matcher. Found end-of-code while looking for ')'.";
51 case Diagnostics::ET_ParserNoComma:
52 return "Error parsing matcher. Found token <$0> while looking for ','.";
53 case Diagnostics::ET_ParserNoCode:
54 return "End of code found while looking for token.";
55 case Diagnostics::ET_ParserNotAMatcher:
56 return "Input value is not a matcher expression.";
57 case Diagnostics::ET_ParserInvalidToken:
58 return "Invalid token <$0> found when looking for a value.";
59
60 case Diagnostics::ET_None:
61 return "<N/A>";
62 }
63 llvm_unreachable("Unknown ErrorType value.");
64}
65
66std::string FormatErrorString(StringRef FormatString,
67 ArrayRef<std::string> Args) {
68 std::string Out;
69 while (!FormatString.empty()) {
70 std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
71 Out += Pieces.first.str();
72 if (Pieces.second.empty()) break;
73
74 const char Next = Pieces.second.front();
75 FormatString = Pieces.second.drop_front();
76 if (Next >= '0' && Next <= '9') {
77 const unsigned Index = Next - '0';
78 if (Index < Args.size()) {
79 Out += Args[Index];
80 } else {
81 Out += "<Argument_Not_Provided>";
82 }
83 }
84 }
85 return Out;
86}
87
88std::string Diagnostics::ErrorFrame::ToString() const {
89 StringRef FormatString = ErrorTypeToString(Type);
90 std::string ErrorOut = FormatErrorString(FormatString, Args);
91 if (Range.Start.Line > 0 && Range.Start.Column > 0)
92 return (Twine(Range.Start.Line) + ":" + Twine(Range.Start.Column) + ": " +
93 ErrorOut).str();
94 return ErrorOut;
95}
96
97std::string Diagnostics::ToString() const {
98 if (Frames.empty()) return "";
99 return Frames[Frames.size() - 1].ToString();
100}
101
102std::string Diagnostics::ToStringFull() const {
103 std::string Result;
104 for (size_t i = 0, end = Frames.size(); i != end; ++i) {
105 if (i > 0) Result += "\n";
106 Result += Frames[i].ToString();
107 }
108 return Result;
109}
110
111} // namespace dynamic
112} // namespace ast_matchers
113} // namespace clang