139 lines · cpp
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-exception6//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(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("$");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(message.range, os);112 os << prefix;113 formatErrorString(errorTypeToFormatString(message.type), 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(content.messages[0], "", 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(content.messages[i],125 "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(error, os);135 }136}137 138} // namespace mlir::query::matcher::internal139