yql_issue_id.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #pragma once
  2. #include <yql/essentials/public/issue/protos/issue_severity.pb.h>
  3. #include <library/cpp/resource/resource.h>
  4. #include <google/protobuf/descriptor.h>
  5. #include <google/protobuf/repeated_field.h>
  6. #include <google/protobuf/text_format.h>
  7. #include <google/protobuf/message.h>
  8. #include <util/generic/hash.h>
  9. #include <util/generic/singleton.h>
  10. #include <util/generic/yexception.h>
  11. #include <util/string/subst.h>
  12. #ifdef _win_
  13. #ifdef GetMessage
  14. #undef GetMessage
  15. #endif
  16. #endif
  17. namespace NYql {
  18. using TIssueCode = ui32;
  19. using ESeverity = NYql::TSeverityIds::ESeverityId;
  20. const TIssueCode DEFAULT_ERROR = 0;
  21. const TIssueCode UNEXPECTED_ERROR = 1;
  22. inline TString SeverityToString(ESeverity severity)
  23. {
  24. auto ret = NYql::TSeverityIds::ESeverityId_Name(severity);
  25. return ret.empty() ? "Unknown" : to_title(ret.substr(2)); //remove prefix "S_"
  26. }
  27. template <typename T>
  28. inline TString IssueCodeToString(TIssueCode id) {
  29. auto ret = T::EIssueCode_Name(static_cast<typename T::EIssueCode>(id));
  30. if (!ret.empty()) {
  31. SubstGlobal(ret, '_', ' ');
  32. return to_title(ret);
  33. } else {
  34. return "Unknown";
  35. }
  36. }
  37. template<typename TProto, const char* ResourceName>
  38. class TIssueId {
  39. TProto ProtoIssues_;
  40. THashMap<TIssueCode, NYql::TSeverityIds::ESeverityId> IssuesMap_;
  41. THashMap<TIssueCode, TString> IssuesFormatMap_;
  42. const google::protobuf::Descriptor* GetProtoDescriptor() const {
  43. auto ret = ProtoIssues_.GetDescriptor();
  44. Y_ENSURE(ret != nullptr, "Bad proto file");
  45. return ret;
  46. }
  47. bool CheckSeverityNameFormat(const TString& name) const {
  48. if (name.size() > 2 && name.substr(0,2) == "S_") {
  49. return true;
  50. }
  51. return false;
  52. }
  53. public:
  54. ESeverity GetSeverity(TIssueCode id) const {
  55. auto it = IssuesMap_.find(id);
  56. Y_ENSURE(it != IssuesMap_.end(), "Unknown issue id: "
  57. << id << "(" << IssueCodeToString<TProto>(id) << ")");
  58. return it->second;
  59. }
  60. TString GetMessage(TIssueCode id) const {
  61. auto it = IssuesFormatMap_.find(id);
  62. Y_ENSURE(it != IssuesFormatMap_.end(), "Unknown issue id: "
  63. << id << "(" << IssueCodeToString<TProto>(id) << ")");
  64. return it->second;
  65. }
  66. TIssueId() {
  67. auto configData = NResource::Find(TStringBuf(ResourceName));
  68. if (!::google::protobuf::TextFormat::ParseFromString(configData, &ProtoIssues_)) {
  69. Y_ENSURE(false, "Bad format of protobuf data file, resource: " << ResourceName);
  70. }
  71. auto sDesc = TSeverityIds::ESeverityId_descriptor();
  72. for (int i = 0; i < sDesc->value_count(); i++) {
  73. const auto& name = sDesc->value(i)->name();
  74. Y_ENSURE(CheckSeverityNameFormat(name),
  75. "Wrong severity name: " << name << ". Severity must starts with \"S_\" prefix");
  76. }
  77. for (const auto& x : ProtoIssues_.ids()) {
  78. auto rv = IssuesMap_.insert(std::make_pair(x.code(), x.severity()));
  79. Y_ENSURE(rv.second, "Duplicate issue code found, code: "
  80. << static_cast<int>(x.code())
  81. << "(" << IssueCodeToString<TProto>(x.code()) <<")");
  82. }
  83. // Check all IssueCodes have mapping to severity
  84. auto eDesc = TProto::EIssueCode_descriptor();
  85. for (int i = 0; i < eDesc->value_count(); i++) {
  86. auto it = IssuesMap_.find(eDesc->value(i)->number());
  87. Y_ENSURE(it != IssuesMap_.end(), "IssueCode: "
  88. << eDesc->value(i)->name()
  89. << " is not found in protobuf data file");
  90. }
  91. for (const auto& x : ProtoIssues_.ids()) {
  92. auto rv = IssuesFormatMap_.insert(std::make_pair(x.code(), x.format()));
  93. Y_ENSURE(rv.second, "Duplicate issue code found, code: "
  94. << static_cast<int>(x.code())
  95. << "(" << IssueCodeToString<TProto>(x.code()) <<")");
  96. }
  97. }
  98. };
  99. template<typename TProto, const char* ResourceName>
  100. inline ESeverity GetSeverity(TIssueCode id) {
  101. return Singleton<TIssueId<TProto, ResourceName>>()->GetSeverity(id);
  102. }
  103. template<typename TProto, const char* ResourceName>
  104. inline TString GetMessage(TIssueCode id) {
  105. return Singleton<TIssueId<TProto, ResourceName>>()->GetMessage(id);
  106. }
  107. }