102d9f4d1SDevajith //===- Diagnostic.cpp -----------------------------------------------------===//
202d9f4d1SDevajith //
302d9f4d1SDevajith // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
402d9f4d1SDevajith // See https://llvm.org/LICENSE.txt for license information.
502d9f4d1SDevajith // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
602d9f4d1SDevajith //
702d9f4d1SDevajith //===----------------------------------------------------------------------===//
802d9f4d1SDevajith
902d9f4d1SDevajith #include "Diagnostics.h"
1002d9f4d1SDevajith #include "mlir/Query/Matcher/ErrorBuilder.h"
1102d9f4d1SDevajith
1202d9f4d1SDevajith namespace mlir::query::matcher::internal {
1302d9f4d1SDevajith
1402d9f4d1SDevajith Diagnostics::ArgStream &
operator <<(const llvm::Twine & arg)1502d9f4d1SDevajith Diagnostics::ArgStream::operator<<(const llvm::Twine &arg) {
1602d9f4d1SDevajith out->push_back(arg.str());
1702d9f4d1SDevajith return *this;
1802d9f4d1SDevajith }
1902d9f4d1SDevajith
addError(SourceRange range,ErrorType error)2002d9f4d1SDevajith Diagnostics::ArgStream Diagnostics::addError(SourceRange range,
2102d9f4d1SDevajith ErrorType error) {
2202d9f4d1SDevajith errorValues.emplace_back();
2302d9f4d1SDevajith ErrorContent &last = errorValues.back();
2402d9f4d1SDevajith last.contextStack = contextStack;
2502d9f4d1SDevajith last.messages.emplace_back();
2602d9f4d1SDevajith last.messages.back().range = range;
2702d9f4d1SDevajith last.messages.back().type = error;
2802d9f4d1SDevajith return ArgStream(&last.messages.back().args);
2902d9f4d1SDevajith }
3002d9f4d1SDevajith
errorTypeToFormatString(ErrorType type)3102d9f4d1SDevajith static llvm::StringRef errorTypeToFormatString(ErrorType type) {
3202d9f4d1SDevajith switch (type) {
3302d9f4d1SDevajith case ErrorType::RegistryMatcherNotFound:
3402d9f4d1SDevajith return "Matcher not found: $0";
3502d9f4d1SDevajith case ErrorType::RegistryWrongArgCount:
3602d9f4d1SDevajith return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
3702d9f4d1SDevajith case ErrorType::RegistryWrongArgType:
3802d9f4d1SDevajith return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
3902d9f4d1SDevajith case ErrorType::RegistryValueNotFound:
4002d9f4d1SDevajith return "Value not found: $0";
41*58b44c81SJacques Pienaar case ErrorType::RegistryNotBindable:
42*58b44c81SJacques Pienaar return "Matcher does not support binding.";
4302d9f4d1SDevajith
4402d9f4d1SDevajith case ErrorType::ParserStringError:
4502d9f4d1SDevajith return "Error parsing string token: <$0>";
4602d9f4d1SDevajith case ErrorType::ParserNoOpenParen:
4702d9f4d1SDevajith return "Error parsing matcher. Found token <$0> while looking for '('.";
4802d9f4d1SDevajith case ErrorType::ParserNoCloseParen:
4902d9f4d1SDevajith return "Error parsing matcher. Found end-of-code while looking for ')'.";
5002d9f4d1SDevajith case ErrorType::ParserNoComma:
5102d9f4d1SDevajith return "Error parsing matcher. Found token <$0> while looking for ','.";
5202d9f4d1SDevajith case ErrorType::ParserNoCode:
5302d9f4d1SDevajith return "End of code found while looking for token.";
5402d9f4d1SDevajith case ErrorType::ParserNotAMatcher:
5502d9f4d1SDevajith return "Input value is not a matcher expression.";
5602d9f4d1SDevajith case ErrorType::ParserInvalidToken:
5702d9f4d1SDevajith return "Invalid token <$0> found when looking for a value.";
5802d9f4d1SDevajith case ErrorType::ParserTrailingCode:
5902d9f4d1SDevajith return "Unexpected end of code.";
6002d9f4d1SDevajith case ErrorType::ParserOverloadedType:
6102d9f4d1SDevajith return "Input value has unresolved overloaded type: $0";
62*58b44c81SJacques Pienaar case ErrorType::ParserMalformedChainedExpr:
63*58b44c81SJacques Pienaar return "Period not followed by valid chained call.";
64*58b44c81SJacques Pienaar case ErrorType::ParserChainedExprInvalidArg:
65*58b44c81SJacques Pienaar return "Missing/Invalid argument for the chained call.";
66*58b44c81SJacques Pienaar case ErrorType::ParserChainedExprNoCloseParen:
67*58b44c81SJacques Pienaar return "Missing ')' for the chained call.";
68*58b44c81SJacques Pienaar case ErrorType::ParserChainedExprNoOpenParen:
69*58b44c81SJacques Pienaar return "Missing '(' for the chained call.";
7002d9f4d1SDevajith case ErrorType::ParserFailedToBuildMatcher:
7102d9f4d1SDevajith return "Failed to build matcher: $0.";
7202d9f4d1SDevajith
7302d9f4d1SDevajith case ErrorType::None:
7402d9f4d1SDevajith return "<N/A>";
7502d9f4d1SDevajith }
7602d9f4d1SDevajith llvm_unreachable("Unknown ErrorType value.");
7702d9f4d1SDevajith }
7802d9f4d1SDevajith
formatErrorString(llvm::StringRef formatString,llvm::ArrayRef<std::string> args,llvm::raw_ostream & os)7902d9f4d1SDevajith static void formatErrorString(llvm::StringRef formatString,
8002d9f4d1SDevajith llvm::ArrayRef<std::string> args,
8102d9f4d1SDevajith llvm::raw_ostream &os) {
8202d9f4d1SDevajith while (!formatString.empty()) {
8302d9f4d1SDevajith std::pair<llvm::StringRef, llvm::StringRef> pieces =
8402d9f4d1SDevajith formatString.split("$");
8502d9f4d1SDevajith os << pieces.first.str();
8602d9f4d1SDevajith if (pieces.second.empty())
8702d9f4d1SDevajith break;
8802d9f4d1SDevajith
8902d9f4d1SDevajith const char next = pieces.second.front();
9002d9f4d1SDevajith formatString = pieces.second.drop_front();
9102d9f4d1SDevajith if (next >= '0' && next <= '9') {
9202d9f4d1SDevajith const unsigned index = next - '0';
9302d9f4d1SDevajith if (index < args.size()) {
9402d9f4d1SDevajith os << args[index];
9502d9f4d1SDevajith } else {
9602d9f4d1SDevajith os << "<Argument_Not_Provided>";
9702d9f4d1SDevajith }
9802d9f4d1SDevajith }
9902d9f4d1SDevajith }
10002d9f4d1SDevajith }
10102d9f4d1SDevajith
maybeAddLineAndColumn(SourceRange range,llvm::raw_ostream & os)10202d9f4d1SDevajith static void maybeAddLineAndColumn(SourceRange range, llvm::raw_ostream &os) {
10302d9f4d1SDevajith if (range.start.line > 0 && range.start.column > 0) {
10402d9f4d1SDevajith os << range.start.line << ":" << range.start.column << ": ";
10502d9f4d1SDevajith }
10602d9f4d1SDevajith }
10702d9f4d1SDevajith
printMessage(const Diagnostics::ErrorContent::Message & message,const llvm::Twine prefix,llvm::raw_ostream & os) const10802d9f4d1SDevajith void Diagnostics::printMessage(
10902d9f4d1SDevajith const Diagnostics::ErrorContent::Message &message, const llvm::Twine prefix,
11002d9f4d1SDevajith llvm::raw_ostream &os) const {
11102d9f4d1SDevajith maybeAddLineAndColumn(message.range, os);
11202d9f4d1SDevajith os << prefix;
11302d9f4d1SDevajith formatErrorString(errorTypeToFormatString(message.type), message.args, os);
11402d9f4d1SDevajith }
11502d9f4d1SDevajith
printErrorContent(const Diagnostics::ErrorContent & content,llvm::raw_ostream & os) const11602d9f4d1SDevajith void Diagnostics::printErrorContent(const Diagnostics::ErrorContent &content,
11702d9f4d1SDevajith llvm::raw_ostream &os) const {
11802d9f4d1SDevajith if (content.messages.size() == 1) {
11902d9f4d1SDevajith printMessage(content.messages[0], "", os);
12002d9f4d1SDevajith } else {
12102d9f4d1SDevajith for (size_t i = 0, e = content.messages.size(); i != e; ++i) {
12202d9f4d1SDevajith if (i != 0)
12302d9f4d1SDevajith os << "\n";
12402d9f4d1SDevajith printMessage(content.messages[i],
12502d9f4d1SDevajith "Candidate " + llvm::Twine(i + 1) + ": ", os);
12602d9f4d1SDevajith }
12702d9f4d1SDevajith }
12802d9f4d1SDevajith }
12902d9f4d1SDevajith
print(llvm::raw_ostream & os) const13002d9f4d1SDevajith void Diagnostics::print(llvm::raw_ostream &os) const {
13102d9f4d1SDevajith for (const ErrorContent &error : errorValues) {
13202d9f4d1SDevajith if (&error != &errorValues.front())
13302d9f4d1SDevajith os << "\n";
13402d9f4d1SDevajith printErrorContent(error, os);
13502d9f4d1SDevajith }
13602d9f4d1SDevajith }
13702d9f4d1SDevajith
13802d9f4d1SDevajith } // namespace mlir::query::matcher::internal
139