1//===- Diagnostic.cpp -----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Diagnostics.h"
10#include "mlir/Query/Matcher/ErrorBuilder.h"
11
12namespace mlir::query::matcher::internal {
13
14Diagnostics::ArgStream &
15Diagnostics::ArgStream::operator<<(const llvm::Twine &arg) {
16 out->push_back(x: arg.str());
17 return *this;
18}
19
20Diagnostics::ArgStream Diagnostics::addError(SourceRange range,
21 ErrorType error) {
22 errorValues.emplace_back();
23 ErrorContent &last = errorValues.back();
24 last.contextStack = contextStack;
25 last.messages.emplace_back();
26 last.messages.back().range = range;
27 last.messages.back().type = error;
28 return ArgStream(&last.messages.back().args);
29}
30
31static llvm::StringRef errorTypeToFormatString(ErrorType type) {
32 switch (type) {
33 case ErrorType::RegistryMatcherNotFound:
34 return "Matcher not found: $0";
35 case ErrorType::RegistryWrongArgCount:
36 return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
37 case ErrorType::RegistryWrongArgType:
38 return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
39 case ErrorType::RegistryValueNotFound:
40 return "Value not found: $0";
41 case ErrorType::RegistryNotBindable:
42 return "Matcher does not support binding.";
43
44 case ErrorType::ParserStringError:
45 return "Error parsing string token: <$0>";
46 case ErrorType::ParserNoOpenParen:
47 return "Error parsing matcher. Found token <$0> while looking for '('.";
48 case ErrorType::ParserNoCloseParen:
49 return "Error parsing matcher. Found end-of-code while looking for ')'.";
50 case ErrorType::ParserNoComma:
51 return "Error parsing matcher. Found token <$0> while looking for ','.";
52 case ErrorType::ParserNoCode:
53 return "End of code found while looking for token.";
54 case ErrorType::ParserNotAMatcher:
55 return "Input value is not a matcher expression.";
56 case ErrorType::ParserInvalidToken:
57 return "Invalid token <$0> found when looking for a value.";
58 case ErrorType::ParserTrailingCode:
59 return "Unexpected end of code.";
60 case ErrorType::ParserOverloadedType:
61 return "Input value has unresolved overloaded type: $0";
62 case ErrorType::ParserMalformedChainedExpr:
63 return "Period not followed by valid chained call.";
64 case ErrorType::ParserChainedExprInvalidArg:
65 return "Missing/Invalid argument for the chained call.";
66 case ErrorType::ParserChainedExprNoCloseParen:
67 return "Missing ')' for the chained call.";
68 case ErrorType::ParserChainedExprNoOpenParen:
69 return "Missing '(' for the chained call.";
70 case ErrorType::ParserFailedToBuildMatcher:
71 return "Failed to build matcher: $0.";
72
73 case ErrorType::None:
74 return "<N/A>";
75 }
76 llvm_unreachable("Unknown ErrorType value.");
77}
78
79static void formatErrorString(llvm::StringRef formatString,
80 llvm::ArrayRef<std::string> args,
81 llvm::raw_ostream &os) {
82 while (!formatString.empty()) {
83 std::pair<llvm::StringRef, llvm::StringRef> pieces =
84 formatString.split(Separator: "$");
85 os << pieces.first.str();
86 if (pieces.second.empty())
87 break;
88
89 const char next = pieces.second.front();
90 formatString = pieces.second.drop_front();
91 if (next >= '0' && next <= '9') {
92 const unsigned index = next - '0';
93 if (index < args.size()) {
94 os << args[index];
95 } else {
96 os << "<Argument_Not_Provided>";
97 }
98 }
99 }
100}
101
102static void maybeAddLineAndColumn(SourceRange range, llvm::raw_ostream &os) {
103 if (range.start.line > 0 && range.start.column > 0) {
104 os << range.start.line << ":" << range.start.column << ": ";
105 }
106}
107
108void Diagnostics::printMessage(
109 const Diagnostics::ErrorContent::Message &message, const llvm::Twine prefix,
110 llvm::raw_ostream &os) const {
111 maybeAddLineAndColumn(range: message.range, os);
112 os << prefix;
113 formatErrorString(formatString: errorTypeToFormatString(type: message.type), args: message.args, os);
114}
115
116void Diagnostics::printErrorContent(const Diagnostics::ErrorContent &content,
117 llvm::raw_ostream &os) const {
118 if (content.messages.size() == 1) {
119 printMessage(message: content.messages[0], prefix: "", os);
120 } else {
121 for (size_t i = 0, e = content.messages.size(); i != e; ++i) {
122 if (i != 0)
123 os << "\n";
124 printMessage(message: content.messages[i],
125 prefix: "Candidate " + llvm::Twine(i + 1) + ": ", os);
126 }
127 }
128}
129
130void Diagnostics::print(llvm::raw_ostream &os) const {
131 for (const ErrorContent &error : errorValues) {
132 if (&error != &errorValues.front())
133 os << "\n";
134 printErrorContent(content: error, os);
135 }
136}
137
138} // namespace mlir::query::matcher::internal
139

source code of mlir/lib/Query/Matcher/Diagnostics.cpp