summaryrefslogtreecommitdiff
path: root/lib/ASTMatchers/Dynamic/Diagnostics.cpp
blob: fb3cac370f53c12f58581e150099bbe65623073a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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